设备驱动-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

 

posted @ 2022-04-10 14:13  张志伟122  阅读(939)  评论(0编辑  收藏  举报