Linux驅動修煉之道 platform

2021-08-25 20:42:15 字數 4850 閱讀 3953

首先看一下我的系統中都有什麼裝置掛在了platform虛擬匯流排上:

hacker@hacker:~/linux-2.6.30.4$ cd /sys/bus/platform/ hacker@hacker:/sys/bus/platform$ tree . |-- devices | |-- fixed mdio bus.0 -> ../../../devices/platform/fixed mdio bus.0 | |-- eisa.0 -> ../../../devices/platform/eisa.0 | |-- i8042 -> ../../../devices/platform/i8042 | |-- pcspkr -> ../../../devices/platform/pcspkr | |-- rtc_cmos -> ../../../devices/platform/rtc_cmos | `-- serial8250 -> ../../../devices/platform/serial8250 |-- drivers | |-- dsa | | |-- bind | | |-- uevent | | `-- unbind | |-- i8042 | | |-- bind | | |-- i8042 -> ../../../../devices/platform/i8042 | | |-- uevent | | `-- unbind | |-- mdio-gpio | | |-- bind | | |-- uevent | | `-- unbind | |-- parport_pc | | |-- bind | | |-- module -> ../../../../module/parport_pc | | |-- uevent | | `-- unbind | |-- rtc_cmos | | |-- bind | | |-- rtc_cmos -> ../../../../devices/platform/rtc_cmos | | |-- uevent | | `-- unbind | |-- serial8250 | | |-- bind | | |-- serial8250 -> ../../../../devices/platform/serial8250 | | |-- uevent | | `-- unbind | `-- twl4030_reg | |-- bind | |-- uevent | `-- unbind |-- drivers_autoprobe |-- drivers_probe `-- uevent 19 directories, 24 files

platform的初始化:首先系統啟動的時候會呼叫platform_bus_init來初始化這個虛擬匯流排,讓後向虛擬匯流排註冊即將掛載這條匯流排上的裝置。platform_bus_type部分是核心為我們實現好的,我們只關係platform_device與platform_driver就行了。

struct bus_type platform_bus_type = ; export_symbol_gpl(platform_bus_type); int __init platform_bus_init(void)

記住匯流排也是一種裝置,所以首先註冊匯流排裝置,然後註冊匯流排。

static struct platform_device *smdk2410_devices __initdata = ;

把裝置掛到platform匯流排上:

static void __init smdk2410_init(void)

首先來看乙個重要的資料結構:

struct resource ; struct platform_device ; struct platform_driver ;

裝置的分配:

struct platform_device *platform_device_alloc(const char *name, int id); //name:裝置名,id:裝置id,一般為-1

裝置的註冊:

int platform_device_add(struct platform_device *pdev);

獲取資源:

struct resource *platform_get_resource(struct platform_device *dev, unsigned int type, unsigned int num);

/*dev:資源所屬的裝置,type:獲取的資源型別,num:獲取的資源數*/

這裡詳述platform_device與platform_driver是怎樣匹配上的,這裡跟蹤函式的執行過程,首先是platform_driver_register:

int platform_driver_register(struct platform_driver *drv) int driver_register(struct device_driver *drv) int bus_add_driver(struct device_driver *drv) 。。。。。。。。。。。。 } int driver_attach(struct device_driver *drv)

這裡來看__driver_attach這個函式,其中分別呼叫了driver_match_device,driver_probe_device函式。如果匹配成果呼叫probe函式,否則返回。

static int __driver_attach(struct device *dev, void *data)

匹配的時候呼叫的bus的match函式。

struct bus_type platform_bus_type = ;

找到platform_match:

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

最後一行可以看到通過pdev->name與drv->name進行匹配,也就是說是通過裝置與驅動的名字進行匹配。匹配成功後呼叫驅動的probe函式。

int driver_probe_device(struct device_driver *drv, struct device *dev) static int really_probe(struct device *dev, struct device_driver *drv) else if (drv->probe) 。。。。。。。。 }

由relly_probe函式可以看出,如果bus定義了probe函式,則呼叫bus的probe函式;如果bus,沒有定義而driver定義了probe函式,則呼叫driver的probe函式。由上邊的platform_bus_type可以看出bus並沒有定義probe函式,所以呼叫driver的probe函式。

測試程式:

device.c

#include #include #include #include #include #include static struct platform_device *my_device; static int __init platform_dev_init(void) static void __exit platform_dev_exit(void) module_init(platform_dev_init); module_exit(platform_dev_exit); module_license("gpl");

driver.c

#include #include #include #include #include #include #include static int my_probe(struct device *dev) static int my_remove(struct device *dev) //定義platform_driver結構體 static struct platform_driver my_driver = , }; static int __init my_driver_init(void) static void __exit my_driver_exit(void) module_init(my_driver_init); module_exit(my_driver_exit); module_license("gpl");

測試效果:

root@hacker:/home/hacker/platform# insmod driver.ko root@hacker:/home/hacker/platform# insmod device.ko root@hacker:/home/hacker/platform# dmesg [ 4499.724439] driver found device! root@hacker:/home/hacker/platform# rmmod driver.ko root@hacker:/home/hacker/platform# dmesg [ 4499.724439] driver found device! [ 4513.368712] driver found device unpluged! root@hacker:/home/hacker/platform# rmmod device.ko root@hacker:/home/hacker/platform# insmod device.ko root@hacker:/home/hacker/platform# insmod driver.ko root@hacker:/home/hacker/platform# dmesg [ 4540.509227] driver found device! root@hacker:/home/hacker/platform# rmmod device.ko root@hacker:/home/hacker/platform# dmesg [ 4540.509227] driver found device! [ 4545.786076] driver found device unpluged! root@hacker:/home/hacker/platform# rmmod driver.ko root@hacker:/home/hacker/platform# dmesg [ 4540.509227] driver found device! [ 4545.786076] driver found device unpluged!

Linux驅動修煉之道

一些學習linux驅動的筆記整理在這裡與大家分享,如果那裡有錯誤也請高手指出。若干年後能進入intel開源中心或ibm搞linux kernel是我目前的目標。君子藏器於身,待時而動。文章 不斷更新中。linux驅動修煉之道 流水燈 linux驅動修煉之道 按鍵 linux驅動修煉之道 lcd背光與...

Linux驅動修煉之道

linux驅動修煉之道 流水燈 linux驅動修煉之道 按鍵 linux驅動修煉之道 lcd背光與gpio控制 linux核心訪問外設i o資源的方式 linux裝置管理檔案系統,mdev,熱插拔 linux驅動修煉之道 混雜裝置 linux驅動修煉之道 clock框架 linux裝置模型 上 之底...

Linux驅動修煉之道

linux驅動修煉之道 流水燈 linux驅動修煉之道 按鍵 linux驅動修煉之道 lcd背光與gpio控制 linux核心訪問外設i o資源的方式 linux裝置管理檔案系統,mdev,熱插拔 linux驅動修煉之道 混雜裝置 linux驅動修煉之道 clock框架 linux裝置模型 上 之底...