提交 7b4fbc50 编写于 作者: D David Brownell 提交者: Jean Delvare

i2c: i2c stack can probe()

One of a series of I2C infrastructure updates to support enumeration using
the standard Linux driver model.

This patch updates probe() and associated hotplug/coldplug support, but
not remove().  Nothing yet _uses_ it to create I2C devices, so those
hotplug/coldplug mechanisms will be the only externally visible change.
This patch will be an overall NOP since the I2C stack doesn't yet create
clients/devices except as part of binding them to legacy drivers.

Some code is moved earlier in the source code, helping group more of the
per-device infrastructure in one place and simplifying handling per-device
attributes.

Terminology being adopted:  "legacy drivers" create devices (i2c_client)
themselves, while "new style" ones follow the driver model (the i2c_client
is handed to the probe routine).  It's an either/or thing; the two models
don't mix, and drivers that try mixing them won't even be registered.
Signed-off-by: NDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: NJean Delvare <khali@linux-fr.org>
上级 5cedb05d
...@@ -44,15 +44,58 @@ static DEFINE_IDR(i2c_adapter_idr); ...@@ -44,15 +44,58 @@ 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) static int i2c_device_match(struct device *dev, struct device_driver *drv)
{ {
return 1; struct i2c_client *client = to_i2c_client(dev);
struct i2c_driver *driver = to_i2c_driver(drv);
/* make legacy i2c drivers bypass driver model probing entirely;
* such drivers scan each i2c adapter/bus themselves.
*/
if (!driver->probe)
return 0;
/* new style drivers use the same kind of driver matching policy
* as platform devices or SPI: compare device and driver IDs.
*/
return strcmp(client->driver_name, drv->name) == 0;
} }
#ifdef CONFIG_HOTPLUG
/* uevent helps with hotplug: modprobe -q $(MODALIAS) */
static int i2c_device_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
struct i2c_client *client = to_i2c_client(dev);
int i = 0, length = 0;
/* by definition, legacy drivers can't hotplug */
if (dev->driver || !client->driver_name)
return 0;
if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
"MODALIAS=%s", client->driver_name))
return -ENOMEM;
envp[i] = NULL;
dev_dbg(dev, "uevent\n");
return 0;
}
#else
#define i2c_device_uevent NULL
#endif /* CONFIG_HOTPLUG */
static int i2c_device_probe(struct device *dev) 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);
if (!driver->probe)
return -ENODEV;
client->driver = driver;
dev_dbg(dev, "probe\n");
return driver->probe(client);
} }
static int i2c_device_remove(struct device *dev) static int i2c_device_remove(struct device *dev)
...@@ -95,9 +138,38 @@ static int i2c_device_resume(struct device * dev) ...@@ -95,9 +138,38 @@ static int i2c_device_resume(struct device * dev)
return driver->resume(to_i2c_client(dev)); return driver->resume(to_i2c_client(dev));
} }
static void i2c_client_release(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
complete(&client->released);
}
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);
}
static ssize_t show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
return client->driver_name
? sprintf(buf, "%s\n", client->driver_name)
: 0;
}
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 = { struct bus_type i2c_bus_type = {
.name = "i2c", .name = "i2c",
.dev_attrs = i2c_dev_attrs,
.match = i2c_device_match, .match = i2c_device_match,
.uevent = i2c_device_uevent,
.probe = i2c_device_probe, .probe = i2c_device_probe,
.remove = i2c_device_remove, .remove = i2c_device_remove,
.shutdown = i2c_device_shutdown, .shutdown = i2c_device_shutdown,
...@@ -134,31 +206,6 @@ struct class i2c_adapter_class = { ...@@ -134,31 +206,6 @@ struct class i2c_adapter_class = {
}; };
static void i2c_client_release(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
complete(&client->released);
}
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 used the same name for
* an i2c adapter attribute (above).
*/
static struct device_attribute dev_attr_client_name =
__ATTR(name, S_IRUGO, &show_client_name, NULL);
/* ---------------------------------------------------
* registering functions
* ---------------------------------------------------
*/
/* ----- /* -----
* i2c_add_adapter is called from within the algorithm layer, * i2c_add_adapter is called from within the algorithm layer,
* when a new hw adapter registers. A new device is register to be * when a new hw adapter registers. A new device is register to be
...@@ -208,7 +255,7 @@ int i2c_add_adapter(struct i2c_adapter *adap) ...@@ -208,7 +255,7 @@ int i2c_add_adapter(struct i2c_adapter *adap)
dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name); dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
/* inform drivers of new adapters */ /* let legacy drivers scan this bus for matching devices */
list_for_each(item,&drivers) { list_for_each(item,&drivers) {
driver = list_entry(item, struct i2c_driver, list); driver = list_entry(item, struct i2c_driver, list);
if (driver->attach_adapter) if (driver->attach_adapter)
...@@ -292,16 +339,32 @@ int i2c_del_adapter(struct i2c_adapter *adap) ...@@ -292,16 +339,32 @@ int i2c_del_adapter(struct i2c_adapter *adap)
} }
/* ----- /* ------------------------------------------------------------------------- */
* 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) int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
{ {
int res; int res;
/* new style driver methods can't mix with legacy ones */
if (driver->probe) {
if (driver->attach_adapter || 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 */ /* add the driver to the list of i2c drivers in the driver core */
driver->driver.owner = owner; driver->driver.owner = owner;
driver->driver.bus = &i2c_bus_type; driver->driver.bus = &i2c_bus_type;
...@@ -315,7 +378,7 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) ...@@ -315,7 +378,7 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
list_add_tail(&driver->list,&drivers); list_add_tail(&driver->list,&drivers);
pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name); pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);
/* now look for instances of driver on our adapters */ /* legacy drivers scan i2c busses directly */
if (driver->attach_adapter) { if (driver->attach_adapter) {
struct i2c_adapter *adapter; struct i2c_adapter *adapter;
...@@ -380,6 +443,8 @@ int i2c_del_driver(struct i2c_driver *driver) ...@@ -380,6 +443,8 @@ int i2c_del_driver(struct i2c_driver *driver)
return 0; return 0;
} }
/* ------------------------------------------------------------------------- */
static int __i2c_check_addr(struct i2c_adapter *adapter, unsigned int addr) static int __i2c_check_addr(struct i2c_adapter *adapter, unsigned int addr)
{ {
struct list_head *item; struct list_head *item;
...@@ -430,9 +495,6 @@ int i2c_attach_client(struct i2c_client *client) ...@@ -430,9 +495,6 @@ int i2c_attach_client(struct i2c_client *client)
res = device_register(&client->dev); res = device_register(&client->dev);
if (res) if (res)
goto out_list; goto out_list;
res = device_create_file(&client->dev, &dev_attr_client_name);
if (res)
goto out_unregister;
mutex_unlock(&adapter->clist_lock); mutex_unlock(&adapter->clist_lock);
if (adapter->client_register) { if (adapter->client_register) {
...@@ -445,10 +507,6 @@ int i2c_attach_client(struct i2c_client *client) ...@@ -445,10 +507,6 @@ int i2c_attach_client(struct i2c_client *client)
return 0; return 0;
out_unregister:
init_completion(&client->released); /* Needed? */
device_unregister(&client->dev);
wait_for_completion(&client->released);
out_list: out_list:
list_del(&client->list); list_del(&client->list);
dev_err(&adapter->dev, "Failed to attach i2c client %s at 0x%02x " dev_err(&adapter->dev, "Failed to attach i2c client %s at 0x%02x "
...@@ -483,7 +541,6 @@ int i2c_detach_client(struct i2c_client *client) ...@@ -483,7 +541,6 @@ int i2c_detach_client(struct i2c_client *client)
mutex_lock(&adapter->clist_lock); mutex_lock(&adapter->clist_lock);
list_del(&client->list); list_del(&client->list);
init_completion(&client->released); init_completion(&client->released);
device_remove_file(&client->dev, &dev_attr_client_name);
device_unregister(&client->dev); device_unregister(&client->dev);
mutex_unlock(&adapter->clist_lock); mutex_unlock(&adapter->clist_lock);
wait_for_completion(&client->released); wait_for_completion(&client->released);
......
...@@ -113,7 +113,7 @@ struct i2c_driver { ...@@ -113,7 +113,7 @@ struct i2c_driver {
* can be used by the driver to test if the bus meets its conditions * can be used by the driver to test if the bus meets its conditions
* & seek for the presence of the chip(s) it supports. If found, it * & seek for the presence of the chip(s) it supports. If found, it
* registers the client(s) that are on the bus to the i2c admin. via * registers the client(s) that are on the bus to the i2c admin. via
* i2c_attach_client. * i2c_attach_client. (LEGACY I2C DRIVERS ONLY)
*/ */
int (*attach_adapter)(struct i2c_adapter *); int (*attach_adapter)(struct i2c_adapter *);
int (*detach_adapter)(struct i2c_adapter *); int (*detach_adapter)(struct i2c_adapter *);
...@@ -121,10 +121,16 @@ struct i2c_driver { ...@@ -121,10 +121,16 @@ struct i2c_driver {
/* tells the driver that a client is about to be deleted & gives it /* tells the driver that a client is about to be deleted & gives it
* the chance to remove its private data. Also, if the client struct * the chance to remove its private data. Also, if the client struct
* has been dynamically allocated by the driver in the function above, * has been dynamically allocated by the driver in the function above,
* it must be freed here. * it must be freed here. (LEGACY I2C DRIVERS ONLY)
*/ */
int (*detach_client)(struct i2c_client *); int (*detach_client)(struct i2c_client *);
/* Standard driver model interfaces, for "new style" i2c drivers.
* With the driver model, device enumeration is NEVER done by drivers;
* it's done by infrastructure. (NEW STYLE DRIVERS ONLY)
*/
int (*probe)(struct i2c_client *);
/* driver model interfaces that don't relate to enumeration */ /* driver model interfaces that don't relate to enumeration */
void (*shutdown)(struct i2c_client *); void (*shutdown)(struct i2c_client *);
int (*suspend)(struct i2c_client *, pm_message_t mesg); int (*suspend)(struct i2c_client *, pm_message_t mesg);
...@@ -148,6 +154,8 @@ struct i2c_driver { ...@@ -148,6 +154,8 @@ struct i2c_driver {
* @name: Indicates the type of the device, usually a chip name that's * @name: Indicates the type of the device, usually a chip name that's
* generic enough to hide second-sourcing and compatible revisions. * generic enough to hide second-sourcing and compatible revisions.
* @dev: Driver model device node for the slave. * @dev: Driver model device node for the slave.
* @driver_name: Identifies new-style driver used with this device; also
* used as the module name for hotplug/coldplug modprobe support.
* *
* An i2c_client identifies a single device (i.e. chip) connected to an * An i2c_client identifies a single device (i.e. chip) connected to an
* i2c bus. The behaviour is defined by the routines of the driver. * i2c bus. The behaviour is defined by the routines of the driver.
...@@ -163,6 +171,7 @@ struct i2c_client { ...@@ -163,6 +171,7 @@ struct i2c_client {
int usage_count; /* How many accesses currently */ int usage_count; /* How many accesses currently */
/* to the client */ /* to the client */
struct device dev; /* the device structure */ struct device dev; /* the device structure */
char driver_name[KOBJ_NAME_LEN];
struct list_head list; struct list_head list;
struct completion released; struct completion released;
}; };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册