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.重用。將物件抽象為匯流排 驅動 裝置三...