久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

Linux平臺總線驅動設備模型是什么

152次閱讀
沒有評論

共計 6549 個字符,預計需要花費 17 分鐘才能閱讀完成。

這篇文章主要介紹“Linux 平臺總線驅動設備模型是什么”,在日常操作中,相信很多人在 Linux 平臺總線驅動設備模型是什么問題上存在疑惑,丸趣 TV 小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Linux 平臺總線驅動設備模型是什么”的疑惑有所幫助!接下來,請跟著丸趣 TV 小編一起來學習吧!

platform 總線是一種虛擬的總線,相應的設備則為 platform_device,而驅動則為 platform_driver。Linux  2.6 的設備驅動模型中,把 I2C、RTC、LCD 等都歸納為 platform_device。

總線將設備和驅動綁定,在系統每注冊一個設備的時候,會尋找與之匹配的驅動; 相反的,在系統每注冊一個驅動的時候,會尋找與之匹配的設備,而匹配由總線完成。

Linux2.6 系統中定義了一個 bus_type 的實例 platform_bus_type

struct bus_type platform_bus_type = { .name =  platform , .dev_attrs = platform_dev_attrs, .match = platform_match, // 設備和驅動使用 match 函數來判斷是否匹配  .uevent = platform_uevent, .pm = PLATFORM_PM_OPS_PTR, };
/* platform_match 函數用于匹配總線中的驅動和設備  */ static int platform_match(struct device *dev, struct device_driver *drv) { struct platform_device *pdev = to_platform_device(dev); struct platform_driver *pdrv = to_platform_driver(drv); /* match against the id table first */ if (pdrv- id_table) return platform_match_id(pdrv- id_table, pdev) != NULL; /* fall-back to driver name match */ return (strcmp(pdev- name, drv- name) == 0); }

platform_match 函數首先判斷是否由 id_table,如果有則使用 id_table 來進行匹配,否則,判斷 platform_device 和 platform_driver 成員里的 name,如果二者的 name 字段相同則匹配,如果匹配則調用 platform_driver 的 probe 函數。

platform_device 結構體的定義

struct platform_device { const char * name; /*  名字  */ int id; struct device dev; u32 num_resources; /*  資源總數  */ struct resource * resource; /*  資源  */ struct platform_device_id *id_entry; };

其中有個重要的成員是 resource,是設備的資源信息,如 IO 地址,中斷號等。

struct resource { resource_size_t start; // 資源的起始值  resource_size_t end; // 資源的結束值  const char *name; unsigned long flags; // 資源的類型,如 IORESOURCE_IO,IORESOURCE_MEM,IORESOURCE_IRQ,IORESOURCE_DMA struct resource *parent, *sibling, *child; };

有的設備可能有多個資源,通常使用 platform_get_resource 函數來獲取資源

/** * platform_get_resource - get a resource for a device * @dev: platform device * @type: resource type * @num: resource index */ struct resource *platform_get_resource(struct platform_device *dev, unsigned int type, unsigned int num) { int i; for (i = 0; i   dev- num_resources; i++) { struct resource *r =  dev- resource[i]; if (type == resource_type(r)   num-- == 0) return r; } return NULL; }

平臺設備的注冊,使用 platform_device_register 函數

int platform_device_register(struct platform_device *pdev) { device_initialize( pdev- dev); return platform_device_add(pdev); }

platform_device_register 函數先通過 device_initialize 函數初始化 platform_device 的 device 成員,然后調用 platform_device_add 向內核添加一個平臺設備。

int platform_device_add(struct platform_device *pdev) { int i, ret = 0; if (!pdev) /*  如果 pdev 為空則返回 EINVAL */ return -EINVAL; /*  如果 pdev- dev.parent 為空則將 pdev- dev.parent 設置為 platform_bus */ if (!pdev- dev.parent) pdev- dev.parent =  platform_bus; pdev- dev.bus =  platform_bus_type; /*  設置總線類型  */ if (pdev- id != -1) /*  如果 id = - 1 則表示自動分配 name */ dev_set_name(pdev- dev,  %s.%d , pdev- name, pdev-  else dev_set_name( pdev- dev, pdev- name); for (i = 0; i   pdev- num_resources; i++) { struct resource *p, *r =  pdev- resource[i]; /*  獲取資源  */ if (r- name == NULL) r- name = dev_name(pdev- dev); p = r- parent; if (!p) { if (resource_type(r) == IORESOURCE_MEM) /*  設置資源類型  */ p =  iomem_resource; else if (resource_type(r) == IORESOURCE_IO) p =  ioport_resource; } if (p   insert_resource(p, r)) { printk(KERN_ERR  %s: failed to claim resource %d\n , dev_name( pdev- dev), i); ret = -EBUSY; goto failed; } } pr_debug(Registering platform device  %s . Parent at %s\n , dev_name( pdev- dev), dev_name(pdev- dev.parent)); /*  向內核添加一個 device */ ret = device_add(pdev- dev); if (ret == 0) return ret; failed: while (--i  = 0) { struct resource *r =  pdev- resource[i]; unsigned long type = resource_type(r); if (type == IORESOURCE_MEM || type == IORESOURCE_IO) release_resource(r); } return ret; }

platform_device_add 最終調用 device_add 來完成平臺設備的注冊。

相反地,如果要注銷平臺設備則使用 platform_device_unregister 函數

void platform_device_unregister(struct platform_device *pdev) { platform_device_del(pdev); platform_device_put(pdev); }

platform_device_unregister 函數調用 platform_device_del 函數來注銷平臺設備

void platform_device_del(struct platform_device *pdev) { int i; if (pdev) { device_del( pdev- dev); for (i = 0; i   pdev- num_resources; i++) { struct resource *r =  pdev- resource[i]; unsigned long type = resource_type(r); if (type == IORESOURCE_MEM || type == IORESOURCE_IO) release_resource(r); } } }

platform_device_del 函數調用 device_del 函數來刪除平臺設備,相應地,要釋放資源應調用 release_resource 函數,前提是資源的類型必須為 IORESOURCE_MEM 或者 IORESOURCE_IO

platform_driver 的定義:

struct platform_driver { int (*probe)(struct platform_device *); int (*remove)(struct platform_device *); void (*shutdown)(struct platform_device *); int (*suspend)(struct platform_device *, pm_message_t state); int (*resume)(struct platform_device *); struct device_driver driver; const struct platform_device_id *id_table; };

device_driver 的定義:

struct device_driver { const char *name; struct bus_type *bus; struct module *owner; const char *mod_name; /* used for built-in modules */ bool suppress_bind_attrs; /* disables bind/unbind via sysfs */ const struct of_device_id *of_match_table; const struct acpi_device_id *acpi_match_table; int (*probe) (struct device *dev); int (*remove) (struct device *dev); void (*shutdown) (struct device *dev); int (*suspend) (struct device *dev, pm_message_t state); int (*resume) (struct device *dev); const struct attribute_group **groups; const struct dev_pm_ops *pm; struct driver_private *p; };

platform_driver 結構體有 device_driver 成員,該成員的各自字段如上所示,device_driver 也有 probe、remove、shutdown 等函數,在平臺驅動注冊的時候被初始化。

前面說過,當系統中存在有平臺設備和平臺驅動通過總線的 match 函數匹配后則會調用 platform_driver 的 probe 函數,參數為 platform_device,有時候也通過 id_table 來判斷是否匹配。

struct platform_device_id { char name[PLATFORM_NAME_SIZE]; kernel_ulong_t driver_data __attribute__((aligned(sizeof(kernel_ulong_t)))); };

平臺驅動的注冊使用 platform_driver_register 函數

int platform_driver_register(struct platform_driver *drv) { drv- driver.bus =  platform_bus_type; if (drv- probe) drv- driver.probe = platform_drv_probe; if (drv- remove) drv- driver.remove = platform_drv_remove; if (drv- shutdown) drv- driver.shutdown = platform_drv_shutdown; if (drv- suspend) drv- driver.suspend = platform_drv_suspend; if (drv- resume) drv- driver.resume = platform_drv_resume; return driver_register(drv- driver); }

先初始化 platform_driver 里的 driver,該 driver 的類型為 device_driver,設置 driver 的 bus 為 platform_bus_type; 設置 driver 的 probe 為 platform_drv_probe; 設置 driver 的 remove 為 platform_drv_remove; 設置 driver 的 shutdown 為 platform_drv_shutdown; 設置 driver 的 suspend 為 platform_drv_suspend; 設置 driver 的 resume 為 platform_drv_resume,*** 調用 driver_register 函數來注冊平臺驅動。

相反地,要注銷平臺驅動的話,使用 platform_driver_unregister 函數

void platform_driver_unregister(struct platform_driver *drv) { driver_unregister( drv- driver); }

到此,關于“Linux 平臺總線驅動設備模型是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注丸趣 TV 網站,丸趣 TV 小編會繼續努力為大家帶來更多實用的文章!

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-08-16發表,共計6549字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 滁州市| 屯门区| 中方县| 澄江县| 将乐县| 鄂州市| 安仁县| 河源市| 漯河市| 嵊泗县| 克东县| 呼伦贝尔市| 太保市| 金塔县| 石首市| 辽中县| 米易县| 斗六市| 密云县| 夏邑县| 汶川县| 宽城| 彰武县| 登封市| 治多县| 新闻| 松阳县| 黎川县| 江北区| 融水| 西充县| 弥勒县| 六枝特区| 观塘区| 万全县| 乐都县| 延长县| 钟山县| 绍兴市| 辽中县| 商丘市|