訂閱
糾錯
加入自媒體

Linux設(shè)備驅(qū)動統(tǒng)一模型解析

soc節(jié)點指定了<0x0 0xe0000000 0x00100000>;此屬性值指定對于1024KB范圍的地址空間,在物理0x0處尋址的子節(jié)點映射到物理0xe0000000的父地址。通過這種映射,串行設(shè)備節(jié)點可以通過0xe0004600地址的加載或存儲、0x4600(在注冊表中指定)的偏移量以及范圍中指定的0xe0000000映射尋址。

dma-ranges屬性名稱dma-ranges值類型<empty>或編碼為任意數(shù)量的(子總線地址、父總線地址、長度)三聯(lián)體描述dma-range屬性用于描述存儲器映射總線的直接存儲器訪問(dma)結(jié)構(gòu),其設(shè)備樹父級可以從總線的dma操作訪問。它提供了一種定義總線物理地址空間與總線父級物理地址空間之間映射或轉(zhuǎn)換的方法。dma-range屬性的值的格式是任意數(shù)量的(子總線地址、母線地址、長度)。指定的每個三聯(lián)體描述連續(xù)DMA地址范圍。1. 子總線地址是子總線地址空間內(nèi)的物理地址。表示地址的單元格數(shù)取決于總線,可以通過該節(jié)點(dma-range屬性出現(xiàn)的節(jié)點)的#address-cells地址單元格確定。2. 父總線地址是父總線地址空間中的物理地址。表示父地址的單元格數(shù)取決于總線,可以通過定義父地址空間的節(jié)點的#address-cells屬性確定。3. 長度指定子地址空間中范圍的大小。表示大小的單元格數(shù)量可以根據(jù)該節(jié)點(dma-range屬性出現(xiàn)的節(jié)點)的#size-cells確定。Name(已棄用)屬性名稱name值類型<string>描述name屬性用于記錄節(jié)點名字,name屬性已經(jīng)被棄用 ,不推薦使用 name屬性,一些老的設(shè)備樹文件可能會使用此屬性。device_type屬性名稱device_type值類型<string>描述由于DTS沒有FCode,因此不建議使用該屬性。只能用于在cpu節(jié)點和memory節(jié)點中,以便與IEEE 1275衍生設(shè)備兼容。1.3.4. 基本設(shè)備節(jié)點類型

所有設(shè)備樹文件均要包含一個根文件,并且所有設(shè)備樹文件均應(yīng)在根節(jié)點下存在以下節(jié)點:

1個/cpus節(jié)點至少一個/memory節(jié)點

使用說明:R = 必需,O = 可選,OR = 可選但推薦,SD = 參見定義,所有其他的標準屬性均可接受,但可選

1.3.4.1. Root node

devicetree有一個單獨的根節(jié)點,所有其他設(shè)備節(jié)點都是它的后代。根節(jié)點的完整路徑為/。

屬性名稱使用說明類型定義#address-cellsR<u32>root子節(jié)點的reg property地址格式。#size-cellsR<u32>root子節(jié)點的reg property大小格式。modelR<string>指定唯一標識。系統(tǒng)板型號。推薦格式為“制造商,型號”compatibleR<stringlist>指定平臺體系結(jié)構(gòu)列表。該平臺兼容。這一建議可供操作系統(tǒng)在選擇平臺特定代碼時使用。1.3.4.2. /aliases節(jié)點

設(shè)備樹文件可能具有一個別名節(jié)點(/aliases),該節(jié)點定義一個或多個別名屬性。別名節(jié)點應(yīng)位于設(shè)備樹的根節(jié)點,并且具有節(jié)點名稱/別名。/aliases節(jié)點的每個屬性都定義了一個別名。屬性名稱指定別名。屬性值指定設(shè)備樹中節(jié)點的完整路徑。例如,屬性serial0 = "/simple-bus@fe000000/serial@llc500"定義了別名serial0。別名的命名規(guī)則如下:

字符描述0-9數(shù)字a-z小寫字母-破折號1.3.4.3. /memory節(jié)點

所有設(shè)備樹都需要內(nèi)存設(shè)備節(jié)點,并描述系統(tǒng)的物理內(nèi)存布局。如果系統(tǒng)具有多個范圍的內(nèi)存,則可以創(chuàng)建多個內(nèi)存節(jié)點,或者可以在單個內(nèi)存節(jié)點的reg屬性中指定范圍。

/memory節(jié)點的屬性要求如下:

屬性名稱使用說明類型定義device_typeRO<string>regR<prop-encoded-array>由任意數(shù)量的地址和大小對組成,它們指定內(nèi)存范圍的物理地址和大小initial-mapped-areaO<prop-encoded-array>指定”初始映射區(qū)域”的地址和大小,是一個由三元組組成的屬性編碼數(shù)組(有效地址、物理地址、大小)。有效和物理地址均應(yīng)為64位(值),大小應(yīng)為32位(值)

在xxx.dts中

memory {
      reg =  <0x40000000 0x10000000>;   起始地址0x40000000 長度0x10000000(32MB)
};
1.3.4.4. /chosen 節(jié)點

/chosen 節(jié)點不代表系統(tǒng)中的實際設(shè)備,而是描述了在運行時由系統(tǒng)固件選擇或指定的參數(shù)。它應(yīng)該是根節(jié)點的子節(jié)點。

屬性名稱使用說明類型定義bootargsO<string>指定程序的啟動參數(shù)。如果不需要引導(dǎo)參數(shù),則該值可能為空字符串stdout-pathO<string>指定到表示用于引導(dǎo)控制臺輸出的設(shè)備的節(jié)點的完整路徑。如果包含’:’,則它將終止路徑。該值可以是別名。stdin-pathO<string>指定到表示用于引導(dǎo)控制臺輸入的設(shè)備的節(jié)點的完整路徑。如果包含’:’,則它將終止路徑。該值可以是別名。

示例:

chosen {
bootargs = "root=/dev/nfs rw nfsroot=192.168.1.1 console=ttyS0,115200";
};
1.3.4.5. /cpus節(jié)點屬性

所有設(shè)備樹均需要/cpus/cpu節(jié)點。它并不代表系統(tǒng)中的真實設(shè)備,而是作為代表系統(tǒng)cpu的子cpu節(jié)點的容器。

屬性名稱使用說明類型定義device_typeR<string>值應(yīng)為“cpu”regR<prop-encoded-array>它為CPU節(jié)點表示的CPU/線程定義了唯一的CPU/線程ID。如果CPU支持多線程,則reg是一個數(shù)組,每個線程具有一個元素。clock-frequencyR<prop-encoded-array>以Hz為單位指定CPU的當前時鐘速度,格式可以是,或timebase-frequencyR<prop-encoded-array>指定更新時基的當前頻率statusSD<string>此屬性應(yīng)存在于對稱多進程(SMP)CPU的節(jié)點中 配置!眔kay”:CPU正在運行;”disable”:CPU處于靜止狀態(tài)。1.3.5. 中斷映射

在設(shè)備樹中,存在邏輯中斷樹,該邏輯中斷樹表示平臺硬件中斷的層次結(jié)構(gòu)和路由。在設(shè)備樹中,使用interrupt-parent屬性表示中斷源與中斷控制器的物理連線。代表產(chǎn)生中斷的設(shè)備節(jié)點包含一個中斷父屬性,該屬性具有一個虛擬值,指向給設(shè)備的中斷所路由到的設(shè)備(通常是中斷控制器)。

如果產(chǎn)生中斷的設(shè)備不具有中斷父屬性,則假定其中斷父節(jié)點為其設(shè)備父節(jié)點。每個中斷產(chǎn)生設(shè)備都包含一個中斷屬性,該屬性的值描述該設(shè)備的一個或多個中斷源。每個源都用稱為中斷描述符表示。中斷描述符的格式和含義是特定于中斷域的,即,取決于中斷域根節(jié)點上節(jié)點的屬性。中斷域的根使用#interrupt-cells屬性定義對中斷描述符進行編碼所需的值數(shù)量。

中斷域是解釋中斷描述符的上下文。中斷域的根可以是中斷控制器(interrupt controller)或中斷連接器(interrupt nexus):

中斷控制器是物理設(shè)備,需要一個驅(qū)動程序來處理通過它路由的中斷。它還可能級聯(lián)到另一個中斷域。中斷控制器由設(shè)備樹中該節(jié)點上的interrupt-controller指定。中斷連接器定義了一個中斷域和另一個中斷域之間的轉(zhuǎn)換。翻譯基于特定領(lǐng)域和總線的信息。使用interrupt-map屬性在域之間進行轉(zhuǎn)換。例如,PCI控制器設(shè)備節(jié)點可以是一個中斷連接器,定義從PCI中斷命名空間(INTA、INTB等)到具有中斷請求(IRQ)編號的中斷控制器的轉(zhuǎn)換。

1.3.5.1. Interrupts屬性名稱interrupts值類型<prop-encoded-array>編碼為任意數(shù)量的中斷描述符描述設(shè)備節(jié)點的中斷屬性定義設(shè)備生成的中斷。interrupts屬性的值由任意數(shù)量的中斷描述符組成。中斷描述符的格式由中斷域根定義。

示例:

interrupts = <GIC_SPI INT_DMA IRQ_TYPE_LEVEL_HIGH>;

1.3.5.2. interrupt-parent屬性名稱interrupt-parent值類型<phandle>描述由于中斷樹中節(jié)點的層次結(jié)構(gòu)可能與device tree不匹配,因此interrupt-parent屬性可用于明確中斷父級的定義。該值是中斷父級的phandle。如果設(shè)備缺少此屬性,則假定其中斷父級為其設(shè)備樹父級。

示例:

interrupt-parent = <&gpe>;

1.3.5.3. interrupts-extended屬性名稱interrupts-extended值類型<phandle>描述擴展的中斷屬性列出了設(shè)備產(chǎn)生的中斷。當設(shè)備連接到多個中斷控制器時,應(yīng)該使用interrupts-extended代替interrupts,因為它會在每一個中斷描述符編碼一個父代phandle

示例:

interrupts-extended = <&pic 0xA 8>, <&gic 0xda>;

1.3.5.4. #interrupt-cells屬性名稱#interrupt-cells值類型<u32>描述#interrupt-cells屬性定義對中斷域的中斷描述符進行編碼所需的單元數(shù)量1.3.5.5. interrupt-controller屬性名稱interrupt-controller值類型<empty>描述中斷控制器屬性的存在將節(jié)點定義為中斷控制器節(jié)點。1.4.Device Tree binary格式

Devicetree Blob (DTB)格式是Devicetree數(shù)據(jù)的平面二進制編碼。它用來在軟件程序之間交換設(shè)備數(shù)據(jù)。例如,在引導(dǎo)操作系統(tǒng)時,固件將向操作系統(tǒng)內(nèi)核傳遞一個DTB。

DTB格式將devicetree數(shù)據(jù)編碼為一個單一的、線性的、無指針的數(shù)據(jù)結(jié)構(gòu)。它由一個小標題組成,接下來是三個大小可變的部分:內(nèi)存保留塊、結(jié)構(gòu)塊和字符串塊這些應(yīng)該按照這個順序出現(xiàn)在扁平的devicetree中。

因此。當按地址加載到內(nèi)存中時,設(shè)備樹結(jié)構(gòu)作為一個整體。將類似于圖中的圖表。

1.4.1. dt_header

設(shè)備樹的頭部是由以下C結(jié)構(gòu)體定義的。所有字段都是32位整數(shù),以big-endian格式存儲。

struct fdt_header {
此字段應(yīng)包含值0xd00dfeed(big-endian)
uint32_t magic;     magic word FDT_MAGIC
此字段應(yīng)包含設(shè)備數(shù)據(jù)結(jié)構(gòu)的總大小(字節(jié))。該大小應(yīng)包含結(jié)構(gòu)的所有部分:報頭、內(nèi)存預(yù)留塊、結(jié)構(gòu)塊和字符串塊,以及塊之間或最終塊之后的自由空間間隙。
uint32_t totalsize;    total size of DT block
此字段應(yīng)包含結(jié)構(gòu)塊從標題開始的字節(jié)偏移
uint32_t off_dt_struct;    offset to structure
此字段應(yīng)包含從標題開始的字符串塊的字節(jié)偏移量
uint32_t off_dt_strings;   offset to strings
此字段應(yīng)包含從標題開始的內(nèi)存保留塊的字節(jié)偏移量
uint32_t off_mem_rsvmap;   offset to memory reserve map
此字段應(yīng)包含設(shè)備數(shù)據(jù)結(jié)構(gòu)的版本
uint32_t version;    format version
此字段應(yīng)包含設(shè)備所用版本向后兼容的最低版本數(shù)據(jù)結(jié)構(gòu)
uint32_t last_comp_version;   last compatible version
 version 2 fields below
此字段應(yīng)包含系統(tǒng)引導(dǎo)CPU的物理ID。它應(yīng)與設(shè)備樹中CPU節(jié)點的reg屬性中給定的物理ID相同
uint32_t boot_cpuid_phys;   Which physical CPU id we're booting on
 version 3 fields below
此字段應(yīng)包含字符串塊部分的字節(jié)長度
uint32_t size_dt_strings;   size of the strings block
 version 17 fields below
此字段應(yīng)包含結(jié)構(gòu)塊部分的字節(jié)長度
uint32_t size_dt_struct;   size of the structure block
};
1.4.2. memory reservation block

內(nèi)存保留塊向客戶端程序提供物理內(nèi)存中被保留的區(qū)域的列表,這些內(nèi)存不用于一般的內(nèi)存分配,目的是保護重要的數(shù)據(jù)結(jié)構(gòu)不被客戶端程序覆蓋。這個區(qū)域包括了若干的reserve memory描述符。每個reserve memory描述符是由address和size組成。其中address和size都是用U64來描述:

struct fdt_reserve_entry {
uint64_t address;
uint64_t size;
};
1.4.3. Structure block

結(jié)構(gòu)塊描述了設(shè)備樹本身的結(jié)構(gòu)和內(nèi)容。它由若干的分片組成,每個分片開始位置都是保存了令牌(token),以此來描述該分片的屬性和內(nèi)容。

FDT_BEGIN_NODE (0x00000001):該token描述了一個node的開始位置,緊挨著該token的就是node name(包括unit address)FDT_END_NODE (0x00000002):該token描述了一個node的結(jié)束位置FDT_PROP (0x00000003):該token描述了一個property的開始位置,該token之后是兩個u32的數(shù)據(jù)。它們之后就是長度為len的具體的屬性值數(shù)據(jù)。struct {
uint32_t len; 表示該property value data的size。
uint32_t nameoff; 表示該屬性字符串在device tree strings block的偏移值

FDT_NOP (0x00000004):被解析設(shè)備樹的程序忽略,可用于覆蓋其他屬性,以刪除它FDT_END (0x00000009):標記結(jié)構(gòu)塊的結(jié)束所以,一個DTB的結(jié)構(gòu)塊可能如下:(optionally) any number of FDT_NOP tokens
FDT_BEGIN_NODE token:
--node’s name
--paddings
For each property of the node:
              --FDT_NOP(optionally)
              --FDT_PROP token
                  --property    
all child nodes in this format
(optionally) any number of FDT_NOP tokens
FDT_END_NODE token
1.4.4. Strings Block

定義了各個node中使用的屬性的字符串表。由于很多屬性會出現(xiàn)在多個node中,因此,所有的屬性字符串組成了一個string block。這樣可以壓縮DTB的size。

1.5.Linux解析設(shè)備樹

設(shè)備樹描述了設(shè)備的詳細信息,這些信息包括數(shù)字類型的、字符串類型的、數(shù)組類型的,我們在編寫驅(qū)動時需要去獲取這些信息。Linux內(nèi)核提供一系列以of_開頭的函數(shù)來獲取設(shè)備樹信息,這些函數(shù)的原型都定義在include/linux/of.h中。設(shè)備以節(jié)點的形式掛在設(shè)備樹上,Linux內(nèi)核使用device_node結(jié)構(gòu)體來描述一個節(jié)點,其定義在include/linux/of.h中:

struct device_node {
const char *name;     device node name
const char *type;     對應(yīng)device_type的屬性
phandle phandle;      對應(yīng)該節(jié)點的phandle屬性
const char *full_name;  從“/”開始的,表示該node的full path
Struct  property *properties;      該節(jié)點的屬性列表
如果需要刪除某些屬性,kernel并非真的刪除,而是掛入到deadprops的列表
struct  property *deadprops;  removed properties
parent、child以及sibling將所有的device node連接起來
Struct  device_node *parent;  
Struct  device_node *child;
Struct  device_node *sibling;
通過該指針可以獲取相同類型的下一個node
Struct  device_node *next;  next device of same type
通過該指針可以獲取node global list下一個node
struct  device_node *allnext;  next in list of all nodes
struct  kobject kobj;
unsigned long _flags;
void *data;
#if defined(CONFIG_SPARC)
const char *path_component_name;
unsigned int unique_id;
struct of_irq_controller *irq_trans;
#endif
};
1.5.1. 查找節(jié)點的 OF函數(shù)1.5.1.1. of_find_node_by_name

功能 :Find a node by its "name" property函數(shù)

struct device_node *of_find_node_by_name(struct device_node *from,
const char *name)

參數(shù) :

@from:開始查找的節(jié)點,如果為NULL表示從根節(jié)點開始查找整個設(shè)備樹。
@name::要查找的節(jié)點名字。

返回值: 找到的節(jié)點,如果為NULL表示查找失敗。

1.5.1.2. of_find_node_by_path

功能 :Find a node matching a full OF path函數(shù) :

struct device_node *of_find_node_by_path(const char *path)

參數(shù) :@path: 完整的匹配路徑返回值 :找到的節(jié)點,如果為NULL表示查找失敗。

1.5.1.3. of_find_node_by_type

功能 Find a node by its "device_type" property函數(shù)

struct device_node *of_find_node_by_type(struct device_node *from,
const char *type)

參數(shù)

@from:開始查找的節(jié)點,如果為NULL表示從根節(jié)點開始查找整個設(shè)備樹
@type: 要查找的節(jié)點類型

返回值 找到的節(jié)點,如果為NULL表示查找失敗。

1.5.1.4. of_find_compatible_node

功能 通過device_type和compatible查找指定節(jié)點函數(shù)

struct device_node *of_find_compatible_node(struct device_node *from,const char *type, const char *compatible)

參數(shù)

@from:開始查找的節(jié)點,如果為NULL表示從根節(jié)點開始查找整個設(shè)備樹
@type: 要查找的節(jié)點device_type屬性
@compatible:節(jié)點的compatible屬性列表

返回值 找到的節(jié)點,如果為NULL表示查找失敗。

1.5.1.5. of_find_node_with_property

功能 通過屬性名查找指定節(jié)點函數(shù)

struct device_node *of_find_node_with_property(struct device_node *from,const char *prop_name)

參數(shù)

@from:開始查找的節(jié)點,如果為NULL表示從根節(jié)點開始查找整個設(shè)備樹
@type: 要查找的節(jié)點屬性名稱

返回值 找到的節(jié)點,如果為NULL表示查找失敗。

1.5.2. 查找父 /子節(jié)點的 OF函數(shù)1.5.2.1. of_get_parent

功能 函數(shù)用于獲取指定節(jié)點的父節(jié)點(如果有父節(jié)點的話 )函數(shù)

struct device_node *of_get_parent(const struct device_node *node)

參數(shù)

@node:要查找父節(jié)點的節(jié)點

返回值 找到的父節(jié)點

1.5.2.2. of_get_next_available_child

功能 獲取子節(jié)點,并跳過status = "disabled"的節(jié)點函數(shù)

struct device_node *of_get_next_available_child(const struct device_node *node,struct device_node *prev)

參數(shù)

@node: 父節(jié)點
@prev:當前父節(jié)點的上一個子節(jié)點, 如果為空,則獲取第一個子節(jié)點

返回值 找到的子節(jié)點

1.5.3. 提取屬性值的 OF函數(shù)

Linux內(nèi)核使用struct property來保存節(jié)點的屬性,其定義在/include/linux/of.h中:

struct property {
char  *name;      屬性的名稱
int  length;      屬性的長度
void  *value;     屬性的值
struct property *next;   下一個屬性
unsigned long _flags;    
unsigned int unique_id;
struct bin_attribute attr;
};
1.5.3.1. of_find_property

功能 尋找指定的屬性函數(shù)

struct property *of_find_property(const struct device_node *np,
     const char *name,
     int *lenp)

參數(shù)

@np: 設(shè)備節(jié)點
@name:屬性名稱
@lenp:屬性的字節(jié)數(shù)

返回值 找到的屬性

1.5.3.2. 讀取屬性中u8、u16、u32和u64類型的數(shù)組數(shù)據(jù)

當設(shè)置sz為1時,就是讀取一個數(shù)據(jù),Linux內(nèi)核也是這么封裝的。

int of_property_read_u8_array(const struct device_node *np,
       const char *propname, u8 *out_values, size_t sz)
int of_property_read_u16_array(const struct device_node *np,
       const char *propname, u16 *out_values, size_t sz)
int of_property_read_u32_array(const struct device_node *np,
       const char *propname, u32 *out_values,size_t sz)
int of_property_read_u64(const struct device_node *np, const char *propname,
       u64 *out_value)
1.5.3.3. of_property_read_string

功能 找到并讀取屬性字符串函數(shù)

int of_property_read_string(struct device_node *np, const char *propname,const char **out_string)

參數(shù)

@np: 設(shè)備節(jié)點
@propname:屬性名稱
@out_string:讀取的字符串

返回值

0:讀取成功
-EINVAL:屬性不存在
-ENODATA:屬性沒有這個值
-EILSEQ:字符串不是以空字符’’結(jié)尾

<上一頁  1  2  3  下一頁>  
聲明: 本文由入駐維科號的作者撰寫,觀點僅代表作者本人,不代表OFweek立場。如有侵權(quán)或其他問題,請聯(lián)系舉報。

發(fā)表評論

0條評論,0人參與

請輸入評論內(nèi)容...

請輸入評論/評論長度6~500個字

您提交的評論過于頻繁,請輸入驗證碼繼續(xù)

暫無評論

暫無評論

    掃碼關(guān)注公眾號
    OFweek人工智能網(wǎng)
    獲取更多精彩內(nèi)容
    文章糾錯
    x
    *文字標題:
    *糾錯內(nèi)容:
    聯(lián)系郵箱:
    *驗 證 碼:

    粵公網(wǎng)安備 44030502002758號