首先看一下我的系統中都有什麼裝置掛在了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裝置模型 上 之底...