Linux裝置驅動程式架構分析之platform(基於3.10.1核心)
作者:劉昊昱
核心版本:3.10.1
一、platform bus的註冊
platform bus註冊是通過platform_bus_init函式完成的,該函式定義在drivers/base/platform.c檔案中,其內容如下:
904int __init platform_bus_init(void) 905{ 906 int error; 907 908 early_platform_cleanup(); 909 910 error = device_register(&platform_bus); 911 if (error) 912 return error; 913 error = bus_register(&platform_bus_type); 914 if (error) 915 device_unregister(&platform_bus); 916 return error; 917}
908行,呼叫early_platform_cleanup作一些清理工作。
910行,呼叫device_register註冊了一個“platform”的device,以後註冊的所有platform裝置均以這個“platform”裝置為父裝置。platform_bus定義在drivers/base/platform.c檔案中,其內容如下:
35struct device platform_bus = {
36 .init_name = "platform",
37};
913行,呼叫bus_register註冊匯流排platform_bus_type。bus_register函式的執行過程我們在《Linux裝置模型分析之bus(基於3.10.1核心)》一文中已經分析過,這裡就不再重複了。platform_bus_type定義在drivers/base/platform.c檔案中,其內容如下:
895struct bus_type platform_bus_type = { 896 .name = "platform", 897 .dev_attrs = platform_dev_attrs, 898 .match = platform_match, 899 .uevent = platform_uevent, 900 .pm = &platform_dev_pm_ops, 901};
platform_match函式定義在drivers/base/platform.c檔案中,其內容如下:
710/**
711 * platform_match - bind platform device to platform driver.
712 * @dev: device.
713 * @drv: driver.
714 *
715 * Platform device IDs are assumed to be encoded like this:
716 * "<name><instance>", where <name> is a short description of the type of
717 * device, like "pci" or "floppy", and <instance> is the enumerated
718 * instance of the device, like '0' or '42'. Driver IDs are simply
719 * "<name>". So, extract the <name> from the platform_device structure,
720 * and compare it against the name of the driver. Return whether they match
721 * or not.
722 */
723static int platform_match(struct device *dev, struct device_driver *drv)
724{
725 struct platform_device *pdev = to_platform_device(dev);
726 struct platform_driver *pdrv = to_platform_driver(drv);
727
728 /* Attempt an OF style match first */
729 if (of_driver_match_device(dev, drv))
730 return 1;
731
732 /* Then try ACPI style match */
733 if (acpi_driver_match_device(dev, drv))
734 return 1;
735
736 /* Then try to match against the id table */
737 if (pdrv->id_table)
738 return platform_match_id(pdrv->id_table, pdev) != NULL;
739
740 /* fall-back to driver name match */
741 return (strcmp(pdev->name, drv->name) == 0);
742}
二、platform device的註冊
platform device通過struct platform_device結構體來描述,這個結構體定義在include/linux/platform_device.h檔案中,其內容如下:
22struct platform_device {
23 const char *name;
24 int id;
25 bool id_auto;
26 struct device dev;
27 u32 num_resources;
28 struct resource *resource;
29
30 const struct platform_device_id *id_entry;
31
32 /* MFD cell pointer */
33 struct mfd_cell *mfd_cell;
34
35 /* arch specific additions */
36 struct pdev_archdata archdata;
37};
註冊一個paltform_device通過呼叫platform_device_register函式完成,該函式定義在drivers/base/platform.c檔案中,其內容如下:
392/**
393 * platform_device_register - add a platform-level device
394 * @pdev: platform device we're adding
395 */
396int platform_device_register(struct platform_device *pdev)
397{
398 device_initialize(&pdev->dev);
399 arch_setup_pdev_archdata(pdev);
400 return platform_device_add(pdev);
401}
398行,呼叫device_initialize初始化platform_device.dev。
399行,arch_setup_pdev_archdata是一個空函式,忽略。
400行,呼叫platform_device_add函式,該函式定義在drivers/base/platform.c檔案中,其內容如下:
273/**
274 * platform_device_add - add a platform device to device hierarchy
275 * @pdev: platform device we're adding
276 *
277 * This is part 2 of platform_device_register(), though may be called
278 * separately _iff_ pdev was allocated by platform_device_alloc().
279 */
280int platform_device_add(struct platform_device *pdev)
281{
282 int i, ret;
283
284 if (!pdev)
285 return -EINVAL;
286
287 if (!pdev->dev.parent)
288 pdev->dev.parent = &platform_bus;
289
290 pdev->dev.bus = &platform_bus_type;
291
292 switch (pdev->id) {
293 default:
294 dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id);
295 break;
296 case PLATFORM_DEVID_NONE:
297 dev_set_name(&pdev->dev, "%s", pdev->name);
298 break;
299 case PLATFORM_DEVID_AUTO:
300 /*
301 * Automatically allocated device ID. We mark it as such so
302 * that we remember it must be freed, and we append a suffix
303 * to avoid namespace collision with explicit IDs.
304 */
305 ret = ida_simple_get(&platform_devid_ida, 0, 0, GFP_KERNEL);
306 if (ret < 0)
307 goto err_out;
308 pdev->id = ret;
309 pdev->id_auto = true;
310 dev_set_name(&pdev->dev, "%s.%d.auto", pdev->name, pdev->id);
311 break;
312 }
313
314 for (i = 0; i < pdev->num_resources; i++) {
315 struct resource *p, *r = &pdev->resource[i];
316
317 if (r->name == NULL)
318 r->name = dev_name(&pdev->dev);
319
320 p = r->parent;
321 if (!p) {
322 if (resource_type(r) == IORESOURCE_MEM)
323 p = &iomem_resource;
324 else if (resource_type(r) == IORESOURCE_IO)
325 p = &ioport_resource;
326 }
327
328 if (p && insert_resource(p, r)) {
329 dev_err(&pdev->dev, "failed to claim resource %d\n", i);
330 ret = -EBUSY;
331 goto failed;
332 }
333 }
334
335 pr_debug("Registering platform device '%s'. Parent at %s\n",
336 dev_name(&pdev->dev), dev_name(pdev->dev.parent));
337
338 ret = device_add(&pdev->dev);
339 if (ret == 0)
340 return ret;
341
342 failed:
343 if (pdev->id_auto) {
344 ida_simple_remove(&platform_devid_ida, pdev->id);
345 pdev->id = PLATFORM_DEVID_AUTO;
346 }
347
348 while (--i >= 0) {
349 struct resource *r = &pdev->resource[i];
350 unsigned long type = resource_type(r);
351
352 if (type == IORESOURCE_MEM || type == IORESOURCE_IO)
353 release_resource(r);
354 }
355
356 err_out:
357 return ret;
358}
287-288行,如果platform_device沒有指定父裝置,則設定pdev->dev.parent為platform_bus,即“platform”裝置。
290行,指定bus型別為platform_bus_type。
292-312行,根據不同情況設定裝置名。
314-333行,呼叫insert_resource函式將platform_device的資源插入到資源樹中。
338行,呼叫device_add將platform_device對應的device註冊到sysfs系統中。這個函式我們在《Linux裝置模型分析之device(基於3.10.1核心)》一文中已經分析過,這裡不再重複了。
三、platform driver的註冊
platform driver是通過struct platform_driver結構體來描述的,該結構體定義在include/linux/platform_device.h檔案中,其內容如下:
173struct platform_driver {
174 int (*probe)(struct platform_device *);
175 int (*remove)(struct platform_device *);
176 void (*shutdown)(struct platform_device *);
177 int (*suspend)(struct platform_device *, pm_message_t state);
178 int (*resume)(struct platform_device *);
179 struct device_driver driver;
180 const struct platform_device_id *id_table;
181};
platform_driver的註冊是通過呼叫platform_driver_register函式完成的,該函式定義在drivers/base/platform.c檔案中,其內容如下:
525/**
526 * platform_driver_register - register a driver for platform-level devices
527 * @drv: platform driver structure
528 */
529int platform_driver_register(struct platform_driver *drv)
530{
531 drv->driver.bus = &platform_bus_type;
532 if (drv->probe)
533 drv->driver.probe = platform_drv_probe;
534 if (drv->remove)
535 drv->driver.remove = platform_drv_remove;
536 if (drv->shutdown)
537 drv->driver.shutdown = platform_drv_shutdown;
538
539 return driver_register(&drv->driver);
540}
531-537行,完成一些初始化工作。
539行,呼叫driver_register註冊platform_driver.driver,該函式我們在《》一文中已經分析過,這裡不再重複。
相關推薦
Linux裝置驅動程式架構分析之platform(基於3.10.1核心)
作者:劉昊昱 核心版本:3.10.1 一、platform bus的註冊 platform bus註冊是通過platform_bus_init函式完成的,該函式定義在drivers/base/platform.c檔案中,其內容如下: 904int __init pl
Linux裝置模型分析之bus(基於3.10.1核心)
作者:劉昊昱 核心版本:3.10.1 一、bus定義 Linux裝置驅動模型中的bus,即可以是物理匯流排(如PCI、I2C匯流排)的抽象,也可以是出於裝置驅動模型架構需要而定義的虛擬的“platform”匯流排。一個符合Linux裝置驅動模型的device或devi
Linux裝置模型分析之device_driver(基於3.10.1核心)
一、device_driver定義 181/** 182 * struct device_driver - The basic device driver structure 183 * @name: Name of the device
Linux裝置驅動程式架構分析之一個I2C驅動例項
作者:劉昊昱 核心版本:3.10.1 編寫一個I2C裝置驅動程式的工作可分為兩部分,一是定義和註冊I2C裝置,即i2c_client;二是定義和註冊I2C裝置驅動,即i2c_driver。下面我們就以mini2440的I2C裝置at24c08 EEPROM為例,介紹如
Linux裝置驅動程式架構分析之I2C架構(基於3.10.1核心)
作者:劉昊昱 核心版本:3.10.1 I2C體系架構的硬體實體包括兩部分: 硬體I2C Adapter:硬體I2C Adapter表示一個硬體I2C介面卡,也就是I2C控制器。一般是SOC中的一個介面,也可以用GPIO模擬。硬體I2C Adapter主要用來在I2
Linux裝置驅動程式架構分析之SD Spec摘要
作者:劉昊昱 本文是對SDSpecifications Part 1 Physical Layer Simplified Specification Version 4.10的摘要記錄,具體資訊可參考該文件。 3、SD Memory Card System Conc
Linux裝置驅動程式架構分析之MMC/SD(二)
作者:劉昊昱 核心版本:3.10.1 一、s3cmci_ops分析 在上一篇文章中我們分析了Mini2440 MMC/SD驅動的probe函式s3cmci_probe。在該函式中初始化了struct mmc_host指標變數mmc,其中,設定mmc->ops為s
linux裝置驅動模型架構分析 一
概述LDD3中說:“Linux核心需要一個對系統結構的一般性描述。”這個描述就是linux裝置驅動模型(下面簡稱為LDDM)。LDDM不是獨立存在,其體系如下圖所示:對架構的每一部分本文都會開闢獨立的章節進行描述。暫且拋開這個架構,首先從總體上了解一下LDDM。LDDM與驅動
linux裝置驅動模型架構分析(一)——概述
概述 LDD3中說:“Linux核心需要一個對系統結構的一般性描述。”這個描述就是linux裝置驅動模型(下面簡稱為LDDM)。LDDM不是獨立存在,其體系如下圖所示: LDDM體系結構 對架構的每一部分本文都會開闢獨立的章節進行描述。暫且拋開這個架構,首先從總體上了
Linux晶片級移植與底層驅動(基於3.7.4核心)
1. SoC Linux底層驅動的組成和現狀 為了讓Linux在一個全新的ARM SoC上執行,需要提供大量的底層支撐,如定時器節拍、中斷控制器、SMP啟動、CPU hotplug以及底層的GPIO、clock、pinctrl和DMA硬體的封裝等。定時器
Linux晶片級移植與底層驅動(基於3.7.4核心)(GPIO&&pinctrl&&clk)
6. GPIO驅動 在drivers/gpio下實現了通用的基於gpiolib的GPIO驅動,其中定義了一個通用的用於描述底層GPIO控制器的gpio_chip結構體,並要求具體的SoC實現gpio_chip結構體的成員函式,最後透過gpiochip_add
【 專欄 】- 手把手教你從零實現Linux裝置驅動程式(基於友善之臂4412開發板)
手把手教你從零實現Linux裝置驅動程式(基於友善之臂4412開發板) ARM-tiny4412這款CPU是基於ARMv7架構的晶片,目前在網上開發現成資源較少,為了彌補這一缺陷,本人決定將我所學所用的這塊晶片的開發技巧和方法共享
《精通Linux 裝置驅動程式開發》下載
2018年11月02日 14:24:20 茹粿鰅莧丨你 閱讀數:1 標籤: 程式設計 資料 區
Linux裝置驅動程式學習(基於2440的GPIO字元裝置驅動)
GPIO驅動程式如下: #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> #include <linux/string.h> #include <li
深入linux裝置驅動程式核心機制(第九章) 讀書筆記
第9章 linux裝置驅動模型 本文歡迎轉載, 請標明出處 本文出處: http://blog.csdn.net/dyron 9.1 sysfs檔案系統 sysfs檔案系統可以取代ioctl的功能. sysfs檔案系統
教你寫Linux裝置驅動程式:一個簡短的教程
摘自:http://blog.chinaunix.net/uid-20799298-id-99675.html 原文為 Writing device driver in Linux:A brief tutorial. 該文重點給出了三個例項來講解Linux驅
Linux裝置驅動程式安裝fatal error: linux/module.h: No such file or directory
在做Linux裝置驅動程式安裝實驗時,執行gcc -c mydev.c產生fatal error: linux/module.h: No such file or directory錯誤資訊 mydev.c程式碼如下: #ifndef __KERNEL__ #define
USB裝置驅動基礎 >>Linux裝置驅動程式
最常用的裝置卻不懂它的工作原理,豈不是最大的不尊敬,感謝USB為我們帶來的便利; 今天也要繼續堅定的前行的… 文章目錄 [0x100] 特徵與概念 [0x110] USB介面特徵 [0x120] USB驅動型別 [0x1
PCI驅動基礎 >> Linux裝置驅動程式
俗話說的好,免費是最貴,閒暇是最累的,但是我自己選的路就要負責走完; 壓力一天比一天重,當學習了理論卻不知道該如何輸出的時候,會有一種油然而生的挫敗感; 看來必須得調整自己的心態還是要調整學習方法,如何才能用最好狀態去接受新的知識; 文章目錄 [0x1
kobject,Kset,bus_type >>Linux裝置驅動程式
狀態不錯,快要元旦了,這是我計劃開始的第一年;時間過的真快啊! 也是逃離舒適圈的一年,不能在日復一日的無聊工作沉浸下去,要明白自己今生適合做哪些事情,而不是隨波逐流; 文章目錄 [0x100]內容概述 [0x110] 核心的裝置管理特性