spi/i2c调用框架

来源:互联网 发布:js parents找祖父元素 编辑:程序博客网 时间:2024/05/16 14:08

1.板级信息中通过 spi_register_board_info来添加设备

drivers/spi/spi.c:

    spi_register_board_info
        /* 对于每一个spi_master,调用spi_match_master_to_boardinfo */
        list_for_each_entry(master, &spi_master_list, list)
            spi_match_master_to_boardinfo
            /* board_info里含有bus_num, 如果某个spi_master的bus_num跟它一样
             * 则创建一个新的spi_device
             */
                    if (master->bus_num == bi->busnum)
                        spi_new_device
                            spi_alloc_device
                            /* 记录bi信息, 比如片选,MODE,MAX HZ */    
                            spi_add_device /* 根据名字找到spi_driver, 调用它的probe函数 */
                                spi_setup(spi);

                                device_add  /* 会绑定到一个spi_driver */




2:控制器驱动:如:spi_s3c2440.c或i2c_s3c24xx.c中的调用关系

1.module_platform_driver(s3c24xx_spi_driver);  

2.platform_driver_register  (drivers/base/platform.c   470行)

3.driver_register(&drv->driver);  //进入此函数进行platfrom_device和platform_driver的匹配  (drivers/base/driver.c)

./*
*调用此函数来判断内核中是否注册名字相同的驱动,
*  若注册了则返回return -EBUSY;
* 若没有注册则执行 bus_add_driver(drv)函数,把驱动添加到总线
*/

4.driver_find(drv->name, drv->bus);    (drivers/base/driver.c)

5.bus_add_driver(drv);//驱动添加到总线后悔调用driver_attach函数去试图绑定设备和驱动  (drivers/base/bus.c)

6.driver_attach(drv);   //对总线上的驱动和每一个设备进行匹配,会调用__driver_attach函数    (drivers/base/Dd.c)

6.1  bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);  //进入__driver_attach函数    (drivers/base/Dd.c)

6.2  if (!driver_match_device(drv, dev))  判断驱动和设备是否匹配,如果匹配成功则会调用driver_probe_device函数,

6.3  driver_probe_device(drv, dev);   此函数又会调用really_probe(dev, drv);函数来调用驱动提供的probe函数

6.4  really_probe(dev, drv);   //进入此函数

6.5  if (dev->bus->probe) {   //总线提供的probe函数
ret = dev->bus->probe(dev);
if (ret)
goto probe_failed;
} else if (drv->probe) {  //驱动提供的probe函数
ret = drv->probe(dev);  //进入s3c24xx_i2c_probe 成功后返回return 0
if (ret)
goto probe_failed;
}

7.static int __devinit s3c24xx_spi_probe(struct platform_device *pdev)  //进入spi控制器驱动的probe函数

8.spi_bitbang_start(&hw->bitbang);   //进入此函数,此函数会调用spi_register_master

9.spi_register_master  //注册spi主机控制器并添加到spi_bus_type总线上  (driver/spi/spi_bitbang.c)

9.1device_add(&master->dev);      //添加设备到spi_bus_type总线

9.2/*
         //遍历总线上的所以master,通过bus_num与spi_board_info中的bus_num进行匹配
*/
list_for_each_entry(bi, &board_list, list)
spi_match_master_to_boardinfo(master, &bi->board_info);

10.spi_match_master_to_boardinfo  ->  spi_new_device(master, bi);  //创建新的spi设备

11.spi_add_device(proxy);

12.bus_add_device(dev);   //添加设备到总线,并把设备挂载到链表上,便于驱动进去设备匹配  

12.1klist_add_tail(&dev->p->knode_bus, &bus->p->klist_devices);  //把设备挂接到链表上

13.bus_probe_device(dev);   //进入,总线上枚举这个设备

13.1device_attach(dev);// 进入:  遍历所以的驱动,找到与新创建的设备匹配的函数 ->bus_for_each_drv(dev->bus, NULL, dev, __device_attach);  //进入:调用总线上的每一个driverr调用 __device_attach来判断是否匹配

13.2__device_attach  - >  driver_probe_device(drv, dev); //如果匹配则调用总线上的probe函数 ->really_probe(dev, drv);   //进入此函数则会调用响应的驱动probe函数


3 数据收发过程
    spi_write
        spi_message_init(&m);
        初始化一个spi_message  /* 一个不可打断的SPI传输过程: cs=0,传数据,cs=1 */
                               /* 一个spi_message由多个spi_transfer组成 */
        spi_message_add_tail(&t, &m);  /* spi_transfe是SPI上传输的单方向1个或多个字节 */
        spi_sync(spi, &m);  /* 启动传输并等待完成 */
    
4.spi_driver如何调用spi_controller
    spi_sync
        __spi_sync(spi, message, 0);
            spi_async_locked
                __spi_async
                    master->transfer(spi, message);  //调用transfer函数发送或接受数据
            wait_for_completion





0 0
原创粉丝点击