Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 53249
b: refs/heads/master
c: 6e13e64
h: refs/heads/master
i:
  53247: 2f024ad
v: v3
  • Loading branch information
David Brownell authored and Jean Delvare committed May 1, 2007
1 parent 991b7d4 commit 9594619
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 27 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 9c1600eda42e52796f49b36cf15b9debcfd09bea
refs/heads/master: 6e13e641841833cc2aa5baefe89bb04bc388801b
126 changes: 100 additions & 26 deletions trunk/drivers/i2c/i2c-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,38 +320,19 @@ static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
mutex_unlock(&__i2c_board_lock);
}


/* -----
* 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.
*/
int i2c_add_adapter(struct i2c_adapter *adap)
static int i2c_register_adapter(struct i2c_adapter *adap)
{
int id, res = 0;
int res = 0;
struct list_head *item;
struct i2c_driver *driver;

mutex_lock(&core_lists);

if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) {
res = -ENOMEM;
goto out_unlock;
}

res = idr_get_new(&i2c_adapter_idr, adap, &id);
if (res < 0) {
if (res == -EAGAIN)
res = -ENOMEM;
goto out_unlock;
}

adap->nr = id & MAX_ID_MASK;
mutex_init(&adap->bus_lock);
mutex_init(&adap->clist_lock);
list_add_tail(&adap->list,&adapters);
INIT_LIST_HEAD(&adap->clients);

mutex_lock(&core_lists);
list_add_tail(&adap->list, &adapters);

/* Add the adapter to the driver core.
* If the parent pointer is not set up,
* we add this adapter to the host bus.
Expand All @@ -370,6 +351,10 @@ int i2c_add_adapter(struct i2c_adapter *adap)

dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);

/* create pre-declared device nodes for new-style drivers */
if (adap->nr < __i2c_first_dynamic_bus_num)
i2c_scan_static_board_info(adap);

/* let legacy drivers scan this bus for matching devices */
list_for_each(item,&drivers) {
driver = list_entry(item, struct i2c_driver, list);
Expand All @@ -388,6 +373,93 @@ int i2c_add_adapter(struct i2c_adapter *adap)
goto out_unlock;
}

/**
* i2c_add_adapter - declare i2c adapter, use dynamic bus number
* @adapter: the adapter to add
*
* 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_lists);
/* "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_lists);

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)
*
* This routine is used to declare an I2C adapter when its bus number
* matters. Example: 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_lists);
/* "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_lists);
if (status == -EAGAIN)
goto retry;

if (status == 0)
status = i2c_register_adapter(adap);
return status;
}
EXPORT_SYMBOL_GPL(i2c_add_numbered_adapter);

int i2c_del_adapter(struct i2c_adapter *adap)
{
struct list_head *item, *_n;
Expand Down Expand Up @@ -452,7 +524,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)
/* wait for sysfs to drop all references */
wait_for_completion(&adap->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);
Expand Down Expand Up @@ -493,6 +565,9 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
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)
return res;
Expand Down Expand Up @@ -1377,7 +1452,6 @@ EXPORT_SYMBOL_GPL(i2c_adapter_dev_release);
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);
Expand Down
1 change: 1 addition & 0 deletions trunk/include/linux/i2c.h
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,7 @@ struct i2c_client_address_data {
*/
extern int i2c_add_adapter(struct i2c_adapter *);
extern int i2c_del_adapter(struct i2c_adapter *);
extern int i2c_add_numbered_adapter(struct i2c_adapter *);

extern int i2c_register_driver(struct module *, struct i2c_driver *);
extern int i2c_del_driver(struct i2c_driver *);
Expand Down

0 comments on commit 9594619

Please sign in to comment.