i2c驱动注册过程---GSL3680为例进行详析---步骤1
2013-06-19 16:06
465 查看
Linux下i2c驱动的加载过程,分为i2c设备层、i2c adapter层与i2c核心层。
I2C设备驱动层也就是我们为特定i2c设备写的驱动。下面是i2c驱动的注册过程。
1:在我们写的i2c设备驱动中,我们会调用i2c_add_driver()开始i2c设备驱动的注册,该函数调用i2c_register_driver()完成所有注册操作。
2:i2c_register_driver会调用driver_register()来将设备驱动添加到总线的设备驱动列链中。
3:在driver_register()中,通过driver_find()来判断驱动是否已经注册,然后会调用bus_add_driver()将设备驱动添加到总线上。
4:在bus_add_driver()中初始化priv->klist_devices的值,并将priv赋值给drv->p,通过调用klist_add_tail(&priv->knode_bus,&bus->p->klist_drivers)将驱动信息保存到总线结构中,在此之前将调用driver_attach()。
5:在driver_attach()中,通过调用bus_for_each_dev(),遍历在总线上挂载的所有设备,并对每个设备(dev)调用__driver_attach()。
6:在__driver_attach()里会调用driver_match_device()来判断dev与driv的id是否相同,在i2c驱动里就会调用i2c_bus_type->match程序进行判断,当id相同时,将会调用driver_probe_device()。
7:在driver_probe_device(),首先会调用device_is_registered()判断dev是否注册,如没有注册则返回;若已经注册,则调用really_probe()。
8:在really_probe()里,首先将drv赋值给dev->driver,然后会调用总线的probe函数,在i2c驱动里,此时将会调用i2c总线的probe函数:i2c_device_probe()。
9:在i2c_device_probe()里,会根据to_i2c_driver(dev->driver)获取i2c驱动,也就是我们编写的具体的i2c设备驱动的结构体:static struct i2c_drivergsl_ts_driver{};。
10:这样就调用了我们驱动的probe()了,这就是我们在驱动里调用i2c_add_driver(),通过driver_register()的一系列调用,最后执行我们所写的probe():gsl_ts_probe()。
函数流程分析:
函数分析:
未完待续。。。
参考文章:
1:http://blog.csdn.net/bingqingsuimeng/article/details/7920593
2:http://blog.csdn.net/lickylin/article/details/6692691
3:http://soft.chinabyte.com/os/455/12259955.shtml
4:http://blog.csdn.net/rockrockwu/article/details/7460407
I2C设备驱动层也就是我们为特定i2c设备写的驱动。下面是i2c驱动的注册过程。
1:在我们写的i2c设备驱动中,我们会调用i2c_add_driver()开始i2c设备驱动的注册,该函数调用i2c_register_driver()完成所有注册操作。
2:i2c_register_driver会调用driver_register()来将设备驱动添加到总线的设备驱动列链中。
3:在driver_register()中,通过driver_find()来判断驱动是否已经注册,然后会调用bus_add_driver()将设备驱动添加到总线上。
4:在bus_add_driver()中初始化priv->klist_devices的值,并将priv赋值给drv->p,通过调用klist_add_tail(&priv->knode_bus,&bus->p->klist_drivers)将驱动信息保存到总线结构中,在此之前将调用driver_attach()。
5:在driver_attach()中,通过调用bus_for_each_dev(),遍历在总线上挂载的所有设备,并对每个设备(dev)调用__driver_attach()。
6:在__driver_attach()里会调用driver_match_device()来判断dev与driv的id是否相同,在i2c驱动里就会调用i2c_bus_type->match程序进行判断,当id相同时,将会调用driver_probe_device()。
7:在driver_probe_device(),首先会调用device_is_registered()判断dev是否注册,如没有注册则返回;若已经注册,则调用really_probe()。
8:在really_probe()里,首先将drv赋值给dev->driver,然后会调用总线的probe函数,在i2c驱动里,此时将会调用i2c总线的probe函数:i2c_device_probe()。
9:在i2c_device_probe()里,会根据to_i2c_driver(dev->driver)获取i2c驱动,也就是我们编写的具体的i2c设备驱动的结构体:static struct i2c_drivergsl_ts_driver{};。
10:这样就调用了我们驱动的probe()了,这就是我们在驱动里调用i2c_add_driver(),通过driver_register()的一系列调用,最后执行我们所写的probe():gsl_ts_probe()。
函数流程分析:
步骤1:分析驱动注册函数:i2c_add_driver()
函数分析:/*此处的owner在i2c_add_driver调用的时候默认传入的是THIS_MODULE,这里的dirver就是i2c_add_driver传入的参数gsl_ts_driver。*/ 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; /* add the driver to the list of i2c drivers in the driver core */ //把驱动注册到内核驱动的i2c驱动列表中 driver->driver.owner = owner; /*设置它的所属模块*/ driver->driver.bus = &i2c_bus_type;/*设置它的总线类型*/ /* When registration returns, the driver core * will have called probe() for all matching-but-unbound devices. */ /*注册设备驱动到总线的i2c设备驱动链中(内核中),它可以去匹配内中已经存在的client而后执行probe函数*/ res = driver_register(&driver->driver);/*注册驱动*/ if (res) return res; /* Drivers should switch to dev_pm_ops instead. */ //警告,用的休眠和唤醒的函数不是最新定义的,即传入的i2c驱动结构体中的休眠唤醒函数为空或者不能用 if (driver->suspend) pr_warn("i2c-core: driver [%s] using legacy suspend method\n", driver->driver.name); if (driver->resume) pr_warn("i2c-core: driver [%s] using legacy resume method\n", driver->driver.name); pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name); //初始化链表头用于挂接client,这是一个循环队列 INIT_LIST_HEAD(&driver->clients); /* Walk the adapters that are already present */ //会尝试和i2c总线上所有的dev进行一次匹配,只要获取的dev为adapter时,就可执行后续操作 i2c_for_each_dev(driver, __process_new_driver); return 0; }
未完待续。。。
参考文章:
1:http://blog.csdn.net/bingqingsuimeng/article/details/7920593
2:http://blog.csdn.net/lickylin/article/details/6692691
3:http://soft.chinabyte.com/os/455/12259955.shtml
4:http://blog.csdn.net/rockrockwu/article/details/7460407
相关文章推荐
- linux I2C 驱动之----i2c驱动的注册过程(i2c_register_driver->driver_register(&driver->driver)->driver_find)
- linux-i2c驱动 之 i2c设备层的注册过程probe函数如何被调用分析
- linux I2C 驱动之----i2c驱动的注册过程(i2c_register_driver->driver_register(&driver->driver)->driver_find)
- linux I2C 驱动之----i2c驱动的注册过程
- linux powerpc i2c驱动 之 i2c设备层的注册过程
- linux powerpc i2c驱动 之 i2c设备层的注册过程
- I2C驱动注册过程
- linux I2C 驱动之----i2c驱动的注册过程(i2c_register_driver->driver_register(&driver->driver)->driver_find)
- linux powerpc i2c驱动 之 i2c设备层的注册过程
- Linux PowerPC I2C驱动 之 I2C设备层的注册过程
- linux powerpc i2c驱动 之 i2c adapter层的注册过程
- 网卡驱动注册到PCI总线这一过程的分析一
- platform_driver平台驱动注册和注销过程(下)
- platform_driver平台驱动注册和注销过程
- linux I2C 驱动之----i2c_client 的注册
- 从编译和链接来看kernel驱动注册的过程
- linux 内核驱动--Platform Device和Platform_driver注册过程
- linux下MMC/SD/SDIO驱动系列之二 ---- host注册过程(一)
- linux platform驱动注册过程
- linux下MMC/SD/SDIO驱动系列之三 ---- host注册过程(二)