相关对象
1、 I2C总线
2、 I2C设备驱动
4、 I2C设备
3、 I2C适配器
-------------------------------------------------------------------------------------------------------
I2C总线
struct bus_type变量i2c_bus_type定义了I2C总线
struct bus_type i2c_bus_type = {
.name = "i2c",
.match = i2c_device_match,
.probe = i2c_device_probe,
.remove = i2c_device_remove,
.shutdown = i2c_device_shutdown,
.pm = &i2c_device_pm_ops,
};
I2C总线对应着/bus下的一条总线,这个i2c总线结构体管理着i2c设备与I2C驱动的匹配,删除等操作,I2C总线会调用i2c_device_match函数看I2C设备和I2C驱动是否匹配,如果匹配就调用i2c_device_probe函数,进而调用I2C驱动的probe函数;
I2C总线注册
I2C总线属于I2C核心层,在driver/i2c/i2c-core.c中postcore_initcall(i2c_init)开始I2C总线注册,调用过程如下:
postcore_initcall(i2c_init);
i2c_init(void)
bus_register(&i2c_bus_type);
i2c_init()实现如下:
static int __init i2c_init(void)
{
... ...
retval = bus_register(&i2c_bus_type);
... ...
}
-------------------------------------------------------------------------------------------------------
I2C设备驱动
定义在include/linux/i2c.h中的struct i2c_driver结构描述I2C驱动,
struct i2c_driver
{
unsigned int class;
int (*attach_adapter)(struct i2c_adapter *) __deprecated;
int (*detach_adapter)(struct i2c_adapter *) __deprecated;
int (*probe)(struct i2c_client *, const struct i2c_device_id *);
int (*remove)(struct i2c_client *);
void (*shutdown)(struct i2c_client *);
int (*suspend)(struct i2c_client *, pm_message_t mesg);
int (*resume)(struct i2c_client *);
void (*alert)(struct i2c_client *, unsigned int data);
int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);
struct device_driver driver; // 表示这是一个设备驱动
const struct i2c_device_id *id_table;
int (*detect)(struct i2c_client *, struct i2c_board_info *);
const unsigned short *address_list;
struct list_head clients;
};
-------------------------------------------------------------------------------------------------------
I2C设备
struct i2c_client结构体描述一个I2C设备,定义在include/linux/i2c.h中
struct i2c_client {
unsigned short flags; /* div., see below */
unsigned short addr; /* chip address - NOTE: 7bit */
/* addresses are stored in the */
/* _LOWER_ 7 bits */
char name[I2C_NAME_SIZE]; // 设备名
struct i2c_adapter *adapter; // 适配器
struct i2c_driver *driver; // 设备对应驱动
struct device dev; // 表明这个是一个设备
int irq; // 中断号
struct list_head detected;
};
-------------------------------------------------------------------------------------------------------
I2C适配器
I2C适配器就是SOC上的I2C控制器
struct i2c_adapter {
... ...
const struct i2c_algorithm *algo;
struct device dev;
... ...
};
struct i2c_algorithm {
int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,
int num);
int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data *data);
u32 (*functionality) (struct i2c_adapter *);
};
-------------------------------------------------------------------------------------------------------
I2C总线:维护两个链表(I2C驱动、I2C设备),管理I2C设备和I2C驱动的匹配和删除等
I2C驱动:I2C设备驱动程序
I2C设备:具体硬件设备的一个抽象
I2C适配器:用于I2C驱动和I2C设备间的通道,SOC上I2C控制器的抽象
-------------------------------------------------------------------------------------------------------
I2C驱动注册
通过调用i2c_add_driver函数注册I2C驱动
static inline int i2c_add_driver(struct i2c_driver *driver)
{
return i2c_register_driver(THIS_MODULE, driver);
}
再调用i2c_register_driver注册
int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
{
/*
struct bus_type i2c_bus_type = {
.name = "i2c",
.match = i2c_device_match,
.probe = i2c_device_probe,
.remove = i2c_device_remove,
.shutdown = i2c_device_shutdown,
.pm = &i2c_device_pm_ops,
};
*/
... ...
driver->driver.bus = &i2c_bus_type; //绑定总线
... ...
res = driver_register(&driver->driver); //向总线注册驱动
... ...
/* 遍历I2C总线上的所有设备,调用__process_new_driver函数 */
i2c_for_each_dev(driver, __process_new_driver);
return 0;
}
进入driver_register函数
int driver_register(struct device_driver *drv)
{
... ...
ret = bus_add_driver(drv); // 将驱动添加到总线
}
进入bus_add_driver函数:
int bus_add_driver(struct device_driver *drv)
{
... ...
if (drv->bus->p->drivers_autoprobe) {
error = driver_attach(drv);
if (error)
goto out_unregister;
}
klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
... ...
}
进入driver_attach函数:
int driver_attach(struct device_driver *drv)
{
return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}
int bus_for_each_dev(struct bus_type *bus, struct device *start,
void *data, int (*fn)(struct device *, void *))
{
/* 遍历总线的所有设备链表(bus->p->klist_devices)的所有设备,执行fn函数 */
while ((dev = next_device(&i)) && !error)
error = fn(dev, data);
}
对于bus_for_each_dev(drv->bus, NULL, drv, __driver_attach),fn对应的函数就是__driver_attach
进入__driver_attach函数:
static int __driver_attach(struct device *dev, void *data)
{
// 判断驱动与设备是否匹配
if (!driver_match_device(drv, dev))
return 0;
// 如果匹配,调用driver_probe_device函数
if (!dev->driver)
driver_probe_device(drv, dev);
}
进入driver_match_device函数
static inline int driver_match_device(struct device_driver *drv, struct device *dev)
{
// 调用bus总线的match函数,判断是否匹配
return drv->bus->match ? drv->bus->match(dev, drv) : 1;
}
match函数在哪里?在最开始的i2c_register_driver函数中,driver->driver.bus = &i2c_bus_type;
i2c_bus_type被赋值给了bus
struct bus_type i2c_bus_type = {
.name = "i2c",
.match = i2c_device_match,
.probe = i2c_device_probe,
.remove = i2c_device_remove,
.shutdown = i2c_device_shutdown,
.pm = &i2c_device_pm_ops,
};
drv->bus->match对应的就是i2c_device_match函数;
进入i2c_device_match函数:
static int i2c_device_match(struct device *dev, struct device_driver *drv)
{
struct i2c_client *client = i2c_verify_client(dev); // 由device获得i2c_client
struct i2c_driver *driver = to_i2c_driver(drv); // 由device_driver获取到i2c_driver
return i2c_match_id(driver->id_table, client) != NULL;
}
进入i2c_match_id函数:
static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
const struct i2c_client *client)
{
while (id->name[0]) {
if (strcmp(client->name, id->name) == 0)
return id;
id++;
}
return NULL;
}
strcmp(client->name, id->name)
比较i2c_client的char name[I2C_NAME_SIZE]与i2c_driver的i2c_device_id中的char name[I2C_NAME_SIZE];
回到__driver_attach函数:
static int __driver_attach(struct device *dev, void *data)
{
// 判断驱动与设备是否匹配
if (!driver_match_device(drv, dev))
return 0;
// 如果匹配,调用driver_probe_device函数
if (!dev->driver)
driver_probe_device(drv, dev);
}
driver_match_device匹配成功后,调用driver_probe_device函数
进入driver_probe_device函数
int driver_probe_device(struct device_driver *drv, struct device *dev)
{
ret = really_probe(dev, drv);
}
进入really_probe函数
static int really_probe(struct device *dev, struct device_driver *drv)
{
if (dev->bus->probe) {
ret = dev->bus->probe(dev); //优先调用总线的probe函数
} else if (drv->probe) {
ret = drv->probe(dev);
}
}
优先调用总线的probe函数,由总线定义:
struct bus_type i2c_bus_type = {
.name = "i2c",
.match = i2c_device_match,
.probe = i2c_device_probe,
.remove = i2c_device_remove,
.shutdown = i2c_device_shutdown,
.pm = &i2c_device_pm_ops,
};
dev->bus->probe就是i2c_device_probe函数;
进入i2c_device_probe函数
static int i2c_device_probe(struct device *dev)
{
struct i2c_driver *driver = to_i2c_driver(dev->driver);
// 调用i2c驱动i2c_driver的probe函数
status = driver->probe(client, i2c_match_id(driver->id_table, client));
}
通过上面的分析,可以知道i2c总线控制,当向内核注册i2c驱动时,会将i2c驱动添加到总线的链表中,遍历总线上所有设备,通过i2c_client->name, i2c_driver->i2c_device_id->name进行字符串匹配,如果匹配,就调用驱动程序的probe函数;
继续回到i2c_register_driver函数
int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
{
/*
struct bus_type i2c_bus_type = {
.name = "i2c",
.match = i2c_device_match,
.probe = i2c_device_probe,
.remove = i2c_device_remove,
.shutdown = i2c_device_shutdown,
.pm = &i2c_device_pm_ops,
};
*/
... ...
driver->driver.bus = &i2c_bus_type; //绑定总线
... ...
res = driver_register(&driver->driver); //向总线注册驱动
... ...
/* 遍历I2C总线上的所有设备,调用__process_new_driver函数 */
i2c_for_each_dev(driver, __process_new_driver);
}
分析i2c_for_each_dev(driver, __process_new_driver),进入i2c_for_each_dev函数
int i2c_for_each_dev(void *data, int (*fn)(struct device *, void *))
{
res = bus_for_each_dev(&i2c_bus_type, NULL, data, fn);
}
进入bus_for_each_dev函数:
int bus_for_each_dev(struct bus_type *bus, struct device *start,
void *data, int (*fn)(struct device *, void *))
{
struct device *dev;
/* 遍历I2C总线上所有的device,调用fn函数 */
while ((dev = next_device(&i)) && !error)
error = fn(dev, data);
}
bus_for_each_dev遍历总线上所有的device,调用fn函数,fn由i2c_for_each_dev传入的__process_new_driver函数
进入__process_new_driver函数
static int __process_new_driver(struct device *dev, void *data)
{
return i2c_do_add_adapter(data, to_i2c_adapter(dev));
}
进入i2c_do_add_adapter函数
static int i2c_do_add_adapter(struct i2c_driver *driver,
struct i2c_adapter *adap)
{
/* 探测I2C总线上能支持的设备 */
i2c_detect(adap, driver);
/* Let legacy drivers scan this bus for matching devices */
if (driver->attach_adapter) {
driver->attach_adapter(adap);
}
return 0;
}
进入i2c_detect函数:
static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver)
{
......
for (i = 0; address_list[i] != I2C_CLIENT_END; i += 1) {
err = i2c_detect_address(temp_client, driver);
}
}
进入i2c_detect_address函数
static int i2c_detect_address(struct i2c_client *temp_client, struct i2c_driver *driver)
{
i2c_check_addr_validity(addr);
i2c_check_addr_busy(adapter, addr);
i2c_default_probe(adapter, addr);
driver->detect(temp_client, &info);
client = i2c_new_device(adapter, &info);
list_add_tail(&client->detected, &driver->clients);
}
I2C设备注册
内核调用i2c_new_device完成I2C设备注册
进入i2c_new_device函数:
struct i2c_client *i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
{
struct i2c_client *client; // i2c_client描述一个I2C设备
client = kzalloc(sizeof *client, GFP_KERNEL);
client->adapter = adap; // I2C适配器
client->dev.platform_data = info->platform_data;
client->flags = info->flags;
client->addr = info->addr;
client->irq = info->irq;
strlcpy(client->name, info->type, sizeof(client->name));
i2c_check_client_addr_validity(client);
i2c_check_addr_busy(adap, client->addr);
client->dev.parent = &client->adapter->dev;
client->dev.bus = &i2c_bus_type;
client->dev.type = &i2c_client_type;
client->dev.of_node = info->of_node;
dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap), client->addr);
device_register(&client->dev);
.......
}
进入device_register函数:
int device_register(struct device *dev)
{
device_initialize(dev);
device_add(dev);
}
进入device_add函数:
int device_add(struct device *dev)
{
bus_add_device(dev); //将I2C设备加入I2C总线
bus_probe_device(dev); //为设备probe对应的驱动
}
进入bus_probe_device:
void bus_probe_device(struct device *dev)
{
if (bus && bus->p->drivers_autoprobe) {
ret = device_attach(dev);
}
}
进入device_attach:
int device_attach(struct device *dev)
{
bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
}
进入bus_for_each_drv:
int bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
void *data, int (*fn)(struct device_driver *, void *))
{
struct device_driver *drv;;
while ((drv = next_driver(&i)) && !error)
fn(drv, data);
}
遍历driver链表,调用fn, fn为device_attach重调用bus_for_each_drv传入的__device_attach函数;
进入__device_attach函数:
static int __device_attach(struct device_driver *drv, void *data)
{
driver_match_device(drv, dev)
driver_probe_device(drv, dev);
}
进入driver_match_device:
static inline int driver_match_device(struct device_driver *drv,
struct device *dev)
{
// 调用i2c_bus_type的i2c_device_match函数,判断是否匹配
drv->bus->match(dev, drv)
}
进入driver_probe_device:
int driver_probe_device(struct device_driver *drv, struct device *dev)
{
ret = really_probe(dev, drv);
}
进入really_probe(dev, drv):
static int really_probe(struct device *dev, struct device_driver *drv)
{
if (dev->bus->probe) {
ret = dev->bus->probe(dev); //优先调用总线的probe函数
} else if (drv->probe) {
ret = drv->probe(dev);
}
}
优先调用总线的probe函数,由总线定义:
struct bus_type i2c_bus_type = {
.name = "i2c",
.match = i2c_device_match,
.probe = i2c_device_probe,
.remove = i2c_device_remove,
.shutdown = i2c_device_shutdown,
.pm = &i2c_device_pm_ops,
};
dev->bus->probe就是i2c_device_probe函数;
进入i2c_device_probe函数
static int i2c_device_probe(struct device *dev)
{
struct i2c_driver *driver = to_i2c_driver(dev->driver);
// 调用i2c驱动i2c_driver的probe函数
status = driver->probe(client, i2c_match_id(driver->id_table, client));
}
最终调用driver的probe函数;
通过i2c_register_board_info注册I2C设备,如在MINI2440Z中:
MACHINE_START(MINI2440, "MINI2440")
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = mini2440_map_io,
.init_machine = mini2440_init,
.init_irq = s3c24xx_init_irq,
.timer = &s3c24xx_timer,
MACHINE_END
进入mini2440_init函数:
static void __init mini2440_init(void)
{
i2c_register_board_info(0, mini2440_i2c_devs, ARRAY_SIZE(mini2440_i2c_devs));
}
进入i2c_register_board_info:
int __init i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsigned len)
{
for (status = 0; len; len--, info++) {
struct i2c_devinfo *devinfo;
devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);
devinfo->busnum = busnum;
devinfo->board_info = *info;
/* 将i2c_devinfo加入__i2c_board_list链表 */
list_add_tail(&devinfo->list, &__i2c_board_list);
}
}
__i2c_board_list调用的另一条线:
__i2c_board_list在什么用?__i2c_board_list在i2c_scan_static_board_info函数中被使用;
进入i2c_scan_static_board_info函数:
static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
{
struct i2c_devinfo *devinfo;
list_for_each_entry(devinfo, &__i2c_board_list, list) {
if (devinfo->busnum == adapter->nr
&& !i2c_new_device(adapter,
&devinfo->board_info))
}
}
循环遍历__i2c_board_list,调用i2c_new_device函数,最终还是调用i2c_new_device函数
i2c_scan_static_board_info在哪里调用?i2c_scan_static_board_info在i2c_register_adapter函数被调用:
进入i2c_register_adapter函数:
static int i2c_register_adapter(struct i2c_adapter *adap)
{
dev_set_name(&adap->dev, "i2c-%d", adap->nr);
adap->dev.bus = &i2c_bus_type;
adap->dev.type = &i2c_adapter_type;
res = device_register(&adap->dev);
// 注册I2C适配器到I2C总线,type为i2c_adapter_type
device_register(&adap->dev);
if (adap->nr < __i2c_first_dynamic_bus_num)
i2c_scan_static_board_info(adap);
bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter);
}
在i2c_register_adapter函数中同时调用了__process_new_adapter函数,与i2c_register_driver注册driver一样。
也就是说,在注册I2C适配器的过程中,通过i2c_scan_static_board_info将静态注册的I2C设备调用i2c_new_device注册到I2C总线上,
I2C设备注册完成后,在调用__process_new_adapter探测该适配器上所有地址,探测成功,调用i2c_new_device生成I2C设备,整个过程也就进入
了上面的I2C设备注册过程。