X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fi2c%2Fi2c-core.c;h=635c488262c0ccbc684ad8d0ca35b43833447d90;hb=66b650f04576a6737579ec404446450026ff2e0b;hp=0ce58b506046b458edb85cf7bda4472a56920da1;hpb=b864c7d5d17c171c4ead0791b44ab05d7a21dc0c;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 0ce58b5..635c488 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -17,7 +17,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* ------------------------------------------------------------------------- */ -/* With some changes from Kyösti Mälkki . +/* With some changes from Kyösti Mälkki . All SMBus-related things are written by Frodo Looijaard SMBus 2.0 support by Mark Studebaker and Jean Delvare */ @@ -29,90 +29,152 @@ #include #include #include -#include #include +#include +#include +#include +#include #include +#include "i2c-core.h" -static LIST_HEAD(adapters); -static LIST_HEAD(drivers); -static DECLARE_MUTEX(core_lists); + +static DEFINE_MUTEX(core_lock); static DEFINE_IDR(i2c_adapter_idr); -/* match always succeeds, as we want the probe() to tell if we really accept this match */ -static int i2c_device_match(struct device *dev, struct device_driver *drv) +#define is_newstyle_driver(d) ((d)->probe || (d)->remove || (d)->detect) + +static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver); + +/* ------------------------------------------------------------------------- */ + +static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id, + const struct i2c_client *client) { - return 1; + while (id->name[0]) { + if (strcmp(client->name, id->name) == 0) + return id; + id++; + } + return NULL; } -static int i2c_bus_suspend(struct device * dev, pm_message_t state) +static int i2c_device_match(struct device *dev, struct device_driver *drv) { - int rc = 0; + struct i2c_client *client = to_i2c_client(dev); + struct i2c_driver *driver = to_i2c_driver(drv); - if (dev->driver && dev->driver->suspend) - rc = dev->driver->suspend(dev, state); - return rc; + /* make legacy i2c drivers bypass driver model probing entirely; + * such drivers scan each i2c adapter/bus themselves. + */ + if (!is_newstyle_driver(driver)) + return 0; + + /* match on an id table if there is one */ + if (driver->id_table) + return i2c_match_id(driver->id_table, client) != NULL; + + return 0; } -static int i2c_bus_resume(struct device * dev) +#ifdef CONFIG_HOTPLUG + +/* uevent helps with hotplug: modprobe -q $(MODALIAS) */ +static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env) { - int rc = 0; - - if (dev->driver && dev->driver->resume) - rc = dev->driver->resume(dev); - return rc; + struct i2c_client *client = to_i2c_client(dev); + + /* by definition, legacy drivers can't hotplug */ + if (dev->driver) + return 0; + + if (add_uevent_var(env, "MODALIAS=%s%s", + I2C_MODULE_PREFIX, client->name)) + return -ENOMEM; + dev_dbg(dev, "uevent\n"); + return 0; } +#else +#define i2c_device_uevent NULL +#endif /* CONFIG_HOTPLUG */ + static int i2c_device_probe(struct device *dev) { - return -ENODEV; + struct i2c_client *client = to_i2c_client(dev); + struct i2c_driver *driver = to_i2c_driver(dev->driver); + int status; + + if (!driver->probe || !driver->id_table) + return -ENODEV; + client->driver = driver; + if (!device_can_wakeup(&client->dev)) + device_init_wakeup(&client->dev, + client->flags & I2C_CLIENT_WAKE); + dev_dbg(dev, "probe\n"); + + status = driver->probe(client, i2c_match_id(driver->id_table, client)); + if (status) + client->driver = NULL; + return status; } static int i2c_device_remove(struct device *dev) { - return 0; -} + struct i2c_client *client = to_i2c_client(dev); + struct i2c_driver *driver; + int status; -struct bus_type i2c_bus_type = { - .name = "i2c", - .match = i2c_device_match, - .probe = i2c_device_probe, - .remove = i2c_device_remove, - .suspend = i2c_bus_suspend, - .resume = i2c_bus_resume, -}; + if (!dev->driver) + return 0; -void i2c_adapter_dev_release(struct device *dev) -{ - struct i2c_adapter *adap = dev_to_i2c_adapter(dev); - complete(&adap->dev_released); + driver = to_i2c_driver(dev->driver); + if (driver->remove) { + dev_dbg(dev, "remove\n"); + status = driver->remove(client); + } else { + dev->driver = NULL; + status = 0; + } + if (status == 0) + client->driver = NULL; + return status; } -struct device_driver i2c_adapter_driver = { - .owner = THIS_MODULE, - .name = "i2c_adapter", - .bus = &i2c_bus_type, -}; - -static void i2c_adapter_class_dev_release(struct class_device *dev) +static void i2c_device_shutdown(struct device *dev) { - struct i2c_adapter *adap = class_dev_to_i2c_adapter(dev); - complete(&adap->class_dev_released); -} + struct i2c_driver *driver; -struct class i2c_adapter_class = { - .owner = THIS_MODULE, - .name = "i2c-adapter", - .release = &i2c_adapter_class_dev_release, -}; + if (!dev->driver) + return; + driver = to_i2c_driver(dev->driver); + if (driver->shutdown) + driver->shutdown(to_i2c_client(dev)); +} -static ssize_t show_adapter_name(struct device *dev, struct device_attribute *attr, char *buf) +static int i2c_device_suspend(struct device *dev, pm_message_t mesg) { - struct i2c_adapter *adap = dev_to_i2c_adapter(dev); - return sprintf(buf, "%s\n", adap->name); + struct i2c_driver *driver; + + if (!dev->driver) + return 0; + driver = to_i2c_driver(dev->driver); + if (!driver->suspend) + return 0; + return driver->suspend(to_i2c_client(dev), mesg); } -static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL); +static int i2c_device_resume(struct device *dev) +{ + struct i2c_driver *driver; + + if (!dev->driver) + return 0; + driver = to_i2c_driver(dev->driver); + if (!driver->resume) + return 0; + return driver->resume(to_i2c_client(dev)); +} static void i2c_client_release(struct device *dev) { @@ -120,133 +182,475 @@ static void i2c_client_release(struct device *dev) complete(&client->released); } -static ssize_t show_client_name(struct device *dev, struct device_attribute *attr, char *buf) +static void i2c_client_dev_release(struct device *dev) +{ + kfree(to_i2c_client(dev)); +} + +static ssize_t +show_client_name(struct device *dev, struct device_attribute *attr, char *buf) { struct i2c_client *client = to_i2c_client(dev); return sprintf(buf, "%s\n", client->name); } -/* - * We can't use the DEVICE_ATTR() macro here as we want the same filename for a - * different type of a device. So beware if the DEVICE_ATTR() macro ever - * changes, this definition will also have to change. - */ -static struct device_attribute dev_attr_client_name = { - .attr = {.name = "name", .mode = S_IRUGO, .owner = THIS_MODULE }, - .show = &show_client_name, +static ssize_t +show_modalias(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + return sprintf(buf, "%s%s\n", I2C_MODULE_PREFIX, client->name); +} + +static struct device_attribute i2c_dev_attrs[] = { + __ATTR(name, S_IRUGO, show_client_name, NULL), + /* modalias helps coldplug: modprobe $(cat .../modalias) */ + __ATTR(modalias, S_IRUGO, show_modalias, NULL), + { }, }; +struct bus_type i2c_bus_type = { + .name = "i2c", + .dev_attrs = i2c_dev_attrs, + .match = i2c_device_match, + .uevent = i2c_device_uevent, + .probe = i2c_device_probe, + .remove = i2c_device_remove, + .shutdown = i2c_device_shutdown, + .suspend = i2c_device_suspend, + .resume = i2c_device_resume, +}; +EXPORT_SYMBOL_GPL(i2c_bus_type); + -/* --------------------------------------------------- - * registering functions - * --------------------------------------------------- +/** + * i2c_verify_client - return parameter as i2c_client, or NULL + * @dev: device, probably from some driver model iterator + * + * When traversing the driver model tree, perhaps using driver model + * iterators like @device_for_each_child(), you can't assume very much + * about the nodes you find. Use this function to avoid oopses caused + * by wrongly treating some non-I2C device as an i2c_client. */ +struct i2c_client *i2c_verify_client(struct device *dev) +{ + return (dev->bus == &i2c_bus_type) + ? to_i2c_client(dev) + : NULL; +} +EXPORT_SYMBOL(i2c_verify_client); + + +/** + * i2c_new_device - instantiate an i2c device for use with a new style driver + * @adap: the adapter managing the device + * @info: describes one I2C device; bus_num is ignored + * Context: can sleep + * + * Create a device to work with a new style i2c driver, where binding is + * handled through driver model probe()/remove() methods. This call is not + * appropriate for use by mainboad initialization logic, which usually runs + * during an arch_initcall() long before any i2c_adapter could exist. + * + * This returns the new i2c client, which may be saved for later use with + * i2c_unregister_device(); or NULL to indicate an error. + */ +struct i2c_client * +i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) +{ + struct i2c_client *client; + int status; + + client = kzalloc(sizeof *client, GFP_KERNEL); + if (!client) + return NULL; + + client->adapter = adap; + + client->dev.platform_data = info->platform_data; + + if (info->archdata) + client->dev.archdata = *info->archdata; + + client->flags = info->flags; + client->addr = info->addr; + client->irq = info->irq; + + strlcpy(client->name, info->type, sizeof(client->name)); + + /* a new style driver may be bound to this device when we + * return from this function, or any later moment (e.g. maybe + * hotplugging will load the driver module). and the device + * refcount model is the standard driver model one. + */ + status = i2c_attach_client(client); + if (status < 0) { + kfree(client); + client = NULL; + } + return client; +} +EXPORT_SYMBOL_GPL(i2c_new_device); + -/* ----- - * i2c_add_adapter is called from within the algorithm layer, - * when a new hw adapter registers. A new device is register to be - * available for clients. +/** + * i2c_unregister_device - reverse effect of i2c_new_device() + * @client: value returned from i2c_new_device() + * Context: can sleep */ -int i2c_add_adapter(struct i2c_adapter *adap) +void i2c_unregister_device(struct i2c_client *client) { - int id, res = 0; - struct list_head *item; - struct i2c_driver *driver; + struct i2c_adapter *adapter = client->adapter; + struct i2c_driver *driver = client->driver; + + if (driver && !is_newstyle_driver(driver)) { + dev_err(&client->dev, "can't unregister devices " + "with legacy drivers\n"); + WARN_ON(1); + return; + } - down(&core_lists); + if (adapter->client_unregister) { + if (adapter->client_unregister(client)) { + dev_warn(&client->dev, + "client_unregister [%s] failed\n", + client->name); + } + } - if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) { - res = -ENOMEM; - goto out_unlock; + mutex_lock(&adapter->clist_lock); + list_del(&client->list); + mutex_unlock(&adapter->clist_lock); + + device_unregister(&client->dev); +} +EXPORT_SYMBOL_GPL(i2c_unregister_device); + + +static const struct i2c_device_id dummy_id[] = { + { "dummy", 0 }, + { }, +}; + +static int dummy_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + return 0; +} + +static int dummy_remove(struct i2c_client *client) +{ + return 0; +} + +static struct i2c_driver dummy_driver = { + .driver.name = "dummy", + .probe = dummy_probe, + .remove = dummy_remove, + .id_table = dummy_id, +}; + +/** + * i2c_new_dummy - return a new i2c device bound to a dummy driver + * @adapter: the adapter managing the device + * @address: seven bit address to be used + * Context: can sleep + * + * This returns an I2C client bound to the "dummy" driver, intended for use + * with devices that consume multiple addresses. Examples of such chips + * include various EEPROMS (like 24c04 and 24c08 models). + * + * These dummy devices have two main uses. First, most I2C and SMBus calls + * except i2c_transfer() need a client handle; the dummy will be that handle. + * And second, this prevents the specified address from being bound to a + * different driver. + * + * This returns the new i2c client, which should be saved for later use with + * i2c_unregister_device(); or NULL to indicate an error. + */ +struct i2c_client *i2c_new_dummy(struct i2c_adapter *adapter, u16 address) +{ + struct i2c_board_info info = { + I2C_BOARD_INFO("dummy", address), + }; + + return i2c_new_device(adapter, &info); +} +EXPORT_SYMBOL_GPL(i2c_new_dummy); + +/* ------------------------------------------------------------------------- */ + +/* I2C bus adapters -- one roots each I2C or SMBUS segment */ + +static void i2c_adapter_dev_release(struct device *dev) +{ + struct i2c_adapter *adap = to_i2c_adapter(dev); + complete(&adap->dev_released); +} + +static ssize_t +show_adapter_name(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct i2c_adapter *adap = to_i2c_adapter(dev); + return sprintf(buf, "%s\n", adap->name); +} + +static struct device_attribute i2c_adapter_attrs[] = { + __ATTR(name, S_IRUGO, show_adapter_name, NULL), + { }, +}; + +static struct class i2c_adapter_class = { + .owner = THIS_MODULE, + .name = "i2c-adapter", + .dev_attrs = i2c_adapter_attrs, +}; + +static void i2c_scan_static_board_info(struct i2c_adapter *adapter) +{ + struct i2c_devinfo *devinfo; + + mutex_lock(&__i2c_board_lock); + list_for_each_entry(devinfo, &__i2c_board_list, list) { + if (devinfo->busnum == adapter->nr + && !i2c_new_device(adapter, + &devinfo->board_info)) + dev_err(&adapter->dev, + "Can't create device at 0x%02x\n", + devinfo->board_info.addr); } + mutex_unlock(&__i2c_board_lock); +} - res = idr_get_new(&i2c_adapter_idr, adap, &id); - if (res < 0) { - if (res == -EAGAIN) - res = -ENOMEM; - goto out_unlock; +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); } + return 0; +} + +static int i2c_register_adapter(struct i2c_adapter *adap) +{ + int res = 0, dummy; - adap->nr = id & MAX_ID_MASK; - init_MUTEX(&adap->bus_lock); - init_MUTEX(&adap->clist_lock); - list_add_tail(&adap->list,&adapters); + /* Can't register until after driver model init */ + if (unlikely(WARN_ON(!i2c_bus_type.p))) + return -EAGAIN; + + mutex_init(&adap->bus_lock); + mutex_init(&adap->clist_lock); INIT_LIST_HEAD(&adap->clients); + mutex_lock(&core_lock); + /* Add the adapter to the driver core. * If the parent pointer is not set up, * we add this adapter to the host bus. */ - if (adap->dev.parent == NULL) + if (adap->dev.parent == NULL) { adap->dev.parent = &platform_bus; - sprintf(adap->dev.bus_id, "i2c-%d", adap->nr); - adap->dev.driver = &i2c_adapter_driver; - adap->dev.release = &i2c_adapter_dev_release; - device_register(&adap->dev); - device_create_file(&adap->dev, &dev_attr_name); + pr_debug("I2C adapter driver [%s] forgot to specify " + "physical device\n", adap->name); + } - /* Add this adapter to the i2c_adapter class */ - memset(&adap->class_dev, 0x00, sizeof(struct class_device)); - adap->class_dev.dev = &adap->dev; - adap->class_dev.class = &i2c_adapter_class; - strlcpy(adap->class_dev.class_id, adap->dev.bus_id, BUS_ID_SIZE); - class_device_register(&adap->class_dev); + /* Set default timeout to 1 second if not already set */ + if (adap->timeout == 0) + adap->timeout = HZ; + + dev_set_name(&adap->dev, "i2c-%d", adap->nr); + adap->dev.release = &i2c_adapter_dev_release; + adap->dev.class = &i2c_adapter_class; + res = device_register(&adap->dev); + if (res) + goto out_list; dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name); - /* inform drivers of new adapters */ - list_for_each(item,&drivers) { - driver = list_entry(item, struct i2c_driver, list); - if (driver->attach_adapter) - /* We ignore the return code; if it fails, too bad */ - driver->attach_adapter(adap); - } + /* create pre-declared device nodes for new-style drivers */ + if (adap->nr < __i2c_first_dynamic_bus_num) + i2c_scan_static_board_info(adap); + + /* Notify drivers */ + dummy = bus_for_each_drv(&i2c_bus_type, NULL, adap, + i2c_do_add_adapter); out_unlock: - up(&core_lists); + mutex_unlock(&core_lock); return res; + +out_list: + idr_remove(&i2c_adapter_idr, adap->nr); + goto out_unlock; } +/** + * i2c_add_adapter - declare i2c adapter, use dynamic bus number + * @adapter: the adapter to add + * Context: can sleep + * + * This routine is used to declare an I2C adapter when its bus number + * doesn't matter. Examples: for I2C adapters dynamically added by + * USB links or PCI plugin cards. + * + * When this returns zero, a new bus number was allocated and stored + * in adap->nr, and the specified adapter became available for clients. + * Otherwise, a negative errno value is returned. + */ +int i2c_add_adapter(struct i2c_adapter *adapter) +{ + int id, res = 0; + +retry: + if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) + return -ENOMEM; + mutex_lock(&core_lock); + /* "above" here means "above or equal to", sigh */ + res = idr_get_new_above(&i2c_adapter_idr, adapter, + __i2c_first_dynamic_bus_num, &id); + mutex_unlock(&core_lock); + + if (res < 0) { + if (res == -EAGAIN) + goto retry; + return res; + } + + adapter->nr = id; + return i2c_register_adapter(adapter); +} +EXPORT_SYMBOL(i2c_add_adapter); + +/** + * i2c_add_numbered_adapter - declare i2c adapter, use static bus number + * @adap: the adapter to register (with adap->nr initialized) + * Context: can sleep + * + * This routine is used to declare an I2C adapter when its bus number + * matters. For example, use it for I2C adapters from system-on-chip CPUs, + * or otherwise built in to the system's mainboard, and where i2c_board_info + * is used to properly configure I2C devices. + * + * If no devices have pre-been declared for this bus, then be sure to + * register the adapter before any dynamically allocated ones. Otherwise + * the required bus ID may not be available. + * + * When this returns zero, the specified adapter became available for + * clients using the bus number provided in adap->nr. Also, the table + * of I2C devices pre-declared using i2c_register_board_info() is scanned, + * and the appropriate driver model device nodes are created. Otherwise, a + * negative errno value is returned. + */ +int i2c_add_numbered_adapter(struct i2c_adapter *adap) +{ + int id; + int status; + + if (adap->nr & ~MAX_ID_MASK) + return -EINVAL; + +retry: + if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) + return -ENOMEM; + + mutex_lock(&core_lock); + /* "above" here means "above or equal to", sigh; + * we need the "equal to" result to force the result + */ + status = idr_get_new_above(&i2c_adapter_idr, adap, adap->nr, &id); + if (status == 0 && id != adap->nr) { + status = -EBUSY; + idr_remove(&i2c_adapter_idr, id); + } + mutex_unlock(&core_lock); + if (status == -EAGAIN) + goto retry; + + if (status == 0) + status = i2c_register_adapter(adap); + return status; +} +EXPORT_SYMBOL_GPL(i2c_add_numbered_adapter); + +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 as the result of hardware + * probing (using a driver's detect method) */ + 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); + if (res) + dev_err(&adapter->dev, "detach_adapter failed (%d) " + "for driver [%s]\n", res, driver->driver.name); + return res; +} + +/** + * i2c_del_adapter - unregister I2C adapter + * @adap: the adapter being unregistered + * Context: can sleep + * + * This unregisters an I2C adapter which was previously registered + * by @i2c_add_adapter or @i2c_add_numbered_adapter. + */ int i2c_del_adapter(struct i2c_adapter *adap) { - struct list_head *item, *_n; - struct i2c_adapter *adap_from_list; - struct i2c_driver *driver; - struct i2c_client *client; + struct i2c_client *client, *_n; int res = 0; - down(&core_lists); + mutex_lock(&core_lock); /* First make sure that this adapter was ever added */ - list_for_each_entry(adap_from_list, &adapters, list) { - if (adap_from_list == adap) - break; - } - if (adap_from_list != adap) { + if (idr_find(&i2c_adapter_idr, adap->nr) != adap) { pr_debug("i2c-core: attempting to delete unregistered " "adapter [%s]\n", adap->name); res = -EINVAL; goto out_unlock; } - list_for_each(item,&drivers) { - driver = list_entry(item, struct i2c_driver, list); - if (driver->detach_adapter) - if ((res = driver->detach_adapter(adap))) { - dev_err(&adap->dev, "detach_adapter failed " - "for driver [%s]\n", - driver->driver.name); - goto out_unlock; - } - } + /* Tell drivers about this removal */ + res = bus_for_each_drv(&i2c_bus_type, NULL, adap, + i2c_do_del_adapter); + if (res) + goto out_unlock; /* 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) { - client = list_entry(item, struct i2c_client, list); + list_for_each_entry_safe_reverse(client, _n, &adap->clients, list) { + struct i2c_driver *driver; + + driver = client->driver; + + /* new style, follow standard driver model */ + if (!driver || is_newstyle_driver(driver)) { + i2c_unregister_device(client); + continue; + } - if ((res=client->driver->detach_client(client))) { + /* legacy drivers create and remove clients themselves */ + if ((res = driver->detach_client(client))) { dev_err(&adap->dev, "detach_client failed for client " "[%s] at address 0x%02x\n", client->name, client->addr); @@ -256,189 +660,233 @@ int i2c_del_adapter(struct i2c_adapter *adap) /* clean up the sysfs representation */ init_completion(&adap->dev_released); - init_completion(&adap->class_dev_released); - class_device_unregister(&adap->class_dev); - device_remove_file(&adap->dev, &dev_attr_name); device_unregister(&adap->dev); - list_del(&adap->list); /* wait for sysfs to drop all references */ wait_for_completion(&adap->dev_released); - wait_for_completion(&adap->class_dev_released); - /* free dynamically allocated bus id */ + /* free bus id */ idr_remove(&i2c_adapter_idr, adap->nr); dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name); + /* Clear the device structure in case this adapter is ever going to be + added again */ + memset(&adap->dev, 0, sizeof(adap->dev)); + out_unlock: - up(&core_lists); + mutex_unlock(&core_lock); return res; } +EXPORT_SYMBOL(i2c_del_adapter); + + +/* ------------------------------------------------------------------------- */ + +static int __attach_adapter(struct device *dev, void *data) +{ + struct i2c_adapter *adapter = to_i2c_adapter(dev); + struct i2c_driver *driver = data; + + i2c_detect(adapter, driver); + + /* Legacy drivers scan i2c busses directly */ + if (driver->attach_adapter) + driver->attach_adapter(adapter); + return 0; +} -/* ----- - * What follows is the "upwards" interface: commands for talking to clients, - * which implement the functions to access the physical information of the - * chips. +/* + * An i2c_driver is used with one or more i2c_client (device) nodes to access + * i2c slave chips, on a bus instance associated with some i2c_adapter. There + * are two models for binding the driver to its device: "new style" drivers + * follow the standard Linux driver model and just respond to probe() calls + * issued if the driver core sees they match(); "legacy" drivers create device + * nodes themselves. */ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) { - struct list_head *item; - struct i2c_adapter *adapter; - int res = 0; + int res; - down(&core_lists); + /* Can't register until after driver model init */ + if (unlikely(WARN_ON(!i2c_bus_type.p))) + return -EAGAIN; + + /* new style driver methods can't mix with legacy ones */ + if (is_newstyle_driver(driver)) { + if (driver->detach_adapter || driver->detach_client) { + printk(KERN_WARNING + "i2c-core: driver [%s] is confused\n", + driver->driver.name); + return -EINVAL; + } + } /* add the driver to the list of i2c drivers in the driver core */ driver->driver.owner = owner; driver->driver.bus = &i2c_bus_type; + /* for new style drivers, when registration returns the driver core + * will have called probe() for all matching-but-unbound devices. + */ res = driver_register(&driver->driver); if (res) - goto out_unlock; - - list_add_tail(&driver->list,&drivers); + return res; + + mutex_lock(&core_lock); + pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name); - /* now look for instances of driver on our adapters */ - if (driver->attach_adapter) { - list_for_each(item,&adapters) { - adapter = list_entry(item, struct i2c_adapter, list); - driver->attach_adapter(adapter); - } - } + INIT_LIST_HEAD(&driver->clients); + /* Walk the adapters that are already present */ + class_for_each_device(&i2c_adapter_class, NULL, driver, + __attach_adapter); - out_unlock: - up(&core_lists); - return res; + mutex_unlock(&core_lock); + return 0; } EXPORT_SYMBOL(i2c_register_driver); -int i2c_del_driver(struct i2c_driver *driver) +static int __detach_adapter(struct device *dev, void *data) { - struct list_head *item1, *item2, *_n; - struct i2c_client *client; - struct i2c_adapter *adap; - - int res = 0; + struct i2c_adapter *adapter = to_i2c_adapter(dev); + struct i2c_driver *driver = data; + struct i2c_client *client, *_n; + + /* Remove the devices we created ourselves as the result of hardware + * probing (using a driver's detect method) */ + 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); + } - down(&core_lists); + 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 + * attached. If so, detach them to be able to kill the driver * afterwards. */ - list_for_each(item1,&adapters) { - adap = list_entry(item1, struct i2c_adapter, list); - if (driver->detach_adapter) { - if ((res = driver->detach_adapter(adap))) { - dev_err(&adap->dev, "detach_adapter failed " - "for driver [%s]\n", - driver->driver.name); - goto out_unlock; - } - } else { - list_for_each_safe(item2, _n, &adap->clients) { - client = list_entry(item2, struct i2c_client, list); - if (client->driver != driver) - continue; - dev_dbg(&adap->dev, "detaching client [%s] " - "at 0x%02x\n", client->name, - client->addr); - if ((res = driver->detach_client(client))) { - dev_err(&adap->dev, "detach_client " - "failed for client [%s] at " - "0x%02x\n", client->name, - client->addr); - goto out_unlock; - } - } + if (driver->detach_adapter) { + if (driver->detach_adapter(adapter)) + dev_err(&adapter->dev, + "detach_adapter failed for driver [%s]\n", + driver->driver.name); + } else { + 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_err(&adapter->dev, "detach_client " + "failed for client [%s] at 0x%02x\n", + client->name, client->addr); } } + return 0; +} + +/** + * i2c_del_driver - unregister I2C driver + * @driver: the driver being unregistered + * Context: can sleep + */ +void i2c_del_driver(struct i2c_driver *driver) +{ + mutex_lock(&core_lock); + + class_for_each_device(&i2c_adapter_class, NULL, driver, + __detach_adapter); + driver_unregister(&driver->driver); - list_del(&driver->list); pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name); - out_unlock: - up(&core_lists); - return 0; + mutex_unlock(&core_lock); } +EXPORT_SYMBOL(i2c_del_driver); -static int __i2c_check_addr(struct i2c_adapter *adapter, unsigned int addr) +/* ------------------------------------------------------------------------- */ + +static int __i2c_check_addr(struct device *dev, void *addrp) { - struct list_head *item; - struct i2c_client *client; + struct i2c_client *client = i2c_verify_client(dev); + int addr = *(int *)addrp; - list_for_each(item,&adapter->clients) { - client = list_entry(item, struct i2c_client, list); - if (client->addr == addr) - return -EBUSY; - } + if (client && client->addr == addr) + return -EBUSY; return 0; } -int i2c_check_addr(struct i2c_adapter *adapter, int addr) +static int i2c_check_addr(struct i2c_adapter *adapter, int addr) { - int rval; - - down(&adapter->clist_lock); - rval = __i2c_check_addr(adapter, addr); - up(&adapter->clist_lock); - - return rval; + return device_for_each_child(&adapter->dev, &addr, __i2c_check_addr); } int i2c_attach_client(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; + int res; + + /* Check for address business */ + res = i2c_check_addr(adapter, client->addr); + if (res) + return res; + + client->dev.parent = &client->adapter->dev; + client->dev.bus = &i2c_bus_type; + + if (client->driver) + client->dev.driver = &client->driver->driver; + + if (client->driver && !is_newstyle_driver(client->driver)) { + client->dev.release = i2c_client_release; + dev_set_uevent_suppress(&client->dev, 1); + } else + client->dev.release = i2c_client_dev_release; + + dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adapter), + client->addr); + res = device_register(&client->dev); + if (res) + goto out_err; + + mutex_lock(&adapter->clist_lock); + list_add_tail(&client->list, &adapter->clients); + mutex_unlock(&adapter->clist_lock); + + dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n", + client->name, dev_name(&client->dev)); - down(&adapter->clist_lock); - if (__i2c_check_addr(client->adapter, client->addr)) { - up(&adapter->clist_lock); - return -EBUSY; - } - list_add_tail(&client->list,&adapter->clients); - up(&adapter->clist_lock); - if (adapter->client_register) { - if (adapter->client_register(client)) { + if (adapter->client_register(client)) { dev_dbg(&adapter->dev, "client_register " "failed for client [%s] at 0x%02x\n", client->name, client->addr); } } - client->usage_count = 0; - - client->dev.parent = &client->adapter->dev; - client->dev.driver = &client->driver->driver; - client->dev.bus = &i2c_bus_type; - client->dev.release = &i2c_client_release; - - snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id), - "%d-%04x", i2c_adapter_id(adapter), client->addr); - dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n", - client->name, client->dev.bus_id); - device_register(&client->dev); - device_create_file(&client->dev, &dev_attr_client_name); - return 0; -} +out_err: + dev_err(&adapter->dev, "Failed to attach i2c client %s at 0x%02x " + "(%d)\n", client->name, client->addr, res); + return res; +} +EXPORT_SYMBOL(i2c_attach_client); int i2c_detach_client(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; int res = 0; - - if (client->usage_count > 0) { - dev_warn(&client->dev, "Client [%s] still busy, " - "can't detach\n", client->name); - return -EBUSY; - } if (adapter->client_unregister) { res = adapter->client_unregister(client); @@ -450,83 +898,75 @@ int i2c_detach_client(struct i2c_client *client) } } - down(&adapter->clist_lock); + mutex_lock(&adapter->clist_lock); list_del(&client->list); + mutex_unlock(&adapter->clist_lock); + init_completion(&client->released); - device_remove_file(&client->dev, &dev_attr_client_name); device_unregister(&client->dev); - up(&adapter->clist_lock); wait_for_completion(&client->released); out: return res; } +EXPORT_SYMBOL(i2c_detach_client); -static int i2c_inc_use_client(struct i2c_client *client) +/** + * i2c_use_client - increments the reference count of the i2c client structure + * @client: the client being referenced + * + * Each live reference to a client should be refcounted. The driver model does + * that automatically as part of driver binding, so that most drivers don't + * need to do this explicitly: they hold a reference until they're unbound + * from the device. + * + * A pointer to the client with the incremented reference counter is returned. + */ +struct i2c_client *i2c_use_client(struct i2c_client *client) { - - if (!try_module_get(client->driver->driver.owner)) - return -ENODEV; - if (!try_module_get(client->adapter->owner)) { - module_put(client->driver->driver.owner); - return -ENODEV; - } - - return 0; + if (client && get_device(&client->dev)) + return client; + return NULL; } +EXPORT_SYMBOL(i2c_use_client); -static void i2c_dec_use_client(struct i2c_client *client) +/** + * i2c_release_client - release a use of the i2c client structure + * @client: the client being no longer referenced + * + * Must be called when a user of a client is finished with it. + */ +void i2c_release_client(struct i2c_client *client) { - module_put(client->driver->driver.owner); - module_put(client->adapter->owner); + if (client) + put_device(&client->dev); } +EXPORT_SYMBOL(i2c_release_client); -int i2c_use_client(struct i2c_client *client) -{ - int ret; - - ret = i2c_inc_use_client(client); - if (ret) - return ret; - - client->usage_count++; - - return 0; -} +struct i2c_cmd_arg { + unsigned cmd; + void *arg; +}; -int i2c_release_client(struct i2c_client *client) +static int i2c_cmd(struct device *dev, void *_arg) { - if (!client->usage_count) { - pr_debug("i2c-core: %s used one too many times\n", - __FUNCTION__); - return -EPERM; - } - - client->usage_count--; - i2c_dec_use_client(client); - + struct i2c_client *client = i2c_verify_client(dev); + struct i2c_cmd_arg *arg = _arg; + + if (client && client->driver && client->driver->command) + client->driver->command(client, arg->cmd, arg->arg); return 0; } void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg) { - struct list_head *item; - struct i2c_client *client; + struct i2c_cmd_arg cmd_arg; - down(&adap->clist_lock); - list_for_each(item,&adap->clients) { - client = list_entry(item, struct i2c_client, list); - if (!try_module_get(client->driver->driver.owner)) - continue; - if (NULL != client->driver->command) { - up(&adap->clist_lock); - client->driver->command(client,cmd,arg); - down(&adap->clist_lock); - } - module_put(client->driver->driver.owner); - } - up(&adap->clist_lock); + cmd_arg.cmd = cmd; + cmd_arg.arg = arg; + device_for_each_child(&adap->dev, &cmd_arg, i2c_cmd); } +EXPORT_SYMBOL(i2c_clients_command); static int __init i2c_init(void) { @@ -535,20 +975,32 @@ static int __init i2c_init(void) retval = bus_register(&i2c_bus_type); if (retval) return retval; - retval = driver_register(&i2c_adapter_driver); + retval = class_register(&i2c_adapter_class); if (retval) - return retval; - return class_register(&i2c_adapter_class); + goto bus_err; + retval = i2c_add_driver(&dummy_driver); + if (retval) + goto class_err; + return 0; + +class_err: + class_unregister(&i2c_adapter_class); +bus_err: + bus_unregister(&i2c_bus_type); + return retval; } static void __exit i2c_exit(void) { + i2c_del_driver(&dummy_driver); class_unregister(&i2c_adapter_class); - driver_unregister(&i2c_adapter_driver); bus_unregister(&i2c_bus_type); } -subsys_initcall(i2c_init); +/* We must initialize early, because some subsystems register i2c drivers + * in subsys_initcall() code, but are linked (and initialized) before i2c. + */ +postcore_initcall(i2c_init); module_exit(i2c_exit); /* ---------------------------------------------------- @@ -556,30 +1008,86 @@ module_exit(i2c_exit); * ---------------------------------------------------- */ -int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num) +/** + * 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; + unsigned long orig_jiffies; + int ret, try; + + /* 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++) { dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, " - "len=%d\n", ret, msgs[ret].flags & I2C_M_RD ? - 'R' : 'W', msgs[ret].addr, msgs[ret].len); + "len=%d%s\n", ret, (msgs[ret].flags & I2C_M_RD) + ? 'R' : 'W', msgs[ret].addr, msgs[ret].len, + (msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : ""); } #endif - down(&adap->bus_lock); - ret = adap->algo->master_xfer(adap,msgs,num); - up(&adap->bus_lock); + if (in_atomic() || irqs_disabled()) { + ret = mutex_trylock(&adap->bus_lock); + if (!ret) + /* I2C activity is ongoing. */ + return -EAGAIN; + } else { + mutex_lock_nested(&adap->bus_lock, adap->level); + } + + /* Retry automatically on arbitration loss */ + orig_jiffies = jiffies; + for (ret = 0, try = 0; try <= adap->retries; try++) { + ret = adap->algo->master_xfer(adap, msgs, num); + if (ret != -EAGAIN) + break; + if (time_after(jiffies, orig_jiffies + adap->timeout)) + break; + } + mutex_unlock(&adap->bus_lock); 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; @@ -590,14 +1098,23 @@ int i2c_master_send(struct i2c_client *client,const char *buf ,int count) msg.flags = client->flags & I2C_M_TEN; msg.len = count; msg.buf = (char *)buf; - + ret = i2c_transfer(adap, &msg, 1); /* If everything went ok (i.e. 1 msg transmitted), return #bytes transmitted, else error code. */ return (ret == 1) ? count : ret; } +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; @@ -616,28 +1133,7 @@ int i2c_master_recv(struct i2c_client *client, char *buf ,int count) transmitted, else error code. */ return (ret == 1) ? count : ret; } - - -int i2c_control(struct i2c_client *client, - unsigned int cmd, unsigned long arg) -{ - int ret = 0; - struct i2c_adapter *adap = client->adapter; - - dev_dbg(&client->adapter->dev, "i2c ioctl, cmd: 0x%x, arg: %#lx\n", cmd, arg); - switch (cmd) { - case I2C_RETRIES: - adap->retries = arg; - break; - case I2C_TIMEOUT: - adap->timeout = arg; - break; - default: - if (adap->algo->algo_control!=NULL) - ret = adap->algo->algo_control(adap,cmd,arg); - } - return ret; -} +EXPORT_SYMBOL(i2c_master_recv); /* ---------------------------------------------------- * the i2c address scanning function @@ -674,15 +1170,20 @@ static int i2c_probe_address(struct i2c_adapter *adapter, int addr, int kind, /* Finally call the custom detection function */ err = found_proc(adapter, addr, kind); - /* -ENODEV can be returned if there is a chip at the given address but it isn't supported by this chip driver. We catch it here as this isn't an error. */ - return (err == -ENODEV) ? 0 : err; + if (err == -ENODEV) + err = 0; + + if (err) + dev_warn(&adapter->dev, "Client creation failed at 0x%x (%d)\n", + addr, err); + return err; } int i2c_probe(struct i2c_adapter *adapter, - struct i2c_client_address_data *address_data, + const struct i2c_client_address_data *address_data, int (*found_proc) (struct i2c_adapter *, int, int)) { int i, err; @@ -691,7 +1192,7 @@ int i2c_probe(struct i2c_adapter *adapter, /* Force entries are done first, and are not affected by ignore entries */ if (address_data->forces) { - unsigned short **forces = address_data->forces; + const unsigned short * const *forces = address_data->forces; int kind; for (kind = 0; forces[kind]; kind++) { @@ -718,11 +1219,11 @@ int i2c_probe(struct i2c_adapter *adapter, 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) - return 0; + return 0; - dev_warn(&adapter->dev, "SMBus Quick command not supported, " - "can't probe for chips\n"); - return -1; + dev_dbg(&adapter->dev, "SMBus Quick command not supported, " + "can't probe for chips\n"); + return -EOPNOTSUPP; } /* Probe entries are done second, and are not affected by ignore @@ -756,9 +1257,9 @@ int i2c_probe(struct i2c_adapter *adapter, "parameter for adapter %d, " "addr 0x%02x\n", adap_id, address_data->ignore[j + 1]); + ignore = 1; + break; } - ignore = 1; - break; } if (ignore) continue; @@ -774,35 +1275,273 @@ int i2c_probe(struct i2c_adapter *adapter, return 0; } +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, "%s detection function provided " + "no name for 0x%x\n", driver->driver.name, + 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 the classes do not match */ + if (!(adapter->class & driver->class)) + 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; + } + + /* 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, + unsigned short const *addr_list) +{ + int i; + + /* Stop here if the bus doesn't support probing */ + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_READ_BYTE)) { + dev_err(&adap->dev, "Probing not supported\n"); + return NULL; + } + + for (i = 0; addr_list[i] != I2C_CLIENT_END; i++) { + /* Check address validity */ + if (addr_list[i] < 0x03 || addr_list[i] > 0x77) { + dev_warn(&adap->dev, "Invalid 7-bit address " + "0x%02x\n", addr_list[i]); + continue; + } + + /* Check address availability */ + if (i2c_check_addr(adap, addr_list[i])) { + dev_dbg(&adap->dev, "Address 0x%02x already in " + "use, not probing\n", addr_list[i]); + continue; + } + + /* Test address responsiveness + The default probe method is a quick write, but it is known + to corrupt the 24RF08 EEPROMs due to a state machine bug, + and could also irreversibly write-protect some EEPROMs, so + for address ranges 0x30-0x37 and 0x50-0x5f, we use a byte + read instead. Also, some bus drivers don't implement + quick write, so we fallback to a byte read it that case + too. */ + if ((addr_list[i] & ~0x07) == 0x30 + || (addr_list[i] & ~0x0f) == 0x50 + || !i2c_check_functionality(adap, I2C_FUNC_SMBUS_QUICK)) { + union i2c_smbus_data data; + + if (i2c_smbus_xfer(adap, addr_list[i], 0, + I2C_SMBUS_READ, 0, + I2C_SMBUS_BYTE, &data) >= 0) + break; + } else { + if (i2c_smbus_xfer(adap, addr_list[i], 0, + I2C_SMBUS_WRITE, 0, + I2C_SMBUS_QUICK, NULL) >= 0) + break; + } + } + + if (addr_list[i] == I2C_CLIENT_END) { + dev_dbg(&adap->dev, "Probing failed, no device found\n"); + return NULL; + } + + info->addr = addr_list[i]; + return i2c_new_device(adap, info); +} +EXPORT_SYMBOL_GPL(i2c_new_probed_device); struct i2c_adapter* i2c_get_adapter(int id) { struct i2c_adapter *adapter; - - down(&core_lists); - adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id); + + mutex_lock(&core_lock); + adapter = idr_find(&i2c_adapter_idr, id); if (adapter && !try_module_get(adapter->owner)) adapter = NULL; - up(&core_lists); + mutex_unlock(&core_lock); return adapter; } +EXPORT_SYMBOL(i2c_get_adapter); void i2c_put_adapter(struct i2c_adapter *adap) { module_put(adap->owner); } +EXPORT_SYMBOL(i2c_put_adapter); /* The SMBus parts */ -#define POLY (0x1070U << 3) -static u8 -crc8(u16 data) +#define POLY (0x1070U << 3) +static u8 crc8(u16 data) { int i; - + for(i = 0; i < 8; i++) { - if (data & 0x8000) + if (data & 0x8000) data = data ^ POLY; data = data << 1; } @@ -850,43 +1589,74 @@ 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); + return 0; } +/** + * 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 0x0FF & 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, I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL); } +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 0x0FF & 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; @@ -895,17 +1665,37 @@ s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value) I2C_SMBUS_WRITE,command, I2C_SMBUS_BYTE_DATA,&data); } +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 0x0FFFF & 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; @@ -914,43 +1704,128 @@ s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value) I2C_SMBUS_WRITE,command, I2C_SMBUS_WORD_DATA,&data); } +EXPORT_SYMBOL(i2c_smbus_write_word_data); + +/** + * i2c_smbus_process_call - SMBus "process call" protocol + * @client: Handle to slave device + * @command: Byte interpreted by slave + * @value: 16-bit "word" being written + * + * This executes the SMBus "process call" protocol, returning negative errno + * else a 16-bit unsigned "word" received from the device. + */ +s32 i2c_smbus_process_call(struct i2c_client *client, u8 command, u16 value) +{ + union i2c_smbus_data data; + int status; + data.word = value; + + status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, + I2C_SMBUS_WRITE, command, + I2C_SMBUS_PROC_CALL, &data); + return (status < 0) ? status : data.word; +} +EXPORT_SYMBOL(i2c_smbus_process_call); + +/** + * i2c_smbus_read_block_data - SMBus "block read" protocol + * @client: Handle to slave device + * @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. + * + * 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 + * support this; its emulation through I2C messaging relies on a specific + * mechanism (I2C_M_RECV_LEN) which may not be implemented. + */ +s32 i2c_smbus_read_block_data(struct i2c_client *client, u8 command, + u8 *values) +{ + union i2c_smbus_data data; + int status; + 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, u8 *values) + u8 length, const u8 *values) { union i2c_smbus_data data; - int i; + if (length > I2C_SMBUS_BLOCK_MAX) length = I2C_SMBUS_BLOCK_MAX; - for (i = 1; i <= length; i++) - data.block[i] = values[i-1]; data.block[0] = length; + memcpy(&data.block[1], values, length); return i2c_smbus_xfer(client->adapter,client->addr,client->flags, I2C_SMBUS_WRITE,command, I2C_SMBUS_BLOCK_DATA,&data); } +EXPORT_SYMBOL(i2c_smbus_write_block_data); /* Returns the number of read bytes */ -s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *values) +s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, + u8 length, u8 *values) { union i2c_smbus_data data; - int i; - if (i2c_smbus_xfer(client->adapter,client->addr,client->flags, - I2C_SMBUS_READ,command, - I2C_SMBUS_I2C_BLOCK_DATA,&data)) - return -1; - else { - for (i = 1; i <= data.block[0]; i++) - values[i-1] = data.block[i]; - return data.block[0]; - } + int status; + + if (length > I2C_SMBUS_BLOCK_MAX) + length = I2C_SMBUS_BLOCK_MAX; + data.block[0] = length; + 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]; +} +EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data); + +s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command, + u8 length, const u8 *values) +{ + union i2c_smbus_data data; + + if (length > I2C_SMBUS_BLOCK_MAX) + length = I2C_SMBUS_BLOCK_MAX; + data.block[0] = length; + memcpy(data.block + 1, values, length); + return i2c_smbus_xfer(client->adapter, client->addr, client->flags, + I2C_SMBUS_WRITE, command, + I2C_SMBUS_I2C_BLOCK_DATA, &data); } +EXPORT_SYMBOL(i2c_smbus_write_i2c_block_data); -/* Simulate a SMBus command using the i2c protocol +/* Simulate a SMBus command using the i2c protocol No checking of parameters is done! */ -static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, +static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, unsigned short flags, - char read_write, u8 command, int size, + char read_write, u8 command, int size, union i2c_smbus_data * data) { /* So we need to generate a series of msgs. In the case of writing, we @@ -960,18 +1835,20 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX+3]; unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2]; int num = read_write == I2C_SMBUS_READ?2:1; - struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 }, + struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 }, { addr, flags | I2C_M_RD, 0, msgbuf1 } }; int i; u8 partial_pec = 0; + int status; msgbuf0[0] = command; switch(size) { case I2C_SMBUS_QUICK: msg[0].len = 0; /* Special case: The read/write field is used as data */ - msg[0].flags = flags | (read_write==I2C_SMBUS_READ)?I2C_M_RD:0; + msg[0].flags = flags | (read_write == I2C_SMBUS_READ ? + I2C_M_RD : 0); num = 1; break; case I2C_SMBUS_BYTE: @@ -995,7 +1872,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, else { msg[0].len=3; msgbuf0[1] = data->word & 0xff; - msgbuf0[2] = (data->word >> 8) & 0xff; + msgbuf0[2] = data->word >> 8; } break; case I2C_SMBUS_PROC_CALL: @@ -1004,48 +1881,59 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, msg[0].len = 3; msg[1].len = 2; msgbuf0[1] = data->word & 0xff; - msgbuf0[2] = (data->word >> 8) & 0xff; + msgbuf0[2] = data->word >> 8; break; case I2C_SMBUS_BLOCK_DATA: if (read_write == I2C_SMBUS_READ) { - dev_err(&adapter->dev, "Block read not supported " - "under I2C emulation!\n"); - return -1; + msg[1].flags |= I2C_M_RECV_LEN; + msg[1].len = 1; /* block length will be added by + the underlying bus driver */ } 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]; } break; case I2C_SMBUS_BLOCK_PROC_CALL: - dev_dbg(&adapter->dev, "Block process call not supported " - "under I2C emulation!\n"); - return -1; + num = 2; /* Another special case */ + read_write = I2C_SMBUS_READ; + if (data->block[0] > I2C_SMBUS_BLOCK_MAX) { + dev_err(&adapter->dev, + "Invalid block write size %d\n", + data->block[0]); + return -EINVAL; + } + msg[0].len = data->block[0] + 2; + for (i = 1; i < msg[0].len; i++) + msgbuf0[i] = data->block[i-1]; + msg[1].flags |= I2C_M_RECV_LEN; + msg[1].len = 1; /* block length will be added by + the underlying bus driver */ + break; case I2C_SMBUS_I2C_BLOCK_DATA: if (read_write == I2C_SMBUS_READ) { - msg[1].len = I2C_SMBUS_BLOCK_MAX; + msg[1].len = data->block[0]; } 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 @@ -1053,23 +1941,25 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, if (i) { /* Compute PEC if first message is a write */ if (!(msg[0].flags & I2C_M_RD)) { - if (num == 1) /* Write only */ + if (num == 1) /* Write only */ i2c_smbus_add_pec(&msg[0]); else /* Write followed by read */ partial_pec = i2c_smbus_msg_pec(0, &msg[0]); } /* Ask for PEC if last message is a read */ if (msg[num-1].flags & I2C_M_RD) - msg[num-1].len++; + 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) @@ -1080,76 +1970,69 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, case I2C_SMBUS_BYTE_DATA: data->byte = msgbuf1[0]; break; - case I2C_SMBUS_WORD_DATA: + case I2C_SMBUS_WORD_DATA: case I2C_SMBUS_PROC_CALL: data->word = msgbuf1[0] | (msgbuf1[1] << 8); break; case I2C_SMBUS_I2C_BLOCK_DATA: - /* fixed at 32 for now */ - data->block[0] = I2C_SMBUS_BLOCK_MAX; - for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++) + for (i = 0; i < data->block[0]; i++) data->block[i+1] = msgbuf1[i]; break; + case I2C_SMBUS_BLOCK_DATA: + case I2C_SMBUS_BLOCK_PROC_CALL: + for (i = 0; i < msgbuf1[0] + 1; i++) + data->block[i] = msgbuf1[i]; + break; } return 0; } - -s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags, - char read_write, u8 command, int size, - union i2c_smbus_data * data) +/** + * 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 protocol, + union i2c_smbus_data *data) { + unsigned long orig_jiffies; + int try; s32 res; flags &= I2C_M_TEN | I2C_CLIENT_PEC; if (adapter->algo->smbus_xfer) { - down(&adapter->bus_lock); - res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write, - command,size,data); - up(&adapter->bus_lock); + mutex_lock(&adapter->bus_lock); + + /* Retry automatically on arbitration loss */ + orig_jiffies = jiffies; + for (res = 0, try = 0; try <= adapter->retries; try++) { + res = adapter->algo->smbus_xfer(adapter, addr, flags, + read_write, command, + protocol, data); + if (res != -EAGAIN) + break; + if (time_after(jiffies, + orig_jiffies + adapter->timeout)) + break; + } + mutex_unlock(&adapter->bus_lock); } else res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write, - command,size,data); + command, protocol, data); return res; } - - -/* Next four are needed by i2c-isa */ -EXPORT_SYMBOL_GPL(i2c_adapter_dev_release); -EXPORT_SYMBOL_GPL(i2c_adapter_driver); -EXPORT_SYMBOL_GPL(i2c_adapter_class); -EXPORT_SYMBOL_GPL(i2c_bus_type); - -EXPORT_SYMBOL(i2c_add_adapter); -EXPORT_SYMBOL(i2c_del_adapter); -EXPORT_SYMBOL(i2c_del_driver); -EXPORT_SYMBOL(i2c_attach_client); -EXPORT_SYMBOL(i2c_detach_client); -EXPORT_SYMBOL(i2c_use_client); -EXPORT_SYMBOL(i2c_release_client); -EXPORT_SYMBOL(i2c_clients_command); -EXPORT_SYMBOL(i2c_check_addr); - -EXPORT_SYMBOL(i2c_master_send); -EXPORT_SYMBOL(i2c_master_recv); -EXPORT_SYMBOL(i2c_control); -EXPORT_SYMBOL(i2c_transfer); -EXPORT_SYMBOL(i2c_get_adapter); -EXPORT_SYMBOL(i2c_put_adapter); -EXPORT_SYMBOL(i2c_probe); - EXPORT_SYMBOL(i2c_smbus_xfer); -EXPORT_SYMBOL(i2c_smbus_write_quick); -EXPORT_SYMBOL(i2c_smbus_read_byte); -EXPORT_SYMBOL(i2c_smbus_write_byte); -EXPORT_SYMBOL(i2c_smbus_read_byte_data); -EXPORT_SYMBOL(i2c_smbus_write_byte_data); -EXPORT_SYMBOL(i2c_smbus_read_word_data); -EXPORT_SYMBOL(i2c_smbus_write_word_data); -EXPORT_SYMBOL(i2c_smbus_write_block_data); -EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data); MODULE_AUTHOR("Simon G. Vogl "); MODULE_DESCRIPTION("I2C-Bus main module");