RESERVEDMEM_OF_DECLARE
在 include/linux/of_reserved_mem.h
11struct reserved_mem { 12 const char *name; 13 unsigned long fdt_node; 14 unsigned long phandle; 15 const struct reserved_mem_ops *ops; 16 phys_addr_t base; 17 phys_addr_t size; 18 void *priv; 19}; 21struct reserved_mem_ops { 22 int (*device_init)(struct reserved_mem *rmem, 23 struct device *dev); 24 void (*device_release)(struct reserved_mem *rmem, 25 struct device *dev); 26}; 28typedef int (*reservedmem_of_init_fn)(struct reserved_mem *rmem); 30#define RESERVEDMEM_OF_DECLARE(name, compat, init) \ 31 _OF_DECLARE(reservedmem, name, compat, init, reservedmem_of_init_fn)
30 - 定義 - 需要 3 個參數, name ,compat, init ;
name 就是一個名稱 , 用來構建變量名稱 ;
compat 是字符串,和 dts 中的 compatible 字符串匹配 ;
init 是一個函數, 函數 , 這個函數 類型 需要 是 reservedmem_of_init_fnc 這樣的類型,即 返回 int , 參數為 reserved_mem 指針;
_OF_DECLARE
_OF_DECLARE 在 include/linux/of.h
1300#define _OF_DECLARE(table, name, compat, fn, fn_type) \
1301 static const struct of_device_id __of_table_##name \
1302 __used __section("__" #table "_of_table") \
1303 = { .compatible = compat, \
1304 .data = (fn == (fn_type)NULL) ? fn : fn }
構建一個 static 的 struct of_device_id 對象 __of_device_name ,這個對象放在 __reservedmem_of_table 這個 section 里面 ;
對象的 compatible 賦值為 compat 字符串; .data 賦值為 fn ;
(fn==(fn_type)NULL)? 這個 檢查, 主要作用就是 檢查 fn 函數 類型 是 fn_type 。 如果不是,編譯就會報錯 ;
示例:
drivers/soc/fsl/qbman/qman_ccsr.c
482static int qman_pfdr(struct reserved_mem *rmem) 483{ 484 pfdr_a = rmem->base; 485 pfdr_sz = rmem->size; 486 487 WARN_ON(!(pfdr_a && pfdr_sz)); 488 489 return 0; 490} 491RESERVEDMEM_OF_DECLARE(qman_pfdr, "fsl,qman-pfdr", qman_pfdr);
這樣就 定義了 一個 struct of_device_id __of_device_qman_pfdr = {.compatible = "fsl,qman-pfdr" , .data = qman_fpdr } ;
qman_pfdr 函數類型,確實是 int qman_pfdr(struct reserved_mem * rmem) ;
dts 中reserved memory 解析和調用匹配的 of_device_id 的 .data 函數
setup_arch
--->arm64_memblock_init
--->early_init_fdt_scan_reserved_mem
--->fdt_init_reserved_mem
--->__reserved_mem_init_node
fdt_init_reserved_mem
drivers/of/of_reserved_mem.c
246void __init fdt_init_reserved_mem(void) 247{ 248 int i; 253 for (i = 0; i < reserved_mem_count; i++) { 254 struct reserved_mem *rmem = &reserved_mem[i]; 255 unsigned long node = rmem->fdt_node; 256 int len; 257 const __be32 *prop; 258 int err = 0; 259 bool nomap; 260 261 nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL; 262 prop = of_get_flat_dt_prop(node, "phandle", &len); 263 if (!prop) 264 prop = of_get_flat_dt_prop(node, "linux,phandle", &len); 265 if (prop) 266 rmem->phandle = of_read_number(prop, len/4); 267 268 if (rmem->size == 0) 269 err = __reserved_mem_alloc_size(node, rmem->name, 270 &rmem->base, &rmem->size); 271 if (err == 0) { 272 err = __reserved_mem_init_node(rmem); 273 if (err != 0 && err != -ENOENT) { 274 pr_info("node %s compatible matching fail\n", 275 rmem->name); 276 memblock_free(rmem->base, rmem->size); 277 if (nomap) 278 memblock_add(rmem->base, rmem->size); 279 } 280 } 281 } 282}
253 - for 循環處理每一塊 reserved memory
268 ~ 269 如果還沒有為 node 預留內存,則使用 __reserved_mem_alloc_size ,繼續解析 node 的 dts 中的 參數,預留內存。
271 err == 0 ,說明預留內存成功, 對預留的這部分內存 調用 __reserved_mem_init_node 函數(下面詳述) ;
如果 __reserved_mem init node 失敗了, 則需要釋放 預留的這部分內存 。 先 memblock free ; 如果 有 nomap 屬性,則還需要進一步把這塊內存 add 到 memblock 的memory type 的 鏈表中 ;
__reserved_mem_init_node
drivers/of/of_reserved_mem.c
170static int __init __reserved_mem_init_node(struct reserved_mem *rmem) 171{ 172 extern const struct of_device_id __reservedmem_of_table[]; 173 const struct of_device_id *i; 174 int ret = -ENOENT; 175 176 for (i = __reservedmem_of_table; i < &__rmem_of_table_sentinel; i++) { 177 reservedmem_of_init_fn initfn = i->data; 178 const char *compat = i->compatible; 179 180 if (!of_flat_dt_is_compatible(rmem->fdt_node, compat)) 181 continue; 182 183 ret = initfn(rmem); 184 if (ret == 0) { 185 pr_info("initialized node %s, compatible id %s\n", 186 rmem->name, compat); 187 break; 188 } 189 } 190 return ret; 191} 192
對 rmem ,遍歷 __reservedmem_of_table 這個 section 里面 的所有 of_device_id 對象 ;
rmem 的 fdt_node 和 of_device_id 對象的 compat (char * 字符串) 進行匹配
匹配成功,調用 of_device_id 的 data 字段 里面存放的函數 。 initfn( rmem ) ;
下一篇:
memory-region和of_reserved_mem_device_init將設備與reserved mem關聯
https://www.cnblogs.com/zhangzhiwei122/p/16125822.html