Linux under the I2C-driven loading process, divided into I2C equipment layer, I2C adapter layer and I2C core layer
The I2C device driver layer is the drive we write for a particular I2C device, and the following is the I2C-driven registration process I understand.
In the I2C device driver we write, we call I2c_add_driver () to start I2C device-driven registration, which calls
I2c_register_driver Complete all Registration actions
static inline int i2c_add_driver (struct i2c_driver *driver)
{
Return I2c_register_driver (This_module, driver);
}
I2c_register_driver calls Driver_register () to add device drivers to the device-driven list of the bus:
int i2c_register_driver (struct module *owner, struct i2c_driver *driver)
{
int res;
* Can ' t register until after driver Model Init * *
if (Unlikely (warn_on (!I2C_BUS_TYPE.P))
Return-eagain;
Driver->driver.owner = owner;
Driver->driver.bus = &i2c_bus_type;
* When registration returns, the driver core
* would have called probe () for all matching-but-unbound devices.
*/
res = Driver_register (&driver->driver);
if (res)
return res;
Pr_debug ("I2c-core:driver [%s] registered\n", driver->driver.name);
Init_list_head (&driver->clients);
/* Walk The adapters that are already present * *
Mutex_lock (&core_lock);
Bus_for_each_dev (&i2c_bus_type, NULL, Driver, __attach_adapter);
Mutex_unlock (&core_lock);
return 0;
}
In Driver_register, the driver_find is used to determine if the driver is registered and then calls
Bus_add_drive
To add device drivers to the bus
int Driver_register (struct device_driver *drv)
{
int ret;
struct Device_driver *other;
BUG_ON (!DRV->BUS->P);
if ((drv->bus->probe && drv->probe) | |
(Drv->bus->remove && drv->remove) | |
(Drv->bus->shutdown && Drv->shutdown))
PRINTK (kern_warning "Driver '%s ' needs updating-please use")
"Bus_type methods\n", drv->name);
other = Driver_find (Drv->name, Drv->bus);
if (other) {
Put_driver (other);
PRINTK (kern_err "Error:driver '%s ' is already registered,"
"aborting...\n", drv->name);
Return-ebusy;
}
ret = Bus_add_driver (DRV);
if (ret)
return ret;
ret = driver_add_groups (DRV, drv->groups);
if (ret)
Bus_remove_driver (DRV);
return ret;
}
Initializes the Priv->klist_devices value in Bus_add_driver and assigns the Priv to Drv->p
**************************************************************************
1, in arch/arm/mach-xxx/own platform file to add I2C information, beauty its name Yue: i2c_board_info
For example:
static struct I2c_board_info __initdata xxxi2c_board_info[] = {
{
I2c_board_info ("Abcd1", 0x20),/* string to match the back, 0x20 from the device address * *
. Platform_data = 0,
},
{
I2c_board_info ("Abcd2", 0x21),
. Platform_data = 0,
},
};
Then call I2c_register_board_info (1, Xxxi2c_board_info, Array_size (Xxxi2c_board_info));
The first argument is 0 or 1, and I don't know:-(.
2, in another device driver file, such as you put into the/driver/char under the character device, generally module_init (Func_init ()) Form, then call I2c_add_driver () can, there are several to define:
static const struct I2C_DEVICE_ID xxx_led_id[] = {
{"ABCD1", 0},/* The name must match the Board_info to invoke the probe function * *
{"Abcd2", 0},
{ }
};
Module_device_table (I2C, xxx_led_id);
static struct I2c_driver Xxx_led_driver = {
. Driver = {
. Name = "Yourname", * * This name does not need to be matched with another * *
. Owner = This_module,
},
. Probe = Xxx_led_probe,
. remove = Xxx_remove,
. id_table = xxx_led_id,
};
See, struct i2c_device_id inside the string and i2c_board_info inside the match, Xxx_led_probe will not call.
If you don't want to use the same probe, write a struct i2c_device_id and struct i2c_driver