基於Mips架構linux下裝置樹解析(三)

2021-10-03 09:07:32 字數 4800 閱讀 8531

本裝置樹解析基於linux3.0.4核心版本

從device_initcall()開始,我們分析追蹤裝置樹device node 檔案轉換platform device流程,有關於device_initcall()核心初始化優先順序載入機制,我們在此不進行贅述,只貼函式原型如下,函式路徑見include/linux/init.h。

#define pure_initcall(fn)       __define_initcall("0",fn,0)

#define core_initcall(fn) __define_initcall("1",fn,1)

#define core_initcall_sync(fn) __define_initcall("1s",fn,1s)

#define postcore_initcall(fn) __define_initcall("2",fn,2)

#define postcore_initcall_sync(fn) __define_initcall("2s",fn,2s)

#define arch_initcall(fn) __define_initcall("3",fn,3)

#define arch_initcall_sync(fn) __define_initcall("3s",fn,3s)

#define subsys_initcall(fn) __define_initcall("4",fn,4)

#define subsys_initcall_sync(fn) __define_initcall("4s",fn,4s)

#define fs_initcall(fn) __define_initcall("5",fn,5)

#define fs_initcall_sync(fn) __define_initcall("5s",fn,5s)

#define rootfs_initcall(fn) __define_initcall("rootfs",fn,rootfs)

#define device_initcall(fn) __define_initcall("6",fn,6)

#define device_initcall_sync(fn) __define_initcall("6s",fn,6s)

#define late_initcall(fn) __define_initcall("7",fn,7)

#define late_initcall_sync(fn) __define_initcall("7s",fn,7s)

從上面可以看到我們當前核心裝置樹匯流排初始化載入優先順序處於第六級,函式原型如下,函式路徑見./arch/mips/***/common/setup.c,通過匹配裝置樹平台匯流排名稱compatible = 「******-bus」,初始化完成結構體struct device node向結構體struct platform device轉換

static

struct of_device_id __initdata ***_ids=

,,};

int __init ***_publish_devices

(void

)device_initcall

(***_publish_devices)

;

繼續追蹤函式of_platform_populate(),函式原型如下,函式路徑見./drivers/of/platform.c,通過上面呼叫可以看到傳入了四個引數,第乙個為root節點,為null,第二個引數為matches,為of_device_id靜態儲存陣列名字,第三個引數與第四個引數均為null,結合下面我們貼的函式原型可以看出,該函式第一步對是否存在root節點判斷,如果不為空,則從根檔案路徑查起。第二步通過查詢matches,遍歷根節點下所有子節點,第三步of_platform_bus_create()就是我們本文重點分析的struct device node轉換struct platform device函式介面,第四步轉換完成後將該節點記錄到節點列表裡。

int

of_platform_populate

(struct device_node *root,

const

struct of_device_id *matches,

const

struct of_dev_auxdata *lookup,

struct device *parent)

of_node_put

(root);.

....

....

....

....

}

繼續追蹤of_platform_bus_create()函式,函式原型如下,函式路徑見

/drivers/of/platform.c,追蹤到這裡我們又看到熟悉的裝置樹解析介面函式,第一步進行名字匹配of_get_property(),,第二步對platform device進行轉換of_platform_device_create_pdata(),第三步of_match_node()函式進行校驗,第四步將轉換好的節點建立。

static

intof_platform_bus_create

(struct device_node *bus,

const

struct of_device_id *matches,

const

struct of_dev_auxdata *lookup,

struct device *parent, bool strict)..

....

....

....

... dev =

of_platform_device_create_pdata

(bus, bus_id, platform_data, parent);if

(!dev ||

!of_match_node

(matches, bus)

)return0;

for_each_child_of_node

(bus, child)

}return rc;

}

struct platform_device *

of_platform_device_create_pdata

(struct device_node *np,

const

char

*bus_id,

void

*platform_data,

struct device *parent)

return dev;

}

繼續追蹤platform_bus_type,結構體初始化賦值如下,該結構體定義路徑見

./drivers/base/platform.c,結構體內可以看到我們熟悉的成員變數.match = platform_match,platform_match()函式就是各個外設驅動呼叫得底層介面實現,追蹤到這裡層次越來越清晰。

struct bus_type platform_bus_type =

;export_symbol_gpl

(platform_bus_type)

;

補充一下platform bus初始化函式,同樣也是在./drivers/base/platform.c,在此不贅述了,只貼函式原型如下

int __init platform_bus_init

(void

)

現在我們回到platform_match()函式,追蹤下它的函式實體,函式原型如下,函式路徑見./drivers/base/platform.c,在這裡對裝置樹dtb檔案內節點名字與驅動名字做了校驗匹配。

static

intplatform_match

(struct device *dev,

struct device_driver *drv)

繼續追蹤函式of_driver_match_device()實體,函式原型如下,函式路徑見

./include/linux/of_device.h,可以看到只是簡單封裝。

static

inline

intof_driver_match_device

(struct device *dev,

const

struct device_driver *drv)

繼續追蹤of_match_device()函式實體,函式原型如下,函式路徑見

./drivers/of/device.c,這裡我們終於又見到了我們熟悉的裝置樹解析介面函式of_match_node(),第一步我們對傳入的裝置樹驅動of match成員變數與轉換後platform device內的of_node節點是否存在做了判斷校驗,第二步才是呼叫of_match_node()去匹配。至此平台匯流排裝置樹驅動流程分析完成。

const

struct of_device_id *

of_match_device

(const

struct of_device_id *matches,

const

struct device *dev)

export_symbol

(of_match_device)

;

基於mips架構的uboot啟動流程(3)

要注意mips具有流水線可見性,所以跟在跳轉指令後的下一條指令,在執行跳轉到的地方前,都會執行,這個叫分支延遲。但是編譯器會隱藏該特性,但可以通過設定 set noreorder 來禁止編譯器重新組織 順序。每個板子都有自己的lds檔案。這個主要是用來說明編譯生成的指令,及執行過程中用到的資料放置的...

基於mips架構的uboot啟動流程(4)

特點和功能 u boot yamon 支援的 cpu 和 board 1.支援種類繁多,包括 arm 的各個系列 ppc,mips 2.mips 的支援較差,目前支援 au1100,au1500 系列,4kec 的需要自己移植 工作量主要在起始 的初始化部分,包括 cahe 和中斷的初始化 1.基本...

基於mips架構的uboot啟動流程(4)

特點和功能 u boot yamon 支援的 cpu 和 board 1.支援種類繁多,包括 arm 的各個系列 ppc,mips 2.mips 的支援較差,目前支援 au1100,au1500 系列,4kec 的需要自己移植 工作量主要在起始 的初始化部分,包括 cahe 和中斷的初始化 1.基本...