1. 程式人生 > 其它 >裝置驅動-RESERVEDMEM_OF_DECLARE預留記憶體-dts匹配-init函式呼叫

裝置驅動-RESERVEDMEM_OF_DECLARE預留記憶體-dts匹配-init函式呼叫

 

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 ) ;