LINUX驱动之SPI子系统之三基本的调用流程

原文地址:http://fpcfjf.blog.163.com/blog/static/5546979320129249420884/

这里有一处说明,因为SPI用的是spi_device这个设备结构,其中与platform_device不同的是没有.resource这个成员,所以就不用再考虑它了。它通过在s3c24xx_spi_probe函数里:

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);来实现资源的生成。

SPI的基本调用流程与平台设备没有什么实质性的差异。主要如下(从spi_s3c24xx.c中开始):

1、static int __init s3c24xx_spi_init(void)这个函数中,调用:

int __init_or_module platform_driver_probe(struct platform_driver drv,

                   int (*probe)(struct platform_device ))

{

        return platform_driver_probe(&s3c24xx_spi_driver, s3c24xx_spi_probe);

}

2、在platform_driver_probe调用:

int platform_driver_register(struct platform_driver *drv)

3、再调用:

int driver_register(struct device_driver *drv)

4、再调用:

int bus_add_driver(struct device_driver *drv)

5、再调用:

int driver_attach(struct device_driver *drv)

{

         return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);

}

这里需要注意,bus_for_each_dev这个函数中调用的函数指针fn是__driver_attch,所以可以略过这个函数直接看匹配。

6、__driver_attch调用:

static inline int driver_match_device(struct device_driver *drv,

                                           struct device *dev)

{

         return drv->bus->match ? drv->bus->match(dev, drv) : 1;

}

大家都知道,在SPI.C中(前边也讲到了):


1.   struct bus_type spi_bus_type = {     

2.      .name       = “spi”,  

3.      .dev_attrs  = spi_dev_attrs,  

4.      .match    = spi_match_device,  

5.      .uevent   = spi_uevent,   

6.      .suspend  = spi_suspend,  

7.      .resume   = spi_resume,  

8.   };   


所以这里调用的是spi_match_device,跳过去:

static int spi_match_device(struct device *dev, struct device_driver *drv)

{

         const struct spi_device   *spi = to_spi_device(dev);

         const struct spi_driver    *sdrv = to_spi_driver(drv);

 

         if (sdrv->id_table)

                   return !!spi_match_id(sdrv->id_table, spi);

 

         return strcmp(spi->modalias, drv->name) == 0;

}

比较名字罢了。

7、再调用int driver_probe_device(struct device_driver *drv, struct device *dev),然后再调用:

static int really_probe(struct device *dev, struct device_driver *drv)

8、在really_probe函数中,又回到了MTD子系统分析中:

         if (dev->bus->probe) {

                   ret = dev->bus->probe(dev);

                   if (ret)

                            goto probe_failed;

         } else if (drv->probe) {

                   ret = drv->probe(dev);

                   if (ret)

                            goto probe_failed;

         }

因为在BUS中并没有给 probe赋值,所以会直接调用驱动的probe,也就是最前面的:

s3c24xx_spi_probe这个探测函数。

上文说过,SPI是专门独立出来了一个子系统(如果不使用GPIO模拟的平台的话),所以他的平台初台化是专门在spi.c中用下面这个函数进行的,和在一般的 platform驱动还是稍微有一些区别的。大家要引起注意。(而平台总线因为是通用的,所以在platform.c中调用int __init platform_bus_init(void)函数来实现。)

static int __init spi_init(void)

{

         int    status;

 

         buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);

         if (!buf) {

                   status = -ENOMEM;

                   goto err0;

         }

    //注册总线

         status = bus_register(&spi_bus_type);//注意:platform_bus_init同样也调用这个函数来实现总线的注册

         if (status < 0)

                   goto err1;

   //注册主设备的class

         status = class_register(&spi_master_class);

         if (status < 0)

                   goto err2;

         return 0;

 

err2:

         bus_unregister(&spi_bus_type);

err1:

         kfree(buf);

         buf = NULL;

err0:

         return status;

}

不要轻易放弃你的理想和追求。

向着梦中的地方去,错了我也不悔过。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值