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的主要内容,如果未能解决你的问题,请参考以下文章

Platform Bus

linux设备驱动之platform平台总线工作原理

Platform Bus

Platform Bus

linux platform device/driver--Platform Device和Platform_driver注册过程之代码对比

[platform]Device和Driver注册顺序