[platform]linux platform device/driver(一)--Driver是如何找到對應的device


 

1.platform device是怎么"自動"關聯到platform driver上的?

轉向linux driver有些時間了,前段時間碰到個問題,在Linux kernel 3.10的drivers/tty/serial/imx.c中,注冊driver的時候調用platform_driver_register(&serial_imx_driver),serial_imx_driver類型為platform_driver, serial_imx_driver中有個成員變量probe,在driver注冊時會調用這個函數,但是probe這個函數的參數是platform_device,而在imx.c中沒有出現platform_device類型的任何變量,問題就此產生了,platform_device這個參數到底是從什么地方傳進來的,內容又是什么,什么時候賦值的?

 

2.設備、總線、驅動三者如何關聯起來? 

后來查閱了相關資料,大體上的意思是,在linux2.6內核以后,設備和驅動的結構划分為設備、總線、驅動,設備和驅動分別掛在總線上,而他們可以通過name來進行匹配(還有其他的方式),二者綁定有兩種方式:一種是先安裝driver,后掛載設備;另一種則是先掛載設備,然后安裝driver。但二者都是后面動作的會在總線上搜索與自己name項相同的設備或者driver進行匹配,也即完成綁定。

 

3.代碼中的實現

在imx.c中,由於平台是3.10,所以使用DTS,設備都是預先掛載了如串口0/1/2/3..., 后面安裝驅動時,會調用上述說到的platform_driver_register(&serial_imx_driver),在驅動注冊過程中會對進行匹配設備,一旦匹配到某個device,就會調用probe進行初始化,這個probe的參量platform_device也就有來源了。具體可以參考下面的調用過程

do_basic_setup()->driver_init()->platform_bus_init()->...初始化platform bus(虛擬總線)
設備向內核注冊的時候platform_device_register()->platform_device_add()->...內核把設備掛在虛擬的platform bus下
驅動注冊的時候platform_driver_register()->driver_register()->bus_add_driver()->driver_attach()->bus_for_each_dev()對每個掛在虛擬的platform bus的設備作__driver_attach()->driver_probe_device()->drv->bus->match()==platform_match()->比較strncmp(pdev->name, drv->name, BUS_ID_SIZE),如果相符就調用platform_drv_probe()->driver->probe(),如果probe成功則設備與驅動成功綁定.

代碼如下:在執行到driver_attach的時候platform_device還沒出現:

int driver_attach(struct device_driver *drv)
{
    return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}
EXPORT_SYMBOL_GPL(driver_attach);

這一步開始出現了,縣初始化device list,然后通過next_device來遍歷節點的屬性,調用fn也即__driver_attach,dev也是從next_device中獲取device指針

int bus_for_each_dev(struct bus_type *bus, struct device *start,
             void *data, int (*fn)(struct device *, void *))
{
    struct klist_iter i;
    struct device *dev;
    int error = 0;

    if (!bus || !bus->p)
        return -EINVAL;

    klist_iter_init_node(&bus->p->klist_devices, &i,
                 (start ? &start->p->knode_bus : NULL));
    while ((dev = next_device(&i)) && !error)
        error = fn(dev, data);
    klist_iter_exit(&i);
    return error;
}
EXPORT_SYMBOL_GPL(bus_for_each_dev);

 


 

以上只是簡單理解,還是沒有深入進去,所以很多原理說不清楚,希望能有時間靜下心好好研究研究,如:

1. 設備、驅動、總線三者設計理念,結構模式

2. 設備、驅動先后掛到總線上的機制

3. linux2.6之前、linux2.6、linux2.6之后,驅動、設備在這些版本中的變遷,如platform的出現,dts的出現等

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM