Linux裝置模型(三)platform

2021-06-20 00:27:12 字數 4938 閱讀 2107

platform裝置和驅動與linux裝置模型密切相關。platform在linux裝置模型中,其實就是一種虛擬匯流排沒有對應的硬體結構。它的主要作用就是管理系統的外設資源。linux在引入了platform機制之後,核心假設所有的這些外設都掛載在platform虛擬匯流排上,以便進行統一管理。

1.platform初始化

在系統中platform對應的檔案drivers/base/platform.c,它不是作為乙個模組註冊到核心的,關鍵的註冊匯流排的函式由系統初始化部分,系統啟動時初始化時建立了platform_bus裝置和platform_bus_type匯流排。

核心初始化函式kernel_init()中呼叫了do_basic_setup(),該函式中呼叫driver_init(),該函式中呼叫platform_bus_init(),我們看看platform_bus_init()函式:

int __init platform_bus_init(void)

struct device platform_bus = ;
struct bus_type platform_bus_type = ;};
改函式把裝置名為platform的裝置platform_bus註冊到系統中,其他的platform的裝置都會以它為parent。它在sysfs中目錄下.即/sys/devices/platform。

接著bus_register(&platform_bus_type)註冊了platform_bus_type匯流排型別。

來看看platform_match函式:

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

static const struct platform_device_id *platform_match_id(

const struct platform_device_id *id,

struct platform_device *pdev)

id++;

} return null;

}

不難看出,如果pdrv的id_table陣列中包含了pdev->name,或者drv->name和pdev->name名字相同,都會認為是匹配成功。id_table陣列是為了應對那些對應裝置和驅動的drv->name和pdev->name名字不同的情況。

再看看platform_uevent()函式:

static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)

新增了modalias環境變數,我們回顧一下:platform_bus. parent->kobj->kset->uevent_ops為device_uevent_ops,bus_uevent_ops的定義如下:

static struct kset_uevent_ops device_uevent_ops = ;

當呼叫device_add()時會呼叫kobject_uevent(&dev->kobj, kobj_add)產生乙個事件,這個函式中會呼叫相應的kset_uevent_ops的uevent函式,這裡即為dev_uevent(),我們看一下這個函式的**片段:

static int dev_uevent(struct kset *kset, struct kobject *kobj,

struct kobj_uevent_env *env)

. .

. }

從這裡看到如果bus->uevent()函式存在則會呼叫它。

到這裡我們清楚了platform_uevent會在**呼叫了。

2.platform裝置的註冊

對於platform裝置的初始化,核心原始碼也提供了platform_device_alloc()函式。

對於platform裝置的初註冊,核心原始碼提供了platform_device_add()函式,它是進行一系列的操作後呼叫device_add()將裝置註冊到相應的匯流排上,核心**中platform裝置的其他註冊函式都是基於這個函式,如platform_device_register()、platform_device_register_******()、platform_device_register_data()等。

我們對這些函式逐個分析,首先看看初始化函式platform_device_alloc():

struct platform_device *platform_device_alloc(const char *name, int id)

return pa ? &pa->pdev : null;

}

該函式首先為platform裝置分配記憶體空間,這裡的struct platform_object結構是struct platform _device結構的封裝,其定義如下:

struct platform_object ;

其中第二個欄位name的位址用於存放第乙個欄位pdev的name指標上的內容,函式中的**說明了這點:

strcpy(pa->name, name);

pa->pdev.name = pa->name;

接著用輸入引數id初始化platform_device的id欄位,這個id是在設定代表它的kobject時會用到的,我們將在後面分析到,如果不用它,則設為-1。

接著呼叫device_initialize()初始化platform_device內嵌的device,並設定其release函式指標。

接著我們看看platform_device_add()函式

/**

* platform_device_add - add a platform device to device hierarchy

* @pdev: platform device we're adding

* * this is part 2 of platform_device_register(), though may be called

* separately _iff_ pdev was allocated by platform_device_alloc().

*/int platform_device_add(struct platform_device *pdev)

if (p && insert_resource(p, r))

}pr_debug("registering platform device '%s'. parent at %s\n",

dev_name(&pdev->dev), dev_name(pdev->dev.parent));

ret = device_add(&pdev->dev);/*資源也分配好了,準備工作也做足,終於可以把裝置新增到裝置鍊錶裡面了*/

if (ret == 0)

return ret;

failed:

while (--i >= 0)

return ret;

}

platform_device_add()函式分析完了,我們看下platform_device_register()函式: 

/**

* platform_device_register - add a platform-level device

* @pdev: platform device we're adding

*/int platform_device_register(struct platform_device *pdev)

初始化pdev->dev後呼叫platform_device_add()把它註冊到platform_bus_type上。

另外乙個註冊函式platform_device_register_******(),它的作用是根據傳入的資源和資源數註冊裝置。

3.platform驅動的註冊

我們在裝置驅動模型的分析中已經知道驅動在註冊要呼叫driver_register(),platform driver的註冊函式platform_driver_register()同樣也是進行其它的一些初始化後呼叫driver_register()將驅動註冊到platform_bus_type匯流排上,看一下這個函式:

int platform_driver_register(struct platform_driver *drv)

先看看struct platform_driver結構:

struct platform_driver ;
上面的函式指定了內嵌的driver的bus欄位為platform_bus_type,即為它將要註冊到的匯流排。

然後設定了platform_driver內嵌的driver的probe、remove、shutdown函式。

static int platform_drv_probe(struct device *_dev)  

static int platform_drv_remove(struct device *_dev)

static void platform_drv_shutdown(struct device *_dev)

從這三個函式的**可以看到,又找到了相應的platform_driver和platform_device,然後呼叫platform_driver的probe、remove、shutdown函式。這是一種高明的做法:在不針對某個驅動具體的probe、remove、shutdown指向的函式,而通過上三個過度函式來找到platform_driver,然後呼叫probe、remove、shutdown介面。

到此我們了解了platform的初始化,以及裝置和驅動的註冊原理和介面函式。

Linux裝置模型

linux裝置驅動模型 我們在寫最簡單的裝置驅動程式的時候,我們將所有的硬體資訊都儲存在了驅動 中,這樣有乙個非常明顯的不足 會導致驅動程式的通用性極差,一旦硬體平台或硬體連線有鎖改變,就一定要修改驅動 為了解決這個問題,linux在2.6版本之後,新增了 匯流排 裝置 驅動 的linux裝置模型,...

linux裝置模型

linux核心的整體架構 linux裝置模型 linux裝置模型 1 基本概念 linux裝置模型 2 kobject linux裝置模型 3 uevent linux裝置模型 4 sysfs linux裝置模型 5 device和device driver linux裝置模型 6 bus linu...

Linux裝置驅動模型

核心版本 2.6.29 裝置驅動模型框架是linux驅動程式設計的基礎。它通過kobject,kset,ktype等底層資料結構將bus type,device,device driver 等高層資料結構組織起來,形成乙個層次 分類清晰的驅動模型。優點如下 1.重用。將物件抽象為匯流排 驅動 裝置三...