diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2008-07-03 12:22:52 +1000 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2008-07-03 12:22:52 +1000 |
commit | 21be97cd6c57fcdebf325540cc4a8ee363859cdb (patch) | |
tree | 56af9021a1f65053001c359a5f9f27c4dace2a39 /drivers | |
parent | 1f35ca51fc09b48f567c002a1108ba3f9faed57c (diff) | |
parent | df9b4983a84fcbc1fd7d977431abd974e86e01dc (diff) |
Merge branch 'quilt/i2c'
Conflicts:
drivers/i2c/i2c-core.c
Diffstat (limited to 'drivers')
84 files changed, 5038 insertions, 4035 deletions
diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c index 1d76de7d75c7..c90e97e02937 100644 --- a/drivers/hwmon/adm1025.c +++ b/drivers/hwmon/adm1025.c @@ -2,7 +2,7 @@ * adm1025.c * * Copyright (C) 2000 Chen-Yuan Wu <gwu@esoft.com> - * Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org> + * Copyright (C) 2003-2008 Jean Delvare <khali@linux-fr.org> * * The ADM1025 is a sensor chip made by Analog Devices. It reports up to 6 * voltages (including its own power source) and up to two temperatures @@ -109,22 +109,35 @@ static const int in_scale[6] = { 2500, 2250, 3300, 5000, 12000, 3300 }; * Functions declaration */ -static int adm1025_attach_adapter(struct i2c_adapter *adapter); -static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind); +static int adm1025_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int adm1025_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); static void adm1025_init_client(struct i2c_client *client); -static int adm1025_detach_client(struct i2c_client *client); +static int adm1025_remove(struct i2c_client *client); static struct adm1025_data *adm1025_update_device(struct device *dev); /* * Driver data (common to all clients) */ +static struct i2c_device_id adm1025_id[] = { + { "adm1025", adm1025 }, + { "ne1619", ne1619 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adm1025_id); + static struct i2c_driver adm1025_driver = { + .class = I2C_CLASS_HWMON, .driver = { .name = "adm1025", }, - .attach_adapter = adm1025_attach_adapter, - .detach_client = adm1025_detach_client, + .probe = adm1025_probe, + .remove = adm1025_remove, + .id_table = adm1025_id, + .detect = adm1025_detect, + .address_data = &addr_data, }; /* @@ -132,7 +145,6 @@ static struct i2c_driver adm1025_driver = { */ struct adm1025_data { - struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ @@ -344,13 +356,6 @@ static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm); * Real code */ -static int adm1025_attach_adapter(struct i2c_adapter *adapter) -{ - if (!(adapter->class & I2C_CLASS_HWMON)) - return 0; - return i2c_probe(adapter, &addr_data, adm1025_detect); -} - static struct attribute *adm1025_attributes[] = { &sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_in1_input.dev_attr.attr, @@ -403,31 +408,16 @@ static const struct attribute_group adm1025_group_in4 = { .attrs = adm1025_attributes_in4, }; -/* - * The following function does more than just detection. If detection - * succeeds, it also registers the new chip. - */ -static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int adm1025_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info) { - struct i2c_client *client; - struct adm1025_data *data; - int err = 0; + struct i2c_adapter *adapter = client->adapter; const char *name = ""; u8 config; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - goto exit; - - if (!(data = kzalloc(sizeof(struct adm1025_data), GFP_KERNEL))) { - err = -ENOMEM; - goto exit; - } - - client = &data->client; - i2c_set_clientdata(client, data); - client->addr = address; - client->adapter = adapter; - client->driver = &adm1025_driver; + return -ENODEV; /* * Now we do the remaining detection. A negative kind means that @@ -448,8 +438,8 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) ADM1025_REG_STATUS2) & 0xBC) != 0x00) { dev_dbg(&adapter->dev, "ADM1025 detection failed at 0x%02x.\n", - address); - goto exit_free; + client->addr); + return -ENODEV; } } @@ -465,7 +455,7 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) } } else if (man_id == 0xA1) { /* Philips */ - if (address != 0x2E + if (client->addr != 0x2E && (chip_id & 0xF0) == 0x20) { /* NE1619 */ kind = ne1619; } @@ -475,7 +465,7 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) dev_info(&adapter->dev, "Unsupported chip (man_id=0x%02X, " "chip_id=0x%02X).\n", man_id, chip_id); - goto exit_free; + return -ENODEV; } } @@ -484,23 +474,36 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) } else if (kind == ne1619) { name = "ne1619"; } + strlcpy(info->type, name, I2C_NAME_SIZE); - /* We can fill in the remaining client fields */ - strlcpy(client->name, name, I2C_NAME_SIZE); - mutex_init(&data->update_lock); + return 0; +} - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(client))) - goto exit_free; +static int adm1025_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct adm1025_data *data; + int err; + u8 config; + + data = kzalloc(sizeof(struct adm1025_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); /* Initialize the ADM1025 chip */ adm1025_init_client(client); /* Register sysfs hooks */ if ((err = sysfs_create_group(&client->dev.kobj, &adm1025_group))) - goto exit_detach; + goto exit_free; /* Pin 11 is either in4 (+12V) or VID4 */ + config = i2c_smbus_read_byte_data(client, ADM1025_REG_CONFIG); if (!(config & 0x20)) { if ((err = sysfs_create_group(&client->dev.kobj, &adm1025_group_in4))) @@ -518,8 +521,6 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) exit_remove: sysfs_remove_group(&client->dev.kobj, &adm1025_group); sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4); -exit_detach: - i2c_detach_client(client); exit_free: kfree(data); exit: @@ -568,18 +569,14 @@ static void adm1025_init_client(struct i2c_client *client) (reg&0x7E)|0x01); } -static int adm1025_detach_client(struct i2c_client *client) +static int adm1025_remove(struct i2c_client *client) { struct adm1025_data *data = i2c_get_clientdata(client); - int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &adm1025_group); sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4); - if ((err = i2c_detach_client(client))) - return err; - kfree(data); return 0; } diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c index fe2eea4d799b..32ecae3c5211 100644 --- a/drivers/hwmon/asb100.c +++ b/drivers/hwmon/asb100.c @@ -176,10 +176,8 @@ static u8 DIV_TO_REG(long val) data is pointed to by client->data. The structure itself is dynamically allocated, at the same time the client itself is allocated. */ struct asb100_data { - struct i2c_client client; struct device *hwmon_dev; struct mutex lock; - enum chips type; struct mutex update_lock; unsigned long last_updated; /* In jiffies */ @@ -206,18 +204,30 @@ struct asb100_data { static int asb100_read_value(struct i2c_client *client, u16 reg); static void asb100_write_value(struct i2c_client *client, u16 reg, u16 val); -static int asb100_attach_adapter(struct i2c_adapter *adapter); -static int asb100_detect(struct i2c_adapter *adapter, int address, int kind); -static int asb100_detach_client(struct i2c_client *client); +static int asb100_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int asb100_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); +static int asb100_remove(struct i2c_client *client); static struct asb100_data *asb100_update_device(struct device *dev); static void asb100_init_client(struct i2c_client *client); +static struct i2c_device_id asb100_id[] = { + { "asb100", asb100 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, asb100_id); + static struct i2c_driver asb100_driver = { + .class = I2C_CLASS_HWMON, .driver = { .name = "asb100", }, - .attach_adapter = asb100_attach_adapter, - .detach_client = asb100_detach_client, + .probe = asb100_probe, + .remove = asb100_remove, + .id_table = asb100_id, + .detect = asb100_detect, + .address_data = &addr_data, }; /* 7 Voltages */ @@ -619,35 +629,13 @@ static const struct attribute_group asb100_group = { .attrs = asb100_attributes, }; -/* This function is called when: - asb100_driver is inserted (when this module is loaded), for each - available adapter - when a new adapter is inserted (and asb100_driver is still present) - */ -static int asb100_attach_adapter(struct i2c_adapter *adapter) -{ - if (!(adapter->class & I2C_CLASS_HWMON)) - return 0; - return i2c_probe(adapter, &addr_data, asb100_detect); -} - -static int asb100_detect_subclients(struct i2c_adapter *adapter, int address, - int kind, struct i2c_client *client) +static int asb100_detect_subclients(struct i2c_client *client) { int i, id, err; + int address = client->addr; + unsigned short sc_addr[2]; struct asb100_data *data = i2c_get_clientdata(client); - - data->lm75[0] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (!(data->lm75[0])) { - err = -ENOMEM; - goto ERROR_SC_0; - } - - data->lm75[1] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (!(data->lm75[1])) { - err = -ENOMEM; - goto ERROR_SC_1; - } + struct i2c_adapter *adapter = client->adapter; id = i2c_adapter_id(adapter); @@ -665,37 +653,34 @@ static int asb100_detect_subclients(struct i2c_adapter *adapter, int address, asb100_write_value(client, ASB100_REG_I2C_SUBADDR, (force_subclients[2] & 0x07) | ((force_subclients[3] & 0x07) << 4)); - data->lm75[0]->addr = force_subclients[2]; - data->lm75[1]->addr = force_subclients[3]; + sc_addr[0] = force_subclients[2]; + sc_addr[1] = force_subclients[3]; } else { int val = asb100_read_value(client, ASB100_REG_I2C_SUBADDR); - data->lm75[0]->addr = 0x48 + (val & 0x07); - data->lm75[1]->addr = 0x48 + ((val >> 4) & 0x07); + sc_addr[0] = 0x48 + (val & 0x07); + sc_addr[1] = 0x48 + ((val >> 4) & 0x07); } - if (data->lm75[0]->addr == data->lm75[1]->addr) { + if (sc_addr[0] == sc_addr[1]) { dev_err(&client->dev, "duplicate addresses 0x%x " - "for subclients\n", data->lm75[0]->addr); + "for subclients\n", sc_addr[0]); err = -ENODEV; goto ERROR_SC_2; } - for (i = 0; i <= 1; i++) { - i2c_set_clientdata(data->lm75[i], NULL); - data->lm75[i]->adapter = adapter; - data->lm75[i]->driver = &asb100_driver; - strlcpy(data->lm75[i]->name, "asb100 subclient", I2C_NAME_SIZE); - } - - if ((err = i2c_attach_client(data->lm75[0]))) { + data->lm75[0] = i2c_new_dummy(adapter, sc_addr[0]); + if (!data->lm75[0]) { dev_err(&client->dev, "subclient %d registration " - "at address 0x%x failed.\n", i, data->lm75[0]->addr); + "at address 0x%x failed.\n", 1, sc_addr[0]); + err = -ENOMEM; goto ERROR_SC_2; } - if ((err = i2c_attach_client(data->lm75[1]))) { + data->lm75[1] = i2c_new_dummy(adapter, sc_addr[1]); + if (!data->lm75[1]) { dev_err(&client->dev, "subclient %d registration " - "at address 0x%x failed.\n", i, data->lm75[1]->addr); + "at address 0x%x failed.\n", 2, sc_addr[1]); + err = -ENOMEM; goto ERROR_SC_3; } @@ -703,55 +688,31 @@ static int asb100_detect_subclients(struct i2c_adapter *adapter, int address, /* Undo inits in case of errors */ ERROR_SC_3: - i2c_detach_client(data->lm75[0]); + i2c_unregister_device(data->lm75[0]); ERROR_SC_2: - kfree(data->lm75[1]); -ERROR_SC_1: - kfree(data->lm75[0]); -ERROR_SC_0: return err; } -static int asb100_detect(struct i2c_adapter *adapter, int address, int kind) +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int asb100_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info) { - int err; - struct i2c_client *client; - struct asb100_data *data; + struct i2c_adapter *adapter = client->adapter; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { pr_debug("asb100.o: detect failed, " "smbus byte data not supported!\n"); - err = -ENODEV; - goto ERROR0; + return -ENODEV; } - /* OK. For now, we presume we have a valid client. We now create the - client structure, even though we cannot fill it completely yet. - But it allows us to access asb100_{read,write}_value. */ - - if (!(data = kzalloc(sizeof(struct asb100_data), GFP_KERNEL))) { - pr_debug("asb100.o: detect failed, kzalloc failed!\n"); - err = -ENOMEM; - goto ERROR0; - } - - client = &data->client; - mutex_init(&data->lock); - i2c_set_clientdata(client, data); - client->addr = address; - client->adapter = adapter; - client->driver = &asb100_driver; - - /* Now, we do the remaining detection. */ - /* The chip may be stuck in some other bank than bank 0. This may make reading other information impossible. Specify a force=... or force_*=... parameter, and the chip will be reset to the right bank. */ if (kind < 0) { - int val1 = asb100_read_value(client, ASB100_REG_BANK); - int val2 = asb100_read_value(client, ASB100_REG_CHIPMAN); + int val1 = i2c_smbus_read_byte_data(client, ASB100_REG_BANK); + int val2 = i2c_smbus_read_byte_data(client, ASB100_REG_CHIPMAN); /* If we're in bank 0 */ if ((!(val1 & 0x07)) && @@ -761,48 +722,60 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind) ((val1 & 0x80) && (val2 != 0x06)))) { pr_debug("asb100.o: detect failed, " "bad chip id 0x%02x!\n", val2); - err = -ENODEV; - goto ERROR1; + return -ENODEV; } } /* kind < 0 */ /* We have either had a force parameter, or we have already detected Winbond. Put it now into bank 0 and Vendor ID High Byte */ - asb100_write_value(client, ASB100_REG_BANK, - (asb100_read_value(client, ASB100_REG_BANK) & 0x78) | 0x80); + i2c_smbus_write_byte_data(client, ASB100_REG_BANK, + (i2c_smbus_read_byte_data(client, ASB100_REG_BANK) & 0x78) + | 0x80); /* Determine the chip type. */ if (kind <= 0) { - int val1 = asb100_read_value(client, ASB100_REG_WCHIPID); - int val2 = asb100_read_value(client, ASB100_REG_CHIPMAN); + int val1 = i2c_smbus_read_byte_data(client, ASB100_REG_WCHIPID); + int val2 = i2c_smbus_read_byte_data(client, ASB100_REG_CHIPMAN); if ((val1 == 0x31) && (val2 == 0x06)) kind = asb100; else { if (kind == 0) - dev_warn(&client->dev, "ignoring " + dev_warn(&adapter->dev, "ignoring " "'force' parameter for unknown chip " "at adapter %d, address 0x%02x.\n", - i2c_adapter_id(adapter), address); - err = -ENODEV; - goto ERROR1; + i2c_adapter_id(adapter), client->addr); + return -ENODEV; } } - /* Fill in remaining client fields and put it into the global list */ - strlcpy(client->name, "asb100", I2C_NAME_SIZE); - data->type = kind; - mutex_init(&data->update_lock); + strlcpy(info->type, "asb100", I2C_NAME_SIZE); - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(client))) - goto ERROR1; + return 0; +} + +static int asb100_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int err; + struct asb100_data *data; + + data = kzalloc(sizeof(struct asb100_data), GFP_KERNEL); + if (!data) { + pr_debug("asb100.o: probe failed, kzalloc failed!\n"); + err = -ENOMEM; + goto ERROR0; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->lock); + mutex_init(&data->update_lock); /* Attach secondary lm75 clients */ - if ((err = asb100_detect_subclients(adapter, address, kind, - client))) - goto ERROR2; + err = asb100_detect_subclients(client); + if (err) + goto ERROR1; /* Initialize the chip */ asb100_init_client(client); @@ -827,39 +800,25 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind) ERROR4: sysfs_remove_group(&client->dev.kobj, &asb100_group); ERROR3: - i2c_detach_client(data->lm75[1]); - i2c_detach_client(data->lm75[0]); - kfree(data->lm75[1]); - kfree(data->lm75[0]); -ERROR2: - i2c_detach_client(client); + i2c_unregister_device(data->lm75[1]); + i2c_unregister_device(data->lm75[0]); ERROR1: kfree(data); ERROR0: return err; } -static int asb100_detach_client(struct i2c_client *client) +static int asb100_remove(struct i2c_client *client) { struct asb100_data *data = i2c_get_clientdata(client); - int err; - - /* main client */ - if (data) { - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &asb100_group); - } - if ((err = i2c_detach_client(client))) - return err; + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &asb100_group); - /* main client */ - if (data) - kfree(data); + i2c_unregister_device(data->lm75[1]); + i2c_unregister_device(data->lm75[0]); - /* subclient */ - else - kfree(client); + kfree(data); return 0; } diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c index 01c17e387f03..d44172d29264 100644 --- a/drivers/hwmon/atxp1.c +++ b/drivers/hwmon/atxp1.c @@ -46,21 +46,32 @@ static const unsigned short normal_i2c[] = { 0x37, 0x4e, I2C_CLIENT_END }; I2C_CLIENT_INSMOD_1(atxp1); -static int atxp1_attach_adapter(struct i2c_adapter * adapter); -static int atxp1_detach_client(struct i2c_client * client); +static int atxp1_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int atxp1_remove(struct i2c_client *client); static struct atxp1_data * atxp1_update_device(struct device *dev); -static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind); +static int atxp1_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); + +static struct i2c_device_id atxp1_id[] = { + { "atxp1", atxp1 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, atxp1_id); static struct i2c_driver atxp1_driver = { + .class = I2C_CLASS_HWMON, .driver = { .name = "atxp1", }, - .attach_adapter = atxp1_attach_adapter, - .detach_client = atxp1_detach_client, + .probe = atxp1_probe, + .remove = atxp1_remove, + .id_table = atxp1_id, + .detect = atxp1_detect, + .address_data = &addr_data, }; struct atxp1_data { - struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; unsigned long last_updated; @@ -263,35 +274,16 @@ static const struct attribute_group atxp1_group = { }; -static int atxp1_attach_adapter(struct i2c_adapter *adapter) +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int atxp1_detect(struct i2c_client *new_client, int kind, + struct i2c_board_info *info) { - if (!(adapter->class & I2C_CLASS_HWMON)) - return 0; - return i2c_probe(adapter, &addr_data, &atxp1_detect); -}; + struct i2c_adapter *adapter = new_client->adapter; -static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind) -{ - struct i2c_client * new_client; - struct atxp1_data * data; - int err = 0; u8 temp; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - goto exit; - - if (!(data = kzalloc(sizeof(struct atxp1_data), GFP_KERNEL))) { - err = -ENOMEM; - goto exit; - } - - new_client = &data->client; - i2c_set_clientdata(new_client, data); - - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &atxp1_driver; - new_client->flags = 0; + return -ENODEV; /* Detect ATXP1, checking if vendor ID registers are all zero */ if (!((i2c_smbus_read_byte_data(new_client, 0x3e) == 0) && @@ -305,35 +297,46 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind) if (!((i2c_smbus_read_byte_data(new_client, 0x10) == temp) && (i2c_smbus_read_byte_data(new_client, 0x11) == temp) )) - goto exit_free; + return -ENODEV; } /* Get VRM */ - data->vrm = vid_which_vrm(); + temp = vid_which_vrm(); - if ((data->vrm != 90) && (data->vrm != 91)) { - dev_err(&new_client->dev, "Not supporting VRM %d.%d\n", - data->vrm / 10, data->vrm % 10); - goto exit_free; + if ((temp != 90) && (temp != 91)) { + dev_err(&adapter->dev, "atxp1: Not supporting VRM %d.%d\n", + temp / 10, temp % 10); + return -ENODEV; } - strncpy(new_client->name, "atxp1", I2C_NAME_SIZE); - - data->valid = 0; + strlcpy(info->type, "atxp1", I2C_NAME_SIZE); - mutex_init(&data->update_lock); + return 0; +} - err = i2c_attach_client(new_client); +static int atxp1_probe(struct i2c_client *new_client, + const struct i2c_device_id *id) +{ + struct atxp1_data *data; + int err; - if (err) - { - dev_err(&new_client->dev, "Attach client error.\n"); - goto exit_free; + data = kzalloc(sizeof(struct atxp1_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; } + /* Get VRM */ + data->vrm = vid_which_vrm(); + + i2c_set_clientdata(new_client, data); + data->valid = 0; + + mutex_init(&data->update_lock); + /* Register sysfs hooks */ if ((err = sysfs_create_group(&new_client->dev.kobj, &atxp1_group))) - goto exit_detach; + goto exit_free; data->hwmon_dev = hwmon_device_register(&new_client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -348,30 +351,22 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind) exit_remove_files: sysfs_remove_group(&new_client->dev.kobj, &atxp1_group); -exit_detach: - i2c_detach_client(new_client); exit_free: kfree(data); exit: return err; }; -static int atxp1_detach_client(struct i2c_client * client) +static int atxp1_remove(struct i2c_client *client) { struct atxp1_data * data = i2c_get_clientdata(client); - int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &atxp1_group); - err = i2c_detach_client(client); - - if (err) - dev_err(&client->dev, "Failed to detach client.\n"); - else - kfree(data); + kfree(data); - return err; + return 0; }; static int __init atxp1_init(void) diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c index dc1f30e432ea..1692de369969 100644 --- a/drivers/hwmon/f75375s.c +++ b/drivers/hwmon/f75375s.c @@ -87,7 +87,6 @@ I2C_CLIENT_INSMOD_2(f75373, f75375); struct f75375_data { unsigned short addr; - struct i2c_client *client; struct device *hwmon_dev; const char *name; @@ -114,21 +113,12 @@ struct f75375_data { s8 temp_max_hyst[2]; }; -static int f75375_attach_adapter(struct i2c_adapter *adapter); -static int f75375_detect(struct i2c_adapter *adapter, int address, int kind); -static int f75375_detach_client(struct i2c_client *client); +static int f75375_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); static int f75375_probe(struct i2c_client *client, const struct i2c_device_id *id); static int f75375_remove(struct i2c_client *client); -static struct i2c_driver f75375_legacy_driver = { - .driver = { - .name = "f75375_legacy", - }, - .attach_adapter = f75375_attach_adapter, - .detach_client = f75375_detach_client, -}; - static const struct i2c_device_id f75375_id[] = { { "f75373", f75373 }, { "f75375", f75375 }, @@ -137,12 +127,15 @@ static const struct i2c_device_id f75375_id[] = { MODULE_DEVICE_TABLE(i2c, f75375_id); static struct i2c_driver f75375_driver = { + .class = I2C_CLASS_HWMON, .driver = { .name = "f75375", }, .probe = f75375_probe, .remove = f75375_remove, .id_table = f75375_id, + .detect = f75375_detect, + .address_data = &addr_data, }; static inline int f75375_read8(struct i2c_client *client, u8 reg) @@ -607,22 +600,6 @@ static const struct attribute_group f75375_group = { .attrs = f75375_attributes, }; -static int f75375_detach_client(struct i2c_client *client) -{ - int err; - - f75375_remove(client); - err = i2c_detach_client(client); - if (err) { - dev_err(&client->dev, - "Client deregistration failed, " - "client not detached.\n"); - return err; - } - kfree(client); - return 0; -} - static void f75375_init(struct i2c_client *client, struct f75375_data *data, struct f75375s_platform_data *f75375s_pdata) { @@ -651,7 +628,6 @@ static int f75375_probe(struct i2c_client *client, return -ENOMEM; i2c_set_clientdata(client, data); - data->client = client; mutex_init(&data->update_lock); data->kind = id->driver_data; @@ -700,29 +676,13 @@ static int f75375_remove(struct i2c_client *client) return 0; } -static int f75375_attach_adapter(struct i2c_adapter *adapter) -{ - if (!(adapter->class & I2C_CLASS_HWMON)) - return 0; - return i2c_probe(adapter, &addr_data, f75375_detect); -} - -/* This function is called by i2c_probe */ -static int f75375_detect(struct i2c_adapter *adapter, int address, int kind) +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int f75375_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info) { - struct i2c_client *client; + struct i2c_adapter *adapter = client->adapter; u8 version = 0; - int err = 0; const char *name = ""; - struct i2c_device_id id; - - if (!(client = kzalloc(sizeof(*client), GFP_KERNEL))) { - err = -ENOMEM; - goto exit; - } - client->addr = address; - client->adapter = adapter; - client->driver = &f75375_legacy_driver; if (kind < 0) { u16 vendid = f75375_read16(client, F75375_REG_VENDOR); @@ -736,7 +696,7 @@ static int f75375_detect(struct i2c_adapter *adapter, int address, int kind) dev_err(&adapter->dev, "failed,%02X,%02X,%02X\n", chipid, version, vendid); - goto exit_free; + return -ENODEV; } } @@ -746,43 +706,18 @@ static int f75375_detect(struct i2c_adapter *adapter, int address, int kind) name = "f75373"; } dev_info(&adapter->dev, "found %s version: %02X\n", name, version); - strlcpy(client->name, name, I2C_NAME_SIZE); - - if ((err = i2c_attach_client(client))) - goto exit_free; - - strlcpy(id.name, name, I2C_NAME_SIZE); - id.driver_data = kind; - if ((err = f75375_probe(client, &id)) < 0) - goto exit_detach; + strlcpy(info->type, name, I2C_NAME_SIZE); return 0; - -exit_detach: - i2c_detach_client(client); -exit_free: - kfree(client); -exit: - return err; } static int __init sensors_f75375_init(void) { - int status; - status = i2c_add_driver(&f75375_driver); - if (status) - return status; - - status = i2c_add_driver(&f75375_legacy_driver); - if (status) - i2c_del_driver(&f75375_driver); - - return status; + return i2c_add_driver(&f75375_driver); } static void __exit sensors_f75375_exit(void) { - i2c_del_driver(&f75375_legacy_driver); i2c_del_driver(&f75375_driver); } diff --git a/drivers/hwmon/fscher.c b/drivers/hwmon/fscher.c index ed26b66e0831..3a3373427a74 100644 --- a/drivers/hwmon/fscher.c +++ b/drivers/hwmon/fscher.c @@ -106,9 +106,11 @@ I2C_CLIENT_INSMOD_1(fscher); * Functions declaration */ -static int fscher_attach_adapter(struct i2c_adapter *adapter); -static int fscher_detect(struct i2c_adapter *adapter, int address, int kind); -static int fscher_detach_client(struct i2c_client *client); +static int fscher_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int fscher_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); +static int fscher_remove(struct i2c_client *client); static struct fscher_data *fscher_update_device(struct device *dev); static void fscher_init_client(struct i2c_client *client); @@ -119,12 +121,21 @@ static int fscher_write_value(struct i2c_client *client, u8 reg, u8 value); * Driver data (common to all clients) */ +static struct i2c_device_id fscher_id[] = { + { "fscher", fscher }, + { } +}; + static struct i2c_driver fscher_driver = { + .class = I2C_CLASS_HWMON, .driver = { .name = "fscher", }, - .attach_adapter = fscher_attach_adapter, - .detach_client = fscher_detach_client, + .probe = fscher_probe, + .remove = fscher_remove, + .id_table = fscher_id, + .detect = fscher_detect, + .address_data = &addr_data, }; /* @@ -132,7 +143,6 @@ static struct i2c_driver fscher_driver = { */ struct fscher_data { - struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ @@ -283,38 +293,14 @@ static const struct attribute_group fscher_group = { * Real code */ -static int fscher_attach_adapter(struct i2c_adapter *adapter) -{ - if (!(adapter->class & I2C_CLASS_HWMON)) - return 0; - return i2c_probe(adapter, &addr_data, fscher_detect); -} - -static int fscher_detect(struct i2c_adapter *adapter, int address, int kind) +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int fscher_detect(struct i2c_client *new_client, int kind, + struct i2c_board_info *info) { - struct i2c_client *new_client; - struct fscher_data *data; - int err = 0; + struct i2c_adapter *adapter = new_client->adapter; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - goto exit; - - /* OK. For now, we presume we have a valid client. We now create the - * client structure, even though we cannot fill it completely yet. - * But it allows us to access i2c_smbus_read_byte_data. */ - if (!(data = kzalloc(sizeof(struct fscher_data), GFP_KERNEL))) { - err = -ENOMEM; - goto exit; - } - - /* The common I2C client data is placed right before the - * Hermes-specific data. */ - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &fscher_driver; - new_client->flags = 0; + return -ENODEV; /* Do the remaining detection unless force or force_fscher parameter */ if (kind < 0) { @@ -324,24 +310,35 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind) FSCHER_REG_IDENT_1) != 0x45) /* 'E' */ || (i2c_smbus_read_byte_data(new_client, FSCHER_REG_IDENT_2) != 0x52)) /* 'R' */ - goto exit_free; + return -ENODEV; + } + + strlcpy(info->type, "fscher", I2C_NAME_SIZE); + + return 0; +} + +static int fscher_probe(struct i2c_client *new_client, + const struct i2c_device_id *id) +{ + struct fscher_data *data; + int err; + + data = kzalloc(sizeof(struct fscher_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; } - /* Fill in the remaining client fields and put it into the - * global list */ - strlcpy(new_client->name, "fscher", I2C_NAME_SIZE); + i2c_set_clientdata(new_client, data); data->valid = 0; mutex_init(&data->update_lock); - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) - goto exit_free; - fscher_init_client(new_client); /* Register sysfs hooks */ if ((err = sysfs_create_group(&new_client->dev.kobj, &fscher_group))) - goto exit_detach; + goto exit_free; data->hwmon_dev = hwmon_device_register(&new_client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -353,25 +350,19 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind) exit_remove_files: sysfs_remove_group(&new_client->dev.kobj, &fscher_group); -exit_detach: - i2c_detach_client(new_client); exit_free: kfree(data); exit: return err; } -static int fscher_detach_client(struct i2c_client *client) +static int fscher_remove(struct i2c_client *client) { struct fscher_data *data = i2c_get_clientdata(client); - int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &fscher_group); - if ((err = i2c_detach_client(client))) - return err; - kfree(data); return 0; } diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c index bd89d270a5ed..aa320f297194 100644 --- a/drivers/hwmon/fschmd.c +++ b/drivers/hwmon/fschmd.c @@ -171,20 +171,37 @@ static const int FSCHMD_NO_TEMP_SENSORS[5] = { 3, 3, 4, 3, 5 }; * Functions declarations */ -static int fschmd_attach_adapter(struct i2c_adapter *adapter); -static int fschmd_detach_client(struct i2c_client *client); +static int fschmd_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int fschmd_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); +static int fschmd_remove(struct i2c_client *client); static struct fschmd_data *fschmd_update_device(struct device *dev); /* * Driver data (common to all clients) */ +static struct i2c_device_id fschmd_id[] = { + { "fscpos", fscpos }, + { "fscher", fscher }, + { "fscscy", fscscy }, + { "fschrc", fschrc }, + { "fschmd", fschmd }, + { } +}; +MODULE_DEVICE_TABLE(i2c, fschmd_id); + static struct i2c_driver fschmd_driver = { + .class = I2C_CLASS_HWMON, .driver = { .name = FSCHMD_NAME, }, - .attach_adapter = fschmd_attach_adapter, - .detach_client = fschmd_detach_client, + .probe = fschmd_probe, + .remove = fschmd_remove, + .id_table = fschmd_id, + .detect = fschmd_detect, + .address_data = &addr_data, }; /* @@ -192,7 +209,6 @@ static struct i2c_driver fschmd_driver = { */ struct fschmd_data { - struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; int kind; @@ -269,7 +285,7 @@ static ssize_t store_temp_max(struct device *dev, struct device_attribute v = SENSORS_LIMIT(v, -128, 127) + 128; mutex_lock(&data->update_lock); - i2c_smbus_write_byte_data(&data->client, + i2c_smbus_write_byte_data(to_i2c_client(dev), FSCHMD_REG_TEMP_LIMIT[data->kind][index], v); data->temp_max[index] = v; mutex_unlock(&data->update_lock); @@ -346,14 +362,14 @@ static ssize_t store_fan_div(struct device *dev, struct device_attribute mutex_lock(&data->update_lock); - reg = i2c_smbus_read_byte_data(&data->client, + reg = i2c_smbus_read_byte_data(to_i2c_client(dev), FSCHMD_REG_FAN_RIPPLE[data->kind][index]); /* bits 2..7 reserved => mask with 0x03 */ reg &= ~0x03; reg |= v; - i2c_smbus_write_byte_data(&data->client, + i2c_smbus_write_byte_data(to_i2c_client(dev), FSCHMD_REG_FAN_RIPPLE[data->kind][index], reg); data->fan_ripple[index] = reg; @@ -416,7 +432,7 @@ static ssize_t store_pwm_auto_point1_pwm(struct device *dev, mutex_lock(&data->update_lock); - i2c_smbus_write_byte_data(&data->client, + i2c_smbus_write_byte_data(to_i2c_client(dev), FSCHMD_REG_FAN_MIN[data->kind][index], v); data->fan_min[index] = v; @@ -448,14 +464,14 @@ static ssize_t store_alert_led(struct device *dev, mutex_lock(&data->update_lock); - reg = i2c_smbus_read_byte_data(&data->client, FSCHMD_REG_CONTROL); + reg = i2c_smbus_read_byte_data(to_i2c_client(dev), FSCHMD_REG_CONTROL); if (v) reg |= FSCHMD_CONTROL_ALERT_LED_MASK; else reg &= ~FSCHMD_CONTROL_ALERT_LED_MASK; - i2c_smbus_write_byte_data(&data->client, FSCHMD_REG_CONTROL, reg); + i2c_smbus_write_byte_data(to_i2c_client(dev), FSCHMD_REG_CONTROL, reg); data->global_control = reg; @@ -600,32 +616,15 @@ static void fschmd_dmi_decode(const struct dmi_header *header) } } -static int fschmd_detect(struct i2c_adapter *adapter, int address, int kind) +static int fschmd_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info) { - struct i2c_client *client; - struct fschmd_data *data; - u8 revision; - const char * const names[5] = { "Poseidon", "Hermes", "Scylla", - "Heracles", "Heimdall" }; + struct i2c_adapter *adapter = client->adapter; const char * const client_names[5] = { "fscpos", "fscher", "fscscy", "fschrc", "fschmd" }; - int i, err = 0; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return 0; - - /* OK. For now, we presume we have a valid client. We now create the - * client structure, even though we cannot fill it completely yet. - * But it allows us to access i2c_smbus_read_byte_data. */ - if (!(data = kzalloc(sizeof(struct fschmd_data), GFP_KERNEL))) - return -ENOMEM; - - client = &data->client; - i2c_set_clientdata(client, data); - client->addr = address; - client->adapter = adapter; - client->driver = &fschmd_driver; - mutex_init(&data->update_lock); + return -ENODEV; /* Detect & Identify the chip */ if (kind <= 0) { @@ -650,9 +649,31 @@ static int fschmd_detect(struct i2c_adapter *adapter, int address, int kind) else if (!strcmp(id, "HMD")) kind = fschmd; else - goto exit_free; + return -ENODEV; } + strlcpy(info->type, client_names[kind - 1], I2C_NAME_SIZE); + + return 0; +} + +static int fschmd_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct fschmd_data *data; + u8 revision; + const char * const names[5] = { "Poseidon", "Hermes", "Scylla", + "Heracles", "Heimdall" }; + int i, err; + enum chips kind = id->driver_data; + + data = kzalloc(sizeof(struct fschmd_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + if (kind == fscpos) { /* The Poseidon has hardwired temp limits, fill these in for the alarm resetting code */ @@ -674,11 +695,6 @@ static int fschmd_detect(struct i2c_adapter *adapter, int address, int kind) /* i2c kind goes from 1-5, we want from 0-4 to address arrays */ data->kind = kind - 1; - strlcpy(client->name, client_names[data->kind], I2C_NAME_SIZE); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(client))) - goto exit_free; for (i = 0; i < ARRAY_SIZE(fschmd_attr); i++) { err = device_create_file(&client->dev, @@ -726,25 +742,14 @@ static int fschmd_detect(struct i2c_adapter *adapter, int address, int kind) return 0; exit_detach: - fschmd_detach_client(client); /* will also free data for us */ - return err; - -exit_free: - kfree(data); + fschmd_remove(client); /* will also free data for us */ return err; } -static int fschmd_attach_adapter(struct i2c_adapter *adapter) -{ - if (!(adapter->class & I2C_CLASS_HWMON)) - return 0; - return i2c_probe(adapter, &addr_data, fschmd_detect); -} - -static int fschmd_detach_client(struct i2c_client *client) +static int fschmd_remove(struct i2c_client *client) { struct fschmd_data *data = i2c_get_clientdata(client); - int i, err; + int i; /* Check if registered in case we're called from fschmd_detect to cleanup after an error */ @@ -760,9 +765,6 @@ static int fschmd_detach_client(struct i2c_client *client) device_remove_file(&client->dev, &fschmd_fan_attr[i].dev_attr); - if ((err = i2c_detach_client(client))) - return err; - kfree(data); return 0; } diff --git a/drivers/hwmon/fscpos.c b/drivers/hwmon/fscpos.c index 00f48484e54b..30a7a4756972 100644 --- a/drivers/hwmon/fscpos.c +++ b/drivers/hwmon/fscpos.c @@ -87,9 +87,11 @@ static u8 FSCPOS_REG_TEMP_STATE[] = { 0x71, 0x81, 0x91 }; /* * Functions declaration */ -static int fscpos_attach_adapter(struct i2c_adapter *adapter); -static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind); -static int fscpos_detach_client(struct i2c_client *client); +static int fscpos_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int fscpos_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); +static int fscpos_remove(struct i2c_client *client); static int fscpos_read_value(struct i2c_client *client, u8 reg); static int fscpos_write_value(struct i2c_client *client, u8 reg, u8 value); @@ -101,19 +103,27 @@ static void reset_fan_alarm(struct i2c_client *client, int nr); /* * Driver data (common to all clients) */ +static struct i2c_device_id fscpos_id[] = { + { "fscpos", fscpos }, + { } +}; + static struct i2c_driver fscpos_driver = { + .class = I2C_CLASS_HWMON, .driver = { .name = "fscpos", }, - .attach_adapter = fscpos_attach_adapter, - .detach_client = fscpos_detach_client, + .probe = fscpos_probe, + .remove = fscpos_remove, + .id_table = fscpos_id, + .detect = fscpos_detect, + .address_data = &addr_data, }; /* * Client data (each client gets its own) */ struct fscpos_data { - struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* 0 until following fields are valid */ @@ -470,39 +480,14 @@ static const struct attribute_group fscpos_group = { .attrs = fscpos_attributes, }; -static int fscpos_attach_adapter(struct i2c_adapter *adapter) -{ - if (!(adapter->class & I2C_CLASS_HWMON)) - return 0; - return i2c_probe(adapter, &addr_data, fscpos_detect); -} - -static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind) +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int fscpos_detect(struct i2c_client *new_client, int kind, + struct i2c_board_info *info) { - struct i2c_client *new_client; - struct fscpos_data *data; - int err = 0; + struct i2c_adapter *adapter = new_client->adapter; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - goto exit; - - /* - * OK. For now, we presume we have a valid client. We now create the - * client structure, even though we cannot fill it completely yet. - * But it allows us to access fscpos_{read,write}_value. - */ - - if (!(data = kzalloc(sizeof(struct fscpos_data), GFP_KERNEL))) { - err = -ENOMEM; - goto exit; - } - - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &fscpos_driver; - new_client->flags = 0; + return -ENODEV; /* Do the remaining detection unless force or force_fscpos parameter */ if (kind < 0) { @@ -512,22 +497,30 @@ static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind) != 0x45) /* 'E' */ || (fscpos_read_value(new_client, FSCPOS_REG_IDENT_2) != 0x47))/* 'G' */ - { - dev_dbg(&new_client->dev, "fscpos detection failed\n"); - goto exit_free; - } + return -ENODEV; } - /* Fill in the remaining client fields and put it in the global list */ - strlcpy(new_client->name, "fscpos", I2C_NAME_SIZE); + strlcpy(info->type, "fscpos", I2C_NAME_SIZE); + return 0; +} + +static int fscpos_probe(struct i2c_client *new_client, + const struct i2c_device_id *id) +{ + struct fscpos_data *data; + int err; + + data = kzalloc(sizeof(struct fscpos_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(new_client, data); data->valid = 0; mutex_init(&data->update_lock); - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) - goto exit_free; - /* Inizialize the fscpos chip */ fscpos_init_client(new_client); @@ -536,7 +529,7 @@ static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind) /* Register sysfs hooks */ if ((err = sysfs_create_group(&new_client->dev.kobj, &fscpos_group))) - goto exit_detach; + goto exit_free; data->hwmon_dev = hwmon_device_register(&new_client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -548,24 +541,19 @@ static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind) exit_remove_files: sysfs_remove_group(&new_client->dev.kobj, &fscpos_group); -exit_detach: - i2c_detach_client(new_client); exit_free: kfree(data); exit: return err; } -static int fscpos_detach_client(struct i2c_client *client) +static int fscpos_remove(struct i2c_client *client) { struct fscpos_data *data = i2c_get_clientdata(client); - int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &fscpos_group); - if ((err = i2c_detach_client(client))) - return err; kfree(data); return 0; } diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c index 33e9e8a8d1ce..b6c10d13f525 100644 --- a/drivers/hwmon/gl518sm.c +++ b/drivers/hwmon/gl518sm.c @@ -114,7 +114,6 @@ static inline u8 FAN_TO_REG(long rpm, int div) /* Each client has this additional data */ struct gl518_data { - struct i2c_client client; struct device *hwmon_dev; enum chips type; @@ -138,21 +137,33 @@ struct gl518_data { u8 beep_enable; /* Boolean */ }; -static int gl518_attach_adapter(struct i2c_adapter *adapter); -static int gl518_detect(struct i2c_adapter *adapter, int address, int kind); +static int gl518_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int gl518_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); static void gl518_init_client(struct i2c_client *client); -static int gl518_detach_client(struct i2c_client *client); +static int gl518_remove(struct i2c_client *client); static int gl518_read_value(struct i2c_client *client, u8 reg); static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value); static struct gl518_data *gl518_update_device(struct device *dev); +static struct i2c_device_id gl518_id[] = { + { "gl518sm", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, gl518_id); + /* This is the driver that will be inserted */ static struct i2c_driver gl518_driver = { + .class = I2C_CLASS_HWMON, .driver = { .name = "gl518sm", }, - .attach_adapter = gl518_attach_adapter, - .detach_client = gl518_detach_client, + .probe = gl518_probe, + .remove = gl518_remove, + .id_table = gl518_id, + .detect = gl518_detect, + .address_data = &addr_data, }; /* @@ -472,46 +483,23 @@ static const struct attribute_group gl518_group_r80 = { * Real code */ -static int gl518_attach_adapter(struct i2c_adapter *adapter) -{ - if (!(adapter->class & I2C_CLASS_HWMON)) - return 0; - return i2c_probe(adapter, &addr_data, gl518_detect); -} - -static int gl518_detect(struct i2c_adapter *adapter, int address, int kind) +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int gl518_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info) { + struct i2c_adapter *adapter = client->adapter; int i; - struct i2c_client *client; - struct gl518_data *data; - int err = 0; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) - goto exit; - - /* OK. For now, we presume we have a valid client. We now create the - client structure, even though we cannot fill it completely yet. - But it allows us to access gl518_{read,write}_value. */ - - if (!(data = kzalloc(sizeof(struct gl518_data), GFP_KERNEL))) { - err = -ENOMEM; - goto exit; - } - - client = &data->client; - i2c_set_clientdata(client, data); - - client->addr = address; - client->adapter = adapter; - client->driver = &gl518_driver; + return -ENODEV; /* Now, we do the remaining detection. */ if (kind < 0) { if ((gl518_read_value(client, GL518_REG_CHIP_ID) != 0x80) || (gl518_read_value(client, GL518_REG_CONF) & 0x80)) - goto exit_free; + return -ENODEV; } /* Determine the chip type. */ @@ -526,19 +514,32 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind) dev_info(&adapter->dev, "Ignoring 'force' parameter for unknown " "chip at adapter %d, address 0x%02x\n", - i2c_adapter_id(adapter), address); - goto exit_free; + i2c_adapter_id(adapter), client->addr); + return -ENODEV; } } - /* Fill in the remaining client fields */ - strlcpy(client->name, "gl518sm", I2C_NAME_SIZE); - data->type = kind; - mutex_init(&data->update_lock); + strlcpy(info->type, "gl518sm", I2C_NAME_SIZE); - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(client))) - goto exit_free; + return 0; +} + +static int gl518_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct gl518_data *data; + int err, revision; + + data = kzalloc(sizeof(struct gl518_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + revision = gl518_read_value(client, GL518_REG_REVISION); + data->type = revision == 0x80 ? gl518sm_r80 : gl518sm_r00; + mutex_init(&data->update_lock); /* Initialize the GL518SM chip */ data->alarm_mask = 0xff; @@ -546,7 +547,7 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind) /* Register sysfs hooks */ if ((err = sysfs_create_group(&client->dev.kobj, &gl518_group))) - goto exit_detach; + goto exit_free; if (data->type == gl518sm_r80) if ((err = sysfs_create_group(&client->dev.kobj, &gl518_group_r80))) @@ -564,8 +565,6 @@ exit_remove_files: sysfs_remove_group(&client->dev.kobj, &gl518_group); if (data->type == gl518sm_r80) sysfs_remove_group(&client->dev.kobj, &gl518_group_r80); -exit_detach: - i2c_detach_client(client); exit_free: kfree(data); exit: @@ -591,19 +590,15 @@ static void gl518_init_client(struct i2c_client *client) gl518_write_value(client, GL518_REG_CONF, 0x40 | regvalue); } -static int gl518_detach_client(struct i2c_client *client) +static int gl518_remove(struct i2c_client *client) { struct gl518_data *data = i2c_get_clientdata(client); - int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &gl518_group); if (data->type == gl518sm_r80) sysfs_remove_group(&client->dev.kobj, &gl518_group_r80); - if ((err = i2c_detach_client(client))) - return err; - kfree(data); return 0; } diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c index 8984ef141627..bd27a7790e83 100644 --- a/drivers/hwmon/gl520sm.c +++ b/drivers/hwmon/gl520sm.c @@ -79,26 +79,37 @@ static const u8 GL520_REG_TEMP_MAX_HYST[] = { 0x06, 0x18 }; * Function declarations */ -static int gl520_attach_adapter(struct i2c_adapter *adapter); -static int gl520_detect(struct i2c_adapter *adapter, int address, int kind); +static int gl520_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int gl520_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); static void gl520_init_client(struct i2c_client *client); -static int gl520_detach_client(struct i2c_client *client); +static int gl520_remove(struct i2c_client *client); static int gl520_read_value(struct i2c_client *client, u8 reg); static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value); static struct gl520_data *gl520_update_device(struct device *dev); /* Driver data */ +static struct i2c_device_id gl520_id[] = { + { "gl520sm", gl520sm }, + { } +}; +MODULE_DEVICE_TABLE(i2c, gl520_id); + static struct i2c_driver gl520_driver = { + .class = I2C_CLASS_HWMON, .driver = { .name = "gl520sm", }, - .attach_adapter = gl520_attach_adapter, - .detach_client = gl520_detach_client, + .probe = gl520_probe, + .remove = gl520_remove, + .id_table = gl520_id, + .detect = gl520_detect, + .address_data = &addr_data, }; /* Client data */ struct gl520_data { - struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until the following fields are valid */ @@ -669,37 +680,15 @@ static const struct attribute_group gl520_group_opt = { * Real code */ -static int gl520_attach_adapter(struct i2c_adapter *adapter) -{ - if (!(adapter->class & I2C_CLASS_HWMON)) - return 0; - return i2c_probe(adapter, &addr_data, gl520_detect); -} - -static int gl520_detect(struct i2c_adapter *adapter, int address, int kind) +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int gl520_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info) { - struct i2c_client *client; - struct gl520_data *data; - int err = 0; + struct i2c_adapter *adapter = client->adapter; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) - goto exit; - - /* OK. For now, we presume we have a valid client. We now create the - client structure, even though we cannot fill it completely yet. - But it allows us to access gl520_{read,write}_value. */ - - if (!(data = kzalloc(sizeof(struct gl520_data), GFP_KERNEL))) { - err = -ENOMEM; - goto exit; - } - - client = &data->client; - i2c_set_clientdata(client, data); - client->addr = address; - client->adapter = adapter; - client->driver = &gl520_driver; + return -ENODEV; /* Determine the chip type. */ if (kind < 0) { @@ -707,24 +696,36 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind) ((gl520_read_value(client, GL520_REG_REVISION) & 0x7f) != 0x00) || ((gl520_read_value(client, GL520_REG_CONF) & 0x80) != 0x00)) { dev_dbg(&client->dev, "Unknown chip type, skipping\n"); - goto exit_free; + return -ENODEV; } } - /* Fill in the remaining client fields */ - strlcpy(client->name, "gl520sm", I2C_NAME_SIZE); - mutex_init(&data->update_lock); + strlcpy(info->type, "gl520sm", I2C_NAME_SIZE); - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(client))) - goto exit_free; + return 0; +} + +static int gl520_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct gl520_data *data; + int err; + + data = kzalloc(sizeof(struct gl520_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); /* Initialize the GL520SM chip */ gl520_init_client(client); /* Register sysfs hooks */ if ((err = sysfs_create_group(&client->dev.kobj, &gl520_group))) - goto exit_detach; + goto exit_free; if (data->two_temps) { if ((err = device_create_file(&client->dev, @@ -764,8 +765,6 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind) exit_remove_files: sysfs_remove_group(&client->dev.kobj, &gl520_group); sysfs_remove_group(&client->dev.kobj, &gl520_group_opt); -exit_detach: - i2c_detach_client(client); exit_free: kfree(data); exit: @@ -811,18 +810,14 @@ static void gl520_init_client(struct i2c_client *client) gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask); } -static int gl520_detach_client(struct i2c_client *client) +static int gl520_remove(struct i2c_client *client) { struct gl520_data *data = i2c_get_clientdata(client); - int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &gl520_group); sysfs_remove_group(&client->dev.kobj, &gl520_group_opt); - if ((err = i2c_detach_client(client))) - return err; - kfree(data); return 0; } diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c index 116287008083..100398b2c112 100644 --- a/drivers/hwmon/lm63.c +++ b/drivers/hwmon/lm63.c @@ -1,7 +1,7 @@ /* * lm63.c - driver for the National Semiconductor LM63 temperature sensor * with integrated fan control - * Copyright (C) 2004-2006 Jean Delvare <khali@linux-fr.org> + * Copyright (C) 2004-2008 Jean Delvare <khali@linux-fr.org> * Based on the lm90 driver. * * The LM63 is a sensor chip made by National Semiconductor. It measures @@ -128,24 +128,36 @@ I2C_CLIENT_INSMOD_1(lm63); * Functions declaration */ -static int lm63_attach_adapter(struct i2c_adapter *adapter); -static int lm63_detach_client(struct i2c_client *client); +static int lm63_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int lm63_remove(struct i2c_client *client); static struct lm63_data *lm63_update_device(struct device *dev); -static int lm63_detect(struct i2c_adapter *adapter, int address, int kind); +static int lm63_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); static void lm63_init_client(struct i2c_client *client); /* * Driver data (common to all clients) */ +static struct i2c_device_id lm63_id[] = { + { "lm63", lm63 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, lm63_id); + static struct i2c_driver lm63_driver = { + .class = I2C_CLASS_HWMON, .driver = { .name = "lm63", }, - .attach_adapter = lm63_attach_adapter, - .detach_client = lm63_detach_client, + .probe = lm63_probe, + .remove = lm63_remove, + .id_table = lm63_id, + .detect = lm63_detect, + .address_data = &addr_data, }; /* @@ -153,7 +165,6 @@ static struct i2c_driver lm63_driver = { */ struct lm63_data { - struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ @@ -411,43 +422,14 @@ static const struct attribute_group lm63_group_fan1 = { * Real code */ -static int lm63_attach_adapter(struct i2c_adapter *adapter) +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int lm63_detect(struct i2c_client *new_client, int kind, + struct i2c_board_info *info) { - if (!(adapter->class & I2C_CLASS_HWMON)) - return 0; - return i2c_probe(adapter, &addr_data, lm63_detect); -} - -/* - * The following function does more than just detection. If detection - * succeeds, it also registers the new chip. - */ -static int lm63_detect(struct i2c_adapter *adapter, int address, int kind) -{ - struct i2c_client *new_client; - struct lm63_data *data; - int err = 0; + struct i2c_adapter *adapter = new_client->adapter; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - goto exit; - - if (!(data = kzalloc(sizeof(struct lm63_data), GFP_KERNEL))) { - err = -ENOMEM; - goto exit; - } - - /* The common I2C client data is placed right before the - LM63-specific data. */ - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &lm63_driver; - new_client->flags = 0; - - /* Default to an LM63 if forced */ - if (kind == 0) - kind = lm63; + return -ENODEV; if (kind < 0) { /* must identify */ u8 man_id, chip_id, reg_config1, reg_config2; @@ -477,25 +459,38 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind) dev_dbg(&adapter->dev, "Unsupported chip " "(man_id=0x%02X, chip_id=0x%02X).\n", man_id, chip_id); - goto exit_free; + return -ENODEV; } } - strlcpy(new_client->name, "lm63", I2C_NAME_SIZE); + strlcpy(info->type, "lm63", I2C_NAME_SIZE); + + return 0; +} + +static int lm63_probe(struct i2c_client *new_client, + const struct i2c_device_id *id) +{ + struct lm63_data *data; + int err; + + data = kzalloc(sizeof(struct lm63_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(new_client, data); data->valid = 0; mutex_init(&data->update_lock); - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) - goto exit_free; - /* Initialize the LM63 chip */ lm63_init_client(new_client); /* Register sysfs hooks */ if ((err = sysfs_create_group(&new_client->dev.kobj, &lm63_group))) - goto exit_detach; + goto exit_free; if (data->config & 0x04) { /* tachometer enabled */ if ((err = sysfs_create_group(&new_client->dev.kobj, &lm63_group_fan1))) @@ -513,8 +508,6 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind) exit_remove_files: sysfs_remove_group(&new_client->dev.kobj, &lm63_group); sysfs_remove_group(&new_client->dev.kobj, &lm63_group_fan1); -exit_detach: - i2c_detach_client(new_client); exit_free: kfree(data); exit: @@ -556,18 +549,14 @@ static void lm63_init_client(struct i2c_client *client) (data->config_fan & 0x20) ? "manual" : "auto"); } -static int lm63_detach_client(struct i2c_client *client) +static int lm63_remove(struct i2c_client *client) { struct lm63_data *data = i2c_get_clientdata(client); - int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm63_group); sysfs_remove_group(&client->dev.kobj, &lm63_group_fan1); - if ((err = i2c_detach_client(client))) - return err; - kfree(data); return 0; } diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c index 36d5a8c3ad8c..cc5abc7c9f0c 100644 --- a/drivers/hwmon/lm77.c +++ b/drivers/hwmon/lm77.c @@ -52,7 +52,6 @@ I2C_CLIENT_INSMOD_1(lm77); /* Each client has this additional data */ struct lm77_data { - struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; @@ -65,23 +64,35 @@ struct lm77_data { u8 alarms; }; -static int lm77_attach_adapter(struct i2c_adapter *adapter); -static int lm77_detect(struct i2c_adapter *adapter, int address, int kind); +static int lm77_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int lm77_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); static void lm77_init_client(struct i2c_client *client); -static int lm77_detach_client(struct i2c_client *client); +static int lm77_remove(struct i2c_client *client); static u16 lm77_read_value(struct i2c_client *client, u8 reg); static int lm77_write_value(struct i2c_client *client, u8 reg, u16 value); static struct lm77_data *lm77_update_device(struct device *dev); +static struct i2c_device_id lm77_id[] = { + { "lm77", lm77 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, lm77_id); + /* This is the driver that will be inserted */ static struct i2c_driver lm77_driver = { + .class = I2C_CLASS_HWMON, .driver = { .name = "lm77", }, - .attach_adapter = lm77_attach_adapter, - .detach_client = lm77_detach_client, + .probe = lm77_probe, + .remove = lm77_remove, + .id_table = lm77_id, + .detect = lm77_detect, + .address_data = &addr_data, }; /* straight from the datasheet */ @@ -215,13 +226,6 @@ static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 2); static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 0); static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 1); -static int lm77_attach_adapter(struct i2c_adapter *adapter) -{ - if (!(adapter->class & I2C_CLASS_HWMON)) - return 0; - return i2c_probe(adapter, &addr_data, lm77_detect); -} - static struct attribute *lm77_attributes[] = { &dev_attr_temp1_input.attr, &dev_attr_temp1_crit.attr, @@ -240,32 +244,15 @@ static const struct attribute_group lm77_group = { .attrs = lm77_attributes, }; -/* This function is called by i2c_probe */ -static int lm77_detect(struct i2c_adapter *adapter, int address, int kind) +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int lm77_detect(struct i2c_client *new_client, int kind, + struct i2c_board_info *info) { - struct i2c_client *new_client; - struct lm77_data *data; - int err = 0; - const char *name = ""; + struct i2c_adapter *adapter = new_client->adapter; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) - goto exit; - - /* OK. For now, we presume we have a valid client. We now create the - client structure, even though we cannot fill it completely yet. - But it allows us to access lm77_{read,write}_value. */ - if (!(data = kzalloc(sizeof(struct lm77_data), GFP_KERNEL))) { - err = -ENOMEM; - goto exit; - } - - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &lm77_driver; - new_client->flags = 0; + return -ENODEV; /* Here comes the remaining detection. Since the LM77 has no register dedicated to identification, we have to rely on the @@ -294,7 +281,7 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind) || i2c_smbus_read_word_data(new_client, i + 3) != crit || i2c_smbus_read_word_data(new_client, i + 4) != min || i2c_smbus_read_word_data(new_client, i + 5) != max) - goto exit_free; + return -ENODEV; /* sign bits */ if (((cur & 0x00f0) != 0xf0 && (cur & 0x00f0) != 0x0) @@ -302,51 +289,55 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind) || ((crit & 0x00f0) != 0xf0 && (crit & 0x00f0) != 0x0) || ((min & 0x00f0) != 0xf0 && (min & 0x00f0) != 0x0) || ((max & 0x00f0) != 0xf0 && (max & 0x00f0) != 0x0)) - goto exit_free; + return -ENODEV; /* unused bits */ if (conf & 0xe0) - goto exit_free; + return -ENODEV; /* 0x06 and 0x07 return the last read value */ cur = i2c_smbus_read_word_data(new_client, 0); if (i2c_smbus_read_word_data(new_client, 6) != cur || i2c_smbus_read_word_data(new_client, 7) != cur) - goto exit_free; + return -ENODEV; hyst = i2c_smbus_read_word_data(new_client, 2); if (i2c_smbus_read_word_data(new_client, 6) != hyst || i2c_smbus_read_word_data(new_client, 7) != hyst) - goto exit_free; + return -ENODEV; min = i2c_smbus_read_word_data(new_client, 4); if (i2c_smbus_read_word_data(new_client, 6) != min || i2c_smbus_read_word_data(new_client, 7) != min) - goto exit_free; + return -ENODEV; } - /* Determine the chip type - only one kind supported! */ - if (kind <= 0) - kind = lm77; + strlcpy(info->type, "lm77", I2C_NAME_SIZE); - if (kind == lm77) { - name = "lm77"; + return 0; +} + +static int lm77_probe(struct i2c_client *new_client, + const struct i2c_device_id *id) +{ + struct lm77_data *data; + int err; + + data = kzalloc(sizeof(struct lm77_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; } - /* Fill in the remaining client fields and put it into the global list */ - strlcpy(new_client->name, name, I2C_NAME_SIZE); + i2c_set_clientdata(new_client, data); data->valid = 0; mutex_init(&data->update_lock); - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) - goto exit_free; - /* Initialize the LM77 chip */ lm77_init_client(new_client); /* Register sysfs hooks */ if ((err = sysfs_create_group(&new_client->dev.kobj, &lm77_group))) - goto exit_detach; + goto exit_free; data->hwmon_dev = hwmon_device_register(&new_client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -358,20 +349,17 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind) exit_remove: sysfs_remove_group(&new_client->dev.kobj, &lm77_group); -exit_detach: - i2c_detach_client(new_client); exit_free: kfree(data); exit: return err; } -static int lm77_detach_client(struct i2c_client *client) +static int lm77_remove(struct i2c_client *client) { struct lm77_data *data = i2c_get_clientdata(client); hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm77_group); - i2c_detach_client(client); kfree(data); return 0; } diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c index 26c91c9d4769..37a3169a4c04 100644 --- a/drivers/hwmon/lm80.c +++ b/drivers/hwmon/lm80.c @@ -108,7 +108,6 @@ static inline long TEMP_FROM_REG(u16 temp) */ struct lm80_data { - struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* !=0 if following fields are valid */ @@ -132,10 +131,12 @@ struct lm80_data { * Functions declaration */ -static int lm80_attach_adapter(struct i2c_adapter *adapter); -static int lm80_detect(struct i2c_adapter *adapter, int address, int kind); +static int lm80_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int lm80_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); static void lm80_init_client(struct i2c_client *client); -static int lm80_detach_client(struct i2c_client *client); +static int lm80_remove(struct i2c_client *client); static struct lm80_data *lm80_update_device(struct device *dev); static int lm80_read_value(struct i2c_client *client, u8 reg); static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value); @@ -144,12 +145,22 @@ static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value); * Driver data (common to all clients) */ +static struct i2c_device_id lm80_id[] = { + { "lm80", lm80 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, lm80_id); + static struct i2c_driver lm80_driver = { + .class = I2C_CLASS_HWMON, .driver = { .name = "lm80", }, - .attach_adapter = lm80_attach_adapter, - .detach_client = lm80_detach_client, + .probe = lm80_probe, + .remove = lm80_remove, + .id_table = lm80_id, + .detect = lm80_detect, + .address_data = &addr_data, }; /* @@ -383,13 +394,6 @@ static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 13); * Real code */ -static int lm80_attach_adapter(struct i2c_adapter *adapter) -{ - if (!(adapter->class & I2C_CLASS_HWMON)) - return 0; - return i2c_probe(adapter, &addr_data, lm80_detect); -} - static struct attribute *lm80_attributes[] = { &sensor_dev_attr_in0_min.dev_attr.attr, &sensor_dev_attr_in1_min.dev_attr.attr, @@ -442,53 +446,46 @@ static const struct attribute_group lm80_group = { .attrs = lm80_attributes, }; -static int lm80_detect(struct i2c_adapter *adapter, int address, int kind) +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int lm80_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info) { + struct i2c_adapter *adapter = client->adapter; int i, cur; - struct i2c_client *client; - struct lm80_data *data; - int err = 0; - const char *name; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - goto exit; - - /* OK. For now, we presume we have a valid client. We now create the - client structure, even though we cannot fill it completely yet. - But it allows us to access lm80_{read,write}_value. */ - if (!(data = kzalloc(sizeof(struct lm80_data), GFP_KERNEL))) { - err = -ENOMEM; - goto exit; - } - - client = &data->client; - i2c_set_clientdata(client, data); - client->addr = address; - client->adapter = adapter; - client->driver = &lm80_driver; + return -ENODEV; /* Now, we do the remaining detection. It is lousy. */ if (lm80_read_value(client, LM80_REG_ALARM2) & 0xc0) - goto error_free; + return -ENODEV; for (i = 0x2a; i <= 0x3d; i++) { cur = i2c_smbus_read_byte_data(client, i); if ((i2c_smbus_read_byte_data(client, i + 0x40) != cur) || (i2c_smbus_read_byte_data(client, i + 0x80) != cur) || (i2c_smbus_read_byte_data(client, i + 0xc0) != cur)) - goto error_free; + return -ENODEV; } - /* Determine the chip type - only one kind supported! */ - kind = lm80; - name = "lm80"; + strlcpy(info->type, "lm80", I2C_NAME_SIZE); - /* Fill in the remaining client fields */ - strlcpy(client->name, name, I2C_NAME_SIZE); - mutex_init(&data->update_lock); + return 0; +} - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(client))) - goto error_free; +static int lm80_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct lm80_data *data; + int err; + + data = kzalloc(sizeof(struct lm80_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); /* Initialize the LM80 chip */ lm80_init_client(client); @@ -499,7 +496,7 @@ static int lm80_detect(struct i2c_adapter *adapter, int address, int kind) /* Register sysfs hooks */ if ((err = sysfs_create_group(&client->dev.kobj, &lm80_group))) - goto error_detach; + goto error_free; data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -511,23 +508,18 @@ static int lm80_detect(struct i2c_adapter *adapter, int address, int kind) error_remove: sysfs_remove_group(&client->dev.kobj, &lm80_group); -error_detach: - i2c_detach_client(client); error_free: kfree(data); exit: return err; } -static int lm80_detach_client(struct i2c_client *client) +static int lm80_remove(struct i2c_client *client) { struct lm80_data *data = i2c_get_clientdata(client); - int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm80_group); - if ((err = i2c_detach_client(client))) - return err; kfree(data); return 0; diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c index 6a8642fa25fb..8872ab25630c 100644 --- a/drivers/hwmon/lm83.c +++ b/drivers/hwmon/lm83.c @@ -1,7 +1,7 @@ /* * lm83.c - Part of lm_sensors, Linux kernel modules for hardware * monitoring - * Copyright (C) 2003-2006 Jean Delvare <khali@linux-fr.org> + * Copyright (C) 2003-2008 Jean Delvare <khali@linux-fr.org> * * Heavily inspired from the lm78, lm75 and adm1021 drivers. The LM83 is * a sensor chip made by National Semiconductor. It reports up to four @@ -118,21 +118,34 @@ static const u8 LM83_REG_W_HIGH[] = { * Functions declaration */ -static int lm83_attach_adapter(struct i2c_adapter *adapter); -static int lm83_detect(struct i2c_adapter *adapter, int address, int kind); -static int lm83_detach_client(struct i2c_client *client); +static int lm83_detect(struct i2c_client *new_client, int kind, + struct i2c_board_info *info); +static int lm83_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int lm83_remove(struct i2c_client *client); static struct lm83_data *lm83_update_device(struct device *dev); /* * Driver data (common to all clients) */ +static struct i2c_device_id lm83_id[] = { + { "lm83", lm83 }, + { "lm82", lm82 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, lm83_id); + static struct i2c_driver lm83_driver = { + .class = I2C_CLASS_HWMON, .driver = { .name = "lm83", }, - .attach_adapter = lm83_attach_adapter, - .detach_client = lm83_detach_client, + .probe = lm83_probe, + .remove = lm83_remove, + .id_table = lm83_id, + .detect = lm83_detect, + .address_data = &addr_data, }; /* @@ -140,7 +153,6 @@ static struct i2c_driver lm83_driver = { */ struct lm83_data { - struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ @@ -278,40 +290,15 @@ static const struct attribute_group lm83_group_opt = { * Real code */ -static int lm83_attach_adapter(struct i2c_adapter *adapter) +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int lm83_detect(struct i2c_client *new_client, int kind, + struct i2c_board_info *info) { - if (!(adapter->class & I2C_CLASS_HWMON)) - return 0; - return i2c_probe(adapter, &addr_data, lm83_detect); -} - -/* - * The following function does more than just detection. If detection - * succeeds, it also registers the new chip. - */ -static int lm83_detect(struct i2c_adapter *adapter, int address, int kind) -{ - struct i2c_client *new_client; - struct lm83_data *data; - int err = 0; + struct i2c_adapter *adapter = new_client->adapter; const char *name = ""; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - goto exit; - - if (!(data = kzalloc(sizeof(struct lm83_data), GFP_KERNEL))) { - err = -ENOMEM; - goto exit; - } - - /* The common I2C client data is placed right after the - * LM83-specific data. */ - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &lm83_driver; - new_client->flags = 0; + return -ENODEV; /* Now we do the detection and identification. A negative kind * means that the driver was loaded with no force parameter @@ -335,8 +322,9 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind) ((i2c_smbus_read_byte_data(new_client, LM83_REG_R_CONFIG) & 0x41) != 0x00)) { dev_dbg(&adapter->dev, - "LM83 detection failed at 0x%02x.\n", address); - goto exit_free; + "LM83 detection failed at 0x%02x.\n", + new_client->addr); + return -ENODEV; } } @@ -361,7 +349,7 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind) dev_info(&adapter->dev, "Unsupported chip (man_id=0x%02X, " "chip_id=0x%02X).\n", man_id, chip_id); - goto exit_free; + return -ENODEV; } } @@ -372,15 +360,27 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind) name = "lm82"; } - /* We can fill in the remaining client fields */ - strlcpy(new_client->name, name, I2C_NAME_SIZE); + strlcpy(info->type, name, I2C_NAME_SIZE); + + return 0; +} + +static int lm83_probe(struct i2c_client *new_client, + const struct i2c_device_id *id) +{ + struct lm83_data *data; + int err; + + data = kzalloc(sizeof(struct lm83_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(new_client, data); data->valid = 0; mutex_init(&data->update_lock); - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) - goto exit_free; - /* * Register sysfs hooks * The LM82 can only monitor one external diode which is @@ -389,9 +389,9 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind) */ if ((err = sysfs_create_group(&new_client->dev.kobj, &lm83_group))) - goto exit_detach; + goto exit_free; - if (kind == lm83) { + if (id->driver_data == lm83) { if ((err = sysfs_create_group(&new_client->dev.kobj, &lm83_group_opt))) goto exit_remove_files; @@ -408,26 +408,20 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind) exit_remove_files: sysfs_remove_group(&new_client->dev.kobj, &lm83_group); sysfs_remove_group(&new_client->dev.kobj, &lm83_group_opt); -exit_detach: - i2c_detach_client(new_client); exit_free: kfree(data); exit: return err; } -static int lm83_detach_client(struct i2c_client *client) +static int lm83_remove(struct i2c_client *client) { struct lm83_data *data = i2c_get_clientdata(client); - int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm83_group); sysfs_remove_group(&client->dev.kobj, &lm83_group_opt); - if ((err = i2c_detach_client(client))) - return err; - kfree(data); return 0; } diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index d1a3da3dd8e0..9464d5fdc816 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -187,23 +187,40 @@ I2C_CLIENT_INSMOD_7(lm90, adm1032, lm99, lm86, max6657, adt7461, max6680); * Functions declaration */ -static int lm90_attach_adapter(struct i2c_adapter *adapter); -static int lm90_detect(struct i2c_adapter *adapter, int address, - int kind); +static int lm90_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); +static int lm90_probe(struct i2c_client *client, + const struct i2c_device_id *id); static void lm90_init_client(struct i2c_client *client); -static int lm90_detach_client(struct i2c_client *client); +static int lm90_remove(struct i2c_client *client); static struct lm90_data *lm90_update_device(struct device *dev); /* * Driver data (common to all clients) */ +static struct i2c_device_id lm90_id[] = { + { "lm90", lm90 }, + { "adm1032", adm1032 }, + { "lm99", lm99 }, + { "lm86", lm86 }, + { "max6657", max6657 }, + { "adt7461", adt7461 }, + { "max6680", max6680 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, lm90_id); + static struct i2c_driver lm90_driver = { + .class = I2C_CLASS_HWMON, .driver = { .name = "lm90", }, - .attach_adapter = lm90_attach_adapter, - .detach_client = lm90_detach_client, + .probe = lm90_probe, + .remove = lm90_remove, + .id_table = lm90_id, + .detect = lm90_detect, + .address_data = &addr_data, }; /* @@ -211,7 +228,6 @@ static struct i2c_driver lm90_driver = { */ struct lm90_data { - struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ @@ -477,40 +493,16 @@ static int lm90_read_reg(struct i2c_client* client, u8 reg, u8 *value) return 0; } -static int lm90_attach_adapter(struct i2c_adapter *adapter) -{ - if (!(adapter->class & I2C_CLASS_HWMON)) - return 0; - return i2c_probe(adapter, &addr_data, lm90_detect); -} - -/* - * The following function does more than just detection. If detection - * succeeds, it also registers the new chip. - */ -static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int lm90_detect(struct i2c_client *new_client, int kind, + struct i2c_board_info *info) { - struct i2c_client *new_client; - struct lm90_data *data; - int err = 0; + struct i2c_adapter *adapter = new_client->adapter; + int address = new_client->addr; const char *name = ""; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - goto exit; - - if (!(data = kzalloc(sizeof(struct lm90_data), GFP_KERNEL))) { - err = -ENOMEM; - goto exit; - } - - /* The common I2C client data is placed right before the - LM90-specific data. */ - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &lm90_driver; - new_client->flags = 0; + return -ENODEV; /* * Now we do the remaining detection. A negative kind means that @@ -538,7 +530,7 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) LM90_REG_R_CONFIG1)) < 0 || (reg_convrate = i2c_smbus_read_byte_data(new_client, LM90_REG_R_CONVRATE)) < 0) - goto exit_free; + return -ENODEV; if ((address == 0x4C || address == 0x4D) && man_id == 0x01) { /* National Semiconductor */ @@ -546,7 +538,7 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) if ((reg_config2 = i2c_smbus_read_byte_data(new_client, LM90_REG_R_CONFIG2)) < 0) - goto exit_free; + return -ENODEV; if ((reg_config1 & 0x2A) == 0x00 && (reg_config2 & 0xF8) == 0x00 @@ -610,10 +602,11 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) dev_info(&adapter->dev, "Unsupported chip (man_id=0x%02X, " "chip_id=0x%02X).\n", man_id, chip_id); - goto exit_free; + return -ENODEV; } } + /* Fill the i2c board info */ if (kind == lm90) { name = "lm90"; } else if (kind == adm1032) { @@ -621,7 +614,7 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) /* The ADM1032 supports PEC, but only if combined transactions are not used. */ if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) - new_client->flags |= I2C_CLIENT_PEC; + info->flags |= I2C_CLIENT_PEC; } else if (kind == lm99) { name = "lm99"; } else if (kind == lm86) { @@ -633,23 +626,39 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) } else if (kind == adt7461) { name = "adt7461"; } + strlcpy(info->type, name, I2C_NAME_SIZE); + + return 0; +} + +static int lm90_probe(struct i2c_client *new_client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adapter = to_i2c_adapter(new_client->dev.parent); + struct lm90_data *data; + int err; - /* We can fill in the remaining client fields */ - strlcpy(new_client->name, name, I2C_NAME_SIZE); - data->valid = 0; - data->kind = kind; + data = kzalloc(sizeof(struct lm90_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + i2c_set_clientdata(new_client, data); mutex_init(&data->update_lock); - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) - goto exit_free; + /* Set the device type */ + data->kind = id->driver_data; + if (data->kind == adm1032) { + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) + new_client->flags &= ~I2C_CLIENT_PEC; + } /* Initialize the LM90 chip */ lm90_init_client(new_client); /* Register sysfs hooks */ if ((err = sysfs_create_group(&new_client->dev.kobj, &lm90_group))) - goto exit_detach; + goto exit_free; if (new_client->flags & I2C_CLIENT_PEC) { if ((err = device_create_file(&new_client->dev, &dev_attr_pec))) @@ -672,8 +681,6 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) exit_remove_files: sysfs_remove_group(&new_client->dev.kobj, &lm90_group); device_remove_file(&new_client->dev, &dev_attr_pec); -exit_detach: - i2c_detach_client(new_client); exit_free: kfree(data); exit: @@ -710,10 +717,9 @@ static void lm90_init_client(struct i2c_client *client) i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config); } -static int lm90_detach_client(struct i2c_client *client) +static int lm90_remove(struct i2c_client *client) { struct lm90_data *data = i2c_get_clientdata(client); - int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm90_group); @@ -722,9 +728,6 @@ static int lm90_detach_client(struct i2c_client *client) device_remove_file(&client->dev, &sensor_dev_attr_temp2_offset.dev_attr); - if ((err = i2c_detach_client(client))) - return err; - kfree(data); return 0; } diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c index c31942e08246..391e4e72fbc0 100644 --- a/drivers/hwmon/lm92.c +++ b/drivers/hwmon/lm92.c @@ -1,6 +1,6 @@ /* * lm92 - Hardware monitoring driver - * Copyright (C) 2005 Jean Delvare <khali@linux-fr.org> + * Copyright (C) 2005-2008 Jean Delvare <khali@linux-fr.org> * * Based on the lm90 driver, with some ideas taken from the lm_sensors * lm92 driver as well. @@ -96,7 +96,6 @@ static struct i2c_driver lm92_driver; /* Client data (each client gets its own) */ struct lm92_data { - struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ @@ -319,32 +318,15 @@ static const struct attribute_group lm92_group = { .attrs = lm92_attributes, }; -/* The following function does more than just detection. If detection - succeeds, it also registers the new chip. */ -static int lm92_detect(struct i2c_adapter *adapter, int address, int kind) +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int lm92_detect(struct i2c_client *new_client, int kind, + struct i2c_board_info *info) { - struct i2c_client *new_client; - struct lm92_data *data; - int err = 0; - char *name; + struct i2c_adapter *adapter = new_client->adapter; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) - goto exit; - - if (!(data = kzalloc(sizeof(struct lm92_data), GFP_KERNEL))) { - err = -ENOMEM; - goto exit; - } - - /* Fill in enough client fields so that we can read from the chip, - which is required for identication */ - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &lm92_driver; - new_client->flags = 0; + return -ENODEV; /* A negative kind means that the driver was loaded with no force parameter (default), so we must identify the chip. */ @@ -364,34 +346,36 @@ static int lm92_detect(struct i2c_adapter *adapter, int address, int kind) kind = lm92; /* No separate prefix */ } else - goto exit_free; - } else - if (kind == 0) /* Default to an LM92 if forced */ - kind = lm92; - - /* Give it the proper name */ - if (kind == lm92) { - name = "lm92"; - } else { /* Supposedly cannot happen */ - dev_dbg(&new_client->dev, "Kind out of range?\n"); - goto exit_free; + return -ENODEV; } - /* Fill in the remaining client fields */ - strlcpy(new_client->name, name, I2C_NAME_SIZE); + strlcpy(info->type, "lm92", I2C_NAME_SIZE); + + return 0; +} + +static int lm92_probe(struct i2c_client *new_client, + const struct i2c_device_id *id) +{ + struct lm92_data *data; + int err; + + data = kzalloc(sizeof(struct lm92_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(new_client, data); data->valid = 0; mutex_init(&data->update_lock); - /* Tell the i2c subsystem a new client has arrived */ - if ((err = i2c_attach_client(new_client))) - goto exit_free; - /* Initialize the chipset */ lm92_init_client(new_client); /* Register sysfs hooks */ if ((err = sysfs_create_group(&new_client->dev.kobj, &lm92_group))) - goto exit_detach; + goto exit_free; data->hwmon_dev = hwmon_device_register(&new_client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -403,32 +387,19 @@ static int lm92_detect(struct i2c_adapter *adapter, int address, int kind) exit_remove: sysfs_remove_group(&new_client->dev.kobj, &lm92_group); -exit_detach: - i2c_detach_client(new_client); exit_free: kfree(data); exit: return err; } -static int lm92_attach_adapter(struct i2c_adapter *adapter) -{ - if (!(adapter->class & I2C_CLASS_HWMON)) - return 0; - return i2c_probe(adapter, &addr_data, lm92_detect); -} - -static int lm92_detach_client(struct i2c_client *client) +static int lm92_remove(struct i2c_client *client) { struct lm92_data *data = i2c_get_clientdata(client); - int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm92_group); - if ((err = i2c_detach_client(client))) - return err; - kfree(data); return 0; } @@ -438,12 +409,23 @@ static int lm92_detach_client(struct i2c_client *client) * Module and driver stuff */ +static struct i2c_device_id lm92_id[] = { + { "lm92", lm92 }, + /* max6635 could be added here */ + { } +}; +MODULE_DEVICE_TABLE(i2c, lm92_id); + static struct i2c_driver lm92_driver = { + .class = I2C_CLASS_HWMON, .driver = { .name = "lm92", }, - .attach_adapter = lm92_attach_adapter, - .detach_client = lm92_detach_client, + .probe = lm92_probe, + .remove = lm92_remove, + .id_table = lm92_id, + .detect = lm92_detect, + .address_data = &addr_data, }; static int __init sensors_lm92_init(void) diff --git a/drivers/hwmon/lm93.c b/drivers/hwmon/lm93.c index 5e678f5c883d..fc8e8ede62fc 100644 --- a/drivers/hwmon/lm93.c +++ b/drivers/hwmon/lm93.c @@ -200,7 +200,6 @@ struct block1_t { * Client-specific data */ struct lm93_data { - struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; @@ -2501,45 +2500,14 @@ static void lm93_init_client(struct i2c_client *client) "chip to signal ready!\n"); } -static int lm93_detect(struct i2c_adapter *adapter, int address, int kind) +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int lm93_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info) { - struct lm93_data *data; - struct i2c_client *client; - - int err = -ENODEV, func; - void (*update)(struct lm93_data *, struct i2c_client *); - - /* choose update routine based on bus capabilities */ - func = i2c_get_functionality(adapter); - if ( ((LM93_SMBUS_FUNC_FULL & func) == LM93_SMBUS_FUNC_FULL) && - (!disable_block) ) { - dev_dbg(&adapter->dev,"using SMBus block data transactions\n"); - update = lm93_update_client_full; - } else if ((LM93_SMBUS_FUNC_MIN & func) == LM93_SMBUS_FUNC_MIN) { - dev_dbg(&adapter->dev,"disabled SMBus block data " - "transactions\n"); - update = lm93_update_client_min; - } else { - dev_dbg(&adapter->dev,"detect failed, " - "smbus byte and/or word data not supported!\n"); - goto err_out; - } + struct i2c_adapter *adapter = client->adapter; - /* OK. For now, we presume we have a valid client. We now create the - client structure, even though we cannot fill it completely yet. - But it allows us to access lm78_{read,write}_value. */ - - if ( !(data = kzalloc(sizeof(struct lm93_data), GFP_KERNEL))) { - dev_dbg(&adapter->dev,"out of memory!\n"); - err = -ENOMEM; - goto err_out; - } - - client = &data->client; - i2c_set_clientdata(client, data); - client->addr = address; - client->adapter = adapter; - client->driver = &lm93_driver; + if (!i2c_check_functionality(adapter, LM93_SMBUS_FUNC_MIN)) + return -ENODEV; /* detection */ if (kind < 0) { @@ -2548,7 +2516,7 @@ static int lm93_detect(struct i2c_adapter *adapter, int address, int kind) if (mfr != 0x01) { dev_dbg(&adapter->dev,"detect failed, " "bad manufacturer id 0x%02x!\n", mfr); - goto err_free; + return -ENODEV; } } @@ -2563,31 +2531,61 @@ static int lm93_detect(struct i2c_adapter *adapter, int address, int kind) if (kind == 0) dev_dbg(&adapter->dev, "(ignored 'force' parameter)\n"); - goto err_free; + return -ENODEV; } } - /* fill in remaining client fields */ - strlcpy(client->name, "lm93", I2C_NAME_SIZE); + strlcpy(info->type, "lm93", I2C_NAME_SIZE); dev_dbg(&adapter->dev,"loading %s at %d,0x%02x\n", client->name, i2c_adapter_id(client->adapter), client->addr); + return 0; +} + +static int lm93_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct lm93_data *data; + int err, func; + void (*update)(struct lm93_data *, struct i2c_client *); + + /* choose update routine based on bus capabilities */ + func = i2c_get_functionality(client->adapter); + if (((LM93_SMBUS_FUNC_FULL & func) == LM93_SMBUS_FUNC_FULL) && + (!disable_block)) { + dev_dbg(&client->dev, "using SMBus block data transactions\n"); + update = lm93_update_client_full; + } else if ((LM93_SMBUS_FUNC_MIN & func) == LM93_SMBUS_FUNC_MIN) { + dev_dbg(&client->dev, "disabled SMBus block data " + "transactions\n"); + update = lm93_update_client_min; + } else { + dev_dbg(&client->dev, "detect failed, " + "smbus byte and/or word data not supported!\n"); + err = -ENODEV; + goto err_out; + } + + data = kzalloc(sizeof(struct lm93_data), GFP_KERNEL); + if (!data) { + dev_dbg(&client->dev, "out of memory!\n"); + err = -ENOMEM; + goto err_out; + } + i2c_set_clientdata(client, data); + /* housekeeping */ data->valid = 0; data->update = update; mutex_init(&data->update_lock); - /* tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(client))) - goto err_free; - /* initialize the chip */ lm93_init_client(client); err = sysfs_create_group(&client->dev.kobj, &lm93_attr_grp); if (err) - goto err_detach; + goto err_free; /* Register hwmon driver class */ data->hwmon_dev = hwmon_device_register(&client->dev); @@ -2597,43 +2595,39 @@ static int lm93_detect(struct i2c_adapter *adapter, int address, int kind) err = PTR_ERR(data->hwmon_dev); dev_err(&client->dev, "error registering hwmon device.\n"); sysfs_remove_group(&client->dev.kobj, &lm93_attr_grp); -err_detach: - i2c_detach_client(client); err_free: kfree(data); err_out: return err; } -/* This function is called when: - * lm93_driver is inserted (when this module is loaded), for each - available adapter - * when a new adapter is inserted (and lm93_driver is still present) */ -static int lm93_attach_adapter(struct i2c_adapter *adapter) -{ - return i2c_probe(adapter, &addr_data, lm93_detect); -} - -static int lm93_detach_client(struct i2c_client *client) +static int lm93_remove(struct i2c_client *client) { struct lm93_data *data = i2c_get_clientdata(client); - int err = 0; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm93_attr_grp); - err = i2c_detach_client(client); - if (!err) - kfree(data); - return err; + kfree(data); + return 0; } +static struct i2c_device_id lm93_id[] = { + { "lm93", lm93 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, lm93_id); + static struct i2c_driver lm93_driver = { + .class = I2C_CLASS_HWMON, .driver = { .name = "lm93", }, - .attach_adapter = lm93_attach_adapter, - .detach_client = lm93_detach_client, + .probe = lm93_probe, + .remove = lm93_remove, + .id_table = lm93_id, + .detect = lm93_detect, + .address_data = &addr_data, }; static int __init lm93_init(void) diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c index 7e7267a04544..1926d9a79b9b 100644 --- a/drivers/hwmon/max1619.c +++ b/drivers/hwmon/max1619.c @@ -79,23 +79,34 @@ I2C_CLIENT_INSMOD_1(max1619); * Functions declaration */ -static int max1619_attach_adapter(struct i2c_adapter *adapter); -static int max1619_detect(struct i2c_adapter *adapter, int address, - int kind); +static int max1619_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int max1619_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); static void max1619_init_client(struct i2c_client *client); -static int max1619_detach_client(struct i2c_client *client); +static int max1619_remove(struct i2c_client *client); static struct max1619_data *max1619_update_device(struct device *dev); /* * Driver data (common to all clients) */ +static struct i2c_device_id max1619_id[] = { + { "max1619", max1619 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, max1619_id); + static struct i2c_driver max1619_driver = { + .class = I2C_CLASS_HWMON, .driver = { .name = "max1619", }, - .attach_adapter = max1619_attach_adapter, - .detach_client = max1619_detach_client, + .probe = max1619_probe, + .remove = max1619_remove, + .id_table = max1619_id, + .detect = max1619_detect, + .address_data = &addr_data, }; /* @@ -103,7 +114,6 @@ static struct i2c_driver max1619_driver = { */ struct max1619_data { - struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ @@ -208,41 +218,15 @@ static const struct attribute_group max1619_group = { * Real code */ -static int max1619_attach_adapter(struct i2c_adapter *adapter) -{ - if (!(adapter->class & I2C_CLASS_HWMON)) - return 0; - return i2c_probe(adapter, &addr_data, max1619_detect); -} - -/* - * The following function does more than just detection. If detection - * succeeds, it also registers the new chip. - */ -static int max1619_detect(struct i2c_adapter *adapter, int address, int kind) +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int max1619_detect(struct i2c_client *new_client, int kind, + struct i2c_board_info *info) { - struct i2c_client *new_client; - struct max1619_data *data; - int err = 0; - const char *name = ""; + struct i2c_adapter *adapter = new_client->adapter; u8 reg_config=0, reg_convrate=0, reg_status=0; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - goto exit; - - if (!(data = kzalloc(sizeof(struct max1619_data), GFP_KERNEL))) { - err = -ENOMEM; - goto exit; - } - - /* The common I2C client data is placed right before the - MAX1619-specific data. */ - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &max1619_driver; - new_client->flags = 0; + return -ENODEV; /* * Now we do the remaining detection. A negative kind means that @@ -265,8 +249,8 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind) || reg_convrate > 0x07 || (reg_status & 0x61 ) !=0x00) { dev_dbg(&adapter->dev, "MAX1619 detection failed at 0x%02x.\n", - address); - goto exit_free; + new_client->addr); + return -ENODEV; } } @@ -285,28 +269,37 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind) dev_info(&adapter->dev, "Unsupported chip (man_id=0x%02X, " "chip_id=0x%02X).\n", man_id, chip_id); - goto exit_free; + return -ENODEV; } } - if (kind == max1619) - name = "max1619"; + strlcpy(info->type, "max1619", I2C_NAME_SIZE); + + return 0; +} + +static int max1619_probe(struct i2c_client *new_client, + const struct i2c_device_id *id) +{ + struct max1619_data *data; + int err; + + data = kzalloc(sizeof(struct max1619_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } - /* We can fill in the remaining client fields */ - strlcpy(new_client->name, name, I2C_NAME_SIZE); + i2c_set_clientdata(new_client, data); data->valid = 0; mutex_init(&data->update_lock); - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) - goto exit_free; - /* Initialize the MAX1619 chip */ max1619_init_client(new_client); /* Register sysfs hooks */ if ((err = sysfs_create_group(&new_client->dev.kobj, &max1619_group))) - goto exit_detach; + goto exit_free; data->hwmon_dev = hwmon_device_register(&new_client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -318,8 +311,6 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind) exit_remove_files: sysfs_remove_group(&new_client->dev.kobj, &max1619_group); -exit_detach: - i2c_detach_client(new_client); exit_free: kfree(data); exit: @@ -341,17 +332,13 @@ static void max1619_init_client(struct i2c_client *client) config & 0xBF); /* run */ } -static int max1619_detach_client(struct i2c_client *client) +static int max1619_remove(struct i2c_client *client) { struct max1619_data *data = i2c_get_clientdata(client); - int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &max1619_group); - if ((err = i2c_detach_client(client))) - return err; - kfree(data); return 0; } diff --git a/drivers/hwmon/max6650.c b/drivers/hwmon/max6650.c index 52d528b76cc3..40e7ba35e4ef 100644 --- a/drivers/hwmon/max6650.c +++ b/drivers/hwmon/max6650.c @@ -104,22 +104,34 @@ I2C_CLIENT_INSMOD_1(max6650); #define DIV_FROM_REG(reg) (1 << (reg & 7)) -static int max6650_attach_adapter(struct i2c_adapter *adapter); -static int max6650_detect(struct i2c_adapter *adapter, int address, int kind); +static int max6650_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int max6650_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); static int max6650_init_client(struct i2c_client *client); -static int max6650_detach_client(struct i2c_client *client); +static int max6650_remove(struct i2c_client *client); static struct max6650_data *max6650_update_device(struct device *dev); /* * Driver data (common to all clients) */ +static struct i2c_device_id max6650_id[] = { + { "max6650", max6650 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, max6650_id); + static struct i2c_driver max6650_driver = { + .class = I2C_CLASS_HWMON, .driver = { .name = "max6650", }, - .attach_adapter = max6650_attach_adapter, - .detach_client = max6650_detach_client, + .probe = max6650_probe, + .remove = max6650_remove, + .id_table = max6650_id, + .detect = max6650_detect, + .address_data = &addr_data, }; /* @@ -128,7 +140,6 @@ static struct i2c_driver max6650_driver = { struct max6650_data { - struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ @@ -437,47 +448,21 @@ static struct attribute_group max6650_attr_grp = { * Real code */ -static int max6650_attach_adapter(struct i2c_adapter *adapter) +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int max6650_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info) { - if (!(adapter->class & I2C_CLASS_HWMON)) { - dev_dbg(&adapter->dev, - "FATAL: max6650_attach_adapter class HWMON not set\n"); - return 0; - } - - return i2c_probe(adapter, &addr_data, max6650_detect); -} - -/* - * The following function does more than just detection. If detection - * succeeds, it also registers the new chip. - */ - -static int max6650_detect(struct i2c_adapter *adapter, int address, int kind) -{ - struct i2c_client *client; - struct max6650_data *data; - int err = -ENODEV; + struct i2c_adapter *adapter = client->adapter; + int address = client->addr; dev_dbg(&adapter->dev, "max6650_detect called, kind = %d\n", kind); if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { dev_dbg(&adapter->dev, "max6650: I2C bus doesn't support " "byte read mode, skipping.\n"); - return 0; - } - - if (!(data = kzalloc(sizeof(struct max6650_data), GFP_KERNEL))) { - dev_err(&adapter->dev, "max6650: out of memory.\n"); - return -ENOMEM; + return -ENODEV; } - client = &data->client; - i2c_set_clientdata(client, data); - client->addr = address; - client->adapter = adapter; - client->driver = &max6650_driver; - /* * Now we do the remaining detection. A negative kind means that * the driver was loaded with no force parameter (default), so we @@ -501,28 +486,40 @@ static int max6650_detect(struct i2c_adapter *adapter, int address, int kind) ||(i2c_smbus_read_byte_data(client, MAX6650_REG_COUNT) & 0xFC))) { dev_dbg(&adapter->dev, "max6650: detection failed at 0x%02x.\n", address); - goto err_free; + return -ENODEV; } dev_info(&adapter->dev, "max6650: chip found at 0x%02x.\n", address); - strlcpy(client->name, "max6650", I2C_NAME_SIZE); - mutex_init(&data->update_lock); + strlcpy(info->type, "max6650", I2C_NAME_SIZE); - if ((err = i2c_attach_client(client))) { - dev_err(&adapter->dev, "max6650: failed to attach client.\n"); - goto err_free; + return 0; +} + +static int max6650_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct max6650_data *data; + int err; + + if (!(data = kzalloc(sizeof(struct max6650_data), GFP_KERNEL))) { + dev_err(&client->dev, "out of memory.\n"); + return -ENOMEM; } + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + /* * Initialize the max6650 chip */ - if (max6650_init_client(client)) - goto err_detach; + err = max6650_init_client(client); + if (err) + goto err_free; err = sysfs_create_group(&client->dev.kobj, &max6650_attr_grp); if (err) - goto err_detach; + goto err_free; data->hwmon_dev = hwmon_device_register(&client->dev); if (!IS_ERR(data->hwmon_dev)) @@ -531,24 +528,19 @@ static int max6650_detect(struct i2c_adapter *adapter, int address, int kind) err = PTR_ERR(data->hwmon_dev); dev_err(&client->dev, "error registering hwmon device.\n"); sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp); -err_detach: - i2c_detach_client(client); err_free: kfree(data); return err; } -static int max6650_detach_client(struct i2c_client *client) +static int max6650_remove(struct i2c_client *client) { struct max6650_data *data = i2c_get_clientdata(client); - int err; sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp); hwmon_device_unregister(data->hwmon_dev); - err = i2c_detach_client(client); - if (!err) - kfree(data); - return err; + kfree(data); + return 0; } static int max6650_init_client(struct i2c_client *client) diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c index 3c9db6598ba7..d2b7a0974261 100644 --- a/drivers/hwmon/smsc47m192.c +++ b/drivers/hwmon/smsc47m192.c @@ -96,7 +96,6 @@ static inline int TEMP_FROM_REG(s8 val) } struct smsc47m192_data { - struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* !=0 if following fields are valid */ @@ -114,18 +113,29 @@ struct smsc47m192_data { u8 vrm; }; -static int smsc47m192_attach_adapter(struct i2c_adapter *adapter); -static int smsc47m192_detect(struct i2c_adapter *adapter, int address, - int kind); -static int smsc47m192_detach_client(struct i2c_client *client); +static int smsc47m192_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int smsc47m192_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); +static int smsc47m192_remove(struct i2c_client *client); static struct smsc47m192_data *smsc47m192_update_device(struct device *dev); +static struct i2c_device_id smsc47m192_id[] = { + { "smsc47m192", smsc47m192 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, smsc47m192_id); + static struct i2c_driver smsc47m192_driver = { + .class = I2C_CLASS_HWMON, .driver = { .name = "smsc47m192", }, - .attach_adapter = smsc47m192_attach_adapter, - .detach_client = smsc47m192_detach_client, + .probe = smsc47m192_probe, + .remove = smsc47m192_remove, + .id_table = smsc47m192_id, + .detect = smsc47m192_detect, + .address_data = &addr_data, }; /* Voltages */ @@ -440,17 +450,6 @@ static const struct attribute_group smsc47m192_group_in4 = { .attrs = smsc47m192_attributes_in4, }; -/* This function is called when: - * smsc47m192_driver is inserted (when this module is loaded), for each - available adapter - * when a new adapter is inserted (and smsc47m192_driver is still present) */ -static int smsc47m192_attach_adapter(struct i2c_adapter *adapter) -{ - if (!(adapter->class & I2C_CLASS_HWMON)) - return 0; - return i2c_probe(adapter, &addr_data, smsc47m192_detect); -} - static void smsc47m192_init_client(struct i2c_client *client) { int i; @@ -481,31 +480,15 @@ static void smsc47m192_init_client(struct i2c_client *client) } } -/* This function is called by i2c_probe */ -static int smsc47m192_detect(struct i2c_adapter *adapter, int address, - int kind) +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int smsc47m192_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info) { - struct i2c_client *client; - struct smsc47m192_data *data; - int err = 0; - int version, config; + struct i2c_adapter *adapter = client->adapter; + int version; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - goto exit; - - if (!(data = kzalloc(sizeof(struct smsc47m192_data), GFP_KERNEL))) { - err = -ENOMEM; - goto exit; - } - - client = &data->client; - i2c_set_clientdata(client, data); - client->addr = address; - client->adapter = adapter; - client->driver = &smsc47m192_driver; - - if (kind == 0) - kind = smsc47m192; + return -ENODEV; /* Detection criteria from sensors_detect script */ if (kind < 0) { @@ -523,26 +506,39 @@ static int smsc47m192_detect(struct i2c_adapter *adapter, int address, } else { dev_dbg(&adapter->dev, "SMSC47M192 detection failed at 0x%02x\n", - address); - goto exit_free; + client->addr); + return -ENODEV; } } - /* Fill in the remaining client fields and put into the global list */ - strlcpy(client->name, "smsc47m192", I2C_NAME_SIZE); + strlcpy(info->type, "smsc47m192", I2C_NAME_SIZE); + + return 0; +} + +static int smsc47m192_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct smsc47m192_data *data; + int config; + int err; + + data = kzalloc(sizeof(struct smsc47m192_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); data->vrm = vid_which_vrm(); mutex_init(&data->update_lock); - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(client))) - goto exit_free; - /* Initialize the SMSC47M192 chip */ smsc47m192_init_client(client); /* Register sysfs hooks */ if ((err = sysfs_create_group(&client->dev.kobj, &smsc47m192_group))) - goto exit_detach; + goto exit_free; /* Pin 110 is either in4 (+12V) or VID4 */ config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG); @@ -563,26 +559,20 @@ static int smsc47m192_detect(struct i2c_adapter *adapter, int address, exit_remove_files: sysfs_remove_group(&client->dev.kobj, &smsc47m192_group); sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4); -exit_detach: - i2c_detach_client(client); exit_free: kfree(data); exit: return err; } -static int smsc47m192_detach_client(struct i2c_client *client) +static int smsc47m192_remove(struct i2c_client *client) { struct smsc47m192_data *data = i2c_get_clientdata(client); - int err; hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &smsc47m192_group); sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4); - if ((err = i2c_detach_client(client))) - return err; - kfree(data); return 0; diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index 299629d47ed6..142352803650 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c @@ -267,9 +267,7 @@ DIV_TO_REG(long val) } struct w83792d_data { - struct i2c_client client; struct device *hwmon_dev; - enum chips type; struct mutex update_lock; char valid; /* !=0 if following fields are valid */ @@ -299,9 +297,11 @@ struct w83792d_data { u8 sf2_levels[3][4]; /* Smart FanII: Fan1,2,3 duty cycle levels */ }; -static int w83792d_attach_adapter(struct i2c_adapter *adapter); -static int w83792d_detect(struct i2c_adapter *adapter, int address, int kind); -static int w83792d_detach_client(struct i2c_client *client); +static int w83792d_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int w83792d_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); +static int w83792d_remove(struct i2c_client *client); static struct w83792d_data *w83792d_update_device(struct device *dev); #ifdef DEBUG @@ -310,12 +310,22 @@ static void w83792d_print_debug(struct w83792d_data *data, struct device *dev); static void w83792d_init_client(struct i2c_client *client); +static struct i2c_device_id w83792d_id[] = { + { "w83792d", w83792d }, + { } +}; +MODULE_DEVICE_TABLE(i2c, w83792d_id); + static struct i2c_driver w83792d_driver = { + .class = I2C_CLASS_HWMON, .driver = { .name = "w83792d", }, - .attach_adapter = w83792d_attach_adapter, - .detach_client = w83792d_detach_client, + .probe = w83792d_probe, + .remove = w83792d_remove, + .id_table = w83792d_id, + .detect = w83792d_detect, + .address_data = &addr_data, }; static inline long in_count_from_reg(int nr, struct w83792d_data *data) @@ -864,53 +874,14 @@ store_sf2_level(struct device *dev, struct device_attribute *attr, return count; } -/* This function is called when: - * w83792d_driver is inserted (when this module is loaded), for each - available adapter - * when a new adapter is inserted (and w83792d_driver is still present) */ -static int -w83792d_attach_adapter(struct i2c_adapter *adapter) -{ - if (!(adapter->class & I2C_CLASS_HWMON)) - return 0; - return i2c_probe(adapter, &addr_data, w83792d_detect); -} - - -static int -w83792d_create_subclient(struct i2c_adapter *adapter, - struct i2c_client *new_client, int addr, - struct i2c_client **sub_cli) -{ - int err; - struct i2c_client *sub_client; - - (*sub_cli) = sub_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (!(sub_client)) { - return -ENOMEM; - } - sub_client->addr = 0x48 + addr; - i2c_set_clientdata(sub_client, NULL); - sub_client->adapter = adapter; - sub_client->driver = &w83792d_driver; - sub_client->flags = 0; - strlcpy(sub_client->name, "w83792d subclient", I2C_NAME_SIZE); - if ((err = i2c_attach_client(sub_client))) { - dev_err(&new_client->dev, "subclient registration " - "at address 0x%x failed\n", sub_client->addr); - kfree(sub_client); - return err; - } - return 0; -} - static int -w83792d_detect_subclients(struct i2c_adapter *adapter, int address, int kind, - struct i2c_client *new_client) +w83792d_detect_subclients(struct i2c_client *new_client) { int i, id, err; + int address = new_client->addr; u8 val; + struct i2c_adapter *adapter = new_client->adapter; struct w83792d_data *data = i2c_get_clientdata(new_client); id = i2c_adapter_id(adapter); @@ -932,10 +903,7 @@ w83792d_detect_subclients(struct i2c_adapter *adapter, int address, int kind, val = w83792d_read_value(new_client, W83792D_REG_I2C_SUBADDR); if (!(val & 0x08)) { - err = w83792d_create_subclient(adapter, new_client, val & 0x7, - &data->lm75[0]); - if (err < 0) - goto ERROR_SC_0; + data->lm75[0] = i2c_new_dummy(adapter, 0x48 + (val & 0x7)); } if (!(val & 0x80)) { if ((data->lm75[0] != NULL) && @@ -945,10 +913,8 @@ w83792d_detect_subclients(struct i2c_adapter *adapter, int address, int kind, err = -ENODEV; goto ERROR_SC_1; } - err = w83792d_create_subclient(adapter, new_client, - (val >> 4) & 0x7, &data->lm75[1]); - if (err < 0) - goto ERROR_SC_1; + data->lm75[1] = i2c_new_dummy(adapter, + 0x48 + ((val >> 4) & 0x7)); } return 0; @@ -956,10 +922,8 @@ w83792d_detect_subclients(struct i2c_adapter *adapter, int address, int kind, /* Undo inits in case of errors */ ERROR_SC_1: - if (data->lm75[0] != NULL) { - i2c_detach_client(data->lm75[0]); - kfree(data->lm75[0]); - } + if (data->lm75[0] != NULL) + i2c_unregister_device(data->lm75[0]); ERROR_SC_0: return err; } @@ -1294,47 +1258,25 @@ static const struct attribute_group w83792d_group = { .attrs = w83792d_attributes, }; +/* Return 0 if detection is successful, -ENODEV otherwise */ static int -w83792d_detect(struct i2c_adapter *adapter, int address, int kind) +w83792d_detect(struct i2c_client *client, int kind, struct i2c_board_info *info) { - int i = 0, val1 = 0, val2; - struct i2c_client *client; - struct device *dev; - struct w83792d_data *data; - int err = 0; - const char *client_name = ""; + struct i2c_adapter *adapter = client->adapter; + int val1, val2; + unsigned short address = client->addr; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { - goto ERROR0; - } - - /* OK. For now, we presume we have a valid client. We now create the - client structure, even though we cannot fill it completely yet. - But it allows us to access w83792d_{read,write}_value. */ - - if (!(data = kzalloc(sizeof(struct w83792d_data), GFP_KERNEL))) { - err = -ENOMEM; - goto ERROR0; + return -ENODEV; } - client = &data->client; - dev = &client->dev; - i2c_set_clientdata(client, data); - client->addr = address; - client->adapter = adapter; - client->driver = &w83792d_driver; - client->flags = 0; - - /* Now, we do the remaining detection. */ - /* The w83792d may be stuck in some other bank than bank 0. This may make reading other information impossible. Specify a force=... or force_*=... parameter, and the Winbond will be reset to the right bank. */ if (kind < 0) { if (w83792d_read_value(client, W83792D_REG_CONFIG) & 0x80) { - dev_dbg(dev, "Detection failed at step 1\n"); - goto ERROR1; + return -ENODEV; } val1 = w83792d_read_value(client, W83792D_REG_BANK); val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN); @@ -1342,16 +1284,14 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind) if (!(val1 & 0x07)) { /* is Bank0 */ if (((!(val1 & 0x80)) && (val2 != 0xa3)) || ((val1 & 0x80) && (val2 != 0x5c))) { - dev_dbg(dev, "Detection failed at step 2\n"); - goto ERROR1; + return -ENODEV; } } /* If Winbond chip, address of chip and W83792D_REG_I2C_ADDR should match */ if (w83792d_read_value(client, W83792D_REG_I2C_ADDR) != address) { - dev_dbg(dev, "Detection failed at step 3\n"); - goto ERROR1; + return -ENODEV; } } @@ -1367,45 +1307,48 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind) /* get vendor ID */ val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN); if (val2 != 0x5c) { /* the vendor is NOT Winbond */ - goto ERROR1; + return -ENODEV; } val1 = w83792d_read_value(client, W83792D_REG_WCHIPID); if (val1 == 0x7a) { kind = w83792d; } else { if (kind == 0) - dev_warn(dev, + dev_warn(&adapter->dev, "w83792d: Ignoring 'force' parameter for" " unknown chip at adapter %d, address" " 0x%02x\n", i2c_adapter_id(adapter), address); - goto ERROR1; + return -ENODEV; } } - if (kind == w83792d) { - client_name = "w83792d"; - } else { - dev_err(dev, "w83792d: Internal error: unknown kind (%d)?!?\n", - kind); - goto ERROR1; - } + strlcpy(info->type, "w83792d", I2C_NAME_SIZE); + + return 0; +} + +static int +w83792d_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct w83792d_data *data; + struct device *dev = &client->dev; + int i, val1, err; - /* Fill in the remaining client fields and put into the global list */ - strlcpy(client->name, client_name, I2C_NAME_SIZE); - data->type = kind; + data = kzalloc(sizeof(struct w83792d_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto ERROR0; + } + i2c_set_clientdata(client, data); data->valid = 0; mutex_init(&data->update_lock); - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(client))) + err = w83792d_detect_subclients(client); + if (err) goto ERROR1; - if ((err = w83792d_detect_subclients(adapter, address, - kind, client))) - goto ERROR2; - /* Initialize the chip */ w83792d_init_client(client); @@ -1457,16 +1400,10 @@ exit_remove_files: for (i = 0; i < ARRAY_SIZE(w83792d_group_fan); i++) sysfs_remove_group(&dev->kobj, &w83792d_group_fan[i]); ERROR3: - if (data->lm75[0] != NULL) { - i2c_detach_client(data->lm75[0]); - kfree(data->lm75[0]); - } - if (data->lm75[1] != NULL) { - i2c_detach_client(data->lm75[1]); - kfree(data->lm75[1]); - } -ERROR2: - i2c_detach_client(client); + if (data->lm75[0] != NULL) + i2c_unregister_device(data->lm75[0]); + if (data->lm75[1] != NULL) + i2c_unregister_device(data->lm75[1]); ERROR1: kfree(data); ERROR0: @@ -1474,30 +1411,23 @@ ERROR0: } static int -w83792d_detach_client(struct i2c_client *client) +w83792d_remove(struct i2c_client *client) { struct w83792d_data *data = i2c_get_clientdata(client); - int err, i; - - /* main client */ - if (data) { - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &w83792d_group); - for (i = 0; i < ARRAY_SIZE(w83792d_group_fan); i++) - sysfs_remove_group(&client->dev.kobj, - &w83792d_group_fan[i]); - } + int i; - if ((err = i2c_detach_client(client))) - return err; + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &w83792d_group); + for (i = 0; i < ARRAY_SIZE(w83792d_group_fan); i++) + sysfs_remove_group(&client->dev.kobj, + &w83792d_group_fan[i]); - /* main client */ - if (data) - kfree(data); - /* subclient */ - else - kfree(client); + if (data->lm75[0] != NULL) + i2c_unregister_device(data->lm75[0]); + if (data->lm75[1] != NULL) + i2c_unregister_device(data->lm75[1]); + kfree(data); return 0; } diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c index ed3c019b78c7..4ad777640753 100644 --- a/drivers/hwmon/w83793.c +++ b/drivers/hwmon/w83793.c @@ -179,7 +179,6 @@ static inline s8 TEMP_TO_REG(long val, s8 min, s8 max) } struct w83793_data { - struct i2c_client client; struct i2c_client *lm75[2]; struct device *hwmon_dev; struct mutex update_lock; @@ -226,19 +225,31 @@ struct w83793_data { static u8 w83793_read_value(struct i2c_client *client, u16 reg); static int w83793_write_value(struct i2c_client *client, u16 reg, u8 value); -static int w83793_attach_adapter(struct i2c_adapter *adapter); -static int w83793_detect(struct i2c_adapter *adapter, int address, int kind); -static int w83793_detach_client(struct i2c_client *client); +static int w83793_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int w83793_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); +static int w83793_remove(struct i2c_client *client); static void w83793_init_client(struct i2c_client *client); static void w83793_update_nonvolatile(struct device *dev); static struct w83793_data *w83793_update_device(struct device *dev); +static struct i2c_device_id w83793_id[] = { + { "w83793", w83793 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, w83793_id); + static struct i2c_driver w83793_driver = { + .class = I2C_CLASS_HWMON, .driver = { .name = "w83793", }, - .attach_adapter = w83793_attach_adapter, - .detach_client = w83793_detach_client, + .probe = w83793_probe, + .remove = w83793_remove, + .id_table = w83793_id, + .detect = w83793_detect, + .address_data = &addr_data, }; static ssize_t @@ -1053,89 +1064,51 @@ static void w83793_init_client(struct i2c_client *client) } -static int w83793_attach_adapter(struct i2c_adapter *adapter) -{ - if (!(adapter->class & I2C_CLASS_HWMON)) - return 0; - return i2c_probe(adapter, &addr_data, w83793_detect); -} - -static int w83793_detach_client(struct i2c_client *client) +static int w83793_remove(struct i2c_client *client) { struct w83793_data *data = i2c_get_clientdata(client); struct device *dev = &client->dev; - int err, i; + int i; - /* main client */ - if (data) { - hwmon_device_unregister(data->hwmon_dev); + hwmon_device_unregister(data->hwmon_dev); - for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++) - device_remove_file(dev, - &w83793_sensor_attr_2[i].dev_attr); + for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++) + device_remove_file(dev, + &w83793_sensor_attr_2[i].dev_attr); - for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) - device_remove_file(dev, &sda_single_files[i].dev_attr); + for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) + device_remove_file(dev, &sda_single_files[i].dev_attr); - for (i = 0; i < ARRAY_SIZE(w83793_vid); i++) - device_remove_file(dev, &w83793_vid[i].dev_attr); - device_remove_file(dev, &dev_attr_vrm); + for (i = 0; i < ARRAY_SIZE(w83793_vid); i++) + device_remove_file(dev, &w83793_vid[i].dev_attr); + device_remove_file(dev, &dev_attr_vrm); - for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++) - device_remove_file(dev, &w83793_left_fan[i].dev_attr); + for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++) + device_remove_file(dev, &w83793_left_fan[i].dev_attr); - for (i = 0; i < ARRAY_SIZE(w83793_left_pwm); i++) - device_remove_file(dev, &w83793_left_pwm[i].dev_attr); + for (i = 0; i < ARRAY_SIZE(w83793_left_pwm); i++) + device_remove_file(dev, &w83793_left_pwm[i].dev_attr); - for (i = 0; i < ARRAY_SIZE(w83793_temp); i++) - device_remove_file(dev, &w83793_temp[i].dev_attr); - } + for (i = 0; i < ARRAY_SIZE(w83793_temp); i++) + device_remove_file(dev, &w83793_temp[i].dev_attr); - if ((err = i2c_detach_client(client))) - return err; + if (data->lm75[0] != NULL) + i2c_unregister_device(data->lm75[0]); + if (data->lm75[1] != NULL) + i2c_unregister_device(data->lm75[1]); - /* main client */ - if (data) - kfree(data); - /* subclient */ - else - kfree(client); + kfree(data); return 0; } static int -w83793_create_subclient(struct i2c_adapter *adapter, - struct i2c_client *client, int addr, - struct i2c_client **sub_cli) -{ - int err = 0; - struct i2c_client *sub_client; - - (*sub_cli) = sub_client = - kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (!(sub_client)) { - return -ENOMEM; - } - sub_client->addr = 0x48 + addr; - i2c_set_clientdata(sub_client, NULL); - sub_client->adapter = adapter; - sub_client->driver = &w83793_driver; - strlcpy(sub_client->name, "w83793 subclient", I2C_NAME_SIZE); - if ((err = i2c_attach_client(sub_client))) { - dev_err(&client->dev, "subclient registration " - "at address 0x%x failed\n", sub_client->addr); - kfree(sub_client); - } - return err; -} - -static int -w83793_detect_subclients(struct i2c_adapter *adapter, int address, - int kind, struct i2c_client *client) +w83793_detect_subclients(struct i2c_client *client) { int i, id, err; + int address = client->addr; u8 tmp; + struct i2c_adapter *adapter = client->adapter; struct w83793_data *data = i2c_get_clientdata(client); id = i2c_adapter_id(adapter); @@ -1158,11 +1131,7 @@ w83793_detect_subclients(struct i2c_adapter *adapter, int address, tmp = w83793_read_value(client, W83793_REG_I2C_SUBADDR); if (!(tmp & 0x08)) { - err = - w83793_create_subclient(adapter, client, tmp & 0x7, - &data->lm75[0]); - if (err < 0) - goto ERROR_SC_0; + data->lm75[0] = i2c_new_dummy(adapter, 0x48 + (tmp & 0x7)); } if (!(tmp & 0x80)) { if ((data->lm75[0] != NULL) @@ -1173,10 +1142,8 @@ w83793_detect_subclients(struct i2c_adapter *adapter, int address, err = -ENODEV; goto ERROR_SC_1; } - err = w83793_create_subclient(adapter, client, - (tmp >> 4) & 0x7, &data->lm75[1]); - if (err < 0) - goto ERROR_SC_1; + data->lm75[1] = i2c_new_dummy(adapter, + 0x48 + ((tmp >> 4) & 0x7)); } return 0; @@ -1184,69 +1151,44 @@ w83793_detect_subclients(struct i2c_adapter *adapter, int address, /* Undo inits in case of errors */ ERROR_SC_1: - if (data->lm75[0] != NULL) { - i2c_detach_client(data->lm75[0]); - kfree(data->lm75[0]); - } + if (data->lm75[0] != NULL) + i2c_unregister_device(data->lm75[0]); ERROR_SC_0: return err; } -static int w83793_detect(struct i2c_adapter *adapter, int address, int kind) +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int w83793_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info) { - int i; - u8 tmp, val; - struct i2c_client *client; - struct device *dev; - struct w83793_data *data; - int files_fan = ARRAY_SIZE(w83793_left_fan) / 7; - int files_pwm = ARRAY_SIZE(w83793_left_pwm) / 5; - int files_temp = ARRAY_SIZE(w83793_temp) / 6; - int err = 0; + u8 tmp, bank; + struct i2c_adapter *adapter = client->adapter; + unsigned short address = client->addr; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { - goto exit; + return -ENODEV; } - /* OK. For now, we presume we have a valid client. We now create the - client structure, even though we cannot fill it completely yet. - But it allows us to access w83793_{read,write}_value. */ - - if (!(data = kzalloc(sizeof(struct w83793_data), GFP_KERNEL))) { - err = -ENOMEM; - goto exit; - } - - client = &data->client; - dev = &client->dev; - i2c_set_clientdata(client, data); - client->addr = address; - client->adapter = adapter; - client->driver = &w83793_driver; + bank = i2c_smbus_read_byte_data(client, W83793_REG_BANKSEL); - data->bank = i2c_smbus_read_byte_data(client, W83793_REG_BANKSEL); - - /* Now, we do the remaining detection. */ if (kind < 0) { - tmp = data->bank & 0x80 ? 0x5c : 0xa3; + tmp = bank & 0x80 ? 0x5c : 0xa3; /* Check Winbond vendor ID */ if (tmp != i2c_smbus_read_byte_data(client, W83793_REG_VENDORID)) { pr_debug("w83793: Detection failed at check " "vendor id\n"); - err = -ENODEV; - goto free_mem; + return -ENODEV; } /* If Winbond chip, address of chip and W83793_REG_I2C_ADDR should match */ - if ((data->bank & 0x07) == 0 + if ((bank & 0x07) == 0 && i2c_smbus_read_byte_data(client, W83793_REG_I2C_ADDR) != (address << 1)) { pr_debug("w83793: Detection failed at check " "i2c addr\n"); - err = -ENODEV; - goto free_mem; + return -ENODEV; } } @@ -1255,30 +1197,47 @@ static int w83793_detect(struct i2c_adapter *adapter, int address, int kind) Winbond. Determine the chip type now */ if (kind <= 0) { - if (0x7b == w83793_read_value(client, W83793_REG_CHIPID)) { + if (0x7b == i2c_smbus_read_byte_data(client, + W83793_REG_CHIPID)) { kind = w83793; } else { if (kind == 0) dev_warn(&adapter->dev, "w83793: Ignoring " "'force' parameter for unknown chip " "at address 0x%02x\n", address); - err = -ENODEV; - goto free_mem; + return -ENODEV; } } - /* Fill in the remaining client fields and put into the global list */ - strlcpy(client->name, "w83793", I2C_NAME_SIZE); + strlcpy(info->type, "w83793", I2C_NAME_SIZE); + + return 0; +} +static int w83793_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct w83793_data *data; + int i, tmp, val, err; + int files_fan = ARRAY_SIZE(w83793_left_fan) / 7; + int files_pwm = ARRAY_SIZE(w83793_left_pwm) / 5; + int files_temp = ARRAY_SIZE(w83793_temp) / 6; + + data = kzalloc(sizeof(struct w83793_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->bank = i2c_smbus_read_byte_data(client, W83793_REG_BANKSEL); mutex_init(&data->update_lock); - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(client))) + err = w83793_detect_subclients(client); + if (err) goto free_mem; - if ((err = w83793_detect_subclients(adapter, address, kind, client))) - goto detach_client; - /* Initialize the chip */ w83793_init_client(client); @@ -1459,16 +1418,10 @@ exit_remove: for (i = 0; i < ARRAY_SIZE(w83793_temp); i++) device_remove_file(dev, &w83793_temp[i].dev_attr); - if (data->lm75[0] != NULL) { - i2c_detach_client(data->lm75[0]); - kfree(data->lm75[0]); - } - if (data->lm75[1] != NULL) { - i2c_detach_client(data->lm75[1]); - kfree(data->lm75[1]); - } -detach_client: - i2c_detach_client(client); + if (data->lm75[0] != NULL) + i2c_unregister_device(data->lm75[0]); + if (data->lm75[1] != NULL) + i2c_unregister_device(data->lm75[1]); free_mem: kfree(data); exit: diff --git a/drivers/hwmon/w83l785ts.c b/drivers/hwmon/w83l785ts.c index 52e268e25dab..c71703527b13 100644 --- a/drivers/hwmon/w83l785ts.c +++ b/drivers/hwmon/w83l785ts.c @@ -81,10 +81,11 @@ I2C_CLIENT_INSMOD_1(w83l785ts); * Functions declaration */ -static int w83l785ts_attach_adapter(struct i2c_adapter *adapter); -static int w83l785ts_detect(struct i2c_adapter *adapter, int address, - int kind); -static int w83l785ts_detach_client(struct i2c_client *client); +static int w83l785ts_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int w83l785ts_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); +static int w83l785ts_remove(struct i2c_client *client); static u8 w83l785ts_read_value(struct i2c_client *client, u8 reg, u8 defval); static struct w83l785ts_data *w83l785ts_update_device(struct device *dev); @@ -92,12 +93,22 @@ static struct w83l785ts_data *w83l785ts_update_device(struct device *dev); * Driver data (common to all clients) */ +static struct i2c_device_id w83l785ts_id[] = { + { "w83l785ts", w83l785ts }, + { } +}; +MODULE_DEVICE_TABLE(i2c, w83l785ts_id); + static struct i2c_driver w83l785ts_driver = { + .class = I2C_CLASS_HWMON, .driver = { .name = "w83l785ts", }, - .attach_adapter = w83l785ts_attach_adapter, - .detach_client = w83l785ts_detach_client, + .probe = w83l785ts_probe, + .remove = w83l785ts_remove, + .id_table = w83l785ts_id, + .detect = w83l785ts_detect, + .address_data = &addr_data, }; /* @@ -105,7 +116,6 @@ static struct i2c_driver w83l785ts_driver = { */ struct w83l785ts_data { - struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ @@ -135,40 +145,14 @@ static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp, NULL, 1); * Real code */ -static int w83l785ts_attach_adapter(struct i2c_adapter *adapter) -{ - if (!(adapter->class & I2C_CLASS_HWMON)) - return 0; - return i2c_probe(adapter, &addr_data, w83l785ts_detect); -} - -/* - * The following function does more than just detection. If detection - * succeeds, it also registers the new chip. - */ -static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind) +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int w83l785ts_detect(struct i2c_client *new_client, int kind, + struct i2c_board_info *info) { - struct i2c_client *new_client; - struct w83l785ts_data *data; - int err = 0; - + struct i2c_adapter *adapter = new_client->adapter; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - goto exit; - - if (!(data = kzalloc(sizeof(struct w83l785ts_data), GFP_KERNEL))) { - err = -ENOMEM; - goto exit; - } - - /* The common I2C client data is placed right before the - * W83L785TS-specific data. */ - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &w83l785ts_driver; - new_client->flags = 0; + return -ENODEV; /* * Now we do the remaining detection. A negative kind means that @@ -188,8 +172,8 @@ static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind) W83L785TS_REG_TYPE, 0) & 0xFC) != 0x00)) { dev_dbg(&adapter->dev, "W83L785TS-S detection failed at 0x%02x.\n", - address); - goto exit_free; + new_client->addr); + return -ENODEV; } } @@ -214,22 +198,34 @@ static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind) dev_info(&adapter->dev, "Unsupported chip (man_id=0x%04X, " "chip_id=0x%02X).\n", man_id, chip_id); - goto exit_free; + return -ENODEV; } } - /* We can fill in the remaining client fields. */ - strlcpy(new_client->name, "w83l785ts", I2C_NAME_SIZE); + strlcpy(info->type, "w83l785ts", I2C_NAME_SIZE); + + return 0; +} + +static int w83l785ts_probe(struct i2c_client *new_client, + const struct i2c_device_id *id) +{ + struct w83l785ts_data *data; + int err = 0; + + data = kzalloc(sizeof(struct w83l785ts_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(new_client, data); data->valid = 0; mutex_init(&data->update_lock); /* Default values in case the first read fails (unlikely). */ data->temp[1] = data->temp[0] = 0; - /* Tell the I2C layer a new client has arrived. */ - if ((err = i2c_attach_client(new_client))) - goto exit_free; - /* * Initialize the W83L785TS chip * Nothing yet, assume it is already started. @@ -259,25 +255,20 @@ exit_remove: &sensor_dev_attr_temp1_input.dev_attr); device_remove_file(&new_client->dev, &sensor_dev_attr_temp1_max.dev_attr); - i2c_detach_client(new_client); -exit_free: kfree(data); exit: return err; } -static int w83l785ts_detach_client(struct i2c_client *client) +static int w83l785ts_remove(struct i2c_client *client) { struct w83l785ts_data *data = i2c_get_clientdata(client); - int err; hwmon_device_unregister(data->hwmon_dev); device_remove_file(&client->dev, &sensor_dev_attr_temp1_input.dev_attr); device_remove_file(&client->dev, &sensor_dev_attr_temp1_max.dev_attr); - if ((err = i2c_detach_client(client))) - return err; kfree(data); return 0; @@ -286,6 +277,18 @@ static int w83l785ts_detach_client(struct i2c_client *client) static u8 w83l785ts_read_value(struct i2c_client *client, u8 reg, u8 defval) { int value, i; + struct device *dev; + const char *prefix; + + /* We might be called during detection, at which point the client + isn't yet fully initialized, so we can't use dev_dbg on it */ + if (i2c_get_clientdata(client)) { + dev = &client->dev; + prefix = ""; + } else { + dev = &client->adapter->dev; + prefix = "w83l785ts: "; + } /* Frequent read errors have been reported on Asus boards, so we * retry on read errors. If it still fails (unlikely), return the @@ -293,15 +296,15 @@ static u8 w83l785ts_read_value(struct i2c_client *client, u8 reg, u8 defval) for (i = 1; i <= MAX_RETRIES; i++) { value = i2c_smbus_read_byte_data(client, reg); if (value >= 0) { - dev_dbg(&client->dev, "Read 0x%02x from register " - "0x%02x.\n", value, reg); + dev_dbg(dev, "%sRead 0x%02x from register 0x%02x.\n", + prefix, value, reg); return value; } - dev_dbg(&client->dev, "Read failed, will retry in %d.\n", i); + dev_dbg(dev, "%sRead failed, will retry in %d.\n", prefix, i); msleep(i); } - dev_err(&client->dev, "Couldn't read value from register 0x%02x.\n", + dev_err(dev, "%sCouldn't read value from register 0x%02x.\n", prefix, reg); return defval; } diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c index 35812823787b..eb8f72ca02f4 100644 --- a/drivers/i2c/algos/i2c-algo-bit.c +++ b/drivers/i2c/algos/i2c-algo-bit.c @@ -320,7 +320,7 @@ static int try_address(struct i2c_adapter *i2c_adap, unsigned char addr, int retries) { struct i2c_algo_bit_data *adap = i2c_adap->algo_data; - int i, ret = -1; + int i, ret = 0; for (i = 0; i <= retries; i++) { ret = i2c_outb(i2c_adap, addr); @@ -508,7 +508,7 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) addr ^= 1; ret = try_address(i2c_adap, addr, retries); if ((ret != 1) && !nak_ok) - return -EREMOTEIO; + return -ENXIO; } return 0; diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c index e954a20b97a6..d50b329a3c94 100644 --- a/drivers/i2c/algos/i2c-algo-pca.c +++ b/drivers/i2c/algos/i2c-algo-pca.c @@ -182,7 +182,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap, } if (state != 0xf8) { dev_dbg(&i2c_adap->dev, "bus is not idle. status is %#04x\n", state); - return -EIO; + return -EAGAIN; } DEB1("{{{ XFER %d messages\n", num); diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c index 8907b0191677..1e328d19cd6d 100644 --- a/drivers/i2c/algos/i2c-algo-pcf.c +++ b/drivers/i2c/algos/i2c-algo-pcf.c @@ -78,6 +78,36 @@ static void i2c_stop(struct i2c_algo_pcf_data *adap) set_pcf(adap, 1, I2C_PCF_STOP); } +static void handle_lab(struct i2c_algo_pcf_data *adap, const int *status) +{ + DEB2(printk(KERN_INFO + "i2c-algo-pcf.o: lost arbitration (CSR 0x%02x)\n", + *status)); + + /* Cleanup from LAB -- reset and enable ESO. + * This resets the PCF8584; since we've lost the bus, no + * further attempts should be made by callers to clean up + * (no i2c_stop() etc.) + */ + set_pcf(adap, 1, I2C_PCF_PIN); + set_pcf(adap, 1, I2C_PCF_ESO); + + /* We pause for a time period sufficient for any running + * I2C transaction to complete -- the arbitration logic won't + * work properly until the next START is seen. + * It is assumed the bus driver or client has set a proper value. + * + * REVISIT: should probably use msleep instead of mdelay if we + * know we can sleep. + */ + if (adap->lab_mdelay) + mdelay(adap->lab_mdelay); + + DEB2(printk(KERN_INFO + "i2c-algo-pcf.o: reset LAB condition (CSR 0x%02x)\n", + get_pcf(adap, 1))); +} + static int wait_for_bb(struct i2c_algo_pcf_data *adap) { int timeout = DEF_TIMEOUT; @@ -109,23 +139,7 @@ static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status) { *status = get_pcf(adap, 1); } if (*status & I2C_PCF_LAB) { - DEB2(printk(KERN_INFO - "i2c-algo-pcf.o: lost arbitration (CSR 0x%02x)\n", - *status)); - /* Cleanup from LAB-- reset and enable ESO. - * This resets the PCF8584; since we've lost the bus, no - * further attempts should be made by callers to clean up - * (no i2c_stop() etc.) - */ - set_pcf(adap, 1, I2C_PCF_PIN); - set_pcf(adap, 1, I2C_PCF_ESO); - /* TODO: we should pause for a time period sufficient for any - * running I2C transaction to complete-- the arbitration - * logic won't work properly until the next START is seen. - */ - DEB2(printk(KERN_INFO - "i2c-algo-pcf.o: reset LAB condition (CSR 0x%02x)\n", - get_pcf(adap,1))); + handle_lab(adap, status); return(-EINTR); } #endif diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 48438cc5d0ca..6fa027410648 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -4,6 +4,9 @@ menu "I2C Hardware Bus support" +comment "PC SMBus host controller drivers" + depends on PCI + config I2C_ALI1535 tristate "ALI 1535" depends on PCI @@ -73,6 +76,176 @@ config I2C_AMD8111 This driver can also be built as a module. If so, the module will be called i2c-amd8111. +config I2C_I801 + tristate "Intel 82801 (ICH)" + depends on PCI + help + If you say yes to this option, support will be included for the Intel + 801 family of mainboard I2C interfaces. Specifically, the following + versions of the chipset are supported: + 82801AA + 82801AB + 82801BA + 82801CA/CAM + 82801DB + 82801EB/ER (ICH5/ICH5R) + 6300ESB + ICH6 + ICH7 + ESB2 + ICH8 + ICH9 + Tolapai + ICH10 + + This driver can also be built as a module. If so, the module + will be called i2c-i801. + +config I2C_PIIX4 + tristate "Intel PIIX4 and compatible (ATI/Serverworks/Broadcom/SMSC)" + depends on PCI + help + If you say yes to this option, support will be included for the Intel + PIIX4 family of mainboard I2C interfaces. Specifically, the following + versions of the chipset are supported (note that Serverworks is part + of Broadcom): + Intel PIIX4 + Intel 440MX + ATI IXP200 + ATI IXP300 + ATI IXP400 + ATI SB600 + ATI SB700 + ATI SB800 + Serverworks OSB4 + Serverworks CSB5 + Serverworks CSB6 + Serverworks HT-1000 + SMSC Victory66 + + This driver can also be built as a module. If so, the module + will be called i2c-piix4. + +config I2C_NFORCE2 + tristate "Nvidia nForce2, nForce3 and nForce4" + depends on PCI + help + If you say yes to this option, support will be included for the Nvidia + nForce2, nForce3 and nForce4 families of mainboard I2C interfaces. + + This driver can also be built as a module. If so, the module + will be called i2c-nforce2. + +config I2C_NFORCE2_S4985 + tristate "SMBus multiplexing on the Tyan S4985" + depends on I2C_NFORCE2 && EXPERIMENTAL + help + Enabling this option will add specific SMBus support for the Tyan + S4985 motherboard. On this 4-CPU board, the SMBus is multiplexed + over 4 different channels, where the various memory module EEPROMs + live. Saying yes here will give you access to these in addition + to the trunk. + + This driver can also be built as a module. If so, the module + will be called i2c-nforce2-s4985. + +config I2C_SIS5595 + tristate "SiS 5595" + depends on PCI + help + If you say yes to this option, support will be included for the + SiS5595 SMBus (a subset of I2C) interface. + + This driver can also be built as a module. If so, the module + will be called i2c-sis5595. + +config I2C_SIS630 + tristate "SiS 630/730" + depends on PCI + help + If you say yes to this option, support will be included for the + SiS630 and SiS730 SMBus (a subset of I2C) interface. + + This driver can also be built as a module. If so, the module + will be called i2c-sis630. + +config I2C_SIS96X + tristate "SiS 96x" + depends on PCI + help + If you say yes to this option, support will be included for the SiS + 96x SMBus (a subset of I2C) interfaces. Specifically, the following + chipsets are supported: + 645/961 + 645DX/961 + 645DX/962 + 648/961 + 650/961 + 735 + 745 + + This driver can also be built as a module. If so, the module + will be called i2c-sis96x. + +config I2C_VIA + tristate "VIA VT82C586B" + depends on PCI && EXPERIMENTAL + select I2C_ALGOBIT + help + If you say yes to this option, support will be included for the VIA + 82C586B I2C interface + + This driver can also be built as a module. If so, the module + will be called i2c-via. + +config I2C_VIAPRO + tristate "VIA VT82C596/82C686/82xx and CX700" + depends on PCI + help + If you say yes to this option, support will be included for the VIA + VT82C596 and later SMBus interface. Specifically, the following + chipsets are supported: + VT82C596A/B + VT82C686A/B + VT8231 + VT8233/A + VT8235 + VT8237R/A/S + VT8251 + CX700 + + This driver can also be built as a module. If so, the module + will be called i2c-viapro. + +comment "Mac SMBus host controller drivers" + depends on PPC_CHRP || PPC_PMAC + +config I2C_HYDRA + tristate "CHRP Apple Hydra Mac I/O I2C interface" + depends on PCI && PPC_CHRP && EXPERIMENTAL + select I2C_ALGOBIT + help + This supports the use of the I2C interface in the Apple Hydra Mac + I/O chip on some CHRP machines (e.g. the LongTrail). Say Y if you + have such a machine. + + This support is also available as a module. If so, the module + will be called i2c-hydra. + +config I2C_POWERMAC + tristate "Powermac I2C interface" + depends on PPC_PMAC + default y + help + This exposes the various PowerMac i2c interfaces to the linux i2c + layer and to userland. It is used by various drivers on the PowerMac + platform, and should generally be enabled. + + This support is also available as a module. If so, the module + will be called i2c-powermac. + +comment "Embebbed system I2C host controller drivers" + config I2C_AT91 tristate "Atmel AT91 I2C Two-Wire interface (TWI)" depends on ARCH_AT91 && EXPERIMENTAL && BROKEN @@ -101,10 +274,9 @@ config I2C_AU1550 config I2C_BLACKFIN_TWI tristate "Blackfin TWI I2C support" depends on BLACKFIN + depends on !BF561 && !BF531 && !BF532 && !BF533 help - This is the TWI I2C device driver for Blackfin BF522, BF525, - BF527, BF534, BF536, BF537 and BF54x. For other Blackfin processors, - please don't use this driver. + This is the I2C bus driver for Blackfin on-chip TWI interface. This driver can also be built as a module. If so, the module will be called i2c-bfin-twi. @@ -117,6 +289,16 @@ config I2C_BLACKFIN_TWI_CLK_KHZ help The unit of the TWI clock is kHz. +config I2C_CPM + tristate "Freescale CPM1 or CPM2 (MPC8xx/826x)" + depends on (CPM1 || CPM2) && OF_I2C + help + This supports the use of the I2C interface on Freescale + processors with CPM1 or CPM2. + + This driver can also be built as a module. If so, the module + will be called i2c-cpm. + config I2C_DAVINCI tristate "DaVinci I2C driver" depends on ARCH_DAVINCI @@ -130,17 +312,6 @@ config I2C_DAVINCI devices such as DaVinci NIC. For details please see http://www.ti.com/davinci -config I2C_ELEKTOR - tristate "Elektor ISA card" - depends on ISA && BROKEN_ON_SMP - select I2C_ALGOPCF - help - This supports the PCF8584 ISA bus I2C adapter. Say Y if you own - such an adapter. - - This support is also available as a module. If so, the module - will be called i2c-elektor. - config I2C_GPIO tristate "GPIO-based bitbanging I2C" depends on GENERIC_GPIO @@ -149,104 +320,6 @@ config I2C_GPIO This is a very simple bitbanging I2C driver utilizing the arch-neutral GPIO API to control the SCL and SDA lines. -config I2C_HYDRA - tristate "CHRP Apple Hydra Mac I/O I2C interface" - depends on PCI && PPC_CHRP && EXPERIMENTAL - select I2C_ALGOBIT - help - This supports the use of the I2C interface in the Apple Hydra Mac - I/O chip on some CHRP machines (e.g. the LongTrail). Say Y if you - have such a machine. - - This support is also available as a module. If so, the module - will be called i2c-hydra. - -config I2C_I801 - tristate "Intel 82801 (ICH)" - depends on PCI - help - If you say yes to this option, support will be included for the Intel - 801 family of mainboard I2C interfaces. Specifically, the following - versions of the chipset are supported: - 82801AA - 82801AB - 82801BA - 82801CA/CAM - 82801DB - 82801EB/ER (ICH5/ICH5R) - 6300ESB - ICH6 - ICH7 - ESB2 - ICH8 - ICH9 - Tolapai - ICH10 - - This driver can also be built as a module. If so, the module - will be called i2c-i801. - -config I2C_I810 - tristate "Intel 810/815 (DEPRECATED)" - default n - depends on PCI - select I2C_ALGOBIT - help - If you say yes to this option, support will be included for the Intel - 810/815 family of mainboard I2C interfaces. Specifically, the - following versions of the chipset are supported: - i810AA - i810AB - i810E - i815 - i845G - - This driver is deprecated in favor of the i810fb and intelfb drivers. - - This driver can also be built as a module. If so, the module - will be called i2c-i810. - -config I2C_PXA - tristate "Intel PXA2XX I2C adapter (EXPERIMENTAL)" - depends on EXPERIMENTAL && ARCH_PXA - help - If you have devices in the PXA I2C bus, say yes to this option. - This driver can also be built as a module. If so, the module - will be called i2c-pxa. - -config I2C_PXA_SLAVE - bool "Intel PXA2XX I2C Slave comms support" - depends on I2C_PXA - help - Support I2C slave mode communications on the PXA I2C bus. This - is necessary for systems where the PXA may be a target on the - I2C bus. - -config I2C_PIIX4 - tristate "Intel PIIX4 and compatible (ATI/Serverworks/Broadcom/SMSC)" - depends on PCI - help - If you say yes to this option, support will be included for the Intel - PIIX4 family of mainboard I2C interfaces. Specifically, the following - versions of the chipset are supported (note that Serverworks is part - of Broadcom): - Intel PIIX4 - Intel 440MX - ATI IXP200 - ATI IXP300 - ATI IXP400 - ATI SB600 - ATI SB700 - ATI SB800 - Serverworks OSB4 - Serverworks CSB5 - Serverworks CSB6 - Serverworks HT-1000 - SMSC Victory66 - - This driver can also be built as a module. If so, the module - will be called i2c-piix4. - config I2C_IBM_IIC tristate "IBM PPC 4xx on-chip I2C interface" depends on 4xx @@ -281,18 +354,6 @@ config I2C_IXP2000 This driver is deprecated and will be dropped soon. Use i2c-gpio instead. -config I2C_POWERMAC - tristate "Powermac I2C interface" - depends on PPC_PMAC - default y - help - This exposes the various PowerMac i2c interfaces to the linux i2c - layer and to userland. It is used by various drivers on the PowerMac - platform, and should generally be enabled. - - This support is also available as a module. If so, the module - will be called i2c-powermac. - config I2C_MPC tristate "MPC107/824x/85xx/52xx/86xx" depends on PPC32 @@ -305,16 +366,6 @@ config I2C_MPC This driver can also be built as a module. If so, the module will be called i2c-mpc. -config I2C_NFORCE2 - tristate "Nvidia nForce2, nForce3 and nForce4" - depends on PCI - help - If you say yes to this option, support will be included for the Nvidia - nForce2, nForce3 and nForce4 families of mainboard I2C interfaces. - - This driver can also be built as a module. If so, the module - will be called i2c-nforce2. - config I2C_OCORES tristate "OpenCores I2C Controller" depends on EXPERIMENTAL @@ -336,6 +387,73 @@ config I2C_OMAP Like OMAP1510/1610/1710/5912 and OMAP242x. For details see http://www.ti.com/omap. +config I2C_PXA + tristate "Intel PXA2XX I2C adapter (EXPERIMENTAL)" + depends on EXPERIMENTAL && ARCH_PXA + help + If you have devices in the PXA I2C bus, say yes to this option. + This driver can also be built as a module. If so, the module + will be called i2c-pxa. + +config I2C_PXA_SLAVE + bool "Intel PXA2XX I2C Slave comms support" + depends on I2C_PXA + help + Support I2C slave mode communications on the PXA I2C bus. This + is necessary for systems where the PXA may be a target on the + I2C bus. + +config I2C_S3C2410 + tristate "S3C2410 I2C Driver" + depends on ARCH_S3C2410 + help + Say Y here to include support for I2C controller in the + Samsung S3C2410 based System-on-Chip devices. + +config I2C_SH7760 + tristate "Renesas SH7760 I2C Controller" + depends on CPU_SUBTYPE_SH7760 + help + This driver supports the 2 I2C interfaces on the Renesas SH7760. + + This driver can also be built as a module. If so, the module + will be called i2c-sh7760. + +config I2C_SH_MOBILE + tristate "SuperH Mobile I2C Controller" + depends on SUPERH + help + If you say yes to this option, support will be included for the + built-in I2C interface on the Renesas SH-Mobile processor. + + This driver can also be built as a module. If so, the module + will be called i2c-sh_mobile. + +config I2C_SIMTEC + tristate "Simtec Generic I2C interface" + select I2C_ALGOBIT + help + If you say yes to this option, support will be included for + the Simtec Generic I2C interface. This driver is for the + simple I2C bus used on newer Simtec products for general + I2C, such as DDC on the Simtec BBD2016A. + + This driver can also be built as a module. If so, the module + will be called i2c-simtec. + +config I2C_VERSATILE + tristate "ARM Versatile/Realview I2C bus support" + depends on ARCH_VERSATILE || ARCH_REALVIEW + select I2C_ALGOBIT + help + Say yes if you want to support the I2C serial bus on ARMs Versatile + range of platforms. + + This driver can also be built as a module. If so, the module + will be called i2c-versatile. + +comment "External I2C/SMBus adapter drivers" + config I2C_PARPORT tristate "Parallel port adapter" depends on PARPORT @@ -383,150 +501,6 @@ config I2C_PARPORT_LIGHT This support is also available as a module. If so, the module will be called i2c-parport-light. -config I2C_PASEMI - tristate "PA Semi SMBus interface" - depends on PPC_PASEMI && PCI - help - Supports the PA Semi PWRficient on-chip SMBus interfaces. - -config I2C_PROSAVAGE - tristate "S3/VIA (Pro)Savage (DEPRECATED)" - default n - depends on PCI - select I2C_ALGOBIT - help - If you say yes to this option, support will be included for the - I2C bus and DDC bus of the S3VIA embedded Savage4 and ProSavage8 - graphics processors. - chipsets supported: - S3/VIA KM266/VT8375 aka ProSavage8 - S3/VIA KM133/VT8365 aka Savage4 - - This driver is deprecated in favor of the savagefb driver. - - This support is also available as a module. If so, the module - will be called i2c-prosavage. - -config I2C_S3C2410 - tristate "S3C2410 I2C Driver" - depends on ARCH_S3C2410 - help - Say Y here to include support for I2C controller in the - Samsung S3C2410 based System-on-Chip devices. - -config I2C_SAVAGE4 - tristate "S3 Savage 4 (DEPRECATED)" - default n - depends on PCI - select I2C_ALGOBIT - help - If you say yes to this option, support will be included for the - S3 Savage 4 I2C interface. - - This driver is deprecated in favor of the savagefb driver. - - This driver can also be built as a module. If so, the module - will be called i2c-savage4. - -config I2C_SIBYTE - tristate "SiByte SMBus interface" - depends on SIBYTE_SB1xxx_SOC - help - Supports the SiByte SOC on-chip I2C interfaces (2 channels). - -config I2C_SIMTEC - tristate "Simtec Generic I2C interface" - select I2C_ALGOBIT - help - If you say yes to this option, support will be included for - the Simtec Generic I2C interface. This driver is for the - simple I2C bus used on newer Simtec products for general - I2C, such as DDC on the Simtec BBD2016A. - - This driver can also be built as a module. If so, the module - will be called i2c-simtec. - -config SCx200_I2C - tristate "NatSemi SCx200 I2C using GPIO pins (DEPRECATED)" - depends on SCx200_GPIO - select I2C_ALGOBIT - help - Enable the use of two GPIO pins of a SCx200 processor as an I2C bus. - - If you don't know what to do here, say N. - - This support is also available as a module. If so, the module - will be called scx200_i2c. - - This driver is deprecated and will be dropped soon. Use i2c-gpio - (or scx200_acb) instead. - -config SCx200_I2C_SCL - int "GPIO pin used for SCL" - depends on SCx200_I2C - default "12" - help - Enter the GPIO pin number used for the SCL signal. This value can - also be specified with a module parameter. - -config SCx200_I2C_SDA - int "GPIO pin used for SDA" - depends on SCx200_I2C - default "13" - help - Enter the GPIO pin number used for the SSA signal. This value can - also be specified with a module parameter. - -config SCx200_ACB - tristate "Geode ACCESS.bus support" - depends on X86_32 && PCI - help - Enable the use of the ACCESS.bus controllers on the Geode SCx200 and - SC1100 processors and the CS5535 and CS5536 Geode companion devices. - - If you don't know what to do here, say N. - - This support is also available as a module. If so, the module - will be called scx200_acb. - -config I2C_SIS5595 - tristate "SiS 5595" - depends on PCI - help - If you say yes to this option, support will be included for the - SiS5595 SMBus (a subset of I2C) interface. - - This driver can also be built as a module. If so, the module - will be called i2c-sis5595. - -config I2C_SIS630 - tristate "SiS 630/730" - depends on PCI - help - If you say yes to this option, support will be included for the - SiS630 and SiS730 SMBus (a subset of I2C) interface. - - This driver can also be built as a module. If so, the module - will be called i2c-sis630. - -config I2C_SIS96X - tristate "SiS 96x" - depends on PCI - help - If you say yes to this option, support will be included for the SiS - 96x SMBus (a subset of I2C) interfaces. Specifically, the following - chipsets are supported: - 645/961 - 645DX/961 - 645DX/962 - 648/961 - 650/961 - 735 - 745 - - This driver can also be built as a module. If so, the module - will be called i2c-sis96x. - config I2C_TAOS_EVM tristate "TAOS evaluation module" depends on EXPERIMENTAL @@ -543,21 +517,8 @@ config I2C_TAOS_EVM This support is also available as a module. If so, the module will be called i2c-taos-evm. -config I2C_STUB - tristate "I2C/SMBus Test Stub" - depends on EXPERIMENTAL && m - default 'n' - help - This module may be useful to developers of SMBus client drivers, - especially for certain kinds of sensor chips. - - If you do build this module, be sure to read the notes and warnings - in <file:Documentation/i2c/i2c-stub>. - - If you don't know what to do here, definitely say N. - config I2C_TINY_USB - tristate "I2C-Tiny-USB" + tristate "Tiny-USB adapter" depends on USB help If you say yes to this option, support will be included for the @@ -567,16 +528,21 @@ config I2C_TINY_USB This driver can also be built as a module. If so, the module will be called i2c-tiny-usb. -config I2C_VERSATILE - tristate "ARM Versatile/Realview I2C bus support" - depends on ARCH_VERSATILE || ARCH_REALVIEW +comment "Graphics adapter I2C/DDC channel drivers" + depends on PCI + +config I2C_VOODOO3 + tristate "Voodoo 3" + depends on PCI select I2C_ALGOBIT help - Say yes if you want to support the I2C serial bus on ARMs Versatile - range of platforms. + If you say yes to this option, support will be included for the + Voodoo 3 I2C interface. This driver can also be built as a module. If so, the module - will be called i2c-versatile. + will be called i2c-voodoo3. + +comment "Other I2C/SMBus bus drivers" config I2C_ACORN tristate "Acorn IOC/IOMD I2C bus support" @@ -588,46 +554,42 @@ config I2C_ACORN If you don't know, say Y. -config I2C_VIA - tristate "VIA 82C586B" - depends on PCI && EXPERIMENTAL - select I2C_ALGOBIT +config I2C_ELEKTOR + tristate "Elektor ISA card" + depends on ISA && BROKEN_ON_SMP + select I2C_ALGOPCF help - If you say yes to this option, support will be included for the VIA - 82C586B I2C interface + This supports the PCF8584 ISA bus I2C adapter. Say Y if you own + such an adapter. - This driver can also be built as a module. If so, the module - will be called i2c-via. + This support is also available as a module. If so, the module + will be called i2c-elektor. -config I2C_VIAPRO - tristate "VIA VT82C596/82C686/82xx and CX700" +config I2C_ISCH + tristate "Intel SCH SMBus 1.0" depends on PCI help - If you say yes to this option, support will be included for the VIA - VT82C596 and later SMBus interface. Specifically, the following - chipsets are supported: - VT82C596A/B - VT82C686A/B - VT8231 - VT8233/A - VT8235 - VT8237R/A/S - VT8251 - CX700 + Say Y here if you want to use SMBus controller on the Intel SCH + based systems. - This driver can also be built as a module. If so, the module - will be called i2c-viapro. + This driver can also be built as a module. If so, the module + will be called i2c-isch. -config I2C_VOODOO3 - tristate "Voodoo 3" - depends on PCI - select I2C_ALGOBIT +config I2C_MV64XXX + tristate "Marvell mv64xxx I2C Controller" + depends on (MV64X60 || PLAT_ORION) && EXPERIMENTAL help If you say yes to this option, support will be included for the - Voodoo 3 I2C interface. + built-in I2C interface on the Marvell 64xxx line of host bridges. This driver can also be built as a module. If so, the module - will be called i2c-voodoo3. + will be called i2c-mv64xxx. + +config I2C_PASEMI + tristate "PA Semi SMBus interface" + depends on PPC_PASEMI && PCI + help + Supports the PA Semi PWRficient on-chip SMBus interfaces. config I2C_PCA_ISA tristate "PCA9564 on an ISA bus" @@ -657,16 +619,6 @@ config I2C_PCA_PLATFORM This driver can also be built as a module. If so, the module will be called i2c-pca-platform. -config I2C_MV64XXX - tristate "Marvell mv64xxx I2C Controller" - depends on (MV64X60 || PLAT_ORION) && EXPERIMENTAL - help - If you say yes to this option, support will be included for the - built-in I2C interface on the Marvell 64xxx line of host bridges. - - This driver can also be built as a module. If so, the module - will be called i2c-mv64xxx. - config I2C_PNX tristate "I2C bus support for Philips PNX targets" depends on ARCH_PNX4008 @@ -686,23 +638,66 @@ config I2C_PMCMSP This driver can also be built as module. If so, the module will be called i2c-pmcmsp. -config I2C_SH7760 - tristate "Renesas SH7760 I2C Controller" - depends on CPU_SUBTYPE_SH7760 +config I2C_SIBYTE + tristate "SiByte SMBus interface" + depends on SIBYTE_SB1xxx_SOC help - This driver supports the 2 I2C interfaces on the Renesas SH7760. + Supports the SiByte SOC on-chip I2C interfaces (2 channels). - This driver can also be built as a module. If so, the module - will be called i2c-sh7760. +config I2C_STUB + tristate "I2C/SMBus Test Stub" + depends on EXPERIMENTAL && m + default 'n' + help + This module may be useful to developers of SMBus client drivers, + especially for certain kinds of sensor chips. -config I2C_SH_MOBILE - tristate "SuperH Mobile I2C Controller" - depends on SUPERH + If you do build this module, be sure to read the notes and warnings + in <file:Documentation/i2c/i2c-stub>. + + If you don't know what to do here, definitely say N. + +config SCx200_I2C + tristate "NatSemi SCx200 I2C using GPIO pins (DEPRECATED)" + depends on SCx200_GPIO + select I2C_ALGOBIT help - If you say yes to this option, support will be included for the - built-in I2C interface on the Renesas SH-Mobile processor. + Enable the use of two GPIO pins of a SCx200 processor as an I2C bus. - This driver can also be built as a module. If so, the module - will be called i2c-sh_mobile. + If you don't know what to do here, say N. + + This support is also available as a module. If so, the module + will be called scx200_i2c. + + This driver is deprecated and will be dropped soon. Use i2c-gpio + (or scx200_acb) instead. + +config SCx200_I2C_SCL + int "GPIO pin used for SCL" + depends on SCx200_I2C + default "12" + help + Enter the GPIO pin number used for the SCL signal. This value can + also be specified with a module parameter. + +config SCx200_I2C_SDA + int "GPIO pin used for SDA" + depends on SCx200_I2C + default "13" + help + Enter the GPIO pin number used for the SSA signal. This value can + also be specified with a module parameter. + +config SCx200_ACB + tristate "Geode ACCESS.bus support" + depends on X86_32 && PCI + help + Enable the use of the ACCESS.bus controllers on the Geode SCx200 and + SC1100 processors and the CS5535 and CS5536 Geode companion devices. + + If you don't know what to do here, say N. + + This support is also available as a module. If so, the module + will be called scx200_acb. endmenu diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index e8c882a5ea66..cfc6dd03ad39 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -2,57 +2,68 @@ # Makefile for the i2c bus drivers. # +# PC SMBus host controller drivers obj-$(CONFIG_I2C_ALI1535) += i2c-ali1535.o obj-$(CONFIG_I2C_ALI1563) += i2c-ali1563.o obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o obj-$(CONFIG_I2C_AMD756_S4882) += i2c-amd756-s4882.o obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o +obj-$(CONFIG_I2C_I801) += i2c-i801.o +obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o +obj-$(CONFIG_I2C_NFORCE2_S4985) += i2c-nforce2-s4985.o +obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o +obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o +obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o +obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o +obj-$(CONFIG_I2C_VIA) += i2c-via.o +obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o + +# Mac SMBus host controller drivers +obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o +obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o + +# Embebbed system I2C/SMBus host controller drivers obj-$(CONFIG_I2C_AT91) += i2c-at91.o obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o +obj-$(CONFIG_I2C_CPM) += i2c-cpm.o obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o -obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o -obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o -obj-$(CONFIG_I2C_I801) += i2c-i801.o -obj-$(CONFIG_I2C_I810) += i2c-i810.o obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o -obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o obj-$(CONFIG_I2C_MPC) += i2c-mpc.o -obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o -obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o obj-$(CONFIG_I2C_OCORES) += i2c-ocores.o obj-$(CONFIG_I2C_OMAP) += i2c-omap.o +obj-$(CONFIG_I2C_PXA) += i2c-pxa.o +obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o +obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o +obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o +obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o +obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o + +# External I2C/SMBus adapter drivers obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o +obj-$(CONFIG_I2C_TAOS_EVM) += i2c-taos-evm.o +obj-$(CONFIG_I2C_TINY_USB) += i2c-tiny-usb.o + +# Graphics adapter I2C/DDC channel drivers +obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o + +# Other I2C/SMBus bus drivers +obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o +obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o +obj-$(CONFIG_I2C_ISCH) += i2c-isch.o +obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o -obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o obj-$(CONFIG_I2C_PMCMSP) += i2c-pmcmsp.o obj-$(CONFIG_I2C_PNX) += i2c-pnx.o -obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o -obj-$(CONFIG_I2C_PXA) += i2c-pxa.o -obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o -obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o -obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o -obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o -obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o -obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o -obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o -obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o obj-$(CONFIG_I2C_STUB) += i2c-stub.o -obj-$(CONFIG_I2C_TAOS_EVM) += i2c-taos-evm.o -obj-$(CONFIG_I2C_TINY_USB) += i2c-tiny-usb.o -obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o -obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o -obj-$(CONFIG_I2C_VIA) += i2c-via.o -obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o -obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o obj-$(CONFIG_SCx200_ACB) += scx200_acb.o obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c index f14372ac2fc5..9cead9b9458e 100644 --- a/drivers/i2c/busses/i2c-ali1535.c +++ b/drivers/i2c/busses/i2c-ali1535.c @@ -1,6 +1,4 @@ /* - i2c-ali1535.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring Copyright (c) 2000 Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, Mark D. Studebaker <mdsxyz123@yahoo.com>, @@ -61,6 +59,7 @@ #include <linux/ioport.h> #include <linux/i2c.h> #include <linux/init.h> +#include <linux/acpi.h> #include <asm/io.h> @@ -159,6 +158,11 @@ static int ali1535_setup(struct pci_dev *dev) goto exit; } + retval = acpi_check_region(ali1535_smba, ALI1535_SMB_IOSIZE, + ali1535_driver.name); + if (retval) + goto exit; + if (!request_region(ali1535_smba, ALI1535_SMB_IOSIZE, ali1535_driver.name)) { dev_err(&dev->dev, "ALI1535_smb region 0x%x already in use!\n", @@ -259,7 +263,7 @@ static int ali1535_transaction(struct i2c_adapter *adap) dev_err(&adap->dev, "SMBus reset failed! (0x%02x) - controller or " "device on bus is probably hung\n", temp); - return -1; + return -EBUSY; } } else { /* check and clear done bit */ @@ -281,12 +285,12 @@ static int ali1535_transaction(struct i2c_adapter *adap) /* If the SMBus is still busy, we give up */ if (timeout >= MAX_TIMEOUT) { - result = -1; + result = -ETIMEDOUT; dev_err(&adap->dev, "SMBus Timeout!\n"); } if (temp & ALI1535_STS_FAIL) { - result = -1; + result = -EIO; dev_dbg(&adap->dev, "Error: Failed bus transaction\n"); } @@ -295,7 +299,7 @@ static int ali1535_transaction(struct i2c_adapter *adap) * do a printk. This means that bus collisions go unreported. */ if (temp & ALI1535_STS_BUSERR) { - result = -1; + result = -ENXIO; dev_dbg(&adap->dev, "Error: no response or bus collision ADD=%02x\n", inb_p(SMBHSTADD)); @@ -303,13 +307,13 @@ static int ali1535_transaction(struct i2c_adapter *adap) /* haven't ever seen this */ if (temp & ALI1535_STS_DEV) { - result = -1; + result = -EIO; dev_err(&adap->dev, "Error: device error\n"); } /* check to see if the "command complete" indication is set */ if (!(temp & ALI1535_STS_DONE)) { - result = -1; + result = -ETIMEDOUT; dev_err(&adap->dev, "Error: command never completed\n"); } @@ -332,7 +336,7 @@ static int ali1535_transaction(struct i2c_adapter *adap) return result; } -/* Return -1 on error. */ +/* Return negative errno on error. */ static s32 ali1535_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data) @@ -357,10 +361,6 @@ static s32 ali1535_access(struct i2c_adapter *adap, u16 addr, outb_p(0xFF, SMBHSTSTS); switch (size) { - case I2C_SMBUS_PROC_CALL: - dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n"); - result = -1; - goto EXIT; case I2C_SMBUS_QUICK: outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD); @@ -418,13 +418,15 @@ static s32 ali1535_access(struct i2c_adapter *adap, u16 addr, outb_p(data->block[i], SMBBLKDAT); } break; + default: + dev_warn(&adap->dev, "Unsupported transaction %d\n", size); + result = -EOPNOTSUPP; + goto EXIT; } - if (ali1535_transaction(adap)) { - /* Error in transaction */ - result = -1; + result = ali1535_transaction(adap); + if (result) goto EXIT; - } if ((read_write == I2C_SMBUS_WRITE) || (size == ALI1535_QUICK)) { result = 0; @@ -475,7 +477,7 @@ static const struct i2c_algorithm smbus_algorithm = { static struct i2c_adapter ali1535_adapter = { .owner = THIS_MODULE, .id = I2C_HW_SMBUS_ALI1535, - .class = I2C_CLASS_HWMON, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, .algo = &smbus_algorithm, }; diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c index 6b68074e518a..fc3e5b026423 100644 --- a/drivers/i2c/busses/i2c-ali1563.c +++ b/drivers/i2c/busses/i2c-ali1563.c @@ -21,6 +21,7 @@ #include <linux/i2c.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/acpi.h> #define ALI1563_MAX_TIMEOUT 500 #define ALI1563_SMBBA 0x80 @@ -67,6 +68,7 @@ static int ali1563_transaction(struct i2c_adapter * a, int size) { u32 data; int timeout; + int status = -EIO; dev_dbg(&a->dev, "Transaction (pre): STS=%02x, CNTL1=%02x, " "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", @@ -103,13 +105,15 @@ static int ali1563_transaction(struct i2c_adapter * a, int size) /* Issue 'kill' to host controller */ outb_p(HST_CNTL2_KILL,SMB_HST_CNTL2); data = inb_p(SMB_HST_STS); + status = -ETIMEDOUT; } /* device error - no response, ignore the autodetection case */ - if ((data & HST_STS_DEVERR) && (size != HST_CNTL2_QUICK)) { - dev_err(&a->dev, "Device error!\n"); + if (data & HST_STS_DEVERR) { + if (size != HST_CNTL2_QUICK) + dev_err(&a->dev, "Device error!\n"); + status = -ENXIO; } - /* bus collision */ if (data & HST_STS_BUSERR) { dev_err(&a->dev, "Bus collision!\n"); @@ -122,13 +126,14 @@ static int ali1563_transaction(struct i2c_adapter * a, int size) outb_p(0x0,SMB_HST_CNTL2); } - return -1; + return status; } static int ali1563_block_start(struct i2c_adapter * a) { u32 data; int timeout; + int status = -EIO; dev_dbg(&a->dev, "Block (pre): STS=%02x, CNTL1=%02x, " "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", @@ -164,13 +169,20 @@ static int ali1563_block_start(struct i2c_adapter * a) if (timeout && !(data & HST_STS_BAD)) return 0; + + if (timeout == 0) + status = -ETIMEDOUT; + + if (data & HST_STS_DEVERR) + status = -ENXIO; + dev_err(&a->dev, "SMBus Error: %s%s%s%s%s\n", - timeout ? "Timeout " : "", + timeout ? "" : "Timeout ", data & HST_STS_FAIL ? "Transaction Failed " : "", data & HST_STS_BUSERR ? "No response or Bus Collision " : "", data & HST_STS_DEVERR ? "Device Error " : "", !(data & HST_STS_DONE) ? "Transaction Never Finished " : ""); - return -1; + return status; } static int ali1563_block(struct i2c_adapter * a, union i2c_smbus_data * data, u8 rw) @@ -235,10 +247,6 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr, /* Map the size to what the chip understands */ switch (size) { - case I2C_SMBUS_PROC_CALL: - dev_err(&a->dev, "I2C_SMBUS_PROC_CALL not supported!\n"); - error = -EINVAL; - break; case I2C_SMBUS_QUICK: size = HST_CNTL2_QUICK; break; @@ -254,6 +262,10 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr, case I2C_SMBUS_BLOCK_DATA: size = HST_CNTL2_BLOCK; break; + default: + dev_warn(&a->dev, "Unsupported transaction %d\n", size); + error = -EOPNOTSUPP; + goto Done; } outb_p(((addr & 0x7f) << 1) | (rw & 0x01), SMB_HST_ADD); @@ -345,6 +357,10 @@ static int __devinit ali1563_setup(struct pci_dev * dev) } } + if (acpi_check_region(ali1563_smba, ALI1563_SMB_IOSIZE, + ali1563_pci_driver.name)) + goto Err; + if (!request_region(ali1563_smba, ALI1563_SMB_IOSIZE, ali1563_pci_driver.name)) { dev_err(&dev->dev, "Could not allocate I/O space at 0x%04x\n", @@ -371,7 +387,7 @@ static const struct i2c_algorithm ali1563_algorithm = { static struct i2c_adapter ali1563_adapter = { .owner = THIS_MODULE, .id = I2C_HW_SMBUS_ALI1563, - .class = I2C_CLASS_HWMON, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, .algo = &ali1563_algorithm, }; diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c index 93bf87d70961..234fdde7d40e 100644 --- a/drivers/i2c/busses/i2c-ali15x3.c +++ b/drivers/i2c/busses/i2c-ali15x3.c @@ -1,6 +1,4 @@ /* - ali15x3.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring Copyright (c) 1999 Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com> and Mark D. Studebaker <mdsxyz123@yahoo.com> @@ -68,6 +66,7 @@ #include <linux/delay.h> #include <linux/i2c.h> #include <linux/init.h> +#include <linux/acpi.h> #include <asm/io.h> /* ALI15X3 SMBus address offsets */ @@ -166,6 +165,10 @@ static int ali15x3_setup(struct pci_dev *ALI15X3_dev) if(force_addr) ali15x3_smba = force_addr & ~(ALI15X3_SMB_IOSIZE - 1); + if (acpi_check_region(ali15x3_smba, ALI15X3_SMB_IOSIZE, + ali15x3_driver.name)) + return -EBUSY; + if (!request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE, ali15x3_driver.name)) { dev_err(&ALI15X3_dev->dev, @@ -282,7 +285,7 @@ static int ali15x3_transaction(struct i2c_adapter *adap) dev_err(&adap->dev, "SMBus reset failed! (0x%02x) - " "controller or device on bus is probably hung\n", temp); - return -1; + return -EBUSY; } } else { /* check and clear done bit */ @@ -304,12 +307,12 @@ static int ali15x3_transaction(struct i2c_adapter *adap) /* If the SMBus is still busy, we give up */ if (timeout >= MAX_TIMEOUT) { - result = -1; + result = -ETIMEDOUT; dev_err(&adap->dev, "SMBus Timeout!\n"); } if (temp & ALI15X3_STS_TERM) { - result = -1; + result = -EIO; dev_dbg(&adap->dev, "Error: Failed bus transaction\n"); } @@ -320,7 +323,7 @@ static int ali15x3_transaction(struct i2c_adapter *adap) This means that bus collisions go unreported. */ if (temp & ALI15X3_STS_COLL) { - result = -1; + result = -ENXIO; dev_dbg(&adap->dev, "Error: no response or bus collision ADD=%02x\n", inb_p(SMBHSTADD)); @@ -328,7 +331,7 @@ static int ali15x3_transaction(struct i2c_adapter *adap) /* haven't ever seen this */ if (temp & ALI15X3_STS_DEV) { - result = -1; + result = -EIO; dev_err(&adap->dev, "Error: device error\n"); } dev_dbg(&adap->dev, "Transaction (post): STS=%02x, CNT=%02x, CMD=%02x, " @@ -338,7 +341,7 @@ static int ali15x3_transaction(struct i2c_adapter *adap) return result; } -/* Return -1 on error. */ +/* Return negative errno on error. */ static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data * data) @@ -362,9 +365,6 @@ static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr, } switch (size) { - case I2C_SMBUS_PROC_CALL: - dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n"); - return -1; case I2C_SMBUS_QUICK: outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD); @@ -417,12 +417,16 @@ static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr, } size = ALI15X3_BLOCK_DATA; break; + default: + dev_warn(&adap->dev, "Unsupported transaction %d\n", size); + return -EOPNOTSUPP; } outb_p(size, SMBHSTCNT); /* output command */ - if (ali15x3_transaction(adap)) /* Error in transaction */ - return -1; + temp = ali15x3_transaction(adap); + if (temp) + return temp; if ((read_write == I2C_SMBUS_WRITE) || (size == ALI15X3_QUICK)) return 0; @@ -470,7 +474,7 @@ static const struct i2c_algorithm smbus_algorithm = { static struct i2c_adapter ali15x3_adapter = { .owner = THIS_MODULE, .id = I2C_HW_SMBUS_ALI15X3, - .class = I2C_CLASS_HWMON, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, .algo = &smbus_algorithm, }; diff --git a/drivers/i2c/busses/i2c-amd756-s4882.c b/drivers/i2c/busses/i2c-amd756-s4882.c index c38a0a112208..2f150e33c74c 100644 --- a/drivers/i2c/busses/i2c-amd756-s4882.c +++ b/drivers/i2c/busses/i2c-amd756-s4882.c @@ -58,7 +58,7 @@ static s32 amd756_access_virt0(struct i2c_adapter * adap, u16 addr, /* We exclude the multiplexed addresses */ if (addr == 0x4c || (addr & 0xfc) == 0x50 || (addr & 0xfc) == 0x30 || addr == 0x18) - return -1; + return -ENXIO; mutex_lock(&amd756_lock); @@ -86,7 +86,7 @@ static inline s32 amd756_access_channel(struct i2c_adapter * adap, u16 addr, /* We exclude the non-multiplexed addresses */ if (addr != 0x4c && (addr & 0xfc) != 0x50 && (addr & 0xfc) != 0x30) - return -1; + return -ENXIO; mutex_lock(&amd756_lock); diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c index 43508d61eb7c..1ea39254dac6 100644 --- a/drivers/i2c/busses/i2c-amd756.c +++ b/drivers/i2c/busses/i2c-amd756.c @@ -1,7 +1,4 @@ /* - amd756.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 1999-2002 Merlin Hughes <merlin@merlin.org> Shamelessly ripped from i2c-piix4.c: @@ -45,6 +42,7 @@ #include <linux/ioport.h> #include <linux/i2c.h> #include <linux/init.h> +#include <linux/acpi.h> #include <asm/io.h> /* AMD756 SMBus address offsets */ @@ -151,17 +149,17 @@ static int amd756_transaction(struct i2c_adapter *adap) } if (temp & GS_PRERR_STS) { - result = -1; + result = -ENXIO; dev_dbg(&adap->dev, "SMBus Protocol error (no response)!\n"); } if (temp & GS_COL_STS) { - result = -1; + result = -EIO; dev_warn(&adap->dev, "SMBus collision!\n"); } if (temp & GS_TO_STS) { - result = -1; + result = -ETIMEDOUT; dev_dbg(&adap->dev, "SMBus protocol timeout!\n"); } @@ -189,22 +187,18 @@ static int amd756_transaction(struct i2c_adapter *adap) outw_p(inw(SMB_GLOBAL_ENABLE) | GE_ABORT, SMB_GLOBAL_ENABLE); msleep(100); outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS); - return -1; + return -EIO; } -/* Return -1 on error. */ +/* Return negative errno on error. */ static s32 amd756_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data * data) { int i, len; + int status; - /** TODO: Should I supporte the 10-bit transfers? */ switch (size) { - case I2C_SMBUS_PROC_CALL: - dev_dbg(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n"); - /* TODO: Well... It is supported, I'm just not sure what to do here... */ - return -1; case I2C_SMBUS_QUICK: outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMB_HOST_ADDRESS); @@ -251,13 +245,17 @@ static s32 amd756_access(struct i2c_adapter * adap, u16 addr, } size = AMD756_BLOCK_DATA; break; + default: + dev_warn(&adap->dev, "Unsupported transaction %d\n", size); + return -EOPNOTSUPP; } /* How about enabling interrupts... */ outw_p(size & GE_CYC_TYPE_MASK, SMB_GLOBAL_ENABLE); - if (amd756_transaction(adap)) /* Error in transaction */ - return -1; + status = amd756_transaction(adap); + if (status) + return status; if ((read_write == I2C_SMBUS_WRITE) || (size == AMD756_QUICK)) return 0; @@ -301,7 +299,7 @@ static const struct i2c_algorithm smbus_algorithm = { struct i2c_adapter amd756_smbus = { .owner = THIS_MODULE, .id = I2C_HW_SMBUS_AMD756, - .class = I2C_CLASS_HWMON, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, .algo = &smbus_algorithm, }; @@ -368,6 +366,11 @@ static int __devinit amd756_probe(struct pci_dev *pdev, amd756_ioport += SMB_ADDR_OFFSET; } + error = acpi_check_region(amd756_ioport, SMB_IOSIZE, + amd756_driver.name); + if (error) + return error; + if (!request_region(amd756_ioport, SMB_IOSIZE, amd756_driver.name)) { dev_err(&pdev->dev, "SMB region 0x%x already in use!\n", amd756_ioport); diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c index 5d1a27ef2504..3972208876b3 100644 --- a/drivers/i2c/busses/i2c-amd8111.c +++ b/drivers/i2c/busses/i2c-amd8111.c @@ -16,6 +16,7 @@ #include <linux/init.h> #include <linux/i2c.h> #include <linux/delay.h> +#include <linux/acpi.h> #include <asm/io.h> MODULE_LICENSE("GPL"); @@ -77,7 +78,7 @@ static unsigned int amd_ec_wait_write(struct amd_smbus *smbus) if (!timeout) { dev_warn(&smbus->dev->dev, "Timeout while waiting for IBF to clear\n"); - return -1; + return -ETIMEDOUT; } return 0; @@ -93,7 +94,7 @@ static unsigned int amd_ec_wait_read(struct amd_smbus *smbus) if (!timeout) { dev_warn(&smbus->dev->dev, "Timeout while waiting for OBF to set\n"); - return -1; + return -ETIMEDOUT; } return 0; @@ -102,16 +103,21 @@ static unsigned int amd_ec_wait_read(struct amd_smbus *smbus) static unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address, unsigned char *data) { - if (amd_ec_wait_write(smbus)) - return -1; + int status; + + status = amd_ec_wait_write(smbus); + if (status) + return status; outb(AMD_EC_CMD_RD, smbus->base + AMD_EC_CMD); - if (amd_ec_wait_write(smbus)) - return -1; + status = amd_ec_wait_write(smbus); + if (status) + return status; outb(address, smbus->base + AMD_EC_DATA); - if (amd_ec_wait_read(smbus)) - return -1; + status = amd_ec_wait_read(smbus); + if (status) + return status; *data = inb(smbus->base + AMD_EC_DATA); return 0; @@ -120,16 +126,21 @@ static unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address, static unsigned int amd_ec_write(struct amd_smbus *smbus, unsigned char address, unsigned char data) { - if (amd_ec_wait_write(smbus)) - return -1; + int status; + + status = amd_ec_wait_write(smbus); + if (status) + return status; outb(AMD_EC_CMD_WR, smbus->base + AMD_EC_CMD); - if (amd_ec_wait_write(smbus)) - return -1; + status = amd_ec_wait_write(smbus); + if (status) + return status; outb(address, smbus->base + AMD_EC_DATA); - if (amd_ec_wait_write(smbus)) - return -1; + status = amd_ec_wait_write(smbus); + if (status) + return status; outb(data, smbus->base + AMD_EC_DATA); return 0; @@ -267,12 +278,17 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, default: dev_warn(&adap->dev, "Unsupported transaction %d\n", size); - return -1; + return -EOPNOTSUPP; } amd_ec_write(smbus, AMD_SMB_ADDR, addr << 1); amd_ec_write(smbus, AMD_SMB_PRTCL, protocol); + /* FIXME this discards status from ec_read(); so temp[0] will + * hold stack garbage ... the rest of this routine will act + * nonsensically. Ignored ec_write() status might explain + * some such failures... + */ amd_ec_read(smbus, AMD_SMB_STS, temp + 0); if (~temp[0] & AMD_SMB_STS_DONE) { @@ -286,7 +302,7 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, } if ((~temp[0] & AMD_SMB_STS_DONE) || (temp[0] & AMD_SMB_STS_STATUS)) - return -1; + return -EIO; if (read_write == I2C_SMBUS_WRITE) return 0; @@ -359,6 +375,10 @@ static int __devinit amd8111_probe(struct pci_dev *dev, smbus->base = pci_resource_start(dev, 0); smbus->size = pci_resource_len(dev, 0); + error = acpi_check_resource_conflict(&dev->resource[0]); + if (error) + goto out_kfree; + if (!request_region(smbus->base, smbus->size, amd8111_driver.name)) { error = -EBUSY; goto out_kfree; @@ -368,7 +388,7 @@ static int __devinit amd8111_probe(struct pci_dev *dev, snprintf(smbus->adapter.name, sizeof(smbus->adapter.name), "SMBus2 AMD8111 adapter at %04x", smbus->base); smbus->adapter.id = I2C_HW_SMBUS_AMD8111; - smbus->adapter.class = I2C_CLASS_HWMON; + smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; smbus->adapter.algo = &smbus_algorithm; smbus->adapter.algo_data = smbus; diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c index cae9dc89d88c..66a04c2c660f 100644 --- a/drivers/i2c/busses/i2c-au1550.c +++ b/drivers/i2c/busses/i2c-au1550.c @@ -269,9 +269,13 @@ static int au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) { struct i2c_au1550_data *adap = i2c_adap->algo_data; + volatile psc_smb_t *sp = (volatile psc_smb_t *)adap->psc_base; struct i2c_msg *p; int i, err = 0; + sp->psc_ctrl = PSC_CTRL_ENABLE; + au_sync(); + for (i = 0; !err && i < num; i++) { p = &msgs[i]; err = do_address(adap, p->addr, p->flags & I2C_M_RD, @@ -288,6 +292,10 @@ au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) */ if (err == 0) err = num; + + sp->psc_ctrl = PSC_CTRL_SUSPEND; + au_sync(); + return err; } @@ -302,6 +310,61 @@ static const struct i2c_algorithm au1550_algo = { .functionality = au1550_func, }; +static void i2c_au1550_setup(struct i2c_au1550_data *priv) +{ + volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base; + u32 stat; + + sp->psc_ctrl = PSC_CTRL_DISABLE; + au_sync(); + sp->psc_sel = PSC_SEL_PS_SMBUSMODE; + sp->psc_smbcfg = 0; + au_sync(); + sp->psc_ctrl = PSC_CTRL_ENABLE; + au_sync(); + do { + stat = sp->psc_smbstat; + au_sync(); + } while ((stat & PSC_SMBSTAT_SR) == 0); + + sp->psc_smbcfg = (PSC_SMBCFG_RT_FIFO8 | PSC_SMBCFG_TT_FIFO8 | + PSC_SMBCFG_DD_DISABLE); + + /* Divide by 8 to get a 6.25 MHz clock. The later protocol + * timings are based on this clock. + */ + sp->psc_smbcfg |= PSC_SMBCFG_SET_DIV(PSC_SMBCFG_DIV8); + sp->psc_smbmsk = PSC_SMBMSK_ALLMASK; + au_sync(); + + /* Set the protocol timer values. See Table 71 in the + * Au1550 Data Book for standard timing values. + */ + sp->psc_smbtmr = PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(15) | \ + PSC_SMBTMR_SET_PU(15) | PSC_SMBTMR_SET_SH(15) | \ + PSC_SMBTMR_SET_SU(15) | PSC_SMBTMR_SET_CL(15) | \ + PSC_SMBTMR_SET_CH(15); + au_sync(); + + sp->psc_smbcfg |= PSC_SMBCFG_DE_ENABLE; + do { + stat = sp->psc_smbstat; + au_sync(); + } while ((stat & PSC_SMBSTAT_SR) == 0); + + sp->psc_ctrl = PSC_CTRL_SUSPEND; + au_sync(); +} + +static void i2c_au1550_disable(struct i2c_au1550_data *priv) +{ + volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base; + + sp->psc_smbcfg = 0; + sp->psc_ctrl = PSC_CTRL_DISABLE; + au_sync(); +} + /* * registering functions to load algorithms at runtime * Prior to calling us, the 50MHz clock frequency and routing @@ -311,9 +374,7 @@ static int __devinit i2c_au1550_probe(struct platform_device *pdev) { struct i2c_au1550_data *priv; - volatile psc_smb_t *sp; struct resource *r; - u32 stat; int ret; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -348,43 +409,7 @@ i2c_au1550_probe(struct platform_device *pdev) /* Now, set up the PSC for SMBus PIO mode. */ - sp = (volatile psc_smb_t *)priv->psc_base; - sp->psc_ctrl = PSC_CTRL_DISABLE; - au_sync(); - sp->psc_sel = PSC_SEL_PS_SMBUSMODE; - sp->psc_smbcfg = 0; - au_sync(); - sp->psc_ctrl = PSC_CTRL_ENABLE; - au_sync(); - do { - stat = sp->psc_smbstat; - au_sync(); - } while ((stat & PSC_SMBSTAT_SR) == 0); - - sp->psc_smbcfg = (PSC_SMBCFG_RT_FIFO8 | PSC_SMBCFG_TT_FIFO8 | - PSC_SMBCFG_DD_DISABLE); - - /* Divide by 8 to get a 6.25 MHz clock. The later protocol - * timings are based on this clock. - */ - sp->psc_smbcfg |= PSC_SMBCFG_SET_DIV(PSC_SMBCFG_DIV8); - sp->psc_smbmsk = PSC_SMBMSK_ALLMASK; - au_sync(); - - /* Set the protocol timer values. See Table 71 in the - * Au1550 Data Book for standard timing values. - */ - sp->psc_smbtmr = PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(15) | \ - PSC_SMBTMR_SET_PU(15) | PSC_SMBTMR_SET_SH(15) | \ - PSC_SMBTMR_SET_SU(15) | PSC_SMBTMR_SET_CL(15) | \ - PSC_SMBTMR_SET_CH(15); - au_sync(); - - sp->psc_smbcfg |= PSC_SMBCFG_DE_ENABLE; - do { - stat = sp->psc_smbstat; - au_sync(); - } while ((stat & PSC_SMBSTAT_DR) == 0); + i2c_au1550_setup(priv); ret = i2c_add_numbered_adapter(&priv->adap); if (ret == 0) { @@ -392,10 +417,7 @@ i2c_au1550_probe(struct platform_device *pdev) return 0; } - /* disable the PSC */ - sp->psc_smbcfg = 0; - sp->psc_ctrl = PSC_CTRL_DISABLE; - au_sync(); + i2c_au1550_disable(priv); release_resource(priv->ioarea); kfree(priv->ioarea); @@ -409,27 +431,24 @@ static int __devexit i2c_au1550_remove(struct platform_device *pdev) { struct i2c_au1550_data *priv = platform_get_drvdata(pdev); - volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base; platform_set_drvdata(pdev, NULL); i2c_del_adapter(&priv->adap); - sp->psc_smbcfg = 0; - sp->psc_ctrl = PSC_CTRL_DISABLE; - au_sync(); + i2c_au1550_disable(priv); release_resource(priv->ioarea); kfree(priv->ioarea); kfree(priv); return 0; } +#ifdef CONFIG_PM static int i2c_au1550_suspend(struct platform_device *pdev, pm_message_t state) { struct i2c_au1550_data *priv = platform_get_drvdata(pdev); - volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base; - sp->psc_ctrl = PSC_CTRL_SUSPEND; - au_sync(); + i2c_au1550_disable(priv); + return 0; } @@ -437,14 +456,15 @@ static int i2c_au1550_resume(struct platform_device *pdev) { struct i2c_au1550_data *priv = platform_get_drvdata(pdev); - volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base; - sp->psc_ctrl = PSC_CTRL_ENABLE; - au_sync(); - while (!(sp->psc_smbstat & PSC_SMBSTAT_SR)) - au_sync(); + i2c_au1550_setup(priv); + return 0; } +#else +#define i2c_au1550_suspend NULL +#define i2c_au1550_resume NULL +#endif static struct platform_driver au1xpsc_smbus_driver = { .driver = { diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c new file mode 100644 index 000000000000..8164de1f4d72 --- /dev/null +++ b/drivers/i2c/busses/i2c-cpm.c @@ -0,0 +1,745 @@ +/* + * Freescale CPM1/CPM2 I2C interface. + * Copyright (c) 1999 Dan Malek (dmalek@jlc.net). + * + * moved into proper i2c interface; + * Brad Parker (brad@heeltoe.com) + * + * Parts from dbox2_i2c.c (cvs.tuxbox.org) + * (C) 2000-2001 Felix Domke (tmbinc@gmx.net), Gillem (htoa@gmx.net) + * + * (C) 2007 Montavista Software, Inc. + * Vitaly Bordug <vitb@kernel.crashing.org> + * + * Converted to of_platform_device. Renamed to i2c-cpm.c. + * (C) 2007,2008 Jochen Friedrich <jochen@scram.de> + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/slab.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/errno.h> +#include <linux/stddef.h> +#include <linux/i2c.h> +#include <linux/io.h> +#include <linux/dma-mapping.h> +#include <linux/of_device.h> +#include <linux/of_platform.h> +#include <linux/of_i2c.h> +#include <sysdev/fsl_soc.h> +#include <asm/cpm.h> + +/* Try to define this if you have an older CPU (earlier than rev D4) */ +/* However, better use a GPIO based bitbang driver in this case :/ */ +#undef I2C_CHIP_ERRATA + +#define CPM_MAX_READ 513 +#define CPM_MAXBD 4 + +#define I2C_EB (0x10) /* Big endian mode */ +#define I2C_EB_CPM2 (0x30) /* Big endian mode, memory snoop */ + +#define DPRAM_BASE ((u8 __iomem __force *)cpm_muram_addr(0)) + +/* I2C parameter RAM. */ +struct i2c_ram { + ushort rbase; /* Rx Buffer descriptor base address */ + ushort tbase; /* Tx Buffer descriptor base address */ + u_char rfcr; /* Rx function code */ + u_char tfcr; /* Tx function code */ + ushort mrblr; /* Max receive buffer length */ + uint rstate; /* Internal */ + uint rdp; /* Internal */ + ushort rbptr; /* Rx Buffer descriptor pointer */ + ushort rbc; /* Internal */ + uint rxtmp; /* Internal */ + uint tstate; /* Internal */ + uint tdp; /* Internal */ + ushort tbptr; /* Tx Buffer descriptor pointer */ + ushort tbc; /* Internal */ + uint txtmp; /* Internal */ + char res1[4]; /* Reserved */ + ushort rpbase; /* Relocation pointer */ + char res2[2]; /* Reserved */ +}; + +#define I2COM_START 0x80 +#define I2COM_MASTER 0x01 +#define I2CER_TXE 0x10 +#define I2CER_BUSY 0x04 +#define I2CER_TXB 0x02 +#define I2CER_RXB 0x01 +#define I2MOD_EN 0x01 + +/* I2C Registers */ +struct i2c_reg { + u8 i2mod; + u8 res1[3]; + u8 i2add; + u8 res2[3]; + u8 i2brg; + u8 res3[3]; + u8 i2com; + u8 res4[3]; + u8 i2cer; + u8 res5[3]; + u8 i2cmr; +}; + +struct cpm_i2c { + char *base; + struct of_device *ofdev; + struct i2c_adapter adap; + uint dp_addr; + int version; /* CPM1=1, CPM2=2 */ + int irq; + int cp_command; + int freq; + struct i2c_reg __iomem *i2c_reg; + struct i2c_ram __iomem *i2c_ram; + u16 i2c_addr; + wait_queue_head_t i2c_wait; + cbd_t __iomem *tbase; + cbd_t __iomem *rbase; + u_char *txbuf[CPM_MAXBD]; + u_char *rxbuf[CPM_MAXBD]; + u32 txdma[CPM_MAXBD]; + u32 rxdma[CPM_MAXBD]; +}; + +static irqreturn_t cpm_i2c_interrupt(int irq, void *dev_id) +{ + struct cpm_i2c *cpm; + struct i2c_reg __iomem *i2c_reg; + struct i2c_adapter *adap = dev_id; + int i; + + cpm = i2c_get_adapdata(dev_id); + i2c_reg = cpm->i2c_reg; + + /* Clear interrupt. */ + i = in_8(&i2c_reg->i2cer); + out_8(&i2c_reg->i2cer, i); + + dev_dbg(&adap->dev, "Interrupt: %x\n", i); + + wake_up_interruptible(&cpm->i2c_wait); + + return i ? IRQ_HANDLED : IRQ_NONE; +} + +static void cpm_reset_i2c_params(struct cpm_i2c *cpm) +{ + struct i2c_ram __iomem *i2c_ram = cpm->i2c_ram; + + /* Set up the I2C parameters in the parameter ram. */ + out_be16(&i2c_ram->tbase, (u8 __iomem *)cpm->tbase - DPRAM_BASE); + out_be16(&i2c_ram->rbase, (u8 __iomem *)cpm->rbase - DPRAM_BASE); + + if (cpm->version == 1) { + out_8(&i2c_ram->tfcr, I2C_EB); + out_8(&i2c_ram->rfcr, I2C_EB); + } else { + out_8(&i2c_ram->tfcr, I2C_EB_CPM2); + out_8(&i2c_ram->rfcr, I2C_EB_CPM2); + } + + out_be16(&i2c_ram->mrblr, CPM_MAX_READ); + + out_be32(&i2c_ram->rstate, 0); + out_be32(&i2c_ram->rdp, 0); + out_be16(&i2c_ram->rbptr, 0); + out_be16(&i2c_ram->rbc, 0); + out_be32(&i2c_ram->rxtmp, 0); + out_be32(&i2c_ram->tstate, 0); + out_be32(&i2c_ram->tdp, 0); + out_be16(&i2c_ram->tbptr, 0); + out_be16(&i2c_ram->tbc, 0); + out_be32(&i2c_ram->txtmp, 0); +} + +static void cpm_i2c_force_close(struct i2c_adapter *adap) +{ + struct cpm_i2c *cpm = i2c_get_adapdata(adap); + struct i2c_reg __iomem *i2c_reg = cpm->i2c_reg; + + dev_dbg(&adap->dev, "cpm_i2c_force_close()\n"); + + cpm_command(cpm->cp_command, CPM_CR_CLOSE_RX_BD); + + out_8(&i2c_reg->i2cmr, 0x00); /* Disable all interrupts */ + out_8(&i2c_reg->i2cer, 0xff); +} + +static void cpm_i2c_parse_message(struct i2c_adapter *adap, + struct i2c_msg *pmsg, int num, int tx, int rx) +{ + cbd_t __iomem *tbdf; + cbd_t __iomem *rbdf; + u_char addr; + u_char *tb; + u_char *rb; + struct cpm_i2c *cpm = i2c_get_adapdata(adap); + + tbdf = cpm->tbase + tx; + rbdf = cpm->rbase + rx; + + addr = pmsg->addr << 1; + if (pmsg->flags & I2C_M_RD) + addr |= 1; + + tb = cpm->txbuf[tx]; + rb = cpm->rxbuf[rx]; + + /* Align read buffer */ + rb = (u_char *) (((ulong) rb + 1) & ~1); + + tb[0] = addr; /* Device address byte w/rw flag */ + + out_be16(&tbdf->cbd_datlen, pmsg->len + 1); + out_be16(&tbdf->cbd_sc, 0); + + if (!(pmsg->flags & I2C_M_NOSTART)) + setbits16(&tbdf->cbd_sc, BD_I2C_START); + + if (tx + 1 == num) + setbits16(&tbdf->cbd_sc, BD_SC_LAST | BD_SC_WRAP); + + if (pmsg->flags & I2C_M_RD) { + /* + * To read, we need an empty buffer of the proper length. + * All that is used is the first byte for address, the remainder + * is just used for timing (and doesn't really have to exist). + */ + + dev_dbg(&adap->dev, "cpm_i2c_read(abyte=0x%x)\n", addr); + + out_be16(&rbdf->cbd_datlen, 0); + out_be16(&rbdf->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT); + + if (rx + 1 == CPM_MAXBD) + setbits16(&rbdf->cbd_sc, BD_SC_WRAP); + + eieio(); + setbits16(&tbdf->cbd_sc, BD_SC_READY); + } else { + dev_dbg(&adap->dev, "cpm_i2c_write(abyte=0x%x)\n", addr); + + memcpy(tb+1, pmsg->buf, pmsg->len); + + eieio(); + setbits16(&tbdf->cbd_sc, BD_SC_READY | BD_SC_INTRPT); + } +} + +static int cpm_i2c_check_message(struct i2c_adapter *adap, + struct i2c_msg *pmsg, int tx, int rx) +{ + cbd_t __iomem *tbdf; + cbd_t __iomem *rbdf; + u_char *tb; + u_char *rb; + struct cpm_i2c *cpm = i2c_get_adapdata(adap); + + tbdf = cpm->tbase + tx; + rbdf = cpm->rbase + rx; + + tb = cpm->txbuf[tx]; + rb = cpm->rxbuf[rx]; + + /* Align read buffer */ + rb = (u_char *) (((uint) rb + 1) & ~1); + + eieio(); + if (pmsg->flags & I2C_M_RD) { + dev_dbg(&adap->dev, "tx sc 0x%04x, rx sc 0x%04x\n", + in_be16(&tbdf->cbd_sc), in_be16(&rbdf->cbd_sc)); + + if (in_be16(&tbdf->cbd_sc) & BD_SC_NAK) { + dev_dbg(&adap->dev, "I2C read; No ack\n"); + return -ENXIO; + } + if (in_be16(&rbdf->cbd_sc) & BD_SC_EMPTY) { + dev_err(&adap->dev, + "I2C read; complete but rbuf empty\n"); + return -EREMOTEIO; + } + if (in_be16(&rbdf->cbd_sc) & BD_SC_OV) { + dev_err(&adap->dev, "I2C read; Overrun\n"); + return -EREMOTEIO; + } + memcpy(pmsg->buf, rb, pmsg->len); + } else { + dev_dbg(&adap->dev, "tx sc %d 0x%04x\n", tx, + in_be16(&tbdf->cbd_sc)); + + if (in_be16(&tbdf->cbd_sc) & BD_SC_NAK) { + dev_dbg(&adap->dev, "I2C write; No ack\n"); + return -ENXIO; + } + if (in_be16(&tbdf->cbd_sc) & BD_SC_UN) { + dev_err(&adap->dev, "I2C write; Underrun\n"); + return -EIO; + } + if (in_be16(&tbdf->cbd_sc) & BD_SC_CL) { + dev_err(&adap->dev, "I2C write; Collision\n"); + return -EIO; + } + } + return 0; +} + +static int cpm_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +{ + struct cpm_i2c *cpm = i2c_get_adapdata(adap); + struct i2c_reg __iomem *i2c_reg = cpm->i2c_reg; + struct i2c_ram __iomem *i2c_ram = cpm->i2c_ram; + struct i2c_msg *pmsg; + int ret, i; + int tptr; + int rptr; + cbd_t __iomem *tbdf; + cbd_t __iomem *rbdf; + + if (num > CPM_MAXBD) + return -EINVAL; + + /* Check if we have any oversized READ requests */ + for (i = 0; i < num; i++) { + pmsg = &msgs[i]; + if (pmsg->len >= CPM_MAX_READ) + return -EINVAL; + } + + /* Reset to use first buffer */ + out_be16(&i2c_ram->rbptr, in_be16(&i2c_ram->rbase)); + out_be16(&i2c_ram->tbptr, in_be16(&i2c_ram->tbase)); + + tbdf = cpm->tbase; + rbdf = cpm->rbase; + + tptr = 0; + rptr = 0; + + while (tptr < num) { + pmsg = &msgs[tptr]; + dev_dbg(&adap->dev, "R: %d T: %d\n", rptr, tptr); + + cpm_i2c_parse_message(adap, pmsg, num, tptr, rptr); + if (pmsg->flags & I2C_M_RD) + rptr++; + tptr++; + } + /* Start transfer now */ + /* Enable RX/TX/Error interupts */ + out_8(&i2c_reg->i2cmr, I2CER_TXE | I2CER_TXB | I2CER_RXB); + out_8(&i2c_reg->i2cer, 0xff); /* Clear interrupt status */ + /* Chip bug, set enable here */ + setbits8(&i2c_reg->i2mod, I2MOD_EN); /* Enable */ + /* Begin transmission */ + setbits8(&i2c_reg->i2com, I2COM_START); + + tptr = 0; + rptr = 0; + + while (tptr < num) { + /* Check for outstanding messages */ + dev_dbg(&adap->dev, "test ready.\n"); + pmsg = &msgs[tptr]; + if (pmsg->flags & I2C_M_RD) + ret = wait_event_interruptible_timeout(cpm->i2c_wait, + !(in_be16(&rbdf[rptr].cbd_sc) & BD_SC_EMPTY), + 1 * HZ); + else + ret = wait_event_interruptible_timeout(cpm->i2c_wait, + !(in_be16(&tbdf[tptr].cbd_sc) & BD_SC_READY), + 1 * HZ); + if (ret == 0) { + ret = -EREMOTEIO; + dev_err(&adap->dev, "I2C transfer: timeout\n"); + goto out_err; + } + if (ret > 0) { + dev_dbg(&adap->dev, "ready.\n"); + ret = cpm_i2c_check_message(adap, pmsg, tptr, rptr); + tptr++; + if (pmsg->flags & I2C_M_RD) + rptr++; + if (ret) + goto out_err; + } + } +#ifdef I2C_CHIP_ERRATA + /* + * Chip errata, clear enable. This is not needed on rev D4 CPUs. + * Disabling I2C too early may cause too short stop condition + */ + udelay(4); + clrbits8(&i2c_reg->i2mod, I2MOD_EN); +#endif + return (num); + +out_err: + cpm_i2c_force_close(adap); +#ifdef I2C_CHIP_ERRATA + /* + * Chip errata, clear enable. This is not needed on rev D4 CPUs. + */ + clrbits8(&i2c_reg->i2mod, I2MOD_EN); +#endif + return ret; +} + +static u32 cpm_i2c_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); +} + +/* -----exported algorithm data: ------------------------------------- */ + +static const struct i2c_algorithm cpm_i2c_algo = { + .master_xfer = cpm_i2c_xfer, + .functionality = cpm_i2c_func, +}; + +static const struct i2c_adapter cpm_ops = { + .owner = THIS_MODULE, + .name = "i2c-cpm", + .algo = &cpm_i2c_algo, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, +}; + +static int __devinit cpm_i2c_setup(struct cpm_i2c *cpm) +{ + struct of_device *ofdev = cpm->ofdev; + const u32 *data; + int len, ret, i; + void __iomem *i2c_base; + cbd_t __iomem *tbdf; + cbd_t __iomem *rbdf; + unsigned char brg; + + dev_dbg(&cpm->ofdev->dev, "cpm_i2c_setup()\n"); + + init_waitqueue_head(&cpm->i2c_wait); + + cpm->irq = of_irq_to_resource(ofdev->node, 0, NULL); + if (cpm->irq == NO_IRQ) + return -EINVAL; + + /* Install interrupt handler. */ + ret = request_irq(cpm->irq, cpm_i2c_interrupt, 0, "cpm_i2c", + &cpm->adap); + if (ret) + return ret; + + /* I2C parameter RAM */ + i2c_base = of_iomap(ofdev->node, 1); + if (i2c_base == NULL) { + ret = -EINVAL; + goto out_irq; + } + + if (of_device_is_compatible(ofdev->node, "fsl,cpm1-i2c")) { + + /* Check for and use a microcode relocation patch. */ + cpm->i2c_ram = i2c_base; + cpm->i2c_addr = in_be16(&cpm->i2c_ram->rpbase); + + /* + * Maybe should use cpm_muram_alloc instead of hardcoding + * this in micropatch.c + */ + if (cpm->i2c_addr) { + cpm->i2c_ram = cpm_muram_addr(cpm->i2c_addr); + iounmap(i2c_base); + } + + cpm->version = 1; + + } else if (of_device_is_compatible(ofdev->node, "fsl,cpm2-i2c")) { + cpm->i2c_addr = cpm_muram_alloc(sizeof(struct i2c_ram), 64); + cpm->i2c_ram = cpm_muram_addr(cpm->i2c_addr); + out_be16(i2c_base, cpm->i2c_addr); + iounmap(i2c_base); + + cpm->version = 2; + + } else { + iounmap(i2c_base); + ret = -EINVAL; + goto out_irq; + } + + /* I2C control/status registers */ + cpm->i2c_reg = of_iomap(ofdev->node, 0); + if (cpm->i2c_reg == NULL) { + ret = -EINVAL; + goto out_ram; + } + + data = of_get_property(ofdev->node, "fsl,cpm-command", &len); + if (!data || len != 4) { + ret = -EINVAL; + goto out_reg; + } + cpm->cp_command = *data; + + data = of_get_property(ofdev->node, "linux,i2c-class", &len); + if (data && len == 4) + cpm->adap.class = *data; + + data = of_get_property(ofdev->node, "clock-frequency", &len); + if (data && len == 4) + cpm->freq = *data; + else + cpm->freq = 60000; /* use 60kHz i2c clock by default */ + + /* + * Allocate space for CPM_MAXBD transmit and receive buffer + * descriptors in the DP ram. + */ + cpm->dp_addr = cpm_muram_alloc(sizeof(cbd_t) * 2 * CPM_MAXBD, 8); + if (!cpm->dp_addr) { + ret = -ENOMEM; + goto out_reg; + } + + cpm->tbase = cpm_muram_addr(cpm->dp_addr); + cpm->rbase = cpm_muram_addr(cpm->dp_addr + sizeof(cbd_t) * CPM_MAXBD); + + /* Allocate TX and RX buffers */ + + tbdf = cpm->tbase; + rbdf = cpm->rbase; + + for (i = 0; i < CPM_MAXBD; i++) { + cpm->rxbuf[i] = dma_alloc_coherent( + NULL, CPM_MAX_READ + 1, &cpm->rxdma[i], GFP_KERNEL); + if (!cpm->rxbuf[i]) { + ret = -ENOMEM; + goto out_muram; + } + out_be32(&rbdf[i].cbd_bufaddr, ((cpm->rxdma[i] + 1) & ~1)); + + cpm->txbuf[i] = (unsigned char *)dma_alloc_coherent( + NULL, CPM_MAX_READ + 1, &cpm->txdma[i], GFP_KERNEL); + if (!cpm->txbuf[i]) { + ret = -ENOMEM; + goto out_muram; + } + out_be32(&tbdf[i].cbd_bufaddr, cpm->txdma[i]); + } + + /* Initialize Tx/Rx parameters. */ + + cpm_reset_i2c_params(cpm); + + dev_dbg(&cpm->ofdev->dev, "i2c_ram 0x%p, i2c_addr 0x%04x, freq %d\n", + cpm->i2c_ram, cpm->i2c_addr, cpm->freq); + dev_dbg(&cpm->ofdev->dev, "tbase 0x%04x, rbase 0x%04x\n", + (u8 __iomem *)cpm->tbase - DPRAM_BASE, + (u8 __iomem *)cpm->rbase - DPRAM_BASE); + + cpm_command(cpm->cp_command, CPM_CR_INIT_TRX); + + /* + * Select an invalid address. Just make sure we don't use loopback mode + */ + out_8(&cpm->i2c_reg->i2add, 0x7f << 1); + + /* + * PDIV is set to 00 in i2mod, so brgclk/32 is used as input to the + * i2c baud rate generator. This is divided by 2 x (DIV + 3) to get + * the actual i2c bus frequency. + */ + brg = get_brgfreq() / (32 * 2 * cpm->freq) - 3; + out_8(&cpm->i2c_reg->i2brg, brg); + + out_8(&cpm->i2c_reg->i2mod, 0x00); + out_8(&cpm->i2c_reg->i2com, I2COM_MASTER); /* Master mode */ + + /* Disable interrupts. */ + out_8(&cpm->i2c_reg->i2cmr, 0); + out_8(&cpm->i2c_reg->i2cer, 0xff); + + return 0; + +out_muram: + for (i = 0; i < CPM_MAXBD; i++) { + if (cpm->rxbuf[i]) + dma_free_coherent(NULL, CPM_MAX_READ + 1, + cpm->rxbuf[i], cpm->rxdma[i]); + if (cpm->txbuf[i]) + dma_free_coherent(NULL, CPM_MAX_READ + 1, + cpm->txbuf[i], cpm->txdma[i]); + } + cpm_muram_free(cpm->dp_addr); +out_reg: + iounmap(cpm->i2c_reg); +out_ram: + if ((cpm->version == 1) && (!cpm->i2c_addr)) + iounmap(cpm->i2c_ram); + if (cpm->version == 2) + cpm_muram_free(cpm->i2c_addr); +out_irq: + free_irq(cpm->irq, &cpm->adap); + return ret; +} + +static void cpm_i2c_shutdown(struct cpm_i2c *cpm) +{ + int i; + + /* Shut down I2C. */ + clrbits8(&cpm->i2c_reg->i2mod, I2MOD_EN); + + /* Disable interrupts */ + out_8(&cpm->i2c_reg->i2cmr, 0); + out_8(&cpm->i2c_reg->i2cer, 0xff); + + free_irq(cpm->irq, &cpm->adap); + + /* Free all memory */ + for (i = 0; i < CPM_MAXBD; i++) { + dma_free_coherent(NULL, CPM_MAX_READ + 1, + cpm->rxbuf[i], cpm->rxdma[i]); + dma_free_coherent(NULL, CPM_MAX_READ + 1, + cpm->txbuf[i], cpm->txdma[i]); + } + + cpm_muram_free(cpm->dp_addr); + iounmap(cpm->i2c_reg); + + if ((cpm->version == 1) && (!cpm->i2c_addr)) + iounmap(cpm->i2c_ram); + if (cpm->version == 2) + cpm_muram_free(cpm->i2c_addr); +} + +static int __devinit cpm_i2c_probe(struct of_device *ofdev, + const struct of_device_id *match) +{ + int result, len; + struct cpm_i2c *cpm; + const u32 *data; + + cpm = kzalloc(sizeof(struct cpm_i2c), GFP_KERNEL); + if (!cpm) + return -ENOMEM; + + cpm->ofdev = ofdev; + + dev_set_drvdata(&ofdev->dev, cpm); + + cpm->adap = cpm_ops; + i2c_set_adapdata(&cpm->adap, cpm); + cpm->adap.dev.parent = &ofdev->dev; + + result = cpm_i2c_setup(cpm); + if (result) { + dev_err(&ofdev->dev, "Unable to init hardware\n"); + goto out_free; + } + + /* register new adapter to i2c module... */ + + data = of_get_property(ofdev->node, "linux,i2c-index", &len); + if (data && len == 4) { + cpm->adap.nr = *data; + result = i2c_add_numbered_adapter(&cpm->adap); + } else + result = i2c_add_adapter(&cpm->adap); + + if (result < 0) { + dev_err(&ofdev->dev, "Unable to register with I2C\n"); + goto out_shut; + } + + dev_dbg(&ofdev->dev, "hw routines for %s registered.\n", + cpm->adap.name); + + /* + * register OF I2C devices + */ + of_register_i2c_devices(&cpm->adap, ofdev->node); + + return 0; +out_shut: + cpm_i2c_shutdown(cpm); +out_free: + dev_set_drvdata(&ofdev->dev, NULL); + kfree(cpm); + + return result; +} + +static int __devexit cpm_i2c_remove(struct of_device *ofdev) +{ + struct cpm_i2c *cpm = dev_get_drvdata(&ofdev->dev); + + i2c_del_adapter(&cpm->adap); + + cpm_i2c_shutdown(cpm); + + dev_set_drvdata(&ofdev->dev, NULL); + kfree(cpm); + + return 0; +} + +static const struct of_device_id cpm_i2c_match[] = { + { + .compatible = "fsl,cpm1-i2c", + }, + { + .compatible = "fsl,cpm2-i2c", + }, + {}, +}; + +MODULE_DEVICE_TABLE(of, cpm_i2c_match); + +static struct of_platform_driver cpm_i2c_driver = { + .match_table = cpm_i2c_match, + .probe = cpm_i2c_probe, + .remove = __devexit_p(cpm_i2c_remove), + .driver = { + .name = "fsl-i2c-cpm", + .owner = THIS_MODULE, + } +}; + +static int __init cpm_i2c_init(void) +{ + return of_register_platform_driver(&cpm_i2c_driver); +} + +static void __exit cpm_i2c_exit(void) +{ + of_unregister_platform_driver(&cpm_i2c_driver); +} + +module_init(cpm_i2c_init); +module_exit(cpm_i2c_exit); + +MODULE_AUTHOR("Jochen Friedrich <jochen@scram.de>"); +MODULE_DESCRIPTION("I2C-Bus adapter routines for CPM boards"); +MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 7ecbfc429b19..af3846eda985 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -85,6 +85,7 @@ #define DAVINCI_I2C_MDR_MST (1 << 10) #define DAVINCI_I2C_MDR_TRX (1 << 9) #define DAVINCI_I2C_MDR_XA (1 << 8) +#define DAVINCI_I2C_MDR_RM (1 << 7) #define DAVINCI_I2C_MDR_IRS (1 << 5) #define DAVINCI_I2C_IMR_AAS (1 << 6) @@ -112,6 +113,7 @@ struct davinci_i2c_dev { u8 *buf; size_t buf_len; int irq; + u8 terminate; struct i2c_adapter adapter; }; @@ -142,6 +144,7 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev) struct davinci_i2c_platform_data *pdata = dev->dev->platform_data; u16 psc; u32 clk; + u32 d; u32 clkh; u32 clkl; u32 input_clock = clk_get_rate(dev->clk); @@ -171,23 +174,29 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev) * if PSC > 1 , d = 5 */ - psc = 26; /* To get 1MHz clock */ + /* get minimum of 7 MHz clock, but max of 12 MHz */ + psc = (input_clock / 7000000) - 1; + if ((input_clock / (psc + 1)) > 12000000) + psc++; /* better to run under spec than over */ + d = (psc >= 2) ? 5 : 7 - psc; - clk = ((input_clock / (psc + 1)) / (pdata->bus_freq * 1000)) - 10; - clkh = (50 * clk) / 100; + clk = ((input_clock / (psc + 1)) / (pdata->bus_freq * 1000)) - (d << 1); + clkh = clk >> 1; clkl = clk - clkh; davinci_i2c_write_reg(dev, DAVINCI_I2C_PSC_REG, psc); davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKH_REG, clkh); davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKL_REG, clkl); - dev_dbg(dev->dev, "CLK = %d\n", clk); + dev_dbg(dev->dev, "input_clock = %d, CLK = %d\n", input_clock, clk); dev_dbg(dev->dev, "PSC = %d\n", davinci_i2c_read_reg(dev, DAVINCI_I2C_PSC_REG)); dev_dbg(dev->dev, "CLKL = %d\n", davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKL_REG)); dev_dbg(dev->dev, "CLKH = %d\n", davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKH_REG)); + dev_dbg(dev->dev, "bus_freq = %dkHz, bus_delay = %d\n", + pdata->bus_freq, pdata->bus_delay); /* Take the I2C module out of reset: */ w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); @@ -233,7 +242,6 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) struct davinci_i2c_dev *dev = i2c_get_adapdata(adap); struct davinci_i2c_platform_data *pdata = dev->dev->platform_data; u32 flag; - u32 stat; u16 w; int r; @@ -254,12 +262,9 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) davinci_i2c_write_reg(dev, DAVINCI_I2C_CNT_REG, dev->buf_len); - init_completion(&dev->cmd_complete); + INIT_COMPLETION(dev->cmd_complete); dev->cmd_err = 0; - /* Clear any pending interrupts by reading the IVR */ - stat = davinci_i2c_read_reg(dev, DAVINCI_I2C_IVR_REG); - /* Take I2C out of reset, configure it as master and set the * start bit */ flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST | DAVINCI_I2C_MDR_STT; @@ -280,20 +285,34 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) MOD_REG_BIT(w, DAVINCI_I2C_IMR_XRDY, 1); davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, w); + dev->terminate = 0; /* write the data into mode register */ davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); r = wait_for_completion_interruptible_timeout(&dev->cmd_complete, DAVINCI_I2C_TIMEOUT); - dev->buf_len = 0; - if (r < 0) - return r; - if (r == 0) { dev_err(dev->dev, "controller timed out\n"); i2c_davinci_init(dev); + dev->buf_len = 0; return -ETIMEDOUT; } + if (dev->buf_len) { + /* This should be 0 if all bytes were transferred + * or dev->cmd_err denotes an error. + * A signal may have aborted the transfer. + */ + if (r >= 0) { + dev_err(dev->dev, "abnormal termination buf_len=%i\n", + dev->buf_len); + r = -EREMOTEIO; + } + dev->terminate = 1; + wmb(); + dev->buf_len = 0; + } + if (r < 0) + return r; /* no error */ if (likely(!dev->cmd_err)) @@ -338,12 +357,11 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) for (i = 0; i < num; i++) { ret = i2c_davinci_xfer_msg(adap, &msgs[i], (i == (num - 1))); + dev_dbg(dev->dev, "%s [%d/%d] ret: %d\n", __func__, i + 1, num, + ret); if (ret < 0) return ret; } - - dev_dbg(dev->dev, "%s:%d ret: %d\n", __func__, __LINE__, ret); - return num; } @@ -352,6 +370,27 @@ static u32 i2c_davinci_func(struct i2c_adapter *adap) return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); } +static void terminate_read(struct davinci_i2c_dev *dev) +{ + u16 w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); + w |= DAVINCI_I2C_MDR_NACK; + davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w); + + /* Throw away data */ + davinci_i2c_read_reg(dev, DAVINCI_I2C_DRR_REG); + if (!dev->terminate) + dev_err(dev->dev, "RDR IRQ while no data requested\n"); +} +static void terminate_write(struct davinci_i2c_dev *dev) +{ + u16 w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); + w |= DAVINCI_I2C_MDR_RM | DAVINCI_I2C_MDR_STP; + davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w); + + if (!dev->terminate) + dev_err(dev->dev, "TDR IRQ while no data to send\n"); +} + /* * Interrupt service routine. This gets called whenever an I2C interrupt * occurs. @@ -372,12 +411,15 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id) switch (stat) { case DAVINCI_I2C_IVR_AL: + /* Arbitration lost, must retry */ dev->cmd_err |= DAVINCI_I2C_STR_AL; + dev->buf_len = 0; complete(&dev->cmd_complete); break; case DAVINCI_I2C_IVR_NACK: dev->cmd_err |= DAVINCI_I2C_STR_NACK; + dev->buf_len = 0; complete(&dev->cmd_complete); break; @@ -399,9 +441,10 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id) davinci_i2c_write_reg(dev, DAVINCI_I2C_STR_REG, DAVINCI_I2C_IMR_RRDY); - } else - dev_err(dev->dev, "RDR IRQ while no " - "data requested\n"); + } else { + /* signal can terminate transfer */ + terminate_read(dev); + } break; case DAVINCI_I2C_IVR_XRDY: @@ -418,9 +461,10 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id) davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, w); - } else - dev_err(dev->dev, "TDR IRQ while no data to " - "send\n"); + } else { + /* signal can terminate transfer */ + terminate_write(dev); + } break; case DAVINCI_I2C_IVR_SCD: @@ -475,6 +519,7 @@ static int davinci_i2c_probe(struct platform_device *pdev) goto err_release_region; } + init_completion(&dev->cmd_complete); dev->dev = get_device(&pdev->dev); dev->irq = irq->start; platform_set_drvdata(pdev, dev); diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c index b7a9977b025f..7f38c01fb3a0 100644 --- a/drivers/i2c/busses/i2c-elektor.c +++ b/drivers/i2c/busses/i2c-elektor.c @@ -196,13 +196,11 @@ static struct i2c_algo_pcf_data pcf_isa_data = { .getown = pcf_isa_getown, .getclock = pcf_isa_getclock, .waitforpin = pcf_isa_waitforpin, - .udelay = 10, - .timeout = 100, }; static struct i2c_adapter pcf_isa_ops = { .owner = THIS_MODULE, - .class = I2C_CLASS_HWMON, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, .id = I2C_HW_P_ELEK, .algo_data = &pcf_isa_data, .name = "i2c-elektor", diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index 7c1b762aa681..79b455a1f090 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -140,7 +140,7 @@ static int __init i2c_gpio_probe(struct platform_device *pdev) adap->owner = THIS_MODULE; snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id); adap->algo_data = bit_data; - adap->class = I2C_CLASS_HWMON; + adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; adap->dev.parent = &pdev->dev; /* diff --git a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c index f9972f9651e4..1098f21ace13 100644 --- a/drivers/i2c/busses/i2c-hydra.c +++ b/drivers/i2c/busses/i2c-hydra.c @@ -1,7 +1,4 @@ /* - i2c-hydra.c - Part of lm_sensors, Linux kernel modules - for hardware monitoring - i2c Support for the Apple `Hydra' Mac I/O Copyright (c) 1999-2004 Geert Uytterhoeven <geert@linux-m68k.org> diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index b0f771fe4326..dc7ea32b69a8 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -1,10 +1,8 @@ /* - i2c-i801.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, and Mark D. 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 @@ -64,6 +62,7 @@ #include <linux/ioport.h> #include <linux/init.h> #include <linux/i2c.h> +#include <linux/acpi.h> #include <asm/io.h> /* I801 SMBus address offsets */ @@ -121,6 +120,10 @@ #define SMBHSTSTS_INTR 0x02 #define SMBHSTSTS_HOST_BUSY 0x01 +#define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_FAILED | \ + SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR | \ + SMBHSTSTS_INTR) + static unsigned long i801_smba; static unsigned char i801_original_hstcfg; static struct pci_driver i801_driver; @@ -132,105 +135,137 @@ static struct pci_dev *I801_dev; #define FEATURE_I2C_BLOCK_READ (1 << 3) static unsigned int i801_features; -static int i801_transaction(int xact) +/* Make sure the SMBus host is ready to start transmitting. + Return 0 if it is, -EBUSY if it is not. */ +static int i801_check_pre(void) { - int temp; - int result = 0; - int timeout = 0; + int status; - dev_dbg(&I801_dev->dev, "Transaction (pre): CNT=%02x, CMD=%02x, " - "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), - inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), - inb_p(SMBHSTDAT1)); - - /* Make sure the SMBus host is ready to start transmitting */ - /* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */ - if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { - dev_dbg(&I801_dev->dev, "SMBus busy (%02x). Resetting...\n", - temp); - outb_p(temp, SMBHSTSTS); - if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { - dev_dbg(&I801_dev->dev, "Failed! (%02x)\n", temp); - return -1; - } else { - dev_dbg(&I801_dev->dev, "Successful!\n"); + status = inb_p(SMBHSTSTS); + if (status & SMBHSTSTS_HOST_BUSY) { + dev_err(&I801_dev->dev, "SMBus is busy, can't use it!\n"); + return -EBUSY; + } + + status &= STATUS_FLAGS; + if (status) { + dev_dbg(&I801_dev->dev, "Clearing status flags (%02x)\n", + status); + outb_p(status, SMBHSTSTS); + status = inb_p(SMBHSTSTS) & STATUS_FLAGS; + if (status) { + dev_err(&I801_dev->dev, + "Failed clearing status flags (%02x)\n", + status); + return -EBUSY; } } - /* the current contents of SMBHSTCNT can be overwritten, since PEC, - * INTREN, SMBSCMD are passed in xact */ - outb_p(xact | I801_START, SMBHSTCNT); + return 0; +} - /* We will always wait for a fraction of a second! */ - do { - msleep(1); - temp = inb_p(SMBHSTSTS); - } while ((temp & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT)); +/* Convert the status register to an error code, and clear it. */ +static int i801_check_post(int status, int timeout) +{ + int result = 0; /* If the SMBus is still busy, we give up */ - if (timeout >= MAX_TIMEOUT) { - dev_dbg(&I801_dev->dev, "SMBus Timeout!\n"); - result = -1; + if (timeout) { + dev_err(&I801_dev->dev, "Transaction timeout\n"); /* try to stop the current command */ dev_dbg(&I801_dev->dev, "Terminating the current operation\n"); outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT); msleep(1); outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL), SMBHSTCNT); - } - if (temp & SMBHSTSTS_FAILED) { - result = -1; - dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n"); + /* Check if it worked */ + status = inb_p(SMBHSTSTS); + if ((status & SMBHSTSTS_HOST_BUSY) || + !(status & SMBHSTSTS_FAILED)) + dev_err(&I801_dev->dev, + "Failed terminating the transaction\n"); + outb_p(STATUS_FLAGS, SMBHSTSTS); + return -ETIMEDOUT; } - if (temp & SMBHSTSTS_BUS_ERR) { - result = -1; - dev_err(&I801_dev->dev, "Bus collision! SMBus may be locked " - "until next hard reset. (sorry!)\n"); - /* Clock stops and slave is stuck in mid-transmission */ + if (status & SMBHSTSTS_FAILED) { + result = -EIO; + dev_err(&I801_dev->dev, "Transaction failed\n"); } - - if (temp & SMBHSTSTS_DEV_ERR) { - result = -1; - dev_dbg(&I801_dev->dev, "Error: no response!\n"); + if (status & SMBHSTSTS_DEV_ERR) { + result = -ENXIO; + dev_dbg(&I801_dev->dev, "No response\n"); + } + if (status & SMBHSTSTS_BUS_ERR) { + result = -EAGAIN; + dev_dbg(&I801_dev->dev, "Lost arbitration\n"); } - if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00) - outb_p(inb(SMBHSTSTS), SMBHSTSTS); - - if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { - dev_dbg(&I801_dev->dev, "Failed reset at end of transaction " - "(%02x)\n", temp); + if (result) { + /* Clear error flags */ + outb_p(status & STATUS_FLAGS, SMBHSTSTS); + status = inb_p(SMBHSTSTS) & STATUS_FLAGS; + if (status) { + dev_warn(&I801_dev->dev, "Failed clearing status " + "flags at end of transaction (%02x)\n", + status); + } } - dev_dbg(&I801_dev->dev, "Transaction (post): CNT=%02x, CMD=%02x, " - "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), - inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), - inb_p(SMBHSTDAT1)); + return result; } +static int i801_transaction(int xact) +{ + int status; + int result; + int timeout = 0; + + result = i801_check_pre(); + if (result < 0) + return result; + + /* the current contents of SMBHSTCNT can be overwritten, since PEC, + * INTREN, SMBSCMD are passed in xact */ + outb_p(xact | I801_START, SMBHSTCNT); + + /* We will always wait for a fraction of a second! */ + do { + msleep(1); + status = inb_p(SMBHSTSTS); + } while ((status & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT)); + + result = i801_check_post(status, timeout >= MAX_TIMEOUT); + if (result < 0) + return result; + + outb_p(SMBHSTSTS_INTR, SMBHSTSTS); + return 0; +} + /* wait for INTR bit as advised by Intel */ static void i801_wait_hwpec(void) { int timeout = 0; - int temp; + int status; do { msleep(1); - temp = inb_p(SMBHSTSTS); - } while ((!(temp & SMBHSTSTS_INTR)) + status = inb_p(SMBHSTSTS); + } while ((!(status & SMBHSTSTS_INTR)) && (timeout++ < MAX_TIMEOUT)); if (timeout >= MAX_TIMEOUT) { dev_dbg(&I801_dev->dev, "PEC Timeout!\n"); } - outb_p(temp, SMBHSTSTS); + outb_p(status, SMBHSTSTS); } static int i801_block_transaction_by_block(union i2c_smbus_data *data, char read_write, int hwpec) { int i, len; + int status; inb_p(SMBHSTCNT); /* reset the data buffer index */ @@ -242,14 +277,15 @@ static int i801_block_transaction_by_block(union i2c_smbus_data *data, outb_p(data->block[i+1], SMBBLKDAT); } - if (i801_transaction(I801_BLOCK_DATA | ENABLE_INT9 | - I801_PEC_EN * hwpec)) - return -1; + status = i801_transaction(I801_BLOCK_DATA | ENABLE_INT9 | + I801_PEC_EN * hwpec); + if (status) + return status; if (read_write == I2C_SMBUS_READ) { len = inb_p(SMBHSTDAT0); if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) - return -1; + return -EPROTO; data->block[0] = len; for (i = 0; i < len; i++) @@ -264,10 +300,13 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data, { int i, len; int smbcmd; - int temp; - int result = 0; + int status; + int result; int timeout; - unsigned char errmask; + + result = i801_check_pre(); + if (result < 0) + return result; len = data->block[0]; @@ -291,36 +330,6 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data, } outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT); - dev_dbg(&I801_dev->dev, "Block (pre %d): CNT=%02x, CMD=%02x, " - "ADD=%02x, DAT0=%02x, DAT1=%02x, BLKDAT=%02x\n", i, - inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), - inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1), inb_p(SMBBLKDAT)); - - /* Make sure the SMBus host is ready to start transmitting */ - temp = inb_p(SMBHSTSTS); - if (i == 1) { - /* Erroneous conditions before transaction: - * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */ - errmask = 0x9f; - } else { - /* Erroneous conditions during transaction: - * Failed, Bus_Err, Dev_Err, Intr */ - errmask = 0x1e; - } - if (temp & errmask) { - dev_dbg(&I801_dev->dev, "SMBus busy (%02x). " - "Resetting...\n", temp); - outb_p(temp, SMBHSTSTS); - if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) { - dev_err(&I801_dev->dev, - "Reset failed! (%02x)\n", temp); - return -1; - } - if (i != 1) - /* if die in middle of block transaction, fail */ - return -1; - } - if (i == 1) outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT); @@ -328,41 +337,28 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data, timeout = 0; do { msleep(1); - temp = inb_p(SMBHSTSTS); + status = inb_p(SMBHSTSTS); } - while ((!(temp & SMBHSTSTS_BYTE_DONE)) + while ((!(status & SMBHSTSTS_BYTE_DONE)) && (timeout++ < MAX_TIMEOUT)); - /* If the SMBus is still busy, we give up */ - if (timeout >= MAX_TIMEOUT) { - /* try to stop the current command */ - dev_dbg(&I801_dev->dev, "Terminating the current " - "operation\n"); - outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT); - msleep(1); - outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL), - SMBHSTCNT); - result = -1; - dev_dbg(&I801_dev->dev, "SMBus Timeout!\n"); - } - - if (temp & SMBHSTSTS_FAILED) { - result = -1; - dev_dbg(&I801_dev->dev, - "Error: Failed bus transaction\n"); - } else if (temp & SMBHSTSTS_BUS_ERR) { - result = -1; - dev_err(&I801_dev->dev, "Bus collision!\n"); - } else if (temp & SMBHSTSTS_DEV_ERR) { - result = -1; - dev_dbg(&I801_dev->dev, "Error: no response!\n"); - } + result = i801_check_post(status, timeout >= MAX_TIMEOUT); + if (result < 0) + return result; if (i == 1 && read_write == I2C_SMBUS_READ && command != I2C_SMBUS_I2C_BLOCK_DATA) { len = inb_p(SMBHSTDAT0); - if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) - return -1; + if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) { + dev_err(&I801_dev->dev, + "Illegal SMBus block read size %d\n", + len); + /* Recover */ + while (inb_p(SMBHSTSTS) & SMBHSTSTS_HOST_BUSY) + outb_p(SMBHSTSTS_BYTE_DONE, SMBHSTSTS); + outb_p(SMBHSTSTS_INTR, SMBHSTSTS); + return -EPROTO; + } data->block[0] = len; } @@ -371,30 +367,19 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data, data->block[i] = inb_p(SMBBLKDAT); if (read_write == I2C_SMBUS_WRITE && i+1 <= len) outb_p(data->block[i+1], SMBBLKDAT); - if ((temp & 0x9e) != 0x00) - outb_p(temp, SMBHSTSTS); /* signals SMBBLKDAT ready */ - - if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) { - dev_dbg(&I801_dev->dev, - "Bad status (%02x) at end of transaction\n", - temp); - } - dev_dbg(&I801_dev->dev, "Block (post %d): CNT=%02x, CMD=%02x, " - "ADD=%02x, DAT0=%02x, DAT1=%02x, BLKDAT=%02x\n", i, - inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), - inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1), inb_p(SMBBLKDAT)); - if (result < 0) - return result; + /* signals SMBBLKDAT ready */ + outb_p(SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR, SMBHSTSTS); } - return result; + + return 0; } static int i801_set_block_buffer_mode(void) { outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_E32B, SMBAUXCTL); if ((inb_p(SMBAUXCTL) & SMBAUXCTL_E32B) == 0) - return -1; + return -EIO; return 0; } @@ -414,7 +399,7 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, } else if (!(i801_features & FEATURE_I2C_BLOCK_READ)) { dev_err(&I801_dev->dev, "I2C block read is unsupported!\n"); - return -1; + return -EOPNOTSUPP; } } @@ -449,7 +434,7 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, return result; } -/* Return -1 on error. */ +/* Return negative errno on error. */ static s32 i801_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data * data) @@ -511,10 +496,9 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr, outb_p(command, SMBHSTCMD); block = 1; break; - case I2C_SMBUS_PROC_CALL: default: dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size); - return -1; + return -EOPNOTSUPP; } if (hwpec) /* enable/disable hardware PEC */ @@ -537,7 +521,7 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr, if(block) return ret; if(ret) - return -1; + return ret; if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK)) return 0; @@ -572,7 +556,7 @@ static const struct i2c_algorithm smbus_algorithm = { static struct i2c_adapter i801_adapter = { .owner = THIS_MODULE, .id = I2C_HW_SMBUS_I801, - .class = I2C_CLASS_HWMON, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, .algo = &smbus_algorithm, }; @@ -639,6 +623,10 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id goto exit; } + err = acpi_check_resource_conflict(&dev->resource[SMBBAR]); + if (err) + goto exit; + err = pci_request_region(dev, SMBBAR, i801_driver.name); if (err) { dev_err(&dev->dev, "Failed to request SMBus region " diff --git a/drivers/i2c/busses/i2c-i810.c b/drivers/i2c/busses/i2c-i810.c deleted file mode 100644 index 42e8d94c276f..000000000000 --- a/drivers/i2c/busses/i2c-i810.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - i2c-i810.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 1998, 1999, 2000 Frodo Looijaard <frodol@dds.nl>, - Philip Edelbrock <phil@netroedge.com>, - Ralph Metzler <rjkm@thp.uni-koeln.de>, and - Mark D. Studebaker <mdsxyz123@yahoo.com> - - Based on code written by Ralph Metzler <rjkm@thp.uni-koeln.de> and - Simon Vogl - - 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 - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ -/* - This interfaces to the I810/I815 to provide access to - the DDC Bus and the I2C Bus. - - SUPPORTED DEVICES PCI ID - i810AA 7121 - i810AB 7123 - i810E 7125 - i815 1132 - i845G 2562 -*/ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/pci.h> -#include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> -#include <asm/io.h> - -/* GPIO register locations */ -#define I810_IOCONTROL_OFFSET 0x5000 -#define I810_HVSYNC 0x00 /* not used */ -#define I810_GPIOA 0x10 -#define I810_GPIOB 0x14 - -/* bit locations in the registers */ -#define SCL_DIR_MASK 0x0001 -#define SCL_DIR 0x0002 -#define SCL_VAL_MASK 0x0004 -#define SCL_VAL_OUT 0x0008 -#define SCL_VAL_IN 0x0010 -#define SDA_DIR_MASK 0x0100 -#define SDA_DIR 0x0200 -#define SDA_VAL_MASK 0x0400 -#define SDA_VAL_OUT 0x0800 -#define SDA_VAL_IN 0x1000 - -/* initialization states */ -#define INIT1 0x1 -#define INIT2 0x2 -#define INIT3 0x4 - -/* delays */ -#define CYCLE_DELAY 10 -#define TIMEOUT (HZ / 2) - -static void __iomem *ioaddr; - -/* The i810 GPIO registers have individual masks for each bit - so we never have to read before writing. Nice. */ - -static void bit_i810i2c_setscl(void *data, int val) -{ - writel((val ? SCL_VAL_OUT : 0) | SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK, - ioaddr + I810_GPIOB); - readl(ioaddr + I810_GPIOB); /* flush posted write */ -} - -static void bit_i810i2c_setsda(void *data, int val) -{ - writel((val ? SDA_VAL_OUT : 0) | SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK, - ioaddr + I810_GPIOB); - readl(ioaddr + I810_GPIOB); /* flush posted write */ -} - -/* The GPIO pins are open drain, so the pins could always remain outputs. - However, some chip versions don't latch the inputs unless they - are set as inputs. - We rely on the i2c-algo-bit routines to set the pins high before - reading the input from other chips. Following guidance in the 815 - prog. ref. guide, we do a "dummy write" of 0 to the register before - reading which forces the input value to be latched. We presume this - applies to the 810 as well; shouldn't hurt anyway. This is necessary to get - i2c_algo_bit bit_test=1 to pass. */ - -static int bit_i810i2c_getscl(void *data) -{ - writel(SCL_DIR_MASK, ioaddr + I810_GPIOB); - writel(0, ioaddr + I810_GPIOB); - return (0 != (readl(ioaddr + I810_GPIOB) & SCL_VAL_IN)); -} - -static int bit_i810i2c_getsda(void *data) -{ - writel(SDA_DIR_MASK, ioaddr + I810_GPIOB); - writel(0, ioaddr + I810_GPIOB); - return (0 != (readl(ioaddr + I810_GPIOB) & SDA_VAL_IN)); -} - -static void bit_i810ddc_setscl(void *data, int val) -{ - writel((val ? SCL_VAL_OUT : 0) | SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK, - ioaddr + I810_GPIOA); - readl(ioaddr + I810_GPIOA); /* flush posted write */ -} - -static void bit_i810ddc_setsda(void *data, int val) -{ - writel((val ? SDA_VAL_OUT : 0) | SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK, - ioaddr + I810_GPIOA); - readl(ioaddr + I810_GPIOA); /* flush posted write */ -} - -static int bit_i810ddc_getscl(void *data) -{ - writel(SCL_DIR_MASK, ioaddr + I810_GPIOA); - writel(0, ioaddr + I810_GPIOA); - return (0 != (readl(ioaddr + I810_GPIOA) & SCL_VAL_IN)); -} - -static int bit_i810ddc_getsda(void *data) -{ - writel(SDA_DIR_MASK, ioaddr + I810_GPIOA); - writel(0, ioaddr + I810_GPIOA); - return (0 != (readl(ioaddr + I810_GPIOA) & SDA_VAL_IN)); -} - -static int config_i810(struct pci_dev *dev) -{ - unsigned long cadr; - - /* map I810 memory */ - cadr = dev->resource[1].start; - cadr += I810_IOCONTROL_OFFSET; - cadr &= PCI_BASE_ADDRESS_MEM_MASK; - ioaddr = ioremap_nocache(cadr, 0x1000); - if (ioaddr) { - bit_i810i2c_setscl(NULL, 1); - bit_i810i2c_setsda(NULL, 1); - bit_i810ddc_setscl(NULL, 1); - bit_i810ddc_setsda(NULL, 1); - return 0; - } - return -ENODEV; -} - -static struct i2c_algo_bit_data i810_i2c_bit_data = { - .setsda = bit_i810i2c_setsda, - .setscl = bit_i810i2c_setscl, - .getsda = bit_i810i2c_getsda, - .getscl = bit_i810i2c_getscl, - .udelay = CYCLE_DELAY, - .timeout = TIMEOUT, -}; - -static struct i2c_adapter i810_i2c_adapter = { - .owner = THIS_MODULE, - .id = I2C_HW_B_I810, - .name = "I810/I815 I2C Adapter", - .algo_data = &i810_i2c_bit_data, -}; - -static struct i2c_algo_bit_data i810_ddc_bit_data = { - .setsda = bit_i810ddc_setsda, - .setscl = bit_i810ddc_setscl, - .getsda = bit_i810ddc_getsda, - .getscl = bit_i810ddc_getscl, - .udelay = CYCLE_DELAY, - .timeout = TIMEOUT, -}; - -static struct i2c_adapter i810_ddc_adapter = { - .owner = THIS_MODULE, - .id = I2C_HW_B_I810, - .name = "I810/I815 DDC Adapter", - .algo_data = &i810_ddc_bit_data, -}; - -static struct pci_device_id i810_ids[] __devinitdata = { - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG1) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG3) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810E_IG) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_CGC) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845G_IG) }, - { 0, }, -}; - -MODULE_DEVICE_TABLE (pci, i810_ids); - -static int __devinit i810_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - int retval; - - retval = config_i810(dev); - if (retval) - return retval; - dev_info(&dev->dev, "i810/i815 i2c device found.\n"); - - /* set up the sysfs linkage to our parent device */ - i810_i2c_adapter.dev.parent = &dev->dev; - i810_ddc_adapter.dev.parent = &dev->dev; - - retval = i2c_bit_add_bus(&i810_i2c_adapter); - if (retval) - return retval; - retval = i2c_bit_add_bus(&i810_ddc_adapter); - if (retval) - i2c_del_adapter(&i810_i2c_adapter); - return retval; -} - -static void __devexit i810_remove(struct pci_dev *dev) -{ - i2c_del_adapter(&i810_ddc_adapter); - i2c_del_adapter(&i810_i2c_adapter); - iounmap(ioaddr); -} - -static struct pci_driver i810_driver = { - .name = "i810_smbus", - .id_table = i810_ids, - .probe = i810_probe, - .remove = __devexit_p(i810_remove), -}; - -static int __init i2c_i810_init(void) -{ - return pci_register_driver(&i810_driver); -} - -static void __exit i2c_i810_exit(void) -{ - pci_unregister_driver(&i810_driver); -} - -MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, " - "Philip Edelbrock <phil@netroedge.com>, " - "Ralph Metzler <rjkm@thp.uni-koeln.de>, " - "and Mark D. Studebaker <mdsxyz123@yahoo.com>"); -MODULE_DESCRIPTION("I810/I815 I2C/DDC driver"); -MODULE_LICENSE("GPL"); - -module_init(i2c_i810_init); -module_exit(i2c_i810_exit); diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index 85dbf34382e1..070f078b5f5c 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c @@ -42,13 +42,7 @@ #include <asm/io.h> #include <linux/i2c.h> #include <linux/i2c-id.h> - -#ifdef CONFIG_IBM_OCP -#include <asm/ocp.h> -#include <asm/ibm4xx.h> -#else #include <linux/of_platform.h> -#endif #include "i2c-ibm_iic.h" @@ -665,180 +659,6 @@ static inline u8 iic_clckdiv(unsigned int opb) return (u8)((opb + 9) / 10 - 1); } -#ifdef CONFIG_IBM_OCP -/* - * Register single IIC interface - */ -static int __devinit iic_probe(struct ocp_device *ocp){ - - struct ibm_iic_private* dev; - struct i2c_adapter* adap; - struct ocp_func_iic_data* iic_data = ocp->def->additions; - int ret; - - if (!iic_data) - printk(KERN_WARNING"ibm-iic%d: missing additional data!\n", - ocp->def->index); - - if (!(dev = kzalloc(sizeof(*dev), GFP_KERNEL))) { - printk(KERN_ERR "ibm-iic%d: failed to allocate device data\n", - ocp->def->index); - return -ENOMEM; - } - - dev->idx = ocp->def->index; - ocp_set_drvdata(ocp, dev); - - if (!request_mem_region(ocp->def->paddr, sizeof(struct iic_regs), - "ibm_iic")) { - ret = -EBUSY; - goto fail1; - } - - if (!(dev->vaddr = ioremap(ocp->def->paddr, sizeof(struct iic_regs)))){ - printk(KERN_ERR "ibm-iic%d: failed to ioremap device registers\n", - dev->idx); - ret = -ENXIO; - goto fail2; - } - - init_waitqueue_head(&dev->wq); - - dev->irq = iic_force_poll ? -1 : ocp->def->irq; - if (dev->irq >= 0){ - /* Disable interrupts until we finish initialization, - assumes level-sensitive IRQ setup... - */ - iic_interrupt_mode(dev, 0); - if (request_irq(dev->irq, iic_handler, 0, "IBM IIC", dev)){ - printk(KERN_ERR "ibm-iic%d: request_irq %d failed\n", - dev->idx, dev->irq); - /* Fallback to the polling mode */ - dev->irq = -1; - } - } - - if (dev->irq < 0) - printk(KERN_WARNING "ibm-iic%d: using polling mode\n", - dev->idx); - - /* Board specific settings */ - dev->fast_mode = iic_force_fast ? 1 : (iic_data ? iic_data->fast_mode : 0); - - /* clckdiv is the same for *all* IIC interfaces, - * but I'd rather make a copy than introduce another global. --ebs - */ - dev->clckdiv = iic_clckdiv(ocp_sys_info.opb_bus_freq); - DBG("%d: clckdiv = %d\n", dev->idx, dev->clckdiv); - - /* Initialize IIC interface */ - iic_dev_init(dev); - - /* Register it with i2c layer */ - adap = &dev->adap; - adap->dev.parent = &ocp->dev; - strcpy(adap->name, "IBM IIC"); - i2c_set_adapdata(adap, dev); - adap->id = I2C_HW_OCP; - adap->class = I2C_CLASS_HWMON; - adap->algo = &iic_algo; - adap->client_register = NULL; - adap->client_unregister = NULL; - adap->timeout = 1; - - /* - * If "dev->idx" is negative we consider it as zero. - * The reason to do so is to avoid sysfs names that only make - * sense when there are multiple adapters. - */ - adap->nr = dev->idx >= 0 ? dev->idx : 0; - - if ((ret = i2c_add_numbered_adapter(adap)) < 0) { - printk(KERN_ERR "ibm-iic%d: failed to register i2c adapter\n", - dev->idx); - goto fail; - } - - printk(KERN_INFO "ibm-iic%d: using %s mode\n", dev->idx, - dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)"); - - return 0; - -fail: - if (dev->irq >= 0){ - iic_interrupt_mode(dev, 0); - free_irq(dev->irq, dev); - } - - iounmap(dev->vaddr); -fail2: - release_mem_region(ocp->def->paddr, sizeof(struct iic_regs)); -fail1: - ocp_set_drvdata(ocp, NULL); - kfree(dev); - return ret; -} - -/* - * Cleanup initialized IIC interface - */ -static void __devexit iic_remove(struct ocp_device *ocp) -{ - struct ibm_iic_private* dev = (struct ibm_iic_private*)ocp_get_drvdata(ocp); - BUG_ON(dev == NULL); - if (i2c_del_adapter(&dev->adap)){ - printk(KERN_ERR "ibm-iic%d: failed to delete i2c adapter :(\n", - dev->idx); - /* That's *very* bad, just shutdown IRQ ... */ - if (dev->irq >= 0){ - iic_interrupt_mode(dev, 0); - free_irq(dev->irq, dev); - dev->irq = -1; - } - } else { - if (dev->irq >= 0){ - iic_interrupt_mode(dev, 0); - free_irq(dev->irq, dev); - } - iounmap(dev->vaddr); - release_mem_region(ocp->def->paddr, sizeof(struct iic_regs)); - kfree(dev); - } -} - -static struct ocp_device_id ibm_iic_ids[] __devinitdata = -{ - { .vendor = OCP_VENDOR_IBM, .function = OCP_FUNC_IIC }, - { .vendor = OCP_VENDOR_INVALID } -}; - -MODULE_DEVICE_TABLE(ocp, ibm_iic_ids); - -static struct ocp_driver ibm_iic_driver = -{ - .name = "iic", - .id_table = ibm_iic_ids, - .probe = iic_probe, - .remove = __devexit_p(iic_remove), -#if defined(CONFIG_PM) - .suspend = NULL, - .resume = NULL, -#endif -}; - -static int __init iic_init(void) -{ - printk(KERN_INFO "IBM IIC driver v" DRIVER_VERSION "\n"); - return ocp_register_driver(&ibm_iic_driver); -} - -static void __exit iic_exit(void) -{ - ocp_unregister_driver(&ibm_iic_driver); -} - -#else /* !CONFIG_IBM_OCP */ - static int __devinit iic_request_irq(struct of_device *ofdev, struct ibm_iic_private *dev) { @@ -934,7 +754,7 @@ static int __devinit iic_probe(struct of_device *ofdev, strlcpy(adap->name, "IBM IIC", sizeof(adap->name)); i2c_set_adapdata(adap, dev); adap->id = I2C_HW_OCP; - adap->class = I2C_CLASS_HWMON; + adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; adap->algo = &iic_algo; adap->timeout = 1; adap->nr = dev->idx; @@ -987,11 +807,7 @@ static int __devexit iic_remove(struct of_device *ofdev) } static const struct of_device_id ibm_iic_match[] = { - { .compatible = "ibm,iic-405ex", }, - { .compatible = "ibm,iic-405gp", }, - { .compatible = "ibm,iic-440gp", }, - { .compatible = "ibm,iic-440gpx", }, - { .compatible = "ibm,iic-440grx", }, + { .compatible = "ibm,iic", }, {} }; @@ -1011,7 +827,6 @@ static void __exit iic_exit(void) { of_unregister_platform_driver(&ibm_iic_driver); } -#endif /* CONFIG_IBM_OCP */ module_init(iic_init); module_exit(iic_exit); diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c index 39884e797594..fc2714ac0c0f 100644 --- a/drivers/i2c/busses/i2c-iop3xx.c +++ b/drivers/i2c/busses/i2c-iop3xx.c @@ -482,7 +482,7 @@ iop3xx_i2c_probe(struct platform_device *pdev) memcpy(new_adapter->name, pdev->name, strlen(pdev->name)); new_adapter->id = I2C_HW_IOP3XX; new_adapter->owner = THIS_MODULE; - new_adapter->class = I2C_CLASS_HWMON; + new_adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; new_adapter->dev.parent = &pdev->dev; new_adapter->nr = pdev->id; diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c new file mode 100644 index 000000000000..b9c01aa90036 --- /dev/null +++ b/drivers/i2c/busses/i2c-isch.c @@ -0,0 +1,339 @@ +/* + i2c-isch.c - Linux kernel driver for Intel SCH chipset SMBus + - Based on i2c-piix4.c + Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl> and + Philip Edelbrock <phil@netroedge.com> + - Intel SCH support + Copyright (c) 2007 - 2008 Jacob Jun Pan <jacob.jun.pan@intel.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + Supports: + Intel SCH chipsets (AF82US15W, AF82US15L, AF82UL11L) + Note: we assume there can only be one device, with one SMBus interface. +*/ + +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/kernel.h> +#include <linux/delay.h> +#include <linux/stddef.h> +#include <linux/ioport.h> +#include <linux/i2c.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/acpi.h> + +/* SCH SMBus address offsets */ +#define SMBHSTCNT (0 + sch_smba) +#define SMBHSTSTS (1 + sch_smba) +#define SMBHSTADD (4 + sch_smba) /* TSA */ +#define SMBHSTCMD (5 + sch_smba) +#define SMBHSTDAT0 (6 + sch_smba) +#define SMBHSTDAT1 (7 + sch_smba) +#define SMBBLKDAT (0x20 + sch_smba) + +/* count for request_region */ +#define SMBIOSIZE 64 + +/* PCI Address Constants */ +#define SMBBA_SCH 0x40 + +/* Other settings */ +#define MAX_TIMEOUT 500 + +/* I2C constants */ +#define SCH_QUICK 0x00 +#define SCH_BYTE 0x01 +#define SCH_BYTE_DATA 0x02 +#define SCH_WORD_DATA 0x03 +#define SCH_BLOCK_DATA 0x05 + +static unsigned short sch_smba; +static struct pci_driver sch_driver; +static struct i2c_adapter sch_adapter; + +/* + * Start the i2c transaction -- the i2c_access will prepare the transaction + * and this function will execute it. + * return 0 for success and others for failure. + */ +static int sch_transaction(void) +{ + int temp; + int result = 0; + int timeout = 0; + + dev_dbg(&sch_adapter.dev, "Transaction (pre): CNT=%02x, CMD=%02x, " + "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb(SMBHSTCNT), + inb(SMBHSTCMD), inb(SMBHSTADD), inb(SMBHSTDAT0), + inb(SMBHSTDAT1)); + + /* Make sure the SMBus host is ready to start transmitting */ + temp = inb(SMBHSTSTS) & 0x0f; + if (temp) { + /* Can not be busy since we checked it in sch_access */ + if (temp & 0x01) { + dev_dbg(&sch_adapter.dev, "Completion (%02x). " + "Clear...\n", temp); + } + if (temp & 0x06) { + dev_dbg(&sch_adapter.dev, "SMBus error (%02x). " + "Resetting...\n", temp); + } + outb(temp, SMBHSTSTS); + temp = inb(SMBHSTSTS) & 0x0f; + if (temp) { + dev_err(&sch_adapter.dev, + "SMBus is not ready: (%02x)\n", temp); + return -EAGAIN; + } + } + + /* start the transaction by setting bit 4 */ + outb(inb(SMBHSTCNT) | 0x10, SMBHSTCNT); + + do { + msleep(1); + temp = inb(SMBHSTSTS) & 0x0f; + } while ((temp & 0x08) && (timeout++ < MAX_TIMEOUT)); + + /* If the SMBus is still busy, we give up */ + if (timeout >= MAX_TIMEOUT) { + dev_err(&sch_adapter.dev, "SMBus Timeout!\n"); + result = -ETIMEDOUT; + } + if (temp & 0x04) { + result = -EIO; + dev_dbg(&sch_adapter.dev, "Bus collision! SMBus may be " + "locked until next hard reset. (sorry!)\n"); + /* Clock stops and slave is stuck in mid-transmission */ + } else if (temp & 0x02) { + result = -EIO; + dev_err(&sch_adapter.dev, "Error: no response!\n"); + } else if (temp & 0x01) { + dev_dbg(&sch_adapter.dev, "Post complete!\n"); + outb(temp, SMBHSTSTS); + temp = inb(SMBHSTSTS) & 0x07; + if (temp & 0x06) { + /* Completion clear failed */ + dev_dbg(&sch_adapter.dev, "Failed reset at end of " + "transaction (%02x), Bus error!\n", temp); + } + } else { + result = -ENXIO; + dev_dbg(&sch_adapter.dev, "No such address.\n"); + } + dev_dbg(&sch_adapter.dev, "Transaction (post): CNT=%02x, CMD=%02x, " + "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb(SMBHSTCNT), + inb(SMBHSTCMD), inb(SMBHSTADD), inb(SMBHSTDAT0), + inb(SMBHSTDAT1)); + return result; +} + +/* + * This is the main access entry for i2c-sch access + * adap is i2c_adapter pointer, addr is the i2c device bus address, read_write + * (0 for read and 1 for write), size is i2c transaction type and data is the + * union of transaction for data to be transfered or data read from bus. + * return 0 for success and others for failure. + */ +static s32 sch_access(struct i2c_adapter *adap, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, union i2c_smbus_data *data) +{ + int i, len, temp, rc; + + /* Make sure the SMBus host is not busy */ + temp = inb(SMBHSTSTS) & 0x0f; + if (temp & 0x08) { + dev_dbg(&sch_adapter.dev, "SMBus busy (%02x)\n", temp); + return -EAGAIN; + } + dev_dbg(&sch_adapter.dev, "access size: %d %s\n", size, + (read_write)?"READ":"WRITE"); + switch (size) { + case I2C_SMBUS_QUICK: + outb((addr << 1) | read_write, SMBHSTADD); + size = SCH_QUICK; + break; + case I2C_SMBUS_BYTE: + outb((addr << 1) | read_write, SMBHSTADD); + if (read_write == I2C_SMBUS_WRITE) + outb(command, SMBHSTCMD); + size = SCH_BYTE; + break; + case I2C_SMBUS_BYTE_DATA: + outb((addr << 1) | read_write, SMBHSTADD); + outb(command, SMBHSTCMD); + if (read_write == I2C_SMBUS_WRITE) + outb(data->byte, SMBHSTDAT0); + size = SCH_BYTE_DATA; + break; + case I2C_SMBUS_WORD_DATA: + outb((addr << 1) | read_write, SMBHSTADD); + outb(command, SMBHSTCMD); + if (read_write == I2C_SMBUS_WRITE) { + outb(data->word & 0xff, SMBHSTDAT0); + outb((data->word & 0xff00) >> 8, SMBHSTDAT1); + } + size = SCH_WORD_DATA; + break; + case I2C_SMBUS_BLOCK_DATA: + outb((addr << 1) | read_write, SMBHSTADD); + outb(command, SMBHSTCMD); + if (read_write == I2C_SMBUS_WRITE) { + len = data->block[0]; + if (len == 0 || len > I2C_SMBUS_BLOCK_MAX) + return -EINVAL; + outb(len, SMBHSTDAT0); + for (i = 1; i <= len; i++) + outb(data->block[i], SMBBLKDAT+i-1); + } + size = SCH_BLOCK_DATA; + break; + default: + dev_warn(&adap->dev, "Unsupported transaction %d\n", size); + return -EOPNOTSUPP; + } + dev_dbg(&sch_adapter.dev, "write size %d to 0x%04x\n", size, SMBHSTCNT); + outb((inb(SMBHSTCNT) & 0xb0) | (size & 0x7), SMBHSTCNT); + + rc = sch_transaction(); + if (rc) /* Error in transaction */ + return rc; + + if ((read_write == I2C_SMBUS_WRITE) || (size == SCH_QUICK)) + return 0; + + switch (size) { + case SCH_BYTE: + case SCH_BYTE_DATA: + data->byte = inb(SMBHSTDAT0); + break; + case SCH_WORD_DATA: + data->word = inb(SMBHSTDAT0) + (inb(SMBHSTDAT1) << 8); + break; + case SCH_BLOCK_DATA: + data->block[0] = inb(SMBHSTDAT0); + if (data->block[0] == 0 || data->block[0] > I2C_SMBUS_BLOCK_MAX) + return -EPROTO; + for (i = 1; i <= data->block[0]; i++) + data->block[i] = inb(SMBBLKDAT+i-1); + break; + } + return 0; +} + +static u32 sch_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_BLOCK_DATA; +} + +static const struct i2c_algorithm smbus_algorithm = { + .smbus_xfer = sch_access, + .functionality = sch_func, +}; + +static struct i2c_adapter sch_adapter = { + .owner = THIS_MODULE, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, + .algo = &smbus_algorithm, +}; + +static struct pci_device_id sch_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) }, + { 0, } +}; + +MODULE_DEVICE_TABLE(pci, sch_ids); + +static int __devinit sch_probe(struct pci_dev *dev, + const struct pci_device_id *id) +{ + int retval; + unsigned int smba; + + pci_read_config_dword(dev, SMBBA_SCH, &smba); + if (!(smba & (1 << 31))) { + dev_err(&dev->dev, "SMBus I/O space disabled!\n"); + return -ENODEV; + } + + sch_smba = (unsigned short)smba; + if (sch_smba == 0) { + dev_err(&dev->dev, "SMBus base address uninitialized!\n"); + return -ENODEV; + } + if (acpi_check_region(sch_smba, SMBIOSIZE, sch_driver.name)) + return -EBUSY; + if (!request_region(sch_smba, SMBIOSIZE, sch_driver.name)) { + dev_err(&dev->dev, "SMBus region 0x%x already in use!\n", + sch_smba); + return -EBUSY; + } + dev_dbg(&dev->dev, "SMBA = 0x%X\n", sch_smba); + + /* set up the sysfs linkage to our parent device */ + sch_adapter.dev.parent = &dev->dev; + + snprintf(sch_adapter.name, sizeof(sch_adapter.name), + "SMBus SCH adapter at %04x", sch_smba); + + retval = i2c_add_adapter(&sch_adapter); + if (retval) { + dev_err(&dev->dev, "Couldn't register adapter!\n"); + release_region(sch_smba, SMBIOSIZE); + sch_smba = 0; + } + + return retval; +} + +static void __devexit sch_remove(struct pci_dev *dev) +{ + if (sch_smba) { + i2c_del_adapter(&sch_adapter); + release_region(sch_smba, SMBIOSIZE); + sch_smba = 0; + } +} + +static struct pci_driver sch_driver = { + .name = "isch_smbus", + .id_table = sch_ids, + .probe = sch_probe, + .remove = __devexit_p(sch_remove), +}; + +static int __init i2c_sch_init(void) +{ + return pci_register_driver(&sch_driver); +} + +static void __exit i2c_sch_exit(void) +{ + pci_unregister_driver(&sch_driver); +} + +MODULE_AUTHOR("Jacob Pan <jacob.jun.pan@intel.com>"); +MODULE_DESCRIPTION("Intel SCH SMBus driver"); +MODULE_LICENSE("GPL"); + +module_init(i2c_sch_init); +module_exit(i2c_sch_exit); diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index a076129de7e8..aaaea85ce1ca 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -17,7 +17,8 @@ #include <linux/module.h> #include <linux/sched.h> #include <linux/init.h> -#include <linux/platform_device.h> +#include <linux/of_platform.h> +#include <linux/of_i2c.h> #include <asm/io.h> #include <linux/fsl_devices.h> @@ -25,13 +26,13 @@ #include <linux/interrupt.h> #include <linux/delay.h> -#define MPC_I2C_ADDR 0x00 +#define DRV_NAME "mpc-i2c" + #define MPC_I2C_FDR 0x04 #define MPC_I2C_CR 0x08 #define MPC_I2C_SR 0x0c #define MPC_I2C_DR 0x10 #define MPC_I2C_DFSRR 0x14 -#define MPC_I2C_REGION 0x20 #define CCR_MEN 0x80 #define CCR_MIEN 0x40 @@ -311,106 +312,123 @@ static struct i2c_adapter mpc_ops = { .name = "MPC adapter", .id = I2C_HW_MPC107, .algo = &mpc_algo, - .class = I2C_CLASS_HWMON, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, .timeout = 1, }; -static int fsl_i2c_probe(struct platform_device *pdev) +static int __devinit fsl_i2c_probe(struct of_device *op, + const struct of_device_id *match) { int result = 0; struct mpc_i2c *i2c; - struct fsl_i2c_platform_data *pdata; - struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - pdata = (struct fsl_i2c_platform_data *) pdev->dev.platform_data; i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); if (!i2c) return -ENOMEM; - i2c->irq = platform_get_irq(pdev, 0); - if (i2c->irq < 0) - i2c->irq = NO_IRQ; /* Use polling */ + if (of_get_property(op->node, "dfsrr", NULL)) + i2c->flags |= FSL_I2C_DEV_SEPARATE_DFSRR; - i2c->flags = pdata->device_flags; - init_waitqueue_head(&i2c->queue); + if (of_device_is_compatible(op->node, "fsl,mpc5200-i2c") || + of_device_is_compatible(op->node, "mpc5200-i2c")) + i2c->flags |= FSL_I2C_DEV_CLOCK_5200; - i2c->base = ioremap((phys_addr_t)r->start, MPC_I2C_REGION); + init_waitqueue_head(&i2c->queue); + i2c->base = of_iomap(op->node, 0); if (!i2c->base) { printk(KERN_ERR "i2c-mpc - failed to map controller\n"); result = -ENOMEM; goto fail_map; } - if (i2c->irq != NO_IRQ) - if ((result = request_irq(i2c->irq, mpc_i2c_isr, - IRQF_SHARED, "i2c-mpc", i2c)) < 0) { + i2c->irq = irq_of_parse_and_map(op->node, 0); + if (i2c->irq != NO_IRQ) { /* i2c->irq = NO_IRQ implies polling */ + result = request_irq(i2c->irq, mpc_i2c_isr, + IRQF_SHARED, "i2c-mpc", i2c); + if (result < 0) { printk(KERN_ERR "i2c-mpc - failed to attach interrupt\n"); goto fail_irq; } + } mpc_i2c_setclock(i2c); - platform_set_drvdata(pdev, i2c); + dev_set_drvdata(&op->dev, i2c); i2c->adap = mpc_ops; - i2c->adap.nr = pdev->id; i2c_set_adapdata(&i2c->adap, i2c); - i2c->adap.dev.parent = &pdev->dev; - if ((result = i2c_add_numbered_adapter(&i2c->adap)) < 0) { + i2c->adap.dev.parent = &op->dev; + + result = i2c_add_adapter(&i2c->adap); + if (result < 0) { printk(KERN_ERR "i2c-mpc - failed to add adapter\n"); goto fail_add; } + of_register_i2c_devices(&i2c->adap, op->node); return result; - fail_add: + fail_add: + dev_set_drvdata(&op->dev, NULL); if (i2c->irq != NO_IRQ) free_irq(i2c->irq, i2c); - fail_irq: + fail_irq: + irq_dispose_mapping(i2c->irq); iounmap(i2c->base); - fail_map: + fail_map: kfree(i2c); return result; }; -static int fsl_i2c_remove(struct platform_device *pdev) +static int __devexit fsl_i2c_remove(struct of_device *op) { - struct mpc_i2c *i2c = platform_get_drvdata(pdev); + struct mpc_i2c *i2c = dev_get_drvdata(&op->dev); i2c_del_adapter(&i2c->adap); - platform_set_drvdata(pdev, NULL); + dev_set_drvdata(&op->dev, NULL); if (i2c->irq != NO_IRQ) free_irq(i2c->irq, i2c); + irq_dispose_mapping(i2c->irq); iounmap(i2c->base); kfree(i2c); return 0; }; -/* work with hotplug and coldplug */ -MODULE_ALIAS("platform:fsl-i2c"); +static const struct of_device_id mpc_i2c_of_match[] = { + {.compatible = "fsl-i2c",}, + {}, +}; +MODULE_DEVICE_TABLE(of, mpc_i2c_of_match); + /* Structure for a device driver */ -static struct platform_driver fsl_i2c_driver = { - .probe = fsl_i2c_probe, - .remove = fsl_i2c_remove, - .driver = { - .owner = THIS_MODULE, - .name = "fsl-i2c", +static struct of_platform_driver mpc_i2c_driver = { + .match_table = mpc_i2c_of_match, + .probe = fsl_i2c_probe, + .remove = __devexit_p(fsl_i2c_remove), + .driver = { + .owner = THIS_MODULE, + .name = DRV_NAME, }, }; static int __init fsl_i2c_init(void) { - return platform_driver_register(&fsl_i2c_driver); + int rv; + + rv = of_register_platform_driver(&mpc_i2c_driver); + if (rv) + printk(KERN_ERR DRV_NAME + " of_register_platform_driver failed (%i)\n", rv); + return rv; } static void __exit fsl_i2c_exit(void) { - platform_driver_unregister(&fsl_i2c_driver); + of_unregister_platform_driver(&mpc_i2c_driver); } module_init(fsl_i2c_init); diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index 036e6a883e67..9e8118d2fe64 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -530,7 +530,7 @@ mv64xxx_i2c_probe(struct platform_device *pd) drv_data->adapter.id = I2C_HW_MV64XXX; drv_data->adapter.algo = &mv64xxx_i2c_algo; drv_data->adapter.owner = THIS_MODULE; - drv_data->adapter.class = I2C_CLASS_HWMON; + drv_data->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; drv_data->adapter.timeout = pdata->timeout; drv_data->adapter.nr = pd->id; platform_set_drvdata(pd, drv_data); diff --git a/drivers/i2c/busses/i2c-nforce2-s4985.c b/drivers/i2c/busses/i2c-nforce2-s4985.c new file mode 100644 index 000000000000..6a8995dfd0bb --- /dev/null +++ b/drivers/i2c/busses/i2c-nforce2-s4985.c @@ -0,0 +1,257 @@ +/* + * i2c-nforce2-s4985.c - i2c-nforce2 extras for the Tyan S4985 motherboard + * + * Copyright (C) 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * We select the channels by sending commands to the Philips + * PCA9556 chip at I2C address 0x18. The main adapter is used for + * the non-multiplexed part of the bus, and 4 virtual adapters + * are defined for the multiplexed addresses: 0x50-0x53 (memory + * module EEPROM) located on channels 1-4. We define one virtual + * adapter per CPU, which corresponds to one multiplexed channel: + * CPU0: virtual adapter 1, channel 1 + * CPU1: virtual adapter 2, channel 2 + * CPU2: virtual adapter 3, channel 3 + * CPU3: virtual adapter 4, channel 4 + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/init.h> +#include <linux/i2c.h> +#include <linux/mutex.h> + +extern struct i2c_adapter *nforce2_smbus; + +static struct i2c_adapter *s4985_adapter; +static struct i2c_algorithm *s4985_algo; + +/* Wrapper access functions for multiplexed SMBus */ +static DEFINE_MUTEX(nforce2_lock); + +static s32 nforce2_access_virt0(struct i2c_adapter *adap, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, + union i2c_smbus_data *data) +{ + int error; + + /* We exclude the multiplexed addresses */ + if ((addr & 0xfc) == 0x50 || (addr & 0xfc) == 0x30 + || addr == 0x18) + return -ENXIO; + + mutex_lock(&nforce2_lock); + error = nforce2_smbus->algo->smbus_xfer(adap, addr, flags, read_write, + command, size, data); + mutex_unlock(&nforce2_lock); + + return error; +} + +/* We remember the last used channels combination so as to only switch + channels when it is really needed. This greatly reduces the SMBus + overhead, but also assumes that nobody will be writing to the PCA9556 + in our back. */ +static u8 last_channels; + +static inline s32 nforce2_access_channel(struct i2c_adapter *adap, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, + union i2c_smbus_data *data, + u8 channels) +{ + int error; + + /* We exclude the non-multiplexed addresses */ + if ((addr & 0xfc) != 0x50 && (addr & 0xfc) != 0x30) + return -ENXIO; + + mutex_lock(&nforce2_lock); + if (last_channels != channels) { + union i2c_smbus_data mplxdata; + mplxdata.byte = channels; + + error = nforce2_smbus->algo->smbus_xfer(adap, 0x18, 0, + I2C_SMBUS_WRITE, 0x01, + I2C_SMBUS_BYTE_DATA, + &mplxdata); + if (error) + goto UNLOCK; + last_channels = channels; + } + error = nforce2_smbus->algo->smbus_xfer(adap, addr, flags, read_write, + command, size, data); + +UNLOCK: + mutex_unlock(&nforce2_lock); + return error; +} + +static s32 nforce2_access_virt1(struct i2c_adapter *adap, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, + union i2c_smbus_data *data) +{ + /* CPU0: channel 1 enabled */ + return nforce2_access_channel(adap, addr, flags, read_write, command, + size, data, 0x02); +} + +static s32 nforce2_access_virt2(struct i2c_adapter *adap, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, + union i2c_smbus_data *data) +{ + /* CPU1: channel 2 enabled */ + return nforce2_access_channel(adap, addr, flags, read_write, command, + size, data, 0x04); +} + +static s32 nforce2_access_virt3(struct i2c_adapter *adap, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, + union i2c_smbus_data *data) +{ + /* CPU2: channel 3 enabled */ + return nforce2_access_channel(adap, addr, flags, read_write, command, + size, data, 0x08); +} + +static s32 nforce2_access_virt4(struct i2c_adapter *adap, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, + union i2c_smbus_data *data) +{ + /* CPU3: channel 4 enabled */ + return nforce2_access_channel(adap, addr, flags, read_write, command, + size, data, 0x10); +} + +static int __init nforce2_s4985_init(void) +{ + int i, error; + union i2c_smbus_data ioconfig; + + /* Unregister physical bus */ + if (!nforce2_smbus) + return -ENODEV; + error = i2c_del_adapter(nforce2_smbus); + if (error) { + dev_err(&nforce2_smbus->dev, "Physical bus removal failed\n"); + goto ERROR0; + } + + printk(KERN_INFO "Enabling SMBus multiplexing for Tyan S4985\n"); + /* Define the 5 virtual adapters and algorithms structures */ + s4985_adapter = kzalloc(5 * sizeof(struct i2c_adapter), GFP_KERNEL); + if (!s4985_adapter) { + error = -ENOMEM; + goto ERROR1; + } + s4985_algo = kzalloc(5 * sizeof(struct i2c_algorithm), GFP_KERNEL); + if (!s4985_algo) { + error = -ENOMEM; + goto ERROR2; + } + + /* Fill in the new structures */ + s4985_algo[0] = *(nforce2_smbus->algo); + s4985_algo[0].smbus_xfer = nforce2_access_virt0; + s4985_adapter[0] = *nforce2_smbus; + s4985_adapter[0].algo = s4985_algo; + s4985_adapter[0].dev.parent = nforce2_smbus->dev.parent; + for (i = 1; i < 5; i++) { + s4985_algo[i] = *(nforce2_smbus->algo); + s4985_adapter[i] = *nforce2_smbus; + snprintf(s4985_adapter[i].name, sizeof(s4985_adapter[i].name), + "SMBus nForce2 adapter (CPU%d)", i - 1); + s4985_adapter[i].algo = s4985_algo + i; + s4985_adapter[i].dev.parent = nforce2_smbus->dev.parent; + } + s4985_algo[1].smbus_xfer = nforce2_access_virt1; + s4985_algo[2].smbus_xfer = nforce2_access_virt2; + s4985_algo[3].smbus_xfer = nforce2_access_virt3; + s4985_algo[4].smbus_xfer = nforce2_access_virt4; + + /* Configure the PCA9556 multiplexer */ + ioconfig.byte = 0x00; /* All I/O to output mode */ + error = nforce2_smbus->algo->smbus_xfer(nforce2_smbus, 0x18, 0, + I2C_SMBUS_WRITE, 0x03, + I2C_SMBUS_BYTE_DATA, &ioconfig); + if (error) { + dev_err(&nforce2_smbus->dev, "PCA9556 configuration failed\n"); + error = -EIO; + goto ERROR3; + } + + /* Register virtual adapters */ + for (i = 0; i < 5; i++) { + error = i2c_add_adapter(s4985_adapter + i); + if (error) { + dev_err(&nforce2_smbus->dev, + "Virtual adapter %d registration " + "failed, module not inserted\n", i); + for (i--; i >= 0; i--) + i2c_del_adapter(s4985_adapter + i); + goto ERROR3; + } + } + + return 0; + +ERROR3: + kfree(s4985_algo); + s4985_algo = NULL; +ERROR2: + kfree(s4985_adapter); + s4985_adapter = NULL; +ERROR1: + /* Restore physical bus */ + i2c_add_adapter(nforce2_smbus); +ERROR0: + return error; +} + +static void __exit nforce2_s4985_exit(void) +{ + if (s4985_adapter) { + int i; + + for (i = 0; i < 5; i++) + i2c_del_adapter(s4985_adapter+i); + kfree(s4985_adapter); + s4985_adapter = NULL; + } + kfree(s4985_algo); + s4985_algo = NULL; + + /* Restore physical bus */ + if (i2c_add_adapter(nforce2_smbus)) + dev_err(&nforce2_smbus->dev, "Physical bus restoration " + "failed\n"); +} + +MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); +MODULE_DESCRIPTION("S4985 SMBus multiplexing"); +MODULE_LICENSE("GPL"); + +module_init(nforce2_s4985_init); +module_exit(nforce2_s4985_exit); diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c index 43c9f8df9509..3b19bc41a60b 100644 --- a/drivers/i2c/busses/i2c-nforce2.c +++ b/drivers/i2c/busses/i2c-nforce2.c @@ -51,6 +51,7 @@ #include <linux/i2c.h> #include <linux/delay.h> #include <linux/dmi.h> +#include <linux/acpi.h> #include <asm/io.h> MODULE_LICENSE("GPL"); @@ -124,6 +125,20 @@ static struct dmi_system_id __devinitdata nforce2_dmi_blacklist2[] = { static struct pci_driver nforce2_driver; +/* For multiplexing support, we need a global reference to the 1st + SMBus channel */ +#if defined CONFIG_I2C_NFORCE2_S4985 || defined CONFIG_I2C_NFORCE2_S4985_MODULE +struct i2c_adapter *nforce2_smbus; +EXPORT_SYMBOL_GPL(nforce2_smbus); + +static void nforce2_set_reference(struct i2c_adapter *adap) +{ + nforce2_smbus = adap; +} +#else +static inline void nforce2_set_reference(struct i2c_adapter *adap) { } +#endif + static void nforce2_abort(struct i2c_adapter *adap) { struct nforce2_smbus *smbus = adap->algo_data; @@ -158,16 +173,16 @@ static int nforce2_check_status(struct i2c_adapter *adap) dev_dbg(&adap->dev, "SMBus Timeout!\n"); if (smbus->can_abort) nforce2_abort(adap); - return -1; + return -ETIMEDOUT; } if (!(temp & NVIDIA_SMB_STS_DONE) || (temp & NVIDIA_SMB_STS_STATUS)) { dev_dbg(&adap->dev, "Transaction failed (0x%02x)!\n", temp); - return -1; + return -EIO; } return 0; } -/* Return -1 on error */ +/* Return negative errno on error */ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data * data) @@ -175,7 +190,7 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr, struct nforce2_smbus *smbus = adap->algo_data; unsigned char protocol, pec; u8 len; - int i; + int i, status; protocol = (read_write == I2C_SMBUS_READ) ? NVIDIA_SMB_PRTCL_READ : NVIDIA_SMB_PRTCL_WRITE; @@ -219,7 +234,7 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr, "Transaction failed " "(requested block size: %d)\n", len); - return -1; + return -EINVAL; } outb_p(len, NVIDIA_SMB_BCNT); for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++) @@ -231,14 +246,15 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr, default: dev_err(&adap->dev, "Unsupported transaction %d\n", size); - return -1; + return -EOPNOTSUPP; } outb_p((addr & 0x7f) << 1, NVIDIA_SMB_ADDR); outb_p(protocol, NVIDIA_SMB_PRTCL); - if (nforce2_check_status(adap)) - return -1; + status = nforce2_check_status(adap); + if (status) + return status; if (read_write == I2C_SMBUS_WRITE) return 0; @@ -260,7 +276,7 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr, dev_err(&adap->dev, "Transaction failed " "(received block size: 0x%02x)\n", len); - return -1; + return -EPROTO; } for (i = 0; i < len; i++) data->block[i+1] = inb_p(NVIDIA_SMB_DATA + i); @@ -321,21 +337,26 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar, != PCIBIOS_SUCCESSFUL) { dev_err(&dev->dev, "Error reading PCI config for %s\n", name); - return -1; + return -EIO; } smbus->base = iobase & PCI_BASE_ADDRESS_IO_MASK; smbus->size = 64; } + error = acpi_check_region(smbus->base, smbus->size, + nforce2_driver.name); + if (error) + return -1; + if (!request_region(smbus->base, smbus->size, nforce2_driver.name)) { dev_err(&smbus->adapter.dev, "Error requesting region %02x .. %02X for %s\n", smbus->base, smbus->base+smbus->size-1, name); - return -1; + return -EBUSY; } smbus->adapter.owner = THIS_MODULE; smbus->adapter.id = I2C_HW_SMBUS_NFORCE2; - smbus->adapter.class = I2C_CLASS_HWMON; + smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; smbus->adapter.algo = &smbus_algorithm; smbus->adapter.algo_data = smbus; smbus->adapter.dev.parent = &dev->dev; @@ -346,7 +367,7 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar, if (error) { dev_err(&smbus->adapter.dev, "Failed to register adapter.\n"); release_region(smbus->base, smbus->size); - return -1; + return error; } dev_info(&smbus->adapter.dev, "nForce2 SMBus adapter at %#x\n", smbus->base); return 0; @@ -398,6 +419,7 @@ static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_ return -ENODEV; } + nforce2_set_reference(&smbuses[0].adapter); return 0; } @@ -406,6 +428,7 @@ static void __devexit nforce2_remove(struct pci_dev *dev) { struct nforce2_smbus *smbuses = (void*) pci_get_drvdata(dev); + nforce2_set_reference(NULL); if (smbuses[0].base) { i2c_del_adapter(&smbuses[0].adapter); release_region(smbuses[0].base, smbuses[0].size); diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index f145692cbb76..e5193bf75483 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -29,6 +29,7 @@ struct ocores_i2c { int pos; int nmsgs; int state; /* see STATE_ */ + int clock_khz; }; /* registers */ @@ -173,8 +174,7 @@ static int ocores_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) return -ETIMEDOUT; } -static void ocores_init(struct ocores_i2c *i2c, - struct ocores_i2c_platform_data *pdata) +static void ocores_init(struct ocores_i2c *i2c) { int prescale; u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL); @@ -182,7 +182,7 @@ static void ocores_init(struct ocores_i2c *i2c, /* make sure the device is disabled */ oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN)); - prescale = (pdata->clock_khz / (5*100)) - 1; + prescale = (i2c->clock_khz / (5*100)) - 1; oc_setreg(i2c, OCI2C_PRELOW, prescale & 0xff); oc_setreg(i2c, OCI2C_PREHIGH, prescale >> 8); @@ -205,7 +205,7 @@ static const struct i2c_algorithm ocores_algorithm = { static struct i2c_adapter ocores_adapter = { .owner = THIS_MODULE, .name = "i2c-ocores", - .class = I2C_CLASS_HWMON, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, .algo = &ocores_algorithm, }; @@ -248,7 +248,8 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev) } i2c->regstep = pdata->regstep; - ocores_init(i2c, pdata); + i2c->clock_khz = pdata->clock_khz; + ocores_init(i2c); init_waitqueue_head(&i2c->wait); ret = request_irq(res2->start, ocores_isr, 0, pdev->name, i2c); @@ -312,13 +313,40 @@ static int __devexit ocores_i2c_remove(struct platform_device* pdev) return 0; } +#ifdef CONFIG_PM +static int ocores_i2c_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct ocores_i2c *i2c = platform_get_drvdata(pdev); + u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL); + + /* make sure the device is disabled */ + oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN)); + + return 0; +} + +static int ocores_i2c_resume(struct platform_device *pdev) +{ + struct ocores_i2c *i2c = platform_get_drvdata(pdev); + + ocores_init(i2c); + + return 0; +} +#else +#define ocores_i2c_suspend NULL +#define ocores_i2c_resume NULL +#endif + /* work with hotplug and coldplug */ MODULE_ALIAS("platform:ocores-i2c"); static struct platform_driver ocores_i2c_driver = { - .probe = ocores_i2c_probe, - .remove = __devexit_p(ocores_i2c_remove), - .driver = { + .probe = ocores_i2c_probe, + .remove = __devexit_p(ocores_i2c_remove), + .suspend = ocores_i2c_suspend, + .resume = ocores_i2c_resume, + .driver = { .owner = THIS_MODULE, .name = "ocores-i2c", }, diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c index 1603c81e39d4..adf0fbb902f0 100644 --- a/drivers/i2c/busses/i2c-pasemi.c +++ b/drivers/i2c/busses/i2c-pasemi.c @@ -365,7 +365,7 @@ static int __devinit pasemi_smb_probe(struct pci_dev *dev, smbus->adapter.owner = THIS_MODULE; snprintf(smbus->adapter.name, sizeof(smbus->adapter.name), "PA Semi SMBus adapter at 0x%lx", smbus->base); - smbus->adapter.class = I2C_CLASS_HWMON; + smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; smbus->adapter.algo = &smbus_algorithm; smbus->adapter.algo_data = smbus; smbus->adapter.nr = PCI_FUNC(dev->devfn); diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c index 9d75f51e8f0e..6bb15ad0a6b6 100644 --- a/drivers/i2c/busses/i2c-pca-platform.c +++ b/drivers/i2c/busses/i2c-pca-platform.c @@ -163,7 +163,7 @@ static int __devinit i2c_pca_pf_probe(struct platform_device *pdev) i2c->reg_base = ioremap(res->start, res_len(res)); if (!i2c->reg_base) { - ret = -EIO; + ret = -ENOMEM; goto e_remap; } i2c->io_base = res->start; diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index ac9165968587..eaa9b387543e 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -1,6 +1,4 @@ /* - piix4.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com> @@ -39,16 +37,10 @@ #include <linux/i2c.h> #include <linux/init.h> #include <linux/dmi.h> +#include <linux/acpi.h> #include <asm/io.h> -struct sd { - const unsigned short mfr; - const unsigned short dev; - const unsigned char fn; - const char *name; -}; - /* PIIX4 SMBus address offsets */ #define SMBHSTSTS (0 + piix4_smba) #define SMBHSLVSTS (1 + piix4_smba) @@ -101,8 +93,6 @@ MODULE_PARM_DESC(force_addr, "Forcibly enable the PIIX4 at the given address. " "EXTREMELY DANGEROUS!"); -static int piix4_transaction(void); - static unsigned short piix4_smba; static int srvrworks_csb5_delay; static struct pci_driver piix4_driver; @@ -141,8 +131,6 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev, { unsigned char temp; - dev_info(&PIIX4_dev->dev, "Found %s device\n", pci_name(PIIX4_dev)); - if ((PIIX4_dev->vendor == PCI_VENDOR_ID_SERVERWORKS) && (PIIX4_dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5)) srvrworks_csb5_delay = 1; @@ -172,17 +160,20 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev, pci_read_config_word(PIIX4_dev, SMBBA, &piix4_smba); piix4_smba &= 0xfff0; if(piix4_smba == 0) { - dev_err(&PIIX4_dev->dev, "SMB base address " + dev_err(&PIIX4_dev->dev, "SMBus base address " "uninitialized - upgrade BIOS or use " "force_addr=0xaddr\n"); return -ENODEV; } } + if (acpi_check_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) + return -EBUSY; + if (!request_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) { - dev_err(&PIIX4_dev->dev, "SMB region 0x%x already in use!\n", + dev_err(&PIIX4_dev->dev, "SMBus region 0x%x already in use!\n", piix4_smba); - return -ENODEV; + return -EBUSY; } pci_read_config_byte(PIIX4_dev, SMBHSTCFG, &temp); @@ -228,13 +219,13 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev, "(or code out of date)!\n"); pci_read_config_byte(PIIX4_dev, SMBREV, &temp); - dev_dbg(&PIIX4_dev->dev, "SMBREV = 0x%X\n", temp); - dev_dbg(&PIIX4_dev->dev, "SMBA = 0x%X\n", piix4_smba); + dev_info(&PIIX4_dev->dev, + "SMBus Host Controller at 0x%x, revision %d\n", + piix4_smba, temp); return 0; } -/* Another internally used function */ static int piix4_transaction(void) { int temp; @@ -253,7 +244,7 @@ static int piix4_transaction(void) outb_p(temp, SMBHSTSTS); if ((temp = inb_p(SMBHSTSTS)) != 0x00) { dev_err(&piix4_adapter.dev, "Failed! (%02x)\n", temp); - return -1; + return -EBUSY; } else { dev_dbg(&piix4_adapter.dev, "Successful!\n"); } @@ -275,23 +266,23 @@ static int piix4_transaction(void) /* If the SMBus is still busy, we give up */ if (timeout >= MAX_TIMEOUT) { dev_err(&piix4_adapter.dev, "SMBus Timeout!\n"); - result = -1; + result = -ETIMEDOUT; } if (temp & 0x10) { - result = -1; + result = -EIO; dev_err(&piix4_adapter.dev, "Error: Failed bus transaction\n"); } if (temp & 0x08) { - result = -1; + result = -EIO; dev_dbg(&piix4_adapter.dev, "Bus collision! SMBus may be " "locked until next hard reset. (sorry!)\n"); /* Clock stops and slave is stuck in mid-transmission */ } if (temp & 0x04) { - result = -1; + result = -ENXIO; dev_dbg(&piix4_adapter.dev, "Error: no response!\n"); } @@ -309,31 +300,29 @@ static int piix4_transaction(void) return result; } -/* Return -1 on error. */ +/* Return negative errno on error. */ static s32 piix4_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data * data) { int i, len; + int status; switch (size) { - case I2C_SMBUS_PROC_CALL: - dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n"); - return -1; case I2C_SMBUS_QUICK: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + outb_p((addr << 1) | read_write, SMBHSTADD); size = PIIX4_QUICK; break; case I2C_SMBUS_BYTE: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + outb_p((addr << 1) | read_write, SMBHSTADD); if (read_write == I2C_SMBUS_WRITE) outb_p(command, SMBHSTCMD); size = PIIX4_BYTE; break; case I2C_SMBUS_BYTE_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + outb_p((addr << 1) | read_write, SMBHSTADD); outb_p(command, SMBHSTCMD); if (read_write == I2C_SMBUS_WRITE) @@ -341,7 +330,7 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr, size = PIIX4_BYTE_DATA; break; case I2C_SMBUS_WORD_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + outb_p((addr << 1) | read_write, SMBHSTADD); outb_p(command, SMBHSTCMD); if (read_write == I2C_SMBUS_WRITE) { @@ -351,15 +340,13 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr, size = PIIX4_WORD_DATA; break; case I2C_SMBUS_BLOCK_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + outb_p((addr << 1) | read_write, SMBHSTADD); outb_p(command, SMBHSTCMD); if (read_write == I2C_SMBUS_WRITE) { len = data->block[0]; - if (len < 0) - len = 0; - if (len > 32) - len = 32; + if (len == 0 || len > I2C_SMBUS_BLOCK_MAX) + return -EINVAL; outb_p(len, SMBHSTDAT0); i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ for (i = 1; i <= len; i++) @@ -367,12 +354,16 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr, } size = PIIX4_BLOCK_DATA; break; + default: + dev_warn(&adap->dev, "Unsupported transaction %d\n", size); + return -EOPNOTSUPP; } outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT); - if (piix4_transaction()) /* Error in transaction */ - return -1; + status = piix4_transaction(); + if (status) + return status; if ((read_write == I2C_SMBUS_WRITE) || (size == PIIX4_QUICK)) return 0; @@ -388,6 +379,8 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr, break; case PIIX4_BLOCK_DATA: data->block[0] = inb_p(SMBHSTDAT0); + if (data->block[0] == 0 || data->block[0] > I2C_SMBUS_BLOCK_MAX) + return -EPROTO; i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ for (i = 1; i <= data->block[0]; i++) data->block[i] = inb_p(SMBBLKDAT); @@ -411,7 +404,7 @@ static const struct i2c_algorithm smbus_algorithm = { static struct i2c_adapter piix4_adapter = { .owner = THIS_MODULE, .id = I2C_HW_SMBUS_PIIX4, - .class = I2C_CLASS_HWMON, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, .algo = &smbus_algorithm, }; diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c index 63b3e2c11cff..dcf2045b5222 100644 --- a/drivers/i2c/busses/i2c-pmcmsp.c +++ b/drivers/i2c/busses/i2c-pmcmsp.c @@ -622,7 +622,7 @@ static struct i2c_algorithm pmcmsptwi_algo = { static struct i2c_adapter pmcmsptwi_adapter = { .owner = THIS_MODULE, - .class = I2C_CLASS_HWMON, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, .algo = &pmcmsptwi_algo, .name = DRV_NAME, }; diff --git a/drivers/i2c/busses/i2c-prosavage.c b/drivers/i2c/busses/i2c-prosavage.c deleted file mode 100644 index 07c1f1e27df1..000000000000 --- a/drivers/i2c/busses/i2c-prosavage.c +++ /dev/null @@ -1,325 +0,0 @@ -/* - * kernel/busses/i2c-prosavage.c - * - * i2c bus driver for S3/VIA 8365/8375 graphics processor. - * Copyright (c) 2003 Henk Vergonet <henk@god.dyndns.org> - * Based on code written by: - * Frodo Looijaard <frodol@dds.nl>, - * Philip Edelbrock <phil@netroedge.com>, - * Ralph Metzler <rjkm@thp.uni-koeln.de>, and - * Mark D. Studebaker <mdsxyz123@yahoo.com> - * Simon Vogl - * and others - * - * Please read the lm_sensors documentation for details on use. - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ -/* 18-05-2003 HVE - created - * 14-06-2003 HVE - adapted for lm_sensors2 - * 17-06-2003 HVE - linux 2.5.xx compatible - * 18-06-2003 HVE - codingstyle - * 21-06-2003 HVE - compatibility lm_sensors2 and linux 2.5.xx - * codingstyle, mmio enabled - * - * This driver interfaces to the I2C bus of the VIA north bridge embedded - * ProSavage4/8 devices. Usefull for gaining access to the TV Encoder chips. - * - * Graphics cores: - * S3/VIA KM266/VT8375 aka ProSavage8 - * S3/VIA KM133/VT8365 aka Savage4 - * - * Two serial busses are implemented: - * SERIAL1 - I2C serial communications interface - * SERIAL2 - DDC2 monitor communications interface - * - * Tested on a FX41 mainboard, see http://www.shuttle.com - * - * - * TODO: - * - integration with prosavage framebuffer device - * (Additional documentation needed :( - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/pci.h> -#include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> -#include <asm/io.h> - -/* - * driver configuration - */ -#define MAX_BUSSES 2 - -struct s_i2c_bus { - void __iomem *mmvga; - int i2c_reg; - int adap_ok; - struct i2c_adapter adap; - struct i2c_algo_bit_data algo; -}; - -struct s_i2c_chip { - void __iomem *mmio; - struct s_i2c_bus i2c_bus[MAX_BUSSES]; -}; - - -/* - * i2c configuration - */ -#define CYCLE_DELAY 10 -#define TIMEOUT (HZ / 2) - - -/* - * S3/VIA 8365/8375 registers - */ -#define VGA_CR_IX 0x3d4 -#define VGA_CR_DATA 0x3d5 - -#define CR_SERIAL1 0xa0 /* I2C serial communications interface */ -#define MM_SERIAL1 0xff20 -#define CR_SERIAL2 0xb1 /* DDC2 monitor communications interface */ - -/* based on vt8365 documentation */ -#define I2C_ENAB 0x10 -#define I2C_SCL_OUT 0x01 -#define I2C_SDA_OUT 0x02 -#define I2C_SCL_IN 0x04 -#define I2C_SDA_IN 0x08 - -#define SET_CR_IX(p, val) writeb((val), (p)->mmvga + VGA_CR_IX) -#define SET_CR_DATA(p, val) writeb((val), (p)->mmvga + VGA_CR_DATA) -#define GET_CR_DATA(p) readb((p)->mmvga + VGA_CR_DATA) - - -/* - * Serial bus line handling - * - * serial communications register as parameter in private data - * - * TODO: locks with other code sections accessing video registers? - */ -static void bit_s3via_setscl(void *bus, int val) -{ - struct s_i2c_bus *p = (struct s_i2c_bus *)bus; - unsigned int r; - - SET_CR_IX(p, p->i2c_reg); - r = GET_CR_DATA(p); - r |= I2C_ENAB; - if (val) { - r |= I2C_SCL_OUT; - } else { - r &= ~I2C_SCL_OUT; - } - SET_CR_DATA(p, r); -} - -static void bit_s3via_setsda(void *bus, int val) -{ - struct s_i2c_bus *p = (struct s_i2c_bus *)bus; - unsigned int r; - - SET_CR_IX(p, p->i2c_reg); - r = GET_CR_DATA(p); - r |= I2C_ENAB; - if (val) { - r |= I2C_SDA_OUT; - } else { - r &= ~I2C_SDA_OUT; - } - SET_CR_DATA(p, r); -} - -static int bit_s3via_getscl(void *bus) -{ - struct s_i2c_bus *p = (struct s_i2c_bus *)bus; - - SET_CR_IX(p, p->i2c_reg); - return (0 != (GET_CR_DATA(p) & I2C_SCL_IN)); -} - -static int bit_s3via_getsda(void *bus) -{ - struct s_i2c_bus *p = (struct s_i2c_bus *)bus; - - SET_CR_IX(p, p->i2c_reg); - return (0 != (GET_CR_DATA(p) & I2C_SDA_IN)); -} - - -/* - * adapter initialisation - */ -static int i2c_register_bus(struct pci_dev *dev, struct s_i2c_bus *p, void __iomem *mmvga, u32 i2c_reg) -{ - int ret; - p->adap.owner = THIS_MODULE; - p->adap.id = I2C_HW_B_S3VIA; - p->adap.algo_data = &p->algo; - p->adap.dev.parent = &dev->dev; - p->algo.setsda = bit_s3via_setsda; - p->algo.setscl = bit_s3via_setscl; - p->algo.getsda = bit_s3via_getsda; - p->algo.getscl = bit_s3via_getscl; - p->algo.udelay = CYCLE_DELAY; - p->algo.timeout = TIMEOUT; - p->algo.data = p; - p->mmvga = mmvga; - p->i2c_reg = i2c_reg; - - ret = i2c_bit_add_bus(&p->adap); - if (ret) { - return ret; - } - - p->adap_ok = 1; - return 0; -} - - -/* - * Cleanup stuff - */ -static void prosavage_remove(struct pci_dev *dev) -{ - struct s_i2c_chip *chip; - int i, ret; - - chip = (struct s_i2c_chip *)pci_get_drvdata(dev); - - if (!chip) { - return; - } - for (i = MAX_BUSSES - 1; i >= 0; i--) { - if (chip->i2c_bus[i].adap_ok == 0) - continue; - - ret = i2c_del_adapter(&chip->i2c_bus[i].adap); - if (ret) { - dev_err(&dev->dev, "%s not removed\n", - chip->i2c_bus[i].adap.name); - } - } - if (chip->mmio) { - iounmap(chip->mmio); - } - kfree(chip); -} - - -/* - * Detect chip and initialize it - */ -static int __devinit prosavage_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - int ret; - unsigned long base, len; - struct s_i2c_chip *chip; - struct s_i2c_bus *bus; - - pci_set_drvdata(dev, kzalloc(sizeof(struct s_i2c_chip), GFP_KERNEL)); - chip = (struct s_i2c_chip *)pci_get_drvdata(dev); - if (chip == NULL) { - return -ENOMEM; - } - - base = dev->resource[0].start & PCI_BASE_ADDRESS_MEM_MASK; - len = dev->resource[0].end - base + 1; - chip->mmio = ioremap_nocache(base, len); - - if (chip->mmio == NULL) { - dev_err(&dev->dev, "ioremap failed\n"); - prosavage_remove(dev); - return -ENODEV; - } - - - /* - * Chip initialisation - */ - /* Unlock Extended IO Space ??? */ - - - /* - * i2c bus registration - */ - bus = &chip->i2c_bus[0]; - snprintf(bus->adap.name, sizeof(bus->adap.name), - "ProSavage I2C bus at %02x:%02x.%x", - dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); - ret = i2c_register_bus(dev, bus, chip->mmio + 0x8000, CR_SERIAL1); - if (ret) { - goto err_adap; - } - /* - * ddc bus registration - */ - bus = &chip->i2c_bus[1]; - snprintf(bus->adap.name, sizeof(bus->adap.name), - "ProSavage DDC bus at %02x:%02x.%x", - dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); - ret = i2c_register_bus(dev, bus, chip->mmio + 0x8000, CR_SERIAL2); - if (ret) { - goto err_adap; - } - return 0; -err_adap: - dev_err(&dev->dev, "%s failed\n", bus->adap.name); - prosavage_remove(dev); - return ret; -} - - -/* - * Data for PCI driver interface - */ -static struct pci_device_id prosavage_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_SAVAGE4) }, - { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_PROSAVAGE8) }, - { 0, }, -}; - -MODULE_DEVICE_TABLE (pci, prosavage_pci_tbl); - -static struct pci_driver prosavage_driver = { - .name = "prosavage_smbus", - .id_table = prosavage_pci_tbl, - .probe = prosavage_probe, - .remove = prosavage_remove, -}; - -static int __init i2c_prosavage_init(void) -{ - return pci_register_driver(&prosavage_driver); -} - -static void __exit i2c_prosavage_exit(void) -{ - pci_unregister_driver(&prosavage_driver); -} - -MODULE_DEVICE_TABLE(pci, prosavage_pci_tbl); -MODULE_AUTHOR("Henk Vergonet"); -MODULE_DESCRIPTION("ProSavage VIA 8365/8375 smbus driver"); -MODULE_LICENSE("GPL"); - -module_init (i2c_prosavage_init); -module_exit (i2c_prosavage_exit); diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index eb69fbadc9cb..78c0fc42bc73 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -1134,5 +1134,5 @@ static void __exit i2c_adap_pxa_exit(void) MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:pxa2xx-i2c"); -module_init(i2c_adap_pxa_init); +subsys_initcall(i2c_adap_pxa_init); module_exit(i2c_adap_pxa_exit); diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 1305ef190fc1..fd7b2308a0b3 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -591,7 +591,7 @@ static struct s3c24xx_i2c s3c24xx_i2c = { .owner = THIS_MODULE, .algo = &s3c24xx_i2c_algorithm, .retries = 2, - .class = I2C_CLASS_HWMON, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, }, }; diff --git a/drivers/i2c/busses/i2c-savage4.c b/drivers/i2c/busses/i2c-savage4.c deleted file mode 100644 index 8adf4abaa035..000000000000 --- a/drivers/i2c/busses/i2c-savage4.c +++ /dev/null @@ -1,185 +0,0 @@ -/* - i2c-savage4.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (C) 1998-2003 The LM Sensors Team - Alexander Wold <awold@bigfoot.com> - Mark D. Studebaker <mdsxyz123@yahoo.com> - - Based on i2c-voodoo3.c. - - 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 - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* This interfaces to the I2C bus of the Savage4 to gain access to - the BT869 and possibly other I2C devices. The DDC bus is not - yet supported because its register is not memory-mapped. -*/ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/pci.h> -#include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> -#include <asm/io.h> - -/* device IDs */ -#define PCI_CHIP_SAVAGE4 0x8A22 -#define PCI_CHIP_SAVAGE2000 0x9102 - -#define REG 0xff20 /* Serial Port 1 Register */ - -/* bit locations in the register */ -#define I2C_ENAB 0x00000020 -#define I2C_SCL_OUT 0x00000001 -#define I2C_SDA_OUT 0x00000002 -#define I2C_SCL_IN 0x00000008 -#define I2C_SDA_IN 0x00000010 - -/* delays */ -#define CYCLE_DELAY 10 -#define TIMEOUT (HZ / 2) - - -static void __iomem *ioaddr; - -/* The sav GPIO registers don't have individual masks for each bit - so we always have to read before writing. */ - -static void bit_savi2c_setscl(void *data, int val) -{ - unsigned int r; - r = readl(ioaddr + REG); - if(val) - r |= I2C_SCL_OUT; - else - r &= ~I2C_SCL_OUT; - writel(r, ioaddr + REG); - readl(ioaddr + REG); /* flush posted write */ -} - -static void bit_savi2c_setsda(void *data, int val) -{ - unsigned int r; - r = readl(ioaddr + REG); - if(val) - r |= I2C_SDA_OUT; - else - r &= ~I2C_SDA_OUT; - writel(r, ioaddr + REG); - readl(ioaddr + REG); /* flush posted write */ -} - -/* The GPIO pins are open drain, so the pins always remain outputs. - We rely on the i2c-algo-bit routines to set the pins high before - reading the input from other chips. */ - -static int bit_savi2c_getscl(void *data) -{ - return (0 != (readl(ioaddr + REG) & I2C_SCL_IN)); -} - -static int bit_savi2c_getsda(void *data) -{ - return (0 != (readl(ioaddr + REG) & I2C_SDA_IN)); -} - -/* Configures the chip */ - -static int config_s4(struct pci_dev *dev) -{ - unsigned long cadr; - - /* map memory */ - cadr = dev->resource[0].start; - cadr &= PCI_BASE_ADDRESS_MEM_MASK; - ioaddr = ioremap_nocache(cadr, 0x0080000); - if (ioaddr) { - /* writel(0x8160, ioaddr + REG2); */ - writel(0x00000020, ioaddr + REG); - dev_info(&dev->dev, "Using Savage4 at %p\n", ioaddr); - return 0; - } - return -ENODEV; -} - -static struct i2c_algo_bit_data sav_i2c_bit_data = { - .setsda = bit_savi2c_setsda, - .setscl = bit_savi2c_setscl, - .getsda = bit_savi2c_getsda, - .getscl = bit_savi2c_getscl, - .udelay = CYCLE_DELAY, - .timeout = TIMEOUT -}; - -static struct i2c_adapter savage4_i2c_adapter = { - .owner = THIS_MODULE, - .id = I2C_HW_B_SAVAGE, - .name = "I2C Savage4 adapter", - .algo_data = &sav_i2c_bit_data, -}; - -static struct pci_device_id savage4_ids[] __devinitdata = { - { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE4) }, - { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE2000) }, - { 0, } -}; - -MODULE_DEVICE_TABLE (pci, savage4_ids); - -static int __devinit savage4_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - int retval; - - retval = config_s4(dev); - if (retval) - return retval; - - /* set up the sysfs linkage to our parent device */ - savage4_i2c_adapter.dev.parent = &dev->dev; - - return i2c_bit_add_bus(&savage4_i2c_adapter); -} - -static void __devexit savage4_remove(struct pci_dev *dev) -{ - i2c_del_adapter(&savage4_i2c_adapter); - iounmap(ioaddr); -} - -static struct pci_driver savage4_driver = { - .name = "savage4_smbus", - .id_table = savage4_ids, - .probe = savage4_probe, - .remove = __devexit_p(savage4_remove), -}; - -static int __init i2c_savage4_init(void) -{ - return pci_register_driver(&savage4_driver); -} - -static void __exit i2c_savage4_exit(void) -{ - pci_unregister_driver(&savage4_driver); -} - -MODULE_AUTHOR("Alexander Wold <awold@bigfoot.com> " - "and Mark D. Studebaker <mdsxyz123@yahoo.com>"); -MODULE_DESCRIPTION("Savage4 I2C/SMBus driver"); -MODULE_LICENSE("GPL"); - -module_init(i2c_savage4_init); -module_exit(i2c_savage4_exit); diff --git a/drivers/i2c/busses/i2c-sibyte.c b/drivers/i2c/busses/i2c-sibyte.c index 114634da6c6e..4ddefbf238e9 100644 --- a/drivers/i2c/busses/i2c-sibyte.c +++ b/drivers/i2c/busses/i2c-sibyte.c @@ -143,7 +143,7 @@ static int __init i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed) csr_out32(speed, SMB_CSR(adap,R_SMB_FREQ)); csr_out32(0, SMB_CSR(adap,R_SMB_CONTROL)); - return i2c_add_adapter(i2c_adap); + return i2c_add_numbered_adapter(i2c_adap); } @@ -156,17 +156,19 @@ static struct i2c_adapter sibyte_board_adapter[2] = { { .owner = THIS_MODULE, .id = I2C_HW_SIBYTE, - .class = I2C_CLASS_HWMON, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, .algo = NULL, .algo_data = &sibyte_board_data[0], + .nr = 0, .name = "SiByte SMBus 0", }, { .owner = THIS_MODULE, .id = I2C_HW_SIBYTE, - .class = I2C_CLASS_HWMON, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, .algo = NULL, .algo_data = &sibyte_board_data[1], + .nr = 1, .name = "SiByte SMBus 1", }, }; diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c index 9ca8f9155f95..dfc2d5eb6a68 100644 --- a/drivers/i2c/busses/i2c-sis5595.c +++ b/drivers/i2c/busses/i2c-sis5595.c @@ -1,6 +1,4 @@ /* - sis5595.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com> @@ -62,6 +60,7 @@ #include <linux/ioport.h> #include <linux/init.h> #include <linux/i2c.h> +#include <linux/acpi.h> #include <asm/io.h> static int blacklist[] = { @@ -174,6 +173,11 @@ static int sis5595_setup(struct pci_dev *SIS5595_dev) /* NB: We grab just the two SMBus registers here, but this may still * interfere with ACPI :-( */ + retval = acpi_check_region(sis5595_base + SMB_INDEX, 2, + sis5595_driver.name); + if (retval) + return retval; + if (!request_region(sis5595_base + SMB_INDEX, 2, sis5595_driver.name)) { dev_err(&SIS5595_dev->dev, "SMBus registers 0x%04x-0x%04x already in use!\n", @@ -236,7 +240,7 @@ static int sis5595_transaction(struct i2c_adapter *adap) sis5595_write(SMB_STS_HI, temp >> 8); if ((temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8)) != 0x00) { dev_dbg(&adap->dev, "Failed! (%02x)\n", temp); - return -1; + return -EBUSY; } else { dev_dbg(&adap->dev, "Successful!\n"); } @@ -254,19 +258,19 @@ static int sis5595_transaction(struct i2c_adapter *adap) /* If the SMBus is still busy, we give up */ if (timeout >= MAX_TIMEOUT) { dev_dbg(&adap->dev, "SMBus Timeout!\n"); - result = -1; + result = -ETIMEDOUT; } if (temp & 0x10) { dev_dbg(&adap->dev, "Error: Failed bus transaction\n"); - result = -1; + result = -ENXIO; } if (temp & 0x20) { dev_err(&adap->dev, "Bus collision! SMBus may be locked until " "next hard reset (or not...)\n"); /* Clock stops and slave is stuck in mid-transmission */ - result = -1; + result = -EIO; } temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8); @@ -282,11 +286,13 @@ static int sis5595_transaction(struct i2c_adapter *adap) return result; } -/* Return -1 on error. */ +/* Return negative errno on error. */ static s32 sis5595_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data) { + int status; + switch (size) { case I2C_SMBUS_QUICK: sis5595_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); @@ -318,13 +324,14 @@ static s32 sis5595_access(struct i2c_adapter *adap, u16 addr, break; default: dev_warn(&adap->dev, "Unsupported transaction %d\n", size); - return -1; + return -EOPNOTSUPP; } sis5595_write(SMB_CTL_LO, ((size & 0x0E))); - if (sis5595_transaction(adap)) - return -1; + status = sis5595_transaction(adap); + if (status) + return status; if ((size != SIS5595_PROC_CALL) && ((read_write == I2C_SMBUS_WRITE) || (size == SIS5595_QUICK))) @@ -359,7 +366,7 @@ static const struct i2c_algorithm smbus_algorithm = { static struct i2c_adapter sis5595_adapter = { .owner = THIS_MODULE, .id = I2C_HW_SMBUS_SIS5595, - .class = I2C_CLASS_HWMON, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, .algo = &smbus_algorithm, }; diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c index 3765dd7f450f..e7c4b790da54 100644 --- a/drivers/i2c/busses/i2c-sis630.c +++ b/drivers/i2c/busses/i2c-sis630.c @@ -1,7 +1,4 @@ /* - i2c-sis630.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 2002,2003 Alexander Malysh <amalysh@web.de> This program is free software; you can redistribute it and/or modify @@ -55,6 +52,7 @@ #include <linux/ioport.h> #include <linux/init.h> #include <linux/i2c.h> +#include <linux/acpi.h> #include <asm/io.h> /* SIS630 SMBus registers */ @@ -134,7 +132,7 @@ static int sis630_transaction_start(struct i2c_adapter *adap, int size, u8 *oldc if ((temp = sis630_read(SMB_CNT) & 0x03) != 0x00) { dev_dbg(&adap->dev, "Failed! (%02x)\n", temp); - return -1; + return -EBUSY; } else { dev_dbg(&adap->dev, "Successful!\n"); } @@ -177,17 +175,17 @@ static int sis630_transaction_wait(struct i2c_adapter *adap, int size) /* If the SMBus is still busy, we give up */ if (timeout >= MAX_TIMEOUT) { dev_dbg(&adap->dev, "SMBus Timeout!\n"); - result = -1; + result = -ETIMEDOUT; } if (temp & 0x02) { dev_dbg(&adap->dev, "Error: Failed bus transaction\n"); - result = -1; + result = -ENXIO; } if (temp & 0x04) { dev_err(&adap->dev, "Bus collision!\n"); - result = -1; + result = -EIO; /* TBD: Datasheet say: the software should clear this bit and restart SMBUS operation. @@ -250,8 +248,10 @@ static int sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *dat if (i==8 || (len<8 && i==len)) { dev_dbg(&adap->dev, "start trans len=%d i=%d\n",len ,i); /* first transaction */ - if (sis630_transaction_start(adap, SIS630_BLOCK_DATA, &oldclock)) - return -1; + rc = sis630_transaction_start(adap, + SIS630_BLOCK_DATA, &oldclock); + if (rc) + return rc; } else if ((i-1)%8 == 7 || i==len) { dev_dbg(&adap->dev, "trans_wait len=%d i=%d\n",len,i); @@ -264,9 +264,10 @@ static int sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *dat */ sis630_write(SMB_STS,0x10); } - if (sis630_transaction_wait(adap, SIS630_BLOCK_DATA)) { + rc = sis630_transaction_wait(adap, + SIS630_BLOCK_DATA); + if (rc) { dev_dbg(&adap->dev, "trans_wait failed\n"); - rc = -1; break; } } @@ -275,13 +276,14 @@ static int sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *dat else { /* read request */ data->block[0] = len = 0; - if (sis630_transaction_start(adap, SIS630_BLOCK_DATA, &oldclock)) { - return -1; - } + rc = sis630_transaction_start(adap, + SIS630_BLOCK_DATA, &oldclock); + if (rc) + return rc; do { - if (sis630_transaction_wait(adap, SIS630_BLOCK_DATA)) { + rc = sis630_transaction_wait(adap, SIS630_BLOCK_DATA); + if (rc) { dev_dbg(&adap->dev, "trans_wait failed\n"); - rc = -1; break; } /* if this first transaction then read byte count */ @@ -311,11 +313,13 @@ static int sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *dat return rc; } -/* Return -1 on error. */ +/* Return negative errno on error. */ static s32 sis630_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data) { + int status; + switch (size) { case I2C_SMBUS_QUICK: sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); @@ -350,13 +354,14 @@ static s32 sis630_access(struct i2c_adapter *adap, u16 addr, size = SIS630_BLOCK_DATA; return sis630_block_data(adap, data, read_write); default: - printk("Unsupported I2C size\n"); - return -1; - break; + dev_warn(&adap->dev, "Unsupported transaction %d\n", + size); + return -EOPNOTSUPP; } - if (sis630_transaction(adap, size)) - return -1; + status = sis630_transaction(adap, size); + if (status) + return status; if ((size != SIS630_PCALL) && ((read_write == I2C_SMBUS_WRITE) || (size == SIS630_QUICK))) { @@ -372,9 +377,6 @@ static s32 sis630_access(struct i2c_adapter *adap, u16 addr, case SIS630_WORD_DATA: data->word = sis630_read(SMB_BYTE) + (sis630_read(SMB_BYTE + 1) << 8); break; - default: - return -1; - break; } return 0; @@ -433,6 +435,11 @@ static int sis630_setup(struct pci_dev *sis630_dev) dev_dbg(&sis630_dev->dev, "ACPI base at 0x%04x\n", acpi_base); + retval = acpi_check_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION, + sis630_driver.name); + if (retval) + goto exit; + /* Everything is happy, let's grab the memory and set things up. */ if (!request_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION, sis630_driver.name)) { @@ -458,7 +465,7 @@ static const struct i2c_algorithm smbus_algorithm = { static struct i2c_adapter sis630_adapter = { .owner = THIS_MODULE, .id = I2C_HW_SMBUS_SIS630, - .class = I2C_CLASS_HWMON, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, .algo = &smbus_algorithm, }; diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c index dc235bb8e24d..f1bba6396641 100644 --- a/drivers/i2c/busses/i2c-sis96x.c +++ b/drivers/i2c/busses/i2c-sis96x.c @@ -1,7 +1,4 @@ /* - sis96x.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 2003 Mark M. Hoffman <mhoffman@lightlink.com> This program is free software; you can redistribute it and/or modify @@ -40,6 +37,7 @@ #include <linux/ioport.h> #include <linux/i2c.h> #include <linux/init.h> +#include <linux/acpi.h> #include <asm/io.h> /* base address register in PCI config space */ @@ -111,7 +109,7 @@ static int sis96x_transaction(int size) /* check it again */ if (((temp = sis96x_read(SMB_CNT)) & 0x03) != 0x00) { dev_dbg(&sis96x_adapter.dev, "Failed (0x%02x)\n", temp); - return -1; + return -EBUSY; } else { dev_dbg(&sis96x_adapter.dev, "Successful\n"); } @@ -136,19 +134,19 @@ static int sis96x_transaction(int size) /* If the SMBus is still busy, we give up */ if (timeout >= MAX_TIMEOUT) { dev_dbg(&sis96x_adapter.dev, "SMBus Timeout! (0x%02x)\n", temp); - result = -1; + result = -ETIMEDOUT; } /* device error - probably missing ACK */ if (temp & 0x02) { dev_dbg(&sis96x_adapter.dev, "Failed bus transaction!\n"); - result = -1; + result = -ENXIO; } /* bus collision */ if (temp & 0x04) { dev_dbg(&sis96x_adapter.dev, "Bus collision!\n"); - result = -1; + result = -EIO; } /* Finish up by resetting the bus */ @@ -161,11 +159,12 @@ static int sis96x_transaction(int size) return result; } -/* Return -1 on error. */ +/* Return negative errno on error. */ static s32 sis96x_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data * data) { + int status; switch (size) { case I2C_SMBUS_QUICK: @@ -200,20 +199,14 @@ static s32 sis96x_access(struct i2c_adapter * adap, u16 addr, SIS96x_PROC_CALL : SIS96x_WORD_DATA); break; - case I2C_SMBUS_BLOCK_DATA: - /* TO DO: */ - dev_info(&adap->dev, "SMBus block not implemented!\n"); - return -1; - break; - default: - dev_info(&adap->dev, "Unsupported I2C size\n"); - return -1; - break; + dev_warn(&adap->dev, "Unsupported transaction %d\n", size); + return -EOPNOTSUPP; } - if (sis96x_transaction(size)) - return -1; + status = sis96x_transaction(size); + if (status) + return status; if ((size != SIS96x_PROC_CALL) && ((read_write == I2C_SMBUS_WRITE) || (size == SIS96x_QUICK))) @@ -249,7 +242,7 @@ static const struct i2c_algorithm smbus_algorithm = { static struct i2c_adapter sis96x_adapter = { .owner = THIS_MODULE, .id = I2C_HW_SMBUS_SIS96X, - .class = I2C_CLASS_HWMON, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, .algo = &smbus_algorithm, }; @@ -286,6 +279,10 @@ static int __devinit sis96x_probe(struct pci_dev *dev, dev_info(&dev->dev, "SiS96x SMBus base address: 0x%04x\n", sis96x_smbus_base); + retval = acpi_check_resource_conflict(&dev->resource[SIS96x_BAR]); + if (retval) + return retval; + /* Everything is happy, let's grab the memory and set things up. */ if (!request_region(sis96x_smbus_base, SMB_IOSIZE, sis96x_driver.name)) { diff --git a/drivers/i2c/busses/i2c-stub.c b/drivers/i2c/busses/i2c-stub.c index d08eeec53913..1b7b2af94036 100644 --- a/drivers/i2c/busses/i2c-stub.c +++ b/drivers/i2c/busses/i2c-stub.c @@ -43,7 +43,7 @@ struct stub_chip { static struct stub_chip *stub_chips; -/* Return -1 on error. */ +/* Return negative errno on error. */ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data * data) { @@ -120,7 +120,7 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags, default: dev_dbg(&adap->dev, "Unsupported I2C/SMBus command\n"); - ret = -1; + ret = -EOPNOTSUPP; break; } /* switch (size) */ @@ -140,7 +140,7 @@ static const struct i2c_algorithm smbus_algorithm = { static struct i2c_adapter stub_adapter = { .owner = THIS_MODULE, - .class = I2C_CLASS_HWMON, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, .algo = &smbus_algorithm, .name = "SMBus stub driver", }; diff --git a/drivers/i2c/busses/i2c-taos-evm.c b/drivers/i2c/busses/i2c-taos-evm.c index de9db49e54d9..224aa12ee7c8 100644 --- a/drivers/i2c/busses/i2c-taos-evm.c +++ b/drivers/i2c/busses/i2c-taos-evm.c @@ -96,9 +96,8 @@ static int taos_smbus_xfer(struct i2c_adapter *adapter, u16 addr, sprintf(p, "$%02X", command); break; default: - dev_dbg(&adapter->dev, "Unsupported transaction size %d\n", - size); - return -EINVAL; + dev_warn(&adapter->dev, "Unsupported transaction %d\n", size); + return -EOPNOTSUPP; } /* Send the transaction to the TAOS EVM */ diff --git a/drivers/i2c/busses/i2c-via.c b/drivers/i2c/busses/i2c-via.c index 61716f6b14dc..29cef0433f34 100644 --- a/drivers/i2c/busses/i2c-via.c +++ b/drivers/i2c/busses/i2c-via.c @@ -1,7 +1,4 @@ /* - i2c-via.c - Part of lm_sensors, Linux kernel modules - for hardware monitoring - i2c Support for Via Technologies 82C586B South Bridge Copyright (c) 1998, 1999 Kyösti Mälkki <kmalkki@cc.hut.fi> @@ -87,7 +84,7 @@ static struct i2c_algo_bit_data bit_data = { static struct i2c_adapter vt586b_adapter = { .owner = THIS_MODULE, .id = I2C_HW_B_VIA, - .class = I2C_CLASS_HWMON, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, .name = "VIA i2c", .algo_data = &bit_data, }; diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c index 77b13d027f86..862eb352a2d9 100644 --- a/drivers/i2c/busses/i2c-viapro.c +++ b/drivers/i2c/busses/i2c-viapro.c @@ -1,6 +1,4 @@ /* - i2c-viapro.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, Kyösti Mälkki <kmalkki@cc.hut.fi>, Mark D. Studebaker <mdsxyz123@yahoo.com> @@ -50,6 +48,7 @@ #include <linux/ioport.h> #include <linux/i2c.h> #include <linux/init.h> +#include <linux/acpi.h> #include <asm/io.h> static struct pci_dev *vt596_pdev; @@ -152,7 +151,7 @@ static int vt596_transaction(u8 size) if ((temp = inb_p(SMBHSTSTS)) & 0x1F) { dev_err(&vt596_adapter.dev, "SMBus reset failed! " "(0x%02x)\n", temp); - return -1; + return -EBUSY; } } @@ -167,24 +166,24 @@ static int vt596_transaction(u8 size) /* If the SMBus is still busy, we give up */ if (timeout >= MAX_TIMEOUT) { - result = -1; + result = -ETIMEDOUT; dev_err(&vt596_adapter.dev, "SMBus timeout!\n"); } if (temp & 0x10) { - result = -1; + result = -EIO; dev_err(&vt596_adapter.dev, "Transaction failed (0x%02x)\n", size); } if (temp & 0x08) { - result = -1; + result = -EIO; dev_err(&vt596_adapter.dev, "SMBus collision!\n"); } if (temp & 0x04) { int read = inb_p(SMBHSTADD) & 0x01; - result = -1; + result = -ENXIO; /* The quick and receive byte commands are used to probe for chips, so errors are expected, and we don't want to frighten the user. */ @@ -202,12 +201,13 @@ static int vt596_transaction(u8 size) return result; } -/* Return -1 on error, 0 on success */ +/* Return negative errno on error, 0 on success */ static s32 vt596_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data) { int i; + int status; switch (size) { case I2C_SMBUS_QUICK: @@ -258,8 +258,9 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr, outb_p(((addr & 0x7f) << 1) | read_write, SMBHSTADD); - if (vt596_transaction(size)) /* Error in transaction */ - return -1; + status = vt596_transaction(size); + if (status) + return status; if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK)) return 0; @@ -285,9 +286,9 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr, return 0; exit_unsupported: - dev_warn(&vt596_adapter.dev, "Unsupported command invoked! (0x%02x)\n", + dev_warn(&vt596_adapter.dev, "Unsupported transaction %d\n", size); - return -1; + return -EOPNOTSUPP; } static u32 vt596_func(struct i2c_adapter *adapter) @@ -309,7 +310,7 @@ static const struct i2c_algorithm smbus_algorithm = { static struct i2c_adapter vt596_adapter = { .owner = THIS_MODULE, .id = I2C_HW_SMBUS_VIA2, - .class = I2C_CLASS_HWMON, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, .algo = &smbus_algorithm, }; @@ -354,6 +355,10 @@ static int __devinit vt596_probe(struct pci_dev *pdev, } found: + error = acpi_check_region(vt596_smba, 8, vt596_driver.name); + if (error) + return error; + if (!request_region(vt596_smba, 8, vt596_driver.name)) { dev_err(&pdev->dev, "SMBus region 0x%x already in use!\n", vt596_smba); diff --git a/drivers/i2c/busses/i2c-voodoo3.c b/drivers/i2c/busses/i2c-voodoo3.c index 88a3447e11e1..1d4ae26ba73d 100644 --- a/drivers/i2c/busses/i2c-voodoo3.c +++ b/drivers/i2c/busses/i2c-voodoo3.c @@ -1,6 +1,4 @@ /* - voodoo3.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, Ralph Metzler <rjkm@thp.uni-koeln.de>, and diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index 61abe0f33255..ed794b145a11 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c @@ -442,7 +442,7 @@ static __init struct scx200_acb_iface *scx200_create_iface(const char *text, adapter->owner = THIS_MODULE; adapter->id = I2C_HW_SMBUS_SCX200; adapter->algo = &scx200_acb_algorithm; - adapter->class = I2C_CLASS_HWMON; + adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; adapter->dev.parent = dev; mutex_init(&iface->mutex); diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig index 2da2edfa68ec..50e0a4653741 100644 --- a/drivers/i2c/chips/Kconfig +++ b/drivers/i2c/chips/Kconfig @@ -14,6 +14,32 @@ config DS1682 This driver can also be built as a module. If so, the module will be called ds1682. +config AT24 + tristate "EEPROMs from most vendors" + depends on SYSFS && EXPERIMENTAL + help + Enable this driver to get read/write support to most I2C EEPROMs, + after you configure the driver to know about each EEPROM on + your target board. Use these generic chip names, instead of + vendor-specific ones like at24c64 or 24lc02: + + 24c00, 24c01, 24c02, spd (readonly 24c02), 24c04, 24c08, + 24c16, 24c32, 24c64, 24c128, 24c256, 24c512, 24c1024 + + Unless you like data loss puzzles, always be sure that any chip + you configure as a 24c32 (32 kbit) or larger is NOT really a + 24c16 (16 kbit) or smaller, and vice versa. Marking the chip + as read-only won't help recover from this. Also, if your chip + has any software write-protect mechanism you may want to review the + code to make sure this driver won't turn it on by accident. + + If you use this with an SMBus adapter instead of an I2C adapter, + full functionality is not available. Only smaller devices are + supported (24c16 and below, max 4 kByte). + + This driver can also be built as a module. If so, the module + will be called at24. + config SENSORS_EEPROM tristate "EEPROM reader" depends on EXPERIMENTAL @@ -26,8 +52,8 @@ config SENSORS_EEPROM will be called eeprom. config SENSORS_PCF8574 - tristate "Philips PCF8574 and PCF8574A" - depends on EXPERIMENTAL + tristate "Philips PCF8574 and PCF8574A (DEPRECATED)" + depends on EXPERIMENTAL && GPIO_PCF857X = "n" default n help If you say yes here you get support for Philips PCF8574 and @@ -36,12 +62,16 @@ config SENSORS_PCF8574 This driver can also be built as a module. If so, the module will be called pcf8574. + This driver is deprecated and will be dropped soon. Use + drivers/gpio/pcf857x.c instead. + These devices are hard to detect and rarely found on mainstream hardware. If unsure, say N. config PCF8575 - tristate "Philips PCF8575" + tristate "Philips PCF8575 (DEPRECATED)" default n + depends on GPIO_PCF857X = "n" help If you say yes here you get support for Philips PCF8575 chip. This chip is a 16-bit I/O expander for the I2C bus. Several other @@ -50,12 +80,15 @@ config PCF8575 This driver can also be built as a module. If so, the module will be called pcf8575. + This driver is deprecated and will be dropped soon. Use + drivers/gpio/pcf857x.c instead. + This device is hard to detect and is rarely found on mainstream hardware. If unsure, say N. config SENSORS_PCA9539 tristate "Philips PCA9539 16-bit I/O port (DEPRECATED)" - depends on EXPERIMENTAL && GPIO_PCA9539 = "n" + depends on EXPERIMENTAL && GPIO_PCA953X = "n" help If you say yes here you get support for the Philips PCA9539 16-bit I/O port. @@ -64,7 +97,7 @@ config SENSORS_PCA9539 will be called pca9539. This driver is deprecated and will be dropped soon. Use - drivers/gpio/pca9539.c instead. + drivers/gpio/pca953x.c instead. config SENSORS_PCF8591 tristate "Philips PCF8591" diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile index e47aca0ca5ae..39e3e69ed125 100644 --- a/drivers/i2c/chips/Makefile +++ b/drivers/i2c/chips/Makefile @@ -10,6 +10,7 @@ # obj-$(CONFIG_DS1682) += ds1682.o +obj-$(CONFIG_AT24) += at24.o obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o obj-$(CONFIG_SENSORS_MAX6875) += max6875.o obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o diff --git a/drivers/i2c/chips/at24.c b/drivers/i2c/chips/at24.c new file mode 100644 index 000000000000..ad1fb331f652 --- /dev/null +++ b/drivers/i2c/chips/at24.c @@ -0,0 +1,585 @@ +/* + * at24.c - handle most I2C EEPROMs + * + * Copyright (C) 2005-2007 David Brownell + * Copyright (C) 2008 Wolfram Sang, Pengutronix + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/mutex.h> +#include <linux/sysfs.h> +#include <linux/mod_devicetable.h> +#include <linux/log2.h> +#include <linux/bitops.h> +#include <linux/jiffies.h> +#include <linux/i2c.h> +#include <linux/i2c/at24.h> + +/* + * I2C EEPROMs from most vendors are inexpensive and mostly interchangeable. + * Differences between different vendor product lines (like Atmel AT24C or + * MicroChip 24LC, etc) won't much matter for typical read/write access. + * There are also I2C RAM chips, likewise interchangeable. One example + * would be the PCF8570, which acts like a 24c02 EEPROM (256 bytes). + * + * However, misconfiguration can lose data. "Set 16-bit memory address" + * to a part with 8-bit addressing will overwrite data. Writing with too + * big a page size also loses data. And it's not safe to assume that the + * conventional addresses 0x50..0x57 only hold eeproms; a PCF8563 RTC + * uses 0x51, for just one example. + * + * Accordingly, explicit board-specific configuration data should be used + * in almost all cases. (One partial exception is an SMBus used to access + * "SPD" data for DRAM sticks. Those only use 24c02 EEPROMs.) + * + * So this driver uses "new style" I2C driver binding, expecting to be + * told what devices exist. That may be in arch/X/mach-Y/board-Z.c or + * similar kernel-resident tables; or, configuration data coming from + * a bootloader. + * + * Other than binding model, current differences from "eeprom" driver are + * that this one handles write access and isn't restricted to 24c02 devices. + * It also handles larger devices (32 kbit and up) with two-byte addresses, + * which won't work on pure SMBus systems. + */ + +struct at24_data { + struct at24_platform_data chip; + bool use_smbus; + + /* + * Lock protects against activities from other Linux tasks, + * but not from changes by other I2C masters. + */ + struct mutex lock; + struct bin_attribute bin; + + u8 *writebuf; + unsigned write_max; + unsigned num_addresses; + + /* + * Some chips tie up multiple I2C addresses; dummy devices reserve + * them for us, and we'll use them with SMBus calls. + */ + struct i2c_client *client[]; +}; + +/* + * This parameter is to help this driver avoid blocking other drivers out + * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C + * clock, one 256 byte read takes about 1/43 second which is excessive; + * but the 1/170 second it takes at 400 kHz may be quite reasonable; and + * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. + * + * This value is forced to be a power of two so that writes align on pages. + */ +static unsigned io_limit = 128; +module_param(io_limit, uint, 0); +MODULE_PARM_DESC(io_limit, "Maximum bytes per I/O (default 128)"); + +/* + * Specs often allow 5 msec for a page write, sometimes 20 msec; + * it's important to recover from write timeouts. + */ +static unsigned write_timeout = 25; +module_param(write_timeout, uint, 0); +MODULE_PARM_DESC(write_timeout, "Time (in ms) to try writes (default 25)"); + +#define AT24_SIZE_BYTELEN 5 +#define AT24_SIZE_FLAGS 8 + +#define AT24_BITMASK(x) (BIT(x) - 1) + +/* create non-zero magic value for given eeprom parameters */ +#define AT24_DEVICE_MAGIC(_len, _flags) \ + ((1 << AT24_SIZE_FLAGS | (_flags)) \ + << AT24_SIZE_BYTELEN | ilog2(_len)) + +static const struct i2c_device_id at24_ids[] = { + /* needs 8 addresses as A0-A2 are ignored */ + { "24c00", AT24_DEVICE_MAGIC(128 / 8, AT24_FLAG_TAKE8ADDR) }, + /* old variants can't be handled with this generic entry! */ + { "24c01", AT24_DEVICE_MAGIC(1024 / 8, 0) }, + { "24c02", AT24_DEVICE_MAGIC(2048 / 8, 0) }, + /* spd is a 24c02 in memory DIMMs */ + { "spd", AT24_DEVICE_MAGIC(2048 / 8, + AT24_FLAG_READONLY | AT24_FLAG_IRUGO) }, + /* pcf8570 has SRAM only */ + { "pcf8570", AT24_DEVICE_MAGIC(2048 / 8, 0) }, + { "24c04", AT24_DEVICE_MAGIC(4096 / 8, 0) }, + /* 24rf08 quirk is handled at i2c-core */ + { "24c08", AT24_DEVICE_MAGIC(8192 / 8, 0) }, + { "24c16", AT24_DEVICE_MAGIC(16384 / 8, 0) }, + { "24c32", AT24_DEVICE_MAGIC(32768 / 8, AT24_FLAG_ADDR16) }, + { "24c64", AT24_DEVICE_MAGIC(65536 / 8, AT24_FLAG_ADDR16) }, + { "24c128", AT24_DEVICE_MAGIC(131072 / 8, AT24_FLAG_ADDR16) }, + { "24c256", AT24_DEVICE_MAGIC(262144 / 8, AT24_FLAG_ADDR16) }, + { "24c512", AT24_DEVICE_MAGIC(524288 / 8, AT24_FLAG_ADDR16) }, + { "24c1024", AT24_DEVICE_MAGIC(1048576 / 8, AT24_FLAG_ADDR16) }, + { "at24", 0 }, + { /* END OF LIST */ } +}; +MODULE_DEVICE_TABLE(i2c, at24_ids); + +/*-------------------------------------------------------------------------*/ + +/* + * This routine supports chips which consume multiple I2C addresses. It + * computes the addressing information to be used for a given r/w request. + * Assumes that sanity checks for offset happened at sysfs-layer. + */ +static struct i2c_client *at24_translate_offset(struct at24_data *at24, + unsigned *offset) +{ + unsigned i; + + if (at24->chip.flags & AT24_FLAG_ADDR16) { + i = *offset >> 16; + *offset &= 0xffff; + } else { + i = *offset >> 8; + *offset &= 0xff; + } + + return at24->client[i]; +} + +static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf, + unsigned offset, size_t count) +{ + struct i2c_msg msg[2]; + u8 msgbuf[2]; + struct i2c_client *client; + int status, i; + + memset(msg, 0, sizeof(msg)); + + /* + * REVISIT some multi-address chips don't rollover page reads to + * the next slave address, so we may need to truncate the count. + * Those chips might need another quirk flag. + * + * If the real hardware used four adjacent 24c02 chips and that + * were misconfigured as one 24c08, that would be a similar effect: + * one "eeprom" file not four, but larger reads would fail when + * they crossed certain pages. + */ + + /* + * Slave address and byte offset derive from the offset. Always + * set the byte address; on a multi-master board, another master + * may have changed the chip's "current" address pointer. + */ + client = at24_translate_offset(at24, &offset); + + if (count > io_limit) + count = io_limit; + + /* Smaller eeproms can work given some SMBus extension calls */ + if (at24->use_smbus) { + if (count > I2C_SMBUS_BLOCK_MAX) + count = I2C_SMBUS_BLOCK_MAX; + status = i2c_smbus_read_i2c_block_data(client, offset, + count, buf); + dev_dbg(&client->dev, "smbus read %zd@%d --> %d\n", + count, offset, status); + return (status < 0) ? -EIO : status; + } + + /* + * When we have a better choice than SMBus calls, use a combined + * I2C message. Write address; then read up to io_limit data bytes. + * Note that read page rollover helps us here (unlike writes). + * msgbuf is u8 and will cast to our needs. + */ + i = 0; + if (at24->chip.flags & AT24_FLAG_ADDR16) + msgbuf[i++] = offset >> 8; + msgbuf[i++] = offset; + + msg[0].addr = client->addr; + msg[0].buf = msgbuf; + msg[0].len = i; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].buf = buf; + msg[1].len = count; + + status = i2c_transfer(client->adapter, msg, 2); + dev_dbg(&client->dev, "i2c read %zd@%d --> %d\n", + count, offset, status); + + if (status == 2) + return count; + else if (status >= 0) + return -EIO; + else + return status; +} + +static ssize_t at24_bin_read(struct kobject *kobj, struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct at24_data *at24; + ssize_t retval = 0; + + at24 = dev_get_drvdata(container_of(kobj, struct device, kobj)); + + if (unlikely(!count)) + return count; + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&at24->lock); + + while (count) { + ssize_t status; + + status = at24_eeprom_read(at24, buf, off, count); + if (status <= 0) { + if (retval == 0) + retval = status; + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&at24->lock); + + return retval; +} + + +/* + * REVISIT: export at24_bin{read,write}() to let other kernel code use + * eeprom data. For example, it might hold a board's Ethernet address, or + * board-specific calibration data generated on the manufacturing floor. + */ + + +/* + * Note that if the hardware write-protect pin is pulled high, the whole + * chip is normally write protected. But there are plenty of product + * variants here, including OTP fuses and partial chip protect. + * + * We only use page mode writes; the alternative is sloooow. This routine + * writes at most one page. + */ +static ssize_t at24_eeprom_write(struct at24_data *at24, char *buf, + unsigned offset, size_t count) +{ + struct i2c_client *client; + struct i2c_msg msg; + ssize_t status; + unsigned long timeout, write_time; + unsigned next_page; + + /* Get corresponding I2C address and adjust offset */ + client = at24_translate_offset(at24, &offset); + + /* write_max is at most a page */ + if (count > at24->write_max) + count = at24->write_max; + + /* Never roll over backwards, to the start of this page */ + next_page = roundup(offset + 1, at24->chip.page_size); + if (offset + count > next_page) + count = next_page - offset; + + /* If we'll use I2C calls for I/O, set up the message */ + if (!at24->use_smbus) { + int i = 0; + + msg.addr = client->addr; + msg.flags = 0; + + /* msg.buf is u8 and casts will mask the values */ + msg.buf = at24->writebuf; + if (at24->chip.flags & AT24_FLAG_ADDR16) + msg.buf[i++] = offset >> 8; + + msg.buf[i++] = offset; + memcpy(&msg.buf[i], buf, count); + msg.len = i + count; + } + + /* + * Writes fail if the previous one didn't complete yet. We may + * loop a few times until this one succeeds, waiting at least + * long enough for one entire page write to work. + */ + timeout = jiffies + msecs_to_jiffies(write_timeout); + do { + write_time = jiffies; + if (at24->use_smbus) { + status = i2c_smbus_write_i2c_block_data(client, + offset, count, buf); + if (status == 0) + status = count; + } else { + status = i2c_transfer(client->adapter, &msg, 1); + if (status == 1) + status = count; + } + dev_dbg(&client->dev, "write %zd@%d --> %zd (%ld)\n", + count, offset, status, jiffies); + + if (status == count) + return count; + + /* REVISIT: at HZ=100, this is sloooow */ + msleep(1); + } while (time_before(write_time, timeout)); + + return -ETIMEDOUT; +} + +static ssize_t at24_bin_write(struct kobject *kobj, struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct at24_data *at24; + ssize_t retval = 0; + + at24 = dev_get_drvdata(container_of(kobj, struct device, kobj)); + + if (unlikely(!count)) + return count; + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&at24->lock); + + while (count) { + ssize_t status; + + status = at24_eeprom_write(at24, buf, off, count); + if (status <= 0) { + if (retval == 0) + retval = status; + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&at24->lock); + + return retval; +} + +/*-------------------------------------------------------------------------*/ + +static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct at24_platform_data chip; + bool writable; + bool use_smbus = false; + struct at24_data *at24; + int err; + unsigned i, num_addresses; + kernel_ulong_t magic; + + if (client->dev.platform_data) { + chip = *(struct at24_platform_data *)client->dev.platform_data; + } else { + if (!id->driver_data) { + err = -ENODEV; + goto err_out; + } + magic = id->driver_data; + chip.byte_len = BIT(magic & AT24_BITMASK(AT24_SIZE_BYTELEN)); + magic >>= AT24_SIZE_BYTELEN; + chip.flags = magic & AT24_BITMASK(AT24_SIZE_FLAGS); + /* + * This is slow, but we can't know all eeproms, so we better + * play safe. Specifying custom eeprom-types via platform_data + * is recommended anyhow. + */ + chip.page_size = 1; + } + + if (!is_power_of_2(chip.byte_len)) + dev_warn(&client->dev, + "byte_len looks suspicious (no power of 2)!\n"); + if (!is_power_of_2(chip.page_size)) + dev_warn(&client->dev, + "page_size looks suspicious (no power of 2)!\n"); + + /* Use I2C operations unless we're stuck with SMBus extensions. */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + if (chip.flags & AT24_FLAG_ADDR16) { + err = -EPFNOSUPPORT; + goto err_out; + } + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { + err = -EPFNOSUPPORT; + goto err_out; + } + use_smbus = true; + } + + if (chip.flags & AT24_FLAG_TAKE8ADDR) + num_addresses = 8; + else + num_addresses = DIV_ROUND_UP(chip.byte_len, + (chip.flags & AT24_FLAG_ADDR16) ? 65536 : 256); + + at24 = kzalloc(sizeof(struct at24_data) + + num_addresses * sizeof(struct i2c_client *), GFP_KERNEL); + if (!at24) { + err = -ENOMEM; + goto err_out; + } + + mutex_init(&at24->lock); + at24->use_smbus = use_smbus; + at24->chip = chip; + at24->num_addresses = num_addresses; + + /* + * Export the EEPROM bytes through sysfs, since that's convenient. + * By default, only root should see the data (maybe passwords etc) + */ + at24->bin.attr.name = "eeprom"; + at24->bin.attr.mode = chip.flags & AT24_FLAG_IRUGO ? S_IRUGO : S_IRUSR; + at24->bin.attr.owner = THIS_MODULE; + at24->bin.read = at24_bin_read; + at24->bin.size = chip.byte_len; + + writable = !(chip.flags & AT24_FLAG_READONLY); + if (writable) { + if (!use_smbus || i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) { + + unsigned write_max = chip.page_size; + + at24->bin.write = at24_bin_write; + at24->bin.attr.mode |= S_IWUSR; + + if (write_max > io_limit) + write_max = io_limit; + if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) + write_max = I2C_SMBUS_BLOCK_MAX; + at24->write_max = write_max; + + /* buffer (data + address at the beginning) */ + at24->writebuf = kmalloc(write_max + 2, GFP_KERNEL); + if (!at24->writebuf) { + err = -ENOMEM; + goto err_struct; + } + } else { + dev_warn(&client->dev, + "cannot write due to controller restrictions."); + } + } + + at24->client[0] = client; + + /* use dummy devices for multiple-address chips */ + for (i = 1; i < num_addresses; i++) { + at24->client[i] = i2c_new_dummy(client->adapter, + client->addr + i); + if (!at24->client[i]) { + dev_err(&client->dev, "address 0x%02x unavailable\n", + client->addr + i); + err = -EADDRINUSE; + goto err_clients; + } + } + + err = sysfs_create_bin_file(&client->dev.kobj, &at24->bin); + if (err) + goto err_clients; + + i2c_set_clientdata(client, at24); + + dev_info(&client->dev, "%Zd byte %s EEPROM %s\n", + at24->bin.size, client->name, + writable ? "(writable)" : "(read-only)"); + dev_dbg(&client->dev, + "page_size %d, num_addresses %d, write_max %d%s\n", + chip.page_size, num_addresses, + at24->write_max, + use_smbus ? ", use_smbus" : ""); + + return 0; + +err_clients: + for (i = 1; i < num_addresses; i++) + if (at24->client[i]) + i2c_unregister_device(at24->client[i]); + + kfree(at24->writebuf); +err_struct: + kfree(at24); +err_out: + dev_dbg(&client->dev, "probe error %d\n", err); + return err; +} + +static int __devexit at24_remove(struct i2c_client *client) +{ + struct at24_data *at24; + int i; + + at24 = i2c_get_clientdata(client); + sysfs_remove_bin_file(&client->dev.kobj, &at24->bin); + + for (i = 1; i < at24->num_addresses; i++) + i2c_unregister_device(at24->client[i]); + + kfree(at24->writebuf); + kfree(at24); + i2c_set_clientdata(client, NULL); + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static struct i2c_driver at24_driver = { + .driver = { + .name = "at24", + .owner = THIS_MODULE, + }, + .probe = at24_probe, + .remove = __devexit_p(at24_remove), + .id_table = at24_ids, +}; + +static int __init at24_init(void) +{ + io_limit = rounddown_pow_of_two(io_limit); + return i2c_add_driver(&at24_driver); +} +module_init(at24_init); + +static void __exit at24_exit(void) +{ + i2c_del_driver(&at24_driver); +} +module_exit(at24_exit); + +MODULE_DESCRIPTION("Driver for most I2C EEPROMs"); +MODULE_AUTHOR("David Brownell and Wolfram Sang"); +MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c index 7dee001e5133..fc17c4de7c21 100644 --- a/drivers/i2c/chips/eeprom.c +++ b/drivers/i2c/chips/eeprom.c @@ -1,6 +1,4 @@ /* - eeprom.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring Copyright (C) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com> Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com> @@ -53,7 +51,6 @@ enum eeprom_nature { /* Each client has this additional data */ struct eeprom_data { - struct i2c_client client; struct mutex update_lock; u8 valid; /* bitfield, bit!=0 if slice is valid */ unsigned long last_updated[8]; /* In jiffies, 8 slices */ @@ -62,23 +59,34 @@ struct eeprom_data { }; -static int eeprom_attach_adapter(struct i2c_adapter *adapter); -static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind); -static int eeprom_detach_client(struct i2c_client *client); +static int eeprom_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int eeprom_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); +static int eeprom_remove(struct i2c_client *client); + +static struct i2c_device_id eeprom_id[] = { + { "eeprom", 0 }, + { } +}; /* This is the driver that will be inserted */ static struct i2c_driver eeprom_driver = { + .class = I2C_CLASS_DDC | I2C_CLASS_SPD, .driver = { .name = "eeprom", }, - .attach_adapter = eeprom_attach_adapter, - .detach_client = eeprom_detach_client, + .probe = eeprom_probe, + .remove = eeprom_remove, + .detect = eeprom_detect, + .id_table = eeprom_id, + .address_data = &addr_data, }; static void eeprom_update_client(struct i2c_client *client, u8 slice) { struct eeprom_data *data = i2c_get_clientdata(client); - int i, j; + int i; mutex_lock(&data->update_lock); @@ -93,15 +101,12 @@ static void eeprom_update_client(struct i2c_client *client, u8 slice) != 32) goto exit; } else { - if (i2c_smbus_write_byte(client, slice << 5)) { - dev_dbg(&client->dev, "eeprom read start has failed!\n"); - goto exit; - } - for (i = slice << 5; i < (slice + 1) << 5; i++) { - j = i2c_smbus_read_byte(client); - if (j < 0) + for (i = slice << 5; i < (slice + 1) << 5; i += 2) { + int word = i2c_smbus_read_word_data(client, i); + if (word < 0) goto exit; - data->data[i] = (u8) j; + data->data[i] = word & 0xff; + data->data[i + 1] = word >> 8; } } data->last_updated[slice] = jiffies; @@ -157,93 +162,85 @@ static struct bin_attribute eeprom_attr = { .read = eeprom_read, }; -static int eeprom_attach_adapter(struct i2c_adapter *adapter) +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int eeprom_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info) { - return i2c_probe(adapter, &addr_data, eeprom_detect); + struct i2c_adapter *adapter = client->adapter; + + /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all + addresses 0x50-0x57, but we only care about 0x50. So decline + attaching to addresses >= 0x51 on DDC buses */ + if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x51) + return -ENODEV; + + /* There are four ways we can read the EEPROM data: + (1) I2C block reads (faster, but unsupported by most adapters) + (2) Word reads (128% overhead) + (3) Consecutive byte reads (88% overhead, unsafe) + (4) Regular byte data reads (265% overhead) + The third and fourth methods are not implemented by this driver + because all known adapters support one of the first two. */ + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA) + && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) + return -ENODEV; + + strlcpy(info->type, "eeprom", I2C_NAME_SIZE); + + return 0; } -/* This function is called by i2c_probe */ -static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind) +static int eeprom_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - struct i2c_client *new_client; + struct i2c_adapter *adapter = client->adapter; struct eeprom_data *data; - int err = 0; - - /* There are three ways we can read the EEPROM data: - (1) I2C block reads (faster, but unsupported by most adapters) - (2) Consecutive byte reads (100% overhead) - (3) Regular byte data reads (200% overhead) - The third method is not implemented by this driver because all - known adapters support at least the second. */ - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA - | I2C_FUNC_SMBUS_BYTE)) - goto exit; + int err; if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { err = -ENOMEM; goto exit; } - new_client = &data->client; memset(data->data, 0xff, EEPROM_SIZE); - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &eeprom_driver; - new_client->flags = 0; - - /* Fill in the remaining client fields */ - strlcpy(new_client->name, "eeprom", I2C_NAME_SIZE); - data->valid = 0; + i2c_set_clientdata(client, data); mutex_init(&data->update_lock); data->nature = UNKNOWN; - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) - goto exit_kfree; - /* Detect the Vaio nature of EEPROMs. We use the "PCG-" or "VGN-" prefix as the signature. */ - if (address == 0x57) { + if (client->addr == 0x57 + && i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) { char name[4]; - name[0] = i2c_smbus_read_byte_data(new_client, 0x80); - name[1] = i2c_smbus_read_byte(new_client); - name[2] = i2c_smbus_read_byte(new_client); - name[3] = i2c_smbus_read_byte(new_client); + name[0] = i2c_smbus_read_byte_data(client, 0x80); + name[1] = i2c_smbus_read_byte_data(client, 0x81); + name[2] = i2c_smbus_read_byte_data(client, 0x82); + name[3] = i2c_smbus_read_byte_data(client, 0x83); if (!memcmp(name, "PCG-", 4) || !memcmp(name, "VGN-", 4)) { - dev_info(&new_client->dev, "Vaio EEPROM detected, " + dev_info(&client->dev, "Vaio EEPROM detected, " "enabling privacy protection\n"); data->nature = VAIO; } } /* create the sysfs eeprom file */ - err = sysfs_create_bin_file(&new_client->dev.kobj, &eeprom_attr); + err = sysfs_create_bin_file(&client->dev.kobj, &eeprom_attr); if (err) - goto exit_detach; + goto exit_kfree; return 0; -exit_detach: - i2c_detach_client(new_client); exit_kfree: kfree(data); exit: return err; } -static int eeprom_detach_client(struct i2c_client *client) +static int eeprom_remove(struct i2c_client *client) { - int err; - sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr); - - err = i2c_detach_client(client); - if (err) - return err; - kfree(i2c_get_clientdata(client)); return 0; diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c index b1b45dddb17e..d21cb32449e2 100644 --- a/drivers/i2c/chips/isp1301_omap.c +++ b/drivers/i2c/chips/isp1301_omap.c @@ -49,10 +49,9 @@ MODULE_LICENSE("GPL"); struct isp1301 { struct otg_transceiver otg; - struct i2c_client client; + struct i2c_client *client; void (*i2c_release)(struct device *dev); - int irq; int irq_type; u32 last_otg_ctrl; @@ -138,14 +137,6 @@ static inline void notresponding(struct isp1301 *isp) /*-------------------------------------------------------------------------*/ -/* only two addresses possible */ -#define ISP_BASE 0x2c -static unsigned short normal_i2c[] = { - ISP_BASE, ISP_BASE + 1, - I2C_CLIENT_END }; - -I2C_CLIENT_INSMOD; - static struct i2c_driver isp1301_driver; /* smbus apis are used for portability */ @@ -153,25 +144,25 @@ static struct i2c_driver isp1301_driver; static inline u8 isp1301_get_u8(struct isp1301 *isp, u8 reg) { - return i2c_smbus_read_byte_data(&isp->client, reg + 0); + return i2c_smbus_read_byte_data(isp->client, reg + 0); } static inline int isp1301_get_u16(struct isp1301 *isp, u8 reg) { - return i2c_smbus_read_word_data(&isp->client, reg); + return i2c_smbus_read_word_data(isp->client, reg); } static inline int isp1301_set_bits(struct isp1301 *isp, u8 reg, u8 bits) { - return i2c_smbus_write_byte_data(&isp->client, reg + 0, bits); + return i2c_smbus_write_byte_data(isp->client, reg + 0, bits); } static inline int isp1301_clear_bits(struct isp1301 *isp, u8 reg, u8 bits) { - return i2c_smbus_write_byte_data(&isp->client, reg + 1, bits); + return i2c_smbus_write_byte_data(isp->client, reg + 1, bits); } /*-------------------------------------------------------------------------*/ @@ -349,10 +340,10 @@ isp1301_defer_work(struct isp1301 *isp, int work) int status; if (isp && !test_and_set_bit(work, &isp->todo)) { - (void) get_device(&isp->client.dev); + (void) get_device(&isp->client->dev); status = schedule_work(&isp->work); if (!status && !isp->working) - dev_vdbg(&isp->client.dev, + dev_vdbg(&isp->client->dev, "work item %d may be lost\n", work); } } @@ -1107,7 +1098,7 @@ isp1301_work(struct work_struct *work) /* transfer state from otg engine to isp1301 */ if (test_and_clear_bit(WORK_UPDATE_ISP, &isp->todo)) { otg_update_isp(isp); - put_device(&isp->client.dev); + put_device(&isp->client->dev); } #endif /* transfer state from isp1301 to otg engine */ @@ -1115,7 +1106,7 @@ isp1301_work(struct work_struct *work) u8 stat = isp1301_clear_latch(isp); isp_update_otg(isp, stat); - put_device(&isp->client.dev); + put_device(&isp->client->dev); } if (test_and_clear_bit(WORK_HOST_RESUME, &isp->todo)) { @@ -1150,7 +1141,7 @@ isp1301_work(struct work_struct *work) } host_resume(isp); // mdelay(10); - put_device(&isp->client.dev); + put_device(&isp->client->dev); } if (test_and_clear_bit(WORK_TIMER, &isp->todo)) { @@ -1159,15 +1150,15 @@ isp1301_work(struct work_struct *work) if (!stop) mod_timer(&isp->timer, jiffies + TIMER_JIFFIES); #endif - put_device(&isp->client.dev); + put_device(&isp->client->dev); } if (isp->todo) - dev_vdbg(&isp->client.dev, + dev_vdbg(&isp->client->dev, "work done, todo = 0x%lx\n", isp->todo); if (stop) { - dev_dbg(&isp->client.dev, "stop\n"); + dev_dbg(&isp->client->dev, "stop\n"); break; } } while (isp->todo); @@ -1191,7 +1182,7 @@ static void isp1301_release(struct device *dev) { struct isp1301 *isp; - isp = container_of(dev, struct isp1301, client.dev); + isp = device_get_drvdata(dev); /* ugly -- i2c hijacks our memory hook to wait_for_completion() */ if (isp->i2c_release) @@ -1201,15 +1192,15 @@ static void isp1301_release(struct device *dev) static struct isp1301 *the_transceiver; -static int isp1301_detach_client(struct i2c_client *i2c) +static int __exit isp1301_remove(struct i2c_client *i2c) { struct isp1301 *isp; - isp = container_of(i2c, struct isp1301, client); + isp = i2c_get_clientdata(i2c); isp1301_clear_bits(isp, ISP1301_INTERRUPT_FALLING, ~0); isp1301_clear_bits(isp, ISP1301_INTERRUPT_RISING, ~0); - free_irq(isp->irq, isp); + free_irq(i2c->irq, isp); #ifdef CONFIG_USB_OTG otg_unbind(isp); #endif @@ -1224,7 +1215,7 @@ static int isp1301_detach_client(struct i2c_client *i2c) put_device(&i2c->dev); the_transceiver = 0; - return i2c_detach_client(i2c); + return 0; } /*-------------------------------------------------------------------------*/ @@ -1257,7 +1248,7 @@ static int isp1301_otg_enable(struct isp1301 *isp) isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING, INTR_VBUS_VLD | INTR_SESS_VLD | INTR_ID_GND); - dev_info(&isp->client.dev, "ready for dual-role USB ...\n"); + dev_info(&isp->client->dev, "ready for dual-role USB ...\n"); return 0; } @@ -1282,7 +1273,7 @@ isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host) #ifdef CONFIG_USB_OTG isp->otg.host = host; - dev_dbg(&isp->client.dev, "registered host\n"); + dev_dbg(&isp->client->dev, "registered host\n"); host_suspend(isp); if (isp->otg.gadget) return isp1301_otg_enable(isp); @@ -1297,7 +1288,7 @@ isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host) if (machine_is_omap_h2()) isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0); - dev_info(&isp->client.dev, "A-Host sessions ok\n"); + dev_info(&isp->client->dev, "A-Host sessions ok\n"); isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING, INTR_ID_GND); isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING, @@ -1315,7 +1306,7 @@ isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host) return 0; #else - dev_dbg(&isp->client.dev, "host sessions not allowed\n"); + dev_dbg(&isp->client->dev, "host sessions not allowed\n"); return -EINVAL; #endif @@ -1341,7 +1332,7 @@ isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget) #ifdef CONFIG_USB_OTG isp->otg.gadget = gadget; - dev_dbg(&isp->client.dev, "registered gadget\n"); + dev_dbg(&isp->client->dev, "registered gadget\n"); /* gadget driver may be suspended until vbus_connect () */ if (isp->otg.host) return isp1301_otg_enable(isp); @@ -1364,7 +1355,7 @@ isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget) INTR_SESS_VLD); isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING, INTR_VBUS_VLD); - dev_info(&isp->client.dev, "B-Peripheral sessions ok\n"); + dev_info(&isp->client->dev, "B-Peripheral sessions ok\n"); dump_regs(isp, __func__); /* If this has a Mini-AB connector, this mode is highly @@ -1377,7 +1368,7 @@ isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget) return 0; #else - dev_dbg(&isp->client.dev, "peripheral sessions not allowed\n"); + dev_dbg(&isp->client->dev, "peripheral sessions not allowed\n"); return -EINVAL; #endif } @@ -1473,12 +1464,10 @@ isp1301_start_hnp(struct otg_transceiver *dev) /*-------------------------------------------------------------------------*/ -/* no error returns, they'd just make bus scanning stop */ -static int isp1301_probe(struct i2c_adapter *bus, int address, int kind) +static int __init isp1301_probe(struct i2c_client *i2c) { int status; struct isp1301 *isp; - struct i2c_client *i2c; if (the_transceiver) return 0; @@ -1492,37 +1481,19 @@ static int isp1301_probe(struct i2c_adapter *bus, int address, int kind) isp->timer.function = isp1301_timer; isp->timer.data = (unsigned long) isp; - isp->irq = -1; - isp->client.addr = address; - i2c_set_clientdata(&isp->client, isp); - isp->client.adapter = bus; - isp->client.driver = &isp1301_driver; - strlcpy(isp->client.name, DRIVER_NAME, I2C_NAME_SIZE); - i2c = &isp->client; - - /* if this is a true probe, verify the chip ... */ - if (kind < 0) { - status = isp1301_get_u16(isp, ISP1301_VENDOR_ID); - if (status != I2C_VENDOR_ID_PHILIPS) { - dev_dbg(&bus->dev, "addr %d not philips id: %d\n", - address, status); - goto fail1; - } - status = isp1301_get_u16(isp, ISP1301_PRODUCT_ID); - if (status != I2C_PRODUCT_ID_PHILIPS_1301) { - dev_dbg(&bus->dev, "%d not isp1301, %d\n", - address, status); - goto fail1; - } - } + i2c_set_clientdata(i2c, isp); + isp->client = i2c; - status = i2c_attach_client(i2c); - if (status < 0) { - dev_dbg(&bus->dev, "can't attach %s to device %d, err %d\n", - DRIVER_NAME, address, status); -fail1: - kfree(isp); - return 0; + /* verify the chip (shouldn't be necesary) */ + status = isp1301_get_u16(isp, ISP1301_VENDOR_ID); + if (status != I2C_VENDOR_ID_PHILIPS) { + dev_dbg(&i2c->dev, "not philips id: %d\n", status); + goto fail; + } + status = isp1301_get_u16(isp, ISP1301_PRODUCT_ID); + if (status != I2C_PRODUCT_ID_PHILIPS_1301) { + dev_dbg(&i2c->dev, "not isp1301, %d\n", status); + goto fail; } isp->i2c_release = i2c->dev.release; i2c->dev.release = isp1301_release; @@ -1551,7 +1522,7 @@ fail1: status = otg_bind(isp); if (status < 0) { dev_dbg(&i2c->dev, "can't bind OTG\n"); - goto fail2; + goto fail; } #endif @@ -1564,26 +1535,21 @@ fail1: /* IRQ wired at M14 */ omap_cfg_reg(M14_1510_GPIO2); - isp->irq = OMAP_GPIO_IRQ(2); if (gpio_request(2, "isp1301") == 0) gpio_direction_input(2); isp->irq_type = IRQF_TRIGGER_FALLING; } isp->irq_type |= IRQF_SAMPLE_RANDOM; - status = request_irq(isp->irq, isp1301_irq, + status = request_irq(i2c->irq, isp1301_irq, isp->irq_type, DRIVER_NAME, isp); if (status < 0) { dev_dbg(&i2c->dev, "can't get IRQ %d, err %d\n", - isp->irq, status); -#ifdef CONFIG_USB_OTG -fail2: -#endif - i2c_detach_client(i2c); - goto fail1; + i2c->irq, status); + goto fail; } - isp->otg.dev = &isp->client.dev; + isp->otg.dev = &i2c->dev; isp->otg.label = DRIVER_NAME; isp->otg.set_host = isp1301_set_host, @@ -1614,22 +1580,25 @@ fail2: status); return 0; -} -static int isp1301_scan_bus(struct i2c_adapter *bus) -{ - if (!i2c_check_functionality(bus, I2C_FUNC_SMBUS_BYTE_DATA - | I2C_FUNC_SMBUS_READ_WORD_DATA)) - return -EINVAL; - return i2c_probe(bus, &addr_data, isp1301_probe); +fail: + kfree(isp); + return -ENODEV; } +static struct i2c_device_id isp1301_id[] = { + { "isp1301_omap", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, isp1301_id); + static struct i2c_driver isp1301_driver = { .driver = { .name = "isp1301_omap", }, - .attach_adapter = isp1301_scan_bus, - .detach_client = isp1301_detach_client, + .probe = isp1301_probe, + .remove = __exit_p(isp1301_remove), + .id_table = isp1301_id, }; /*-------------------------------------------------------------------------*/ diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c index cf507b3f60f3..d8dd3649f8a4 100644 --- a/drivers/i2c/chips/max6875.c +++ b/drivers/i2c/chips/max6875.c @@ -53,7 +53,7 @@ I2C_CLIENT_INSMOD_1(max6875); /* Each client has this additional data */ struct max6875_data { - struct i2c_client client; + struct i2c_client *fake_client; struct mutex update_lock; u32 valid; @@ -61,17 +61,27 @@ struct max6875_data { unsigned long last_updated[USER_EEPROM_SLICES]; }; -static int max6875_attach_adapter(struct i2c_adapter *adapter); -static int max6875_detect(struct i2c_adapter *adapter, int address, int kind); -static int max6875_detach_client(struct i2c_client *client); +static int max6875_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int max6875_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); +static int max6875_remove(struct i2c_client *client); + +static struct i2c_device_id max6875_id[] = { + { "max6875", 0 }, + { } +}; /* This is the driver that will be inserted */ static struct i2c_driver max6875_driver = { .driver = { .name = "max6875", }, - .attach_adapter = max6875_attach_adapter, - .detach_client = max6875_detach_client, + .probe = max6875_probe, + .remove = max6875_remove, + .id_table = max6875_id, + .detect = max6875_detect, + .address_data = &addr_data, }; static void max6875_update_slice(struct i2c_client *client, int slice) @@ -159,95 +169,67 @@ static struct bin_attribute user_eeprom_attr = { .read = max6875_read, }; -static int max6875_attach_adapter(struct i2c_adapter *adapter) -{ - return i2c_probe(adapter, &addr_data, max6875_detect); -} - -/* This function is called by i2c_probe */ -static int max6875_detect(struct i2c_adapter *adapter, int address, int kind) +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int max6875_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info) { - struct i2c_client *real_client; - struct i2c_client *fake_client; - struct max6875_data *data; - int err = 0; + struct i2c_adapter *adapter = client->adapter; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA | I2C_FUNC_SMBUS_READ_BYTE)) - return 0; + return -ENODEV; /* Only check even addresses */ - if (address & 1) - return 0; + if (client->addr & 1) + return -ENODEV; + + strlcpy(info->type, "max6875", I2C_NAME_SIZE); + + return 0; +} + +static int max6875_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct max6875_data *data; + int err; if (!(data = kzalloc(sizeof(struct max6875_data), GFP_KERNEL))) return -ENOMEM; /* A fake client is created on the odd address */ - if (!(fake_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) { + data->fake_client = i2c_new_dummy(client->adapter, client->addr + 1); + if (!data->fake_client) { err = -ENOMEM; - goto exit_kfree1; + goto exit_kfree; } /* Init real i2c_client */ - real_client = &data->client; - i2c_set_clientdata(real_client, data); - real_client->addr = address; - real_client->adapter = adapter; - real_client->driver = &max6875_driver; - real_client->flags = 0; - strlcpy(real_client->name, "max6875", I2C_NAME_SIZE); + i2c_set_clientdata(client, data); mutex_init(&data->update_lock); - /* Init fake client data */ - i2c_set_clientdata(fake_client, NULL); - fake_client->addr = address | 1; - fake_client->adapter = adapter; - fake_client->driver = &max6875_driver; - fake_client->flags = 0; - strlcpy(fake_client->name, "max6875 subclient", I2C_NAME_SIZE); - - if ((err = i2c_attach_client(real_client)) != 0) - goto exit_kfree2; - - if ((err = i2c_attach_client(fake_client)) != 0) - goto exit_detach1; - - err = sysfs_create_bin_file(&real_client->dev.kobj, &user_eeprom_attr); + err = sysfs_create_bin_file(&client->dev.kobj, &user_eeprom_attr); if (err) - goto exit_detach2; + goto exit_remove_fake; return 0; -exit_detach2: - i2c_detach_client(fake_client); -exit_detach1: - i2c_detach_client(real_client); -exit_kfree2: - kfree(fake_client); -exit_kfree1: +exit_remove_fake: + i2c_unregister_device(data->fake_client); +exit_kfree: kfree(data); return err; } -/* Will be called for both the real client and the fake client */ -static int max6875_detach_client(struct i2c_client *client) +static int max6875_remove(struct i2c_client *client) { - int err; struct max6875_data *data = i2c_get_clientdata(client); - /* data is NULL for the fake client */ - if (data) - sysfs_remove_bin_file(&client->dev.kobj, &user_eeprom_attr); + i2c_unregister_device(data->fake_client); - err = i2c_detach_client(client); - if (err) - return err; + sysfs_remove_bin_file(&client->dev.kobj, &user_eeprom_attr); + kfree(data); - if (data) /* real client */ - kfree(data); - else /* fake client */ - kfree(client); return 0; } diff --git a/drivers/i2c/chips/pca9539.c b/drivers/i2c/chips/pca9539.c index f43c4e79b55e..5e46036cf664 100644 --- a/drivers/i2c/chips/pca9539.c +++ b/drivers/i2c/chips/pca9539.c @@ -14,8 +14,8 @@ #include <linux/i2c.h> #include <linux/hwmon-sysfs.h> -/* Addresses to scan */ -static unsigned short normal_i2c[] = {0x74, 0x75, 0x76, 0x77, I2C_CLIENT_END}; +/* Addresses to scan: none, device is not autodetected */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; /* Insmod parameters */ I2C_CLIENT_INSMOD_1(pca9539); @@ -32,21 +32,27 @@ enum pca9539_cmd PCA9539_DIRECTION_1 = 7, }; -static int pca9539_attach_adapter(struct i2c_adapter *adapter); -static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind); -static int pca9539_detach_client(struct i2c_client *client); +static int pca9539_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int pca9539_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); +static int pca9539_remove(struct i2c_client *client); + +static struct i2c_device_id pca9539_id[] = { + { "pca9539", 0 }, + { } +}; /* This is the driver that will be inserted */ static struct i2c_driver pca9539_driver = { .driver = { .name = "pca9539", }, - .attach_adapter = pca9539_attach_adapter, - .detach_client = pca9539_detach_client, -}; - -struct pca9539_data { - struct i2c_client client; + .probe = pca9539_probe, + .remove = pca9539_remove, + .id_table = pca9539_id, + .detect = pca9539_detect, + .address_data = &addr_data, }; /* following are the sysfs callback functions */ @@ -105,75 +111,31 @@ static struct attribute_group pca9539_defattr_group = { .attrs = pca9539_attributes, }; -static int pca9539_attach_adapter(struct i2c_adapter *adapter) -{ - return i2c_probe(adapter, &addr_data, pca9539_detect); -} - -/* This function is called by i2c_probe */ -static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind) +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int pca9539_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info) { - struct i2c_client *new_client; - struct pca9539_data *data; - int err = 0; + struct i2c_adapter *adapter = client->adapter; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - goto exit; - - /* OK. For now, we presume we have a valid client. We now create the - client structure, even though we cannot fill it completely yet. */ - if (!(data = kzalloc(sizeof(struct pca9539_data), GFP_KERNEL))) { - err = -ENOMEM; - goto exit; - } - - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &pca9539_driver; - new_client->flags = 0; - - if (kind < 0) { - /* Detection: the pca9539 only has 8 registers (0-7). - A read of 7 should succeed, but a read of 8 should fail. */ - if ((i2c_smbus_read_byte_data(new_client, 7) < 0) || - (i2c_smbus_read_byte_data(new_client, 8) >= 0)) - goto exit_kfree; - } - - strlcpy(new_client->name, "pca9539", I2C_NAME_SIZE); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) - goto exit_kfree; + return -ENODEV; - /* Register sysfs hooks */ - err = sysfs_create_group(&new_client->dev.kobj, - &pca9539_defattr_group); - if (err) - goto exit_detach; + strlcpy(info->type, "pca9539", I2C_NAME_SIZE); return 0; - -exit_detach: - i2c_detach_client(new_client); -exit_kfree: - kfree(data); -exit: - return err; } -static int pca9539_detach_client(struct i2c_client *client) +static int pca9539_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - int err; + /* Register sysfs hooks */ + return sysfs_create_group(&client->dev.kobj, + &pca9539_defattr_group); +} +static int pca9539_remove(struct i2c_client *client) +{ sysfs_remove_group(&client->dev.kobj, &pca9539_defattr_group); - - if ((err = i2c_detach_client(client))) - return err; - - kfree(i2c_get_clientdata(client)); return 0; } diff --git a/drivers/i2c/chips/pcf8574.c b/drivers/i2c/chips/pcf8574.c index e5b31329b56e..efbe53c826a3 100644 --- a/drivers/i2c/chips/pcf8574.c +++ b/drivers/i2c/chips/pcf8574.c @@ -1,6 +1,4 @@ /* - pcf8574.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring Copyright (c) 2000 Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, Dan Eaton <dan.eaton@rocketlogix.com> @@ -40,35 +38,40 @@ #include <linux/slab.h> #include <linux/i2c.h> -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - I2C_CLIENT_END -}; +/* Addresses to scan: none, device can't be detected */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; /* Insmod parameters */ I2C_CLIENT_INSMOD_2(pcf8574, pcf8574a); /* Each client has this additional data */ struct pcf8574_data { - struct i2c_client client; - int write; /* Remember last written value */ }; -static int pcf8574_attach_adapter(struct i2c_adapter *adapter); -static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind); -static int pcf8574_detach_client(struct i2c_client *client); +static int pcf8574_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int pcf8574_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); +static int pcf8574_remove(struct i2c_client *client); static void pcf8574_init_client(struct i2c_client *client); +static struct i2c_device_id pcf8574_id[] = { + { "pcf8574", 0 }, + { "pcf8574a", 0 }, + { } +}; + /* This is the driver that will be inserted */ static struct i2c_driver pcf8574_driver = { .driver = { .name = "pcf8574", }, - .attach_adapter = pcf8574_attach_adapter, - .detach_client = pcf8574_detach_client, + .probe = pcf8574_probe, + .remove = pcf8574_remove, + .id_table = pcf8574_id, + .detect = pcf8574_detect, + .address_data = &addr_data, }; /* following are the sysfs callback functions */ @@ -121,42 +124,22 @@ static const struct attribute_group pcf8574_attr_group = { * Real code */ -static int pcf8574_attach_adapter(struct i2c_adapter *adapter) +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int pcf8574_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info) { - return i2c_probe(adapter, &addr_data, pcf8574_detect); -} - -/* This function is called by i2c_probe */ -static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind) -{ - struct i2c_client *new_client; - struct pcf8574_data *data; - int err = 0; - const char *client_name = ""; + struct i2c_adapter *adapter = client->adapter; + const char *client_name; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) - goto exit; - - /* OK. For now, we presume we have a valid client. We now create the - client structure, even though we cannot fill it completely yet. */ - if (!(data = kzalloc(sizeof(struct pcf8574_data), GFP_KERNEL))) { - err = -ENOMEM; - goto exit; - } - - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &pcf8574_driver; - new_client->flags = 0; + return -ENODEV; /* Now, we would do the remaining detection. But the PCF8574 is plainly impossible to detect! Stupid chip. */ /* Determine the chip type */ if (kind <= 0) { - if (address >= 0x38 && address <= 0x3f) + if (client->addr >= 0x38 && client->addr <= 0x3f) kind = pcf8574a; else kind = pcf8574; @@ -166,40 +149,43 @@ static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind) client_name = "pcf8574a"; else client_name = "pcf8574"; + strlcpy(info->type, client_name, I2C_NAME_SIZE); - /* Fill in the remaining client fields and put it into the global list */ - strlcpy(new_client->name, client_name, I2C_NAME_SIZE); + return 0; +} + +static int pcf8574_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct pcf8574_data *data; + int err; + + data = kzalloc(sizeof(struct pcf8574_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) - goto exit_free; - /* Initialize the PCF8574 chip */ - pcf8574_init_client(new_client); + pcf8574_init_client(client); /* Register sysfs hooks */ - err = sysfs_create_group(&new_client->dev.kobj, &pcf8574_attr_group); + err = sysfs_create_group(&client->dev.kobj, &pcf8574_attr_group); if (err) - goto exit_detach; + goto exit_free; return 0; - exit_detach: - i2c_detach_client(new_client); exit_free: kfree(data); exit: return err; } -static int pcf8574_detach_client(struct i2c_client *client) +static int pcf8574_remove(struct i2c_client *client) { - int err; - sysfs_remove_group(&client->dev.kobj, &pcf8574_attr_group); - - if ((err = i2c_detach_client(client))) - return err; - kfree(i2c_get_clientdata(client)); return 0; } diff --git a/drivers/i2c/chips/pcf8575.c b/drivers/i2c/chips/pcf8575.c index 3ea08ac0bfa3..4555415b8bda 100644 --- a/drivers/i2c/chips/pcf8575.c +++ b/drivers/i2c/chips/pcf8575.c @@ -32,11 +32,8 @@ #include <linux/slab.h> /* kzalloc() */ #include <linux/sysfs.h> /* sysfs_create_group() */ -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - I2C_CLIENT_END -}; +/* Addresses to scan: none, device can't be detected */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; /* Insmod parameters */ I2C_CLIENT_INSMOD; @@ -44,13 +41,19 @@ I2C_CLIENT_INSMOD; /* Each client has this additional data */ struct pcf8575_data { - struct i2c_client client; int write; /* last written value, or error code */ }; -static int pcf8575_attach_adapter(struct i2c_adapter *adapter); -static int pcf8575_detect(struct i2c_adapter *adapter, int address, int kind); -static int pcf8575_detach_client(struct i2c_client *client); +static int pcf8575_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int pcf8575_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); +static int pcf8575_remove(struct i2c_client *client); + +static struct i2c_device_id pcf8575_id[] = { + { "pcf8575", 0 }, + { } +}; /* This is the driver that will be inserted */ static struct i2c_driver pcf8575_driver = { @@ -58,8 +61,11 @@ static struct i2c_driver pcf8575_driver = { .owner = THIS_MODULE, .name = "pcf8575", }, - .attach_adapter = pcf8575_attach_adapter, - .detach_client = pcf8575_detach_client, + .probe = pcf8575_probe, + .remove = pcf8575_remove, + .id_table = pcf8575_id, + .detect = pcf8575_detect, + .address_data = &addr_data, }; /* following are the sysfs callback functions */ @@ -126,71 +132,55 @@ static const struct attribute_group pcf8575_attr_group = { * Real code */ -static int pcf8575_attach_adapter(struct i2c_adapter *adapter) +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int pcf8575_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info) { - return i2c_probe(adapter, &addr_data, pcf8575_detect); + struct i2c_adapter *adapter = client->adapter; + + if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) + return -ENODEV; + + /* This is the place to detect whether the chip at the specified + address really is a PCF8575 chip. However, there is no method known + to detect whether an I2C chip is a PCF8575 or any other I2C chip. */ + + strlcpy(info->type, "pcf8575", I2C_NAME_SIZE); + + return 0; } -/* This function is called by i2c_probe */ -static int pcf8575_detect(struct i2c_adapter *adapter, int address, int kind) +static int pcf8575_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - struct i2c_client *client; struct pcf8575_data *data; - int err = 0; - - if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) - goto exit; + int err; - /* OK. For now, we presume we have a valid client. We now create the - client structure, even though we cannot fill it completely yet. */ data = kzalloc(sizeof(struct pcf8575_data), GFP_KERNEL); if (!data) { err = -ENOMEM; goto exit; } - client = &data->client; i2c_set_clientdata(client, data); - client->addr = address; - client->adapter = adapter; - client->driver = &pcf8575_driver; - strlcpy(client->name, "pcf8575", I2C_NAME_SIZE); data->write = -EAGAIN; - /* This is the place to detect whether the chip at the specified - address really is a PCF8575 chip. However, there is no method known - to detect whether an I2C chip is a PCF8575 or any other I2C chip. */ - - /* Tell the I2C layer a new client has arrived */ - err = i2c_attach_client(client); - if (err) - goto exit_free; - /* Register sysfs hooks */ err = sysfs_create_group(&client->dev.kobj, &pcf8575_attr_group); if (err) - goto exit_detach; + goto exit_free; return 0; -exit_detach: - i2c_detach_client(client); exit_free: kfree(data); exit: return err; } -static int pcf8575_detach_client(struct i2c_client *client) +static int pcf8575_remove(struct i2c_client *client) { - int err; - sysfs_remove_group(&client->dev.kobj, &pcf8575_attr_group); - - err = i2c_detach_client(client); - if (err) - return err; - kfree(i2c_get_clientdata(client)); return 0; } diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c index 66c7c3bb9429..df9eb164f893 100644 --- a/drivers/i2c/chips/pcf8591.c +++ b/drivers/i2c/chips/pcf8591.c @@ -1,6 +1,4 @@ /* - pcf8591.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring Copyright (C) 2001-2004 Aurelien Jarno <aurelien@aurel32.net> Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with the help of Jean Delvare <khali@linux-fr.org> @@ -74,26 +72,37 @@ MODULE_PARM_DESC(input_mode, #define REG_TO_SIGNED(reg) (((reg) & 0x80)?((reg) - 256):(reg)) struct pcf8591_data { - struct i2c_client client; struct mutex update_lock; u8 control; u8 aout; }; -static int pcf8591_attach_adapter(struct i2c_adapter *adapter); -static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind); -static int pcf8591_detach_client(struct i2c_client *client); +static int pcf8591_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int pcf8591_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); +static int pcf8591_remove(struct i2c_client *client); static void pcf8591_init_client(struct i2c_client *client); static int pcf8591_read_channel(struct device *dev, int channel); +static struct i2c_device_id pcf8591_id[] = { + { "pcf8591", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, pcf8591_id); + /* This is the driver that will be inserted */ static struct i2c_driver pcf8591_driver = { + .class = I2C_CLASS_HWMON, /* Nearest choice */ .driver = { .name = "pcf8591", }, - .attach_adapter = pcf8591_attach_adapter, - .detach_client = pcf8591_detach_client, + .probe = pcf8591_probe, + .remove = pcf8591_remove, + .id_table = pcf8591_id, + .detect = pcf8591_detect, + .address_data = &addr_data, }; /* following are the sysfs callback functions */ @@ -182,70 +191,57 @@ static const struct attribute_group pcf8591_attr_group_opt = { /* * Real code */ -static int pcf8591_attach_adapter(struct i2c_adapter *adapter) -{ - return i2c_probe(adapter, &addr_data, pcf8591_detect); -} -/* This function is called by i2c_probe */ -static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind) +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int pcf8591_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info) { - struct i2c_client *new_client; - struct pcf8591_data *data; - int err = 0; + struct i2c_adapter *adapter = client->adapter; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) - goto exit; + return -ENODEV; + + /* Now, we would do the remaining detection. But the PCF8591 is plainly + impossible to detect! Stupid chip. */ + + strlcpy(info->type, "pcf8591", I2C_NAME_SIZE); + + return 0; +} + +static int pcf8591_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct pcf8591_data *data; + int err; - /* OK. For now, we presume we have a valid client. We now create the - client structure, even though we cannot fill it completely yet. */ if (!(data = kzalloc(sizeof(struct pcf8591_data), GFP_KERNEL))) { err = -ENOMEM; goto exit; } - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &pcf8591_driver; - new_client->flags = 0; - - /* Now, we would do the remaining detection. But the PCF8591 is plainly - impossible to detect! Stupid chip. */ - - /* Determine the chip type - only one kind supported! */ - if (kind <= 0) - kind = pcf8591; - - /* Fill in the remaining client fields and put it into the global - list */ - strlcpy(new_client->name, "pcf8591", I2C_NAME_SIZE); + i2c_set_clientdata(client, data); mutex_init(&data->update_lock); - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) - goto exit_kfree; - /* Initialize the PCF8591 chip */ - pcf8591_init_client(new_client); + pcf8591_init_client(client); /* Register sysfs hooks */ - err = sysfs_create_group(&new_client->dev.kobj, &pcf8591_attr_group); + err = sysfs_create_group(&client->dev.kobj, &pcf8591_attr_group); if (err) - goto exit_detach; + goto exit_kfree; /* Register input2 if not in "two differential inputs" mode */ if (input_mode != 3) { - if ((err = device_create_file(&new_client->dev, + if ((err = device_create_file(&client->dev, &dev_attr_in2_input))) goto exit_sysfs_remove; } /* Register input3 only in "four single ended inputs" mode */ if (input_mode == 0) { - if ((err = device_create_file(&new_client->dev, + if ((err = device_create_file(&client->dev, &dev_attr_in3_input))) goto exit_sysfs_remove; } @@ -253,26 +249,18 @@ static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind) return 0; exit_sysfs_remove: - sysfs_remove_group(&new_client->dev.kobj, &pcf8591_attr_group_opt); - sysfs_remove_group(&new_client->dev.kobj, &pcf8591_attr_group); -exit_detach: - i2c_detach_client(new_client); + sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt); + sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group); exit_kfree: kfree(data); exit: return err; } -static int pcf8591_detach_client(struct i2c_client *client) +static int pcf8591_remove(struct i2c_client *client) { - int err; - sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt); sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group); - - if ((err = i2c_detach_client(client))) - return err; - kfree(i2c_get_clientdata(client)); return 0; } diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 97d826827956..2aa42127fb72 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -29,13 +29,11 @@ #include <linux/i2c.h> #include <linux/init.h> #include <linux/idr.h> -#include <linux/seq_file.h> #include <linux/platform_device.h> #include <linux/mutex.h> #include <linux/completion.h> #include <linux/hardirq.h> #include <linux/irqflags.h> -#include <linux/semaphore.h> #include <asm/uaccess.h> #include "i2c-core.h" @@ -44,7 +42,9 @@ static DEFINE_MUTEX(core_lock); static DEFINE_IDR(i2c_adapter_idr); -#define is_newstyle_driver(d) ((d)->probe || (d)->remove) +#define is_newstyle_driver(d) ((d)->probe || (d)->remove || (d)->detect) + +static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver); /* ------------------------------------------------------------------------- */ @@ -103,19 +103,14 @@ static int i2c_device_probe(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct i2c_driver *driver = to_i2c_driver(dev->driver); - const struct i2c_device_id *id; int status; - if (!driver->probe) + if (!driver->probe || !driver->id_table) return -ENODEV; client->driver = driver; dev_dbg(dev, "probe\n"); - if (driver->id_table) - id = i2c_match_id(driver->id_table, client); - else - id = NULL; - status = driver->probe(client, id); + status = driver->probe(client, i2c_match_id(driver->id_table, client)); if (status) client->driver = NULL; return status; @@ -208,7 +203,7 @@ static struct device_attribute i2c_dev_attrs[] = { { }, }; -static struct bus_type i2c_bus_type = { +struct bus_type i2c_bus_type = { .name = "i2c", .dev_attrs = i2c_dev_attrs, .match = i2c_device_match, @@ -219,6 +214,7 @@ static struct bus_type i2c_bus_type = { .suspend = i2c_device_suspend, .resume = i2c_device_resume, }; +EXPORT_SYMBOL_GPL(i2c_bus_type); /** @@ -416,6 +412,10 @@ static int i2c_do_add_adapter(struct device_driver *d, void *data) struct i2c_driver *driver = to_i2c_driver(d); struct i2c_adapter *adap = data; + /* Detect supported devices on that bus, and instantiate them */ + i2c_detect(adap, driver); + + /* Let legacy drivers scan this bus for matching devices */ if (driver->attach_adapter) { /* We ignore the return code; if it fails, too bad */ driver->attach_adapter(adap); @@ -455,7 +455,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap) if (adap->nr < __i2c_first_dynamic_bus_num) i2c_scan_static_board_info(adap); - /* let legacy drivers scan this bus for matching devices */ + /* Notify drivers */ dummy = bus_for_each_drv(&i2c_bus_type, NULL, adap, i2c_do_add_adapter); @@ -561,8 +561,19 @@ static int i2c_do_del_adapter(struct device_driver *d, void *data) { struct i2c_driver *driver = to_i2c_driver(d); struct i2c_adapter *adapter = data; + struct i2c_client *client, *_n; int res; + /* Remove the devices we created ourselves */ + list_for_each_entry_safe(client, _n, &driver->clients, detected) { + if (client->adapter == adapter) { + dev_dbg(&adapter->dev, "Removing %s at 0x%x\n", + client->name, client->addr); + list_del(&client->detected); + i2c_unregister_device(client); + } + } + if (!driver->detach_adapter) return 0; res = driver->detach_adapter(adapter); @@ -582,8 +593,7 @@ static int i2c_do_del_adapter(struct device_driver *d, void *data) */ int i2c_del_adapter(struct i2c_adapter *adap) { - struct list_head *item, *_n; - struct i2c_client *client; + struct i2c_client *client, *_n; int res = 0; mutex_lock(&core_lock); @@ -604,10 +614,9 @@ 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 up. */ - list_for_each_safe(item, _n, &adap->clients) { + list_for_each_entry_safe(client, _n, &adap->clients, list) { struct i2c_driver *driver; - client = list_entry(item, struct i2c_client, list); driver = client->driver; /* new style, follow standard driver model */ @@ -646,12 +655,17 @@ EXPORT_SYMBOL(i2c_del_adapter); /* ------------------------------------------------------------------------- */ -static int attach_device(struct device *dev, void *data) +static int __attach_adapter(struct device *dev, void *data) { struct i2c_adapter *adapter = to_i2c_adapter(dev); struct i2c_driver *driver = data; - driver->attach_adapter(adapter); + i2c_detect(adapter, driver); + + /* Legacy drivers scan i2c busses directly */ + if (driver->attach_adapter) + driver->attach_adapter(adapter); + return 0; } @@ -694,50 +708,57 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name); - /* legacy drivers scan i2c busses directly */ - if (driver->attach_adapter) - class_for_each_device(&i2c_adapter_class, NULL, - (void *)driver, attach_device); + INIT_LIST_HEAD(&driver->clients); + /* Walk the adapters that are already present */ + class_for_each_device(&i2c_adapter_class, NULL, driver, + __attach_adapter); mutex_unlock(&core_lock); return 0; } EXPORT_SYMBOL(i2c_register_driver); -static int detach_device(struct device *dev, void *data) +static int __detach_adapter(struct device *dev, void *data) { struct i2c_adapter *adapter = to_i2c_adapter(dev); struct i2c_driver *driver = data; - struct list_head *item2; - struct list_head *_n; - struct i2c_client *client; + struct i2c_client *client, *_n; + + list_for_each_entry_safe(client, _n, &driver->clients, detected) { + dev_dbg(&adapter->dev, "Removing %s at 0x%x\n", + client->name, client->addr); + list_del(&client->detected); + i2c_unregister_device(client); + } + + if (is_newstyle_driver(driver)) + return 0; /* Have a look at each adapter, if clients of this driver are still * attached. If so, detach them to be able to kill the driver * afterwards. */ if (driver->detach_adapter) { - if (driver->detach_adapter(adapter)) { - dev_err(&adapter->dev, "detach_adapter failed " - "for driver [%s]\n", + if (driver->detach_adapter(adapter)) + dev_err(&adapter->dev, + "detach_adapter failed for driver [%s]\n", driver->driver.name); - } } else { - list_for_each_safe(item2, _n, &adapter->clients) { - client = list_entry(item2, struct i2c_client, list); + struct i2c_client *client, *_n; + + list_for_each_entry_safe(client, _n, &adapter->clients, list) { if (client->driver != driver) continue; - dev_dbg(&adapter->dev, "detaching client [%s] " - "at 0x%02x\n", client->name, - client->addr); - if (driver->detach_client(client)) { + dev_dbg(&adapter->dev, + "detaching client [%s] at 0x%02x\n", + client->name, client->addr); + if (driver->detach_client(client)) dev_err(&adapter->dev, "detach_client " - "failed for client [%s] at " - "0x%02x\n", client->name, - client->addr); - } + "failed for client [%s] at 0x%02x\n", + client->name, client->addr); } } + return 0; } @@ -750,15 +771,9 @@ void i2c_del_driver(struct i2c_driver *driver) { mutex_lock(&core_lock); - /* new-style driver? */ - if (is_newstyle_driver(driver)) - goto unregister; - - /* old-style driver, do it by hand */ - class_for_each_device(&i2c_adapter_class, NULL, (void *)driver, - detach_device); + class_for_each_device(&i2c_adapter_class, NULL, driver, + __detach_adapter); - unregister: driver_unregister(&driver->driver); pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name); @@ -871,8 +886,9 @@ EXPORT_SYMBOL(i2c_detach_client); */ struct i2c_client *i2c_use_client(struct i2c_client *client) { - get_device(&client->dev); - return client; + if (client && get_device(&client->dev)) + return client; + return NULL; } EXPORT_SYMBOL(i2c_use_client); @@ -884,7 +900,8 @@ EXPORT_SYMBOL(i2c_use_client); */ void i2c_release_client(struct i2c_client *client) { - put_device(&client->dev); + if (client) + put_device(&client->dev); } EXPORT_SYMBOL(i2c_release_client); @@ -950,10 +967,39 @@ module_exit(i2c_exit); * ---------------------------------------------------- */ +/** + * i2c_transfer - execute a single or combined I2C message + * @adap: Handle to I2C bus + * @msgs: One or more messages to execute before STOP is issued to + * terminate the operation; each message begins with a START. + * @num: Number of messages to be executed. + * + * Returns negative errno, else the number of messages executed. + * + * Note that there is no requirement that each message be sent to + * the same slave address, although that is the most common model. + */ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num) { int ret; + /* REVISIT the fault reporting model here is weak: + * + * - When we get an error after receiving N bytes from a slave, + * there is no way to report "N". + * + * - When we get a NAK after transmitting N bytes to a slave, + * there is no way to report "N" ... or to let the master + * continue executing the rest of this combined message, if + * that's the appropriate response. + * + * - When for example "num" is two and we successfully complete + * the first message but get an error part way through the + * second, it's unclear whether that should be reported as + * one (discarding status on the second message) or errno + * (discarding status on the first one). + */ + if (adap->algo->master_xfer) { #ifdef DEBUG for (ret = 0; ret < num; ret++) { @@ -979,11 +1025,19 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num) return ret; } else { dev_dbg(&adap->dev, "I2C level transfers not supported\n"); - return -ENOSYS; + return -EOPNOTSUPP; } } EXPORT_SYMBOL(i2c_transfer); +/** + * i2c_master_send - issue a single I2C message in master transmit mode + * @client: Handle to slave device + * @buf: Data that will be written to the slave + * @count: How many bytes to write + * + * Returns negative errno, or else the number of bytes written. + */ int i2c_master_send(struct i2c_client *client,const char *buf ,int count) { int ret; @@ -1003,6 +1057,14 @@ int i2c_master_send(struct i2c_client *client,const char *buf ,int count) } EXPORT_SYMBOL(i2c_master_send); +/** + * i2c_master_recv - issue a single I2C message in master receive mode + * @client: Handle to slave device + * @buf: Where to store data read from slave + * @count: How many bytes to read + * + * Returns negative errno, or else the number of bytes read. + */ int i2c_master_recv(struct i2c_client *client, char *buf ,int count) { struct i2c_adapter *adap=client->adapter; @@ -1111,7 +1173,7 @@ int i2c_probe(struct i2c_adapter *adapter, dev_warn(&adapter->dev, "SMBus Quick command not supported, " "can't probe for chips\n"); - return -1; + return -EOPNOTSUPP; } /* Probe entries are done second, and are not affected by ignore @@ -1165,6 +1227,178 @@ int i2c_probe(struct i2c_adapter *adapter, } EXPORT_SYMBOL(i2c_probe); +/* Separate detection function for new-style drivers */ +static int i2c_detect_address(struct i2c_client *temp_client, int kind, + struct i2c_driver *driver) +{ + struct i2c_board_info info; + struct i2c_adapter *adapter = temp_client->adapter; + int addr = temp_client->addr; + int err; + + /* Make sure the address is valid */ + if (addr < 0x03 || addr > 0x77) { + dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n", + addr); + return -EINVAL; + } + + /* Skip if already in use */ + if (i2c_check_addr(adapter, addr)) + return 0; + + /* Make sure there is something at this address, unless forced */ + if (kind < 0) { + if (i2c_smbus_xfer(adapter, addr, 0, 0, 0, + I2C_SMBUS_QUICK, NULL) < 0) + return 0; + + /* prevent 24RF08 corruption */ + if ((addr & ~0x0f) == 0x50) + i2c_smbus_xfer(adapter, addr, 0, 0, 0, + I2C_SMBUS_QUICK, NULL); + } + + /* Finally call the custom detection function */ + memset(&info, 0, sizeof(struct i2c_board_info)); + info.addr = addr; + err = driver->detect(temp_client, kind, &info); + if (err) { + /* -ENODEV is returned if the detection fails. We catch it + here as this isn't an error. */ + return err == -ENODEV ? 0 : err; + } + + /* Consistency check */ + if (info.type[0] == '\0') { + dev_err(&adapter->dev, "Detection function returned " + "inconsistent data for 0x%x\n", addr); + } else { + struct i2c_client *client; + + /* Detection succeeded, instantiate the device */ + dev_dbg(&adapter->dev, "Creating %s at 0x%02x\n", + info.type, info.addr); + client = i2c_new_device(adapter, &info); + if (client) + list_add_tail(&client->detected, &driver->clients); + else + dev_err(&adapter->dev, "Failed creating %s at 0x%02x\n", + info.type, info.addr); + } + return 0; +} + +static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver) +{ + const struct i2c_client_address_data *address_data; + struct i2c_client *temp_client; + int i, err = 0; + int adap_id = i2c_adapter_id(adapter); + + address_data = driver->address_data; + if (!driver->detect || !address_data) + return 0; + + /* Set up a temporary client to help detect callback */ + temp_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (!temp_client) + return -ENOMEM; + temp_client->adapter = adapter; + + /* Force entries are done first, and are not affected by ignore + entries */ + if (address_data->forces) { + const unsigned short * const *forces = address_data->forces; + int kind; + + for (kind = 0; forces[kind]; kind++) { + for (i = 0; forces[kind][i] != I2C_CLIENT_END; + i += 2) { + if (forces[kind][i] == adap_id + || forces[kind][i] == ANY_I2C_BUS) { + dev_dbg(&adapter->dev, "found force " + "parameter for adapter %d, " + "addr 0x%02x, kind %d\n", + adap_id, forces[kind][i + 1], + kind); + temp_client->addr = forces[kind][i + 1]; + err = i2c_detect_address(temp_client, + kind, driver); + if (err) + goto exit_free; + } + } + } + } + + /* Stop here if we can't use SMBUS_QUICK */ + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK)) { + if (address_data->probe[0] == I2C_CLIENT_END + && address_data->normal_i2c[0] == I2C_CLIENT_END) + goto exit_free; + + dev_warn(&adapter->dev, "SMBus Quick command not supported, " + "can't probe for chips\n"); + err = -EOPNOTSUPP; + goto exit_free; + } + + /* Stop here if the classes do not match */ + if (!(adapter->class & driver->class)) + goto exit_free; + + /* Probe entries are done second, and are not affected by ignore + entries either */ + for (i = 0; address_data->probe[i] != I2C_CLIENT_END; i += 2) { + if (address_data->probe[i] == adap_id + || address_data->probe[i] == ANY_I2C_BUS) { + dev_dbg(&adapter->dev, "found probe parameter for " + "adapter %d, addr 0x%02x\n", adap_id, + address_data->probe[i + 1]); + temp_client->addr = address_data->probe[i + 1]; + err = i2c_detect_address(temp_client, -1, driver); + if (err) + goto exit_free; + } + } + + /* Normal entries are done last, unless shadowed by an ignore entry */ + for (i = 0; address_data->normal_i2c[i] != I2C_CLIENT_END; i += 1) { + int j, ignore; + + ignore = 0; + for (j = 0; address_data->ignore[j] != I2C_CLIENT_END; + j += 2) { + if ((address_data->ignore[j] == adap_id || + address_data->ignore[j] == ANY_I2C_BUS) + && address_data->ignore[j + 1] + == address_data->normal_i2c[i]) { + dev_dbg(&adapter->dev, "found ignore " + "parameter for adapter %d, " + "addr 0x%02x\n", adap_id, + address_data->ignore[j + 1]); + ignore = 1; + break; + } + } + if (ignore) + continue; + + dev_dbg(&adapter->dev, "found normal entry for adapter %d, " + "addr 0x%02x\n", adap_id, + address_data->normal_i2c[i]); + temp_client->addr = address_data->normal_i2c[i]; + err = i2c_detect_address(temp_client, -1, driver); + if (err) + goto exit_free; + } + + exit_free: + kfree(temp_client); + return err; +} + struct i2c_client * i2c_new_probed_device(struct i2c_adapter *adap, struct i2c_board_info *info, @@ -1303,29 +1537,38 @@ static int i2c_smbus_check_pec(u8 cpec, struct i2c_msg *msg) if (rpec != cpec) { pr_debug("i2c-core: Bad PEC 0x%02x vs. 0x%02x\n", rpec, cpec); - return -1; + return -EBADMSG; } return 0; } -s32 i2c_smbus_write_quick(struct i2c_client *client, u8 value) -{ - return i2c_smbus_xfer(client->adapter,client->addr,client->flags, - value,0,I2C_SMBUS_QUICK,NULL); -} -EXPORT_SYMBOL(i2c_smbus_write_quick); - +/** + * i2c_smbus_read_byte - SMBus "receive byte" protocol + * @client: Handle to slave device + * + * This executes the SMBus "receive byte" protocol, returning negative errno + * else the byte received from the device. + */ s32 i2c_smbus_read_byte(struct i2c_client *client) { union i2c_smbus_data data; - if (i2c_smbus_xfer(client->adapter,client->addr,client->flags, - I2C_SMBUS_READ,0,I2C_SMBUS_BYTE, &data)) - return -1; - else - return data.byte; + int status; + + status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, + I2C_SMBUS_READ, 0, + I2C_SMBUS_BYTE, &data); + return (status < 0) ? status : data.byte; } EXPORT_SYMBOL(i2c_smbus_read_byte); +/** + * i2c_smbus_write_byte - SMBus "send byte" protocol + * @client: Handle to slave device + * @value: Byte to be sent + * + * This executes the SMBus "send byte" protocol, returning negative errno + * else zero on success. + */ s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value) { return i2c_smbus_xfer(client->adapter,client->addr,client->flags, @@ -1333,17 +1576,35 @@ s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value) } EXPORT_SYMBOL(i2c_smbus_write_byte); +/** + * i2c_smbus_read_byte_data - SMBus "read byte" protocol + * @client: Handle to slave device + * @command: Byte interpreted by slave + * + * This executes the SMBus "read byte" protocol, returning negative errno + * else a data byte received from the device. + */ s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command) { union i2c_smbus_data data; - if (i2c_smbus_xfer(client->adapter,client->addr,client->flags, - I2C_SMBUS_READ,command, I2C_SMBUS_BYTE_DATA,&data)) - return -1; - else - return data.byte; + int status; + + status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, + I2C_SMBUS_READ, command, + I2C_SMBUS_BYTE_DATA, &data); + return (status < 0) ? status : data.byte; } EXPORT_SYMBOL(i2c_smbus_read_byte_data); +/** + * i2c_smbus_write_byte_data - SMBus "write byte" protocol + * @client: Handle to slave device + * @command: Byte interpreted by slave + * @value: Byte being written + * + * This executes the SMBus "write byte" protocol, returning negative errno + * else zero on success. + */ s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value) { union i2c_smbus_data data; @@ -1354,17 +1615,35 @@ s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value) } EXPORT_SYMBOL(i2c_smbus_write_byte_data); +/** + * i2c_smbus_read_word_data - SMBus "read word" protocol + * @client: Handle to slave device + * @command: Byte interpreted by slave + * + * This executes the SMBus "read word" protocol, returning negative errno + * else a 16-bit unsigned "word" received from the device. + */ s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command) { union i2c_smbus_data data; - if (i2c_smbus_xfer(client->adapter,client->addr,client->flags, - I2C_SMBUS_READ,command, I2C_SMBUS_WORD_DATA, &data)) - return -1; - else - return data.word; + int status; + + status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, + I2C_SMBUS_READ, command, + I2C_SMBUS_WORD_DATA, &data); + return (status < 0) ? status : data.word; } EXPORT_SYMBOL(i2c_smbus_read_word_data); +/** + * i2c_smbus_write_word_data - SMBus "write word" protocol + * @client: Handle to slave device + * @command: Byte interpreted by slave + * @value: 16-bit "word" being written + * + * This executes the SMBus "write word" protocol, returning negative errno + * else zero on success. + */ s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value) { union i2c_smbus_data data; @@ -1376,15 +1655,14 @@ s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value) EXPORT_SYMBOL(i2c_smbus_write_word_data); /** - * i2c_smbus_read_block_data - SMBus block read request + * i2c_smbus_read_block_data - SMBus "block read" protocol * @client: Handle to slave device - * @command: Command byte issued to let the slave know what data should - * be returned + * @command: Byte interpreted by slave * @values: Byte array into which data will be read; big enough to hold * the data returned by the slave. SMBus allows at most 32 bytes. * - * Returns the number of bytes read in the slave's response, else a - * negative number to indicate some kind of error. + * This executes the SMBus "block read" protocol, returning negative errno + * else the number of data bytes in the slave's response. * * Note that using this function requires that the client's adapter support * the I2C_FUNC_SMBUS_READ_BLOCK_DATA functionality. Not all adapter drivers @@ -1395,17 +1673,29 @@ s32 i2c_smbus_read_block_data(struct i2c_client *client, u8 command, u8 *values) { union i2c_smbus_data data; + int status; - if (i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_READ, command, - I2C_SMBUS_BLOCK_DATA, &data)) - return -1; + status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, + I2C_SMBUS_READ, command, + I2C_SMBUS_BLOCK_DATA, &data); + if (status) + return status; memcpy(values, &data.block[1], data.block[0]); return data.block[0]; } EXPORT_SYMBOL(i2c_smbus_read_block_data); +/** + * i2c_smbus_write_block_data - SMBus "block write" protocol + * @client: Handle to slave device + * @command: Byte interpreted by slave + * @length: Size of data block; SMBus allows at most 32 bytes + * @values: Byte array which will be written. + * + * This executes the SMBus "block write" protocol, returning negative errno + * else zero on success. + */ s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command, u8 length, const u8 *values) { @@ -1426,14 +1716,16 @@ s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 length, u8 *values) { union i2c_smbus_data data; + int status; if (length > I2C_SMBUS_BLOCK_MAX) length = I2C_SMBUS_BLOCK_MAX; data.block[0] = length; - if (i2c_smbus_xfer(client->adapter,client->addr,client->flags, - I2C_SMBUS_READ,command, - I2C_SMBUS_I2C_BLOCK_DATA,&data)) - return -1; + status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, + I2C_SMBUS_READ, command, + I2C_SMBUS_I2C_BLOCK_DATA, &data); + if (status < 0) + return status; memcpy(values, &data.block[1], data.block[0]); return data.block[0]; @@ -1474,6 +1766,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, }; int i; u8 partial_pec = 0; + int status; msgbuf0[0] = command; switch(size) { @@ -1523,10 +1816,10 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, } else { msg[0].len = data->block[0] + 2; if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) { - dev_err(&adapter->dev, "smbus_access called with " - "invalid block write size (%d)\n", - data->block[0]); - return -1; + dev_err(&adapter->dev, + "Invalid block write size %d\n", + data->block[0]); + return -EINVAL; } for (i = 1; i < msg[0].len; i++) msgbuf0[i] = data->block[i-1]; @@ -1536,10 +1829,10 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, num = 2; /* Another special case */ read_write = I2C_SMBUS_READ; if (data->block[0] > I2C_SMBUS_BLOCK_MAX) { - dev_err(&adapter->dev, "%s called with invalid " - "block proc call size (%d)\n", __func__, + dev_err(&adapter->dev, + "Invalid block write size %d\n", data->block[0]); - return -1; + return -EINVAL; } msg[0].len = data->block[0] + 2; for (i = 1; i < msg[0].len; i++) @@ -1554,19 +1847,18 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, } else { msg[0].len = data->block[0] + 1; if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 1) { - dev_err(&adapter->dev, "i2c_smbus_xfer_emulated called with " - "invalid block write size (%d)\n", - data->block[0]); - return -1; + dev_err(&adapter->dev, + "Invalid block write size %d\n", + data->block[0]); + return -EINVAL; } for (i = 1; i <= data->block[0]; i++) msgbuf0[i] = data->block[i]; } break; default: - dev_err(&adapter->dev, "smbus_access called with invalid size (%d)\n", - size); - return -1; + dev_err(&adapter->dev, "Unsupported transaction %d\n", size); + return -EOPNOTSUPP; } i = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK @@ -1584,13 +1876,15 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, msg[num-1].len++; } - if (i2c_transfer(adapter, msg, num) < 0) - return -1; + status = i2c_transfer(adapter, msg, num); + if (status < 0) + return status; /* Check PEC if last message is a read */ if (i && (msg[num-1].flags & I2C_M_RD)) { - if (i2c_smbus_check_pec(partial_pec, &msg[num-1]) < 0) - return -1; + status = i2c_smbus_check_pec(partial_pec, &msg[num-1]); + if (status < 0) + return status; } if (read_write == I2C_SMBUS_READ) @@ -1618,9 +1912,21 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, return 0; } - +/** + * i2c_smbus_xfer - execute SMBus protocol operations + * @adapter: Handle to I2C bus + * @addr: Address of SMBus slave on that bus + * @flags: I2C_CLIENT_* flags (usually zero or I2C_CLIENT_PEC) + * @read_write: I2C_SMBUS_READ or I2C_SMBUS_WRITE + * @command: Byte interpreted by slave, for protocols which use such bytes + * @protocol: SMBus protocol operation to execute, such as I2C_SMBUS_PROC_CALL + * @data: Data to be read or written + * + * This executes an SMBus protocol operation, and returns a negative + * errno code else zero on success. + */ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags, - char read_write, u8 command, int size, + char read_write, u8 command, int protocol, union i2c_smbus_data * data) { s32 res; @@ -1630,11 +1936,11 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags, if (adapter->algo->smbus_xfer) { mutex_lock(&adapter->bus_lock); res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write, - command,size,data); + command, protocol, data); mutex_unlock(&adapter->bus_lock); } else res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write, - command,size,data); + command, protocol, data); return res; } diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 7cd3c32dd0fb..212573959a45 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -366,8 +366,7 @@ static noinline int i2cdev_ioctl_smbus(struct i2c_client *client, return res; } -static int i2cdev_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct i2c_client *client = (struct i2c_client *)file->private_data; unsigned long funcs; @@ -487,7 +486,7 @@ static const struct file_operations i2cdev_fops = { .llseek = no_llseek, .read = i2cdev_read, .write = i2cdev_write, - .ioctl = i2cdev_ioctl, + .unlocked_ioctl = i2cdev_ioctl, .open = i2cdev_open, .release = i2cdev_release, }; @@ -549,19 +548,12 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap) return 0; } -static int i2cdev_detach_client(struct i2c_client *client) -{ - return 0; -} - static struct i2c_driver i2cdev_driver = { .driver = { .name = "dev_driver", }, - .id = I2C_DRIVERID_I2CDEV, .attach_adapter = i2cdev_attach_adapter, .detach_adapter = i2cdev_detach_adapter, - .detach_client = i2cdev_detach_client, }; /* ------------------------------------------------------------------------- */ diff --git a/drivers/video/fb_ddc.c b/drivers/video/fb_ddc.c index a0df63289b5f..0cf96eb8a60f 100644 --- a/drivers/video/fb_ddc.c +++ b/drivers/video/fb_ddc.c @@ -106,6 +106,7 @@ unsigned char *fb_ddc_read(struct i2c_adapter *adapter) algo_data->setsda(algo_data->data, 1); algo_data->setscl(algo_data->data, 1); + adapter->class |= I2C_CLASS_DDC; return edid; } diff --git a/drivers/video/intelfb/intelfb_i2c.c b/drivers/video/intelfb/intelfb_i2c.c index ca95f09d8b43..fcf9fadbf572 100644 --- a/drivers/video/intelfb/intelfb_i2c.c +++ b/drivers/video/intelfb/intelfb_i2c.c @@ -100,7 +100,8 @@ static int intelfb_gpio_getsda(void *data) static int intelfb_setup_i2c_bus(struct intelfb_info *dinfo, struct intelfb_i2c_chan *chan, - const u32 reg, const char *name) + const u32 reg, const char *name, + int class) { int rc; @@ -108,6 +109,7 @@ static int intelfb_setup_i2c_bus(struct intelfb_info *dinfo, chan->reg = reg; snprintf(chan->adapter.name, sizeof(chan->adapter.name), "intelfb %s", name); + chan->adapter.class = class; chan->adapter.owner = THIS_MODULE; chan->adapter.id = I2C_HW_B_INTELFB; chan->adapter.algo_data = &chan->algo; @@ -145,7 +147,7 @@ void intelfb_create_i2c_busses(struct intelfb_info *dinfo) /* setup the DDC bus for analog output */ intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus, GPIOA, - "CRTDDC_A"); + "CRTDDC_A", I2C_CLASS_DDC); i++; /* need to add the output busses for each device @@ -159,9 +161,9 @@ void intelfb_create_i2c_busses(struct intelfb_info *dinfo) case INTEL_865G: dinfo->output[i].type = INTELFB_OUTPUT_DVO; intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus, - GPIOD, "DVODDC_D"); + GPIOD, "DVODDC_D", I2C_CLASS_DDC); intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus, - GPIOE, "DVOI2C_E"); + GPIOE, "DVOI2C_E", 0); i++; break; case INTEL_915G: @@ -174,7 +176,7 @@ void intelfb_create_i2c_busses(struct intelfb_info *dinfo) /* SDVO ports have a single control bus - 2 devices */ dinfo->output[i].type = INTELFB_OUTPUT_SDVO; intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus, - GPIOE, "SDVOCTRL_E"); + GPIOE, "SDVOCTRL_E", 0); /* TODO: initialize the SDVO */ /* I830SDVOInit(pScrn, i, DVOB); */ i++; diff --git a/drivers/video/matrox/i2c-matroxfb.c b/drivers/video/matrox/i2c-matroxfb.c index 4baab7be58de..c14e3e2212b3 100644 --- a/drivers/video/matrox/i2c-matroxfb.c +++ b/drivers/video/matrox/i2c-matroxfb.c @@ -87,13 +87,7 @@ static int matroxfb_gpio_getscl(void* data) { return (matroxfb_read_gpio(b->minfo) & b->mask.clock) ? 1 : 0; } -static struct i2c_adapter matrox_i2c_adapter_template = -{ - .owner = THIS_MODULE, - .id = I2C_HW_B_G400, -}; - -static struct i2c_algo_bit_data matrox_i2c_algo_template = +static const struct i2c_algo_bit_data matrox_i2c_algo_template = { .setsda = matroxfb_gpio_setsda, .setscl = matroxfb_gpio_setscl, @@ -104,16 +98,19 @@ static struct i2c_algo_bit_data matrox_i2c_algo_template = }; static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo, - unsigned int data, unsigned int clock, const char* name) { + unsigned int data, unsigned int clock, const char *name, + int class) +{ int err; b->minfo = minfo; b->mask.data = data; b->mask.clock = clock; - b->adapter = matrox_i2c_adapter_template; + b->adapter.owner = THIS_MODULE; snprintf(b->adapter.name, sizeof(b->adapter.name), name, minfo->fbcon.node); i2c_set_adapdata(&b->adapter, b); + b->adapter.class = class; b->adapter.algo_data = &b->bac; b->adapter.dev.parent = &ACCESS_FBINFO(pcidev)->dev; b->bac = matrox_i2c_algo_template; @@ -159,24 +156,42 @@ static void* i2c_matroxfb_probe(struct matrox_fb_info* minfo) { switch (ACCESS_FBINFO(chip)) { case MGA_2064: case MGA_2164: - err = i2c_bus_reg(&m2info->ddc1, minfo, DDC1B_DATA, DDC1B_CLK, "DDC:fb%u #0"); + err = i2c_bus_reg(&m2info->ddc1, minfo, + DDC1B_DATA, DDC1B_CLK, + "DDC:fb%u #0", I2C_CLASS_DDC); break; default: - err = i2c_bus_reg(&m2info->ddc1, minfo, DDC1_DATA, DDC1_CLK, "DDC:fb%u #0"); + err = i2c_bus_reg(&m2info->ddc1, minfo, + DDC1_DATA, DDC1_CLK, + "DDC:fb%u #0", I2C_CLASS_DDC); break; } if (err) goto fail_ddc1; if (ACCESS_FBINFO(devflags.dualhead)) { - err = i2c_bus_reg(&m2info->ddc2, minfo, DDC2_DATA, DDC2_CLK, "DDC:fb%u #1"); + err = i2c_bus_reg(&m2info->ddc2, minfo, + DDC2_DATA, DDC2_CLK, + "DDC:fb%u #1", I2C_CLASS_DDC); if (err == -ENODEV) { printk(KERN_INFO "i2c-matroxfb: VGA->TV plug detected, DDC unavailable.\n"); } else if (err) printk(KERN_INFO "i2c-matroxfb: Could not register secondary output i2c bus. Continuing anyway.\n"); /* Register maven bus even on G450/G550 */ - err = i2c_bus_reg(&m2info->maven, minfo, MAT_DATA, MAT_CLK, "MAVEN:fb%u"); + err = i2c_bus_reg(&m2info->maven, minfo, + MAT_DATA, MAT_CLK, "MAVEN:fb%u", 0); if (err) printk(KERN_INFO "i2c-matroxfb: Could not register Maven i2c bus. Continuing anyway.\n"); + else { + struct i2c_board_info maven_info = { + I2C_BOARD_INFO("maven", 0x1b), + }; + unsigned short const addr_list[2] = { + 0x1b, I2C_CLIENT_END + }; + + i2c_new_probed_device(&m2info->maven.adapter, + &maven_info, addr_list); + } } return m2info; fail_ddc1:; diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c index 89da27bd5c49..6d31eb4b674e 100644 --- a/drivers/video/matrox/matroxfb_maven.c +++ b/drivers/video/matrox/matroxfb_maven.c @@ -19,8 +19,6 @@ #include <linux/matroxfb.h> #include <asm/div64.h> -#define MAVEN_I2CID (0x1B) - #define MGATVO_B 1 #define MGATVO_C 2 @@ -128,7 +126,7 @@ static int get_ctrl_id(__u32 v4l2_id) { struct maven_data { struct matrox_fb_info* primary_head; - struct i2c_client client; + struct i2c_client *client; int version; }; @@ -974,7 +972,7 @@ static inline int maven_compute_timming(struct maven_data* md, static int maven_program_timming(struct maven_data* md, const struct mavenregs* m) { - struct i2c_client* c = &md->client; + struct i2c_client *c = md->client; if (m->mode == MATROXFB_OUTPUT_MODE_MONITOR) { LR(0x80); @@ -1011,7 +1009,7 @@ static int maven_program_timming(struct maven_data* md, } static inline int maven_resync(struct maven_data* md) { - struct i2c_client* c = &md->client; + struct i2c_client *c = md->client; maven_set_reg(c, 0x95, 0x20); /* start whole thing */ return 0; } @@ -1069,48 +1067,48 @@ static int maven_set_control (struct maven_data* md, maven_compute_bwlevel(md, &blacklevel, &whitelevel); blacklevel = (blacklevel >> 2) | ((blacklevel & 3) << 8); whitelevel = (whitelevel >> 2) | ((whitelevel & 3) << 8); - maven_set_reg_pair(&md->client, 0x0e, blacklevel); - maven_set_reg_pair(&md->client, 0x1e, whitelevel); + maven_set_reg_pair(md->client, 0x0e, blacklevel); + maven_set_reg_pair(md->client, 0x1e, whitelevel); } break; case V4L2_CID_SATURATION: { - maven_set_reg(&md->client, 0x20, p->value); - maven_set_reg(&md->client, 0x22, p->value); + maven_set_reg(md->client, 0x20, p->value); + maven_set_reg(md->client, 0x22, p->value); } break; case V4L2_CID_HUE: { - maven_set_reg(&md->client, 0x25, p->value); + maven_set_reg(md->client, 0x25, p->value); } break; case V4L2_CID_GAMMA: { const struct maven_gamma* g; g = maven_compute_gamma(md); - maven_set_reg(&md->client, 0x83, g->reg83); - maven_set_reg(&md->client, 0x84, g->reg84); - maven_set_reg(&md->client, 0x85, g->reg85); - maven_set_reg(&md->client, 0x86, g->reg86); - maven_set_reg(&md->client, 0x87, g->reg87); - maven_set_reg(&md->client, 0x88, g->reg88); - maven_set_reg(&md->client, 0x89, g->reg89); - maven_set_reg(&md->client, 0x8a, g->reg8a); - maven_set_reg(&md->client, 0x8b, g->reg8b); + maven_set_reg(md->client, 0x83, g->reg83); + maven_set_reg(md->client, 0x84, g->reg84); + maven_set_reg(md->client, 0x85, g->reg85); + maven_set_reg(md->client, 0x86, g->reg86); + maven_set_reg(md->client, 0x87, g->reg87); + maven_set_reg(md->client, 0x88, g->reg88); + maven_set_reg(md->client, 0x89, g->reg89); + maven_set_reg(md->client, 0x8a, g->reg8a); + maven_set_reg(md->client, 0x8b, g->reg8b); } break; case MATROXFB_CID_TESTOUT: { unsigned char val - = maven_get_reg(&md->client,0x8d); + = maven_get_reg(md->client, 0x8d); if (p->value) val |= 0x10; else val &= ~0x10; - maven_set_reg(&md->client, 0x8d, val); + maven_set_reg(md->client, 0x8d, val); } break; case MATROXFB_CID_DEFLICKER: { - maven_set_reg(&md->client, 0x93, maven_compute_deflicker(md)); + maven_set_reg(md->client, 0x93, maven_compute_deflicker(md)); } break; } @@ -1189,6 +1187,7 @@ static int maven_init_client(struct i2c_client* clnt) { MINFO_FROM(container_of(clnt->adapter, struct i2c_bit_adapter, adapter)->minfo); md->primary_head = MINFO; + md->client = clnt; down_write(&ACCESS_FBINFO(altout.lock)); ACCESS_FBINFO(outputs[1]).output = &maven_altout; ACCESS_FBINFO(outputs[1]).src = ACCESS_FBINFO(outputs[1]).default_src; @@ -1232,14 +1231,11 @@ static int maven_shutdown_client(struct i2c_client* clnt) { return 0; } -static const unsigned short normal_i2c[] = { MAVEN_I2CID, I2C_CLIENT_END }; -I2C_CLIENT_INSMOD; - -static struct i2c_driver maven_driver; - -static int maven_detect_client(struct i2c_adapter* adapter, int address, int kind) { - int err = 0; - struct i2c_client* new_client; +static int maven_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adapter = client->adapter; + int err = -ENODEV; struct maven_data* data; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_WORD_DATA | @@ -1250,50 +1246,37 @@ static int maven_detect_client(struct i2c_adapter* adapter, int address, int kin err = -ENOMEM; goto ERROR0; } - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &maven_driver; - new_client->flags = 0; - strlcpy(new_client->name, "maven", I2C_NAME_SIZE); - if ((err = i2c_attach_client(new_client))) - goto ERROR3; - err = maven_init_client(new_client); + i2c_set_clientdata(client, data); + err = maven_init_client(client); if (err) goto ERROR4; return 0; ERROR4:; - i2c_detach_client(new_client); -ERROR3:; - kfree(new_client); + kfree(data); ERROR0:; return err; } -static int maven_attach_adapter(struct i2c_adapter* adapter) { - if (adapter->id == I2C_HW_B_G400) - return i2c_probe(adapter, &addr_data, &maven_detect_client); - return 0; -} - -static int maven_detach_client(struct i2c_client* client) { - int err; - - if ((err = i2c_detach_client(client))) - return err; +static int maven_remove(struct i2c_client *client) +{ maven_shutdown_client(client); kfree(i2c_get_clientdata(client)); return 0; } +static struct i2c_device_id maven_id[] = { + { "maven", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, maven_id); + static struct i2c_driver maven_driver={ .driver = { .name = "maven", }, - .id = I2C_DRIVERID_MGATVO, - .attach_adapter = maven_attach_adapter, - .detach_client = maven_detach_client, + .probe = maven_probe, + .remove = maven_remove, + .id_table = maven_id, }; static int __init matroxfb_maven_init(void) diff --git a/drivers/w1/masters/ds2482.c b/drivers/w1/masters/ds2482.c index 0fd5820d5c61..74c199dd41ec 100644 --- a/drivers/w1/masters/ds2482.c +++ b/drivers/w1/masters/ds2482.c @@ -94,21 +94,31 @@ static const u8 ds2482_chan_rd[8] = #define DS2482_REG_STS_1WB 0x01 -static int ds2482_attach_adapter(struct i2c_adapter *adapter); -static int ds2482_detect(struct i2c_adapter *adapter, int address, int kind); -static int ds2482_detach_client(struct i2c_client *client); +static int ds2482_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int ds2482_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); +static int ds2482_remove(struct i2c_client *client); /** * Driver data (common to all clients) */ +static struct i2c_device_id ds2482_id[] = { + { "ds2482", 0 }, + { } +}; + static struct i2c_driver ds2482_driver = { .driver = { .owner = THIS_MODULE, .name = "ds2482", }, - .attach_adapter = ds2482_attach_adapter, - .detach_client = ds2482_detach_client, + .probe = ds2482_probe, + .remove = ds2482_remove, + .id_table = ds2482_id, + .detect = ds2482_detect, + .address_data = &addr_data, }; /* @@ -124,7 +134,7 @@ struct ds2482_w1_chan { }; struct ds2482_data { - struct i2c_client client; + struct i2c_client *client; struct mutex access_lock; /* 1-wire interface(s) */ @@ -147,7 +157,7 @@ struct ds2482_data { static inline int ds2482_select_register(struct ds2482_data *pdev, u8 read_ptr) { if (pdev->read_prt != read_ptr) { - if (i2c_smbus_write_byte_data(&pdev->client, + if (i2c_smbus_write_byte_data(pdev->client, DS2482_CMD_SET_READ_PTR, read_ptr) < 0) return -1; @@ -167,7 +177,7 @@ static inline int ds2482_select_register(struct ds2482_data *pdev, u8 read_ptr) */ static inline int ds2482_send_cmd(struct ds2482_data *pdev, u8 cmd) { - if (i2c_smbus_write_byte(&pdev->client, cmd) < 0) + if (i2c_smbus_write_byte(pdev->client, cmd) < 0) return -1; pdev->read_prt = DS2482_PTR_CODE_STATUS; @@ -187,7 +197,7 @@ static inline int ds2482_send_cmd(struct ds2482_data *pdev, u8 cmd) static inline int ds2482_send_cmd_data(struct ds2482_data *pdev, u8 cmd, u8 byte) { - if (i2c_smbus_write_byte_data(&pdev->client, cmd, byte) < 0) + if (i2c_smbus_write_byte_data(pdev->client, cmd, byte) < 0) return -1; /* all cmds leave in STATUS, except CONFIG */ @@ -216,7 +226,7 @@ static int ds2482_wait_1wire_idle(struct ds2482_data *pdev) if (!ds2482_select_register(pdev, DS2482_PTR_CODE_STATUS)) { do { - temp = i2c_smbus_read_byte(&pdev->client); + temp = i2c_smbus_read_byte(pdev->client); } while ((temp >= 0) && (temp & DS2482_REG_STS_1WB) && (++retries < DS2482_WAIT_IDLE_TIMEOUT)); } @@ -238,13 +248,13 @@ static int ds2482_wait_1wire_idle(struct ds2482_data *pdev) */ static int ds2482_set_channel(struct ds2482_data *pdev, u8 channel) { - if (i2c_smbus_write_byte_data(&pdev->client, DS2482_CMD_CHANNEL_SELECT, + if (i2c_smbus_write_byte_data(pdev->client, DS2482_CMD_CHANNEL_SELECT, ds2482_chan_wr[channel]) < 0) return -1; pdev->read_prt = DS2482_PTR_CODE_CHANNEL; pdev->channel = -1; - if (i2c_smbus_read_byte(&pdev->client) == ds2482_chan_rd[channel]) { + if (i2c_smbus_read_byte(pdev->client) == ds2482_chan_rd[channel]) { pdev->channel = channel; return 0; } @@ -368,7 +378,7 @@ static u8 ds2482_w1_read_byte(void *data) ds2482_select_register(pdev, DS2482_PTR_CODE_DATA); /* Read the data byte */ - result = i2c_smbus_read_byte(&pdev->client); + result = i2c_smbus_read_byte(pdev->client); mutex_unlock(&pdev->access_lock); @@ -415,47 +425,38 @@ static u8 ds2482_w1_reset_bus(void *data) } -/** - * Called to see if the device exists on an i2c bus. - */ -static int ds2482_attach_adapter(struct i2c_adapter *adapter) +static int ds2482_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info) { - return i2c_probe(adapter, &addr_data, ds2482_detect); -} + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_BYTE_DATA | + I2C_FUNC_SMBUS_BYTE)) + return -ENODEV; + strlcpy(info->type, "ds2482", I2C_NAME_SIZE); -/* - * The following function does more than just detection. If detection - * succeeds, it also registers the new chip. - */ -static int ds2482_detect(struct i2c_adapter *adapter, int address, int kind) + return 0; +} + +static int ds2482_probe(struct i2c_client *client, + const struct i2c_device_id *id) { struct ds2482_data *data; - struct i2c_client *new_client; - int err = 0; + int err = -ENODEV; int temp1; int idx; - if (!i2c_check_functionality(adapter, - I2C_FUNC_SMBUS_WRITE_BYTE_DATA | - I2C_FUNC_SMBUS_BYTE)) - goto exit; - if (!(data = kzalloc(sizeof(struct ds2482_data), GFP_KERNEL))) { err = -ENOMEM; goto exit; } - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->driver = &ds2482_driver; - new_client->adapter = adapter; + data->client = client; + i2c_set_clientdata(client, data); /* Reset the device (sets the read_ptr to status) */ if (ds2482_send_cmd(data, DS2482_CMD_RESET) < 0) { - dev_dbg(&adapter->dev, "DS2482 reset failed at 0x%02x.\n", - address); + dev_warn(&client->dev, "DS2482 reset failed.\n"); goto exit_free; } @@ -463,10 +464,10 @@ static int ds2482_detect(struct i2c_adapter *adapter, int address, int kind) ndelay(525); /* Read the status byte - only reset bit and line should be set */ - temp1 = i2c_smbus_read_byte(new_client); + temp1 = i2c_smbus_read_byte(client); if (temp1 != (DS2482_REG_STS_LL | DS2482_REG_STS_RST)) { - dev_dbg(&adapter->dev, "DS2482 (0x%02x) reset status " - "0x%02X - not a DS2482\n", address, temp1); + dev_warn(&client->dev, "DS2482 reset status " + "0x%02X - not a DS2482\n", temp1); goto exit_free; } @@ -478,16 +479,8 @@ static int ds2482_detect(struct i2c_adapter *adapter, int address, int kind) /* Set all config items to 0 (off) */ ds2482_send_cmd_data(data, DS2482_CMD_WRITE_CONFIG, 0xF0); - /* We can fill in the remaining client fields */ - snprintf(new_client->name, sizeof(new_client->name), "ds2482-%d00", - data->w1_count); - mutex_init(&data->access_lock); - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) - goto exit_free; - /* Register 1-wire interface(s) */ for (idx = 0; idx < data->w1_count; idx++) { data->w1_ch[idx].pdev = data; @@ -511,8 +504,6 @@ static int ds2482_detect(struct i2c_adapter *adapter, int address, int kind) return 0; exit_w1_remove: - i2c_detach_client(new_client); - for (idx = 0; idx < data->w1_count; idx++) { if (data->w1_ch[idx].pdev != NULL) w1_remove_master_device(&data->w1_ch[idx].w1_bm); @@ -523,10 +514,10 @@ exit: return err; } -static int ds2482_detach_client(struct i2c_client *client) +static int ds2482_remove(struct i2c_client *client) { struct ds2482_data *data = i2c_get_clientdata(client); - int err, idx; + int idx; /* Unregister the 1-wire bridge(s) */ for (idx = 0; idx < data->w1_count; idx++) { @@ -534,13 +525,6 @@ static int ds2482_detach_client(struct i2c_client *client) w1_remove_master_device(&data->w1_ch[idx].w1_bm); } - /* Detach the i2c device */ - if ((err = i2c_detach_client(client))) { - dev_err(&client->dev, - "Deregistration failed, client not detached.\n"); - return err; - } - /* Free the memory */ kfree(data); return 0; |