Platform Bus
Posted 四季帆
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Platform Bus相关的知识,希望对你有一定的参考价值。
1. plarform_driver中probe要实现的功能
probe函数的原型为:int xxx_probe(struct platform_device *pdev);
probe 函数接收到plarform_device这个参数后,就需要从中提取出需要的信息。它一般会通过调用内核提供的 platform_get_resource和platform_get_irq等函数来获得相关信息。如通过 platform_get_resource获得设备的起始地址后,可以对其进行request_mem_region和ioremap等操作,以便应用程序对其进行操作。通过platform_get_irq得到设备的中断号以后,就可以调用request_irq函数来向系统申请中断。这些操作在设备驱动程序中的probe()函数中一般都要完成。
在完成了上面这些工作和一些其他必须的初始化操作后,就可以向系统注册我们在/dev目录下能看的设备文件了。
2. 经验教训
我刚工作的时候,领导让我在某款芯片的驱动代码中添加一个功能,检查芯片是否正常工作,该芯片提供了一个寄存器来鉴别该芯片是否正常工作,但是SOC端要想读该芯片的寄存器,需要通过IIC读写该芯片的寄存器,考虑到 IIC 不一定完全可靠,领导希望我看看,能不能通过检测引脚来判断。
该芯片的数据手册并没有明说哪个引脚提供这个功能,通过万用表量取所有引脚在该芯片正常工作和低功耗工作时的电平,最终确认出一个引脚的电平可以鉴别该芯片是否正常工作。
在驱动代码中添加的代码也很简单,就是另开一个线程,循环定时读取该引脚的电平判断是否正常工作。该引脚接到了SOC端的一个GPIO,大家知道,在驱动代码中要使用GPIO是需要申请的,然后我干了一个很蠢的事情,把申请GPIO的操作放到了驱动的open()操作中,而不是放到probe()操作中,其实这样也可以工作,但是就是偶尔会申请失败(比如读了20次报一次错,显示gpio申请失败),尬!
3. 注册平台driver的两种方式
我们知道,设备是多种多样的,而且一直在变,比如同一个厂家会生产不同规格、类型的设备,但是有的设备之间差异不是特别大,我们可以称之为同一系列的设备,那么它们对应的驱动就没有特别大的差异,为了减少重复代码,往往同一系列的设备会使用同一套驱动,这就意味着一个driver可以和多个device匹配,所以driver->probe就有可能执行多次,我猜测这就是这里出现两个接口的原因。
这两种方式分别为platform_driver_register()和platform_driver_probe(),两者都是有用来注册platform_driver驱动的,区别在于后者注册的驱动只会和设备匹配一次。根据代码可知,后者在使用platform_driver_register注册以后,无论成功与否都会将platform_driver->probe置为NULL或者直接从链表中移除platform_driver。
int __init_or_module platform_driver_probe(struct platform_driver *drv,
int (*probe)(struct platform_device *))
{
drv->probe = probe;
retval = code = platform_driver_register(drv);
······
drv->probe = NULL; //将probe置为NULL
drv->driver.probe = platform_drv_probe_fail;
if (code != retval)
platform_driver_unregister(drv); //从平台驱动的链表中移除driver
}
以上是关于Platform Bus的主要内容,如果未能解决你的问题,请参考以下文章
linux platform device/driver--Platform Device和Platform_driver注册过程之代码对比