設備驅動-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 ) ; 

 

下一篇:

memory-region和of_reserved_mem_device_init將設備與reserved mem關聯 

https://www.cnblogs.com/zhangzhiwei122/p/16125822.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM