Navigation

    全志在线开发者论坛

    • Register
    • Login
    • Search
    • Categories
    • Tags
    • 在线文档
    • 社区主页

    【FAQ】全志D1芯片 如何在 Linux Device Tree 中配置预留内存?

    其它全志芯片讨论区
    d1 f133 r329 faq 技术支持
    1
    1
    489
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • q1215200171
      budbool LV 8 last edited by

      前言

      有时我们需要在 Linux 内核中预留一部分内存空间用作特殊用途(给安全模块使用,给其它处理器使用,或是给特定的驱动程序使用等),在 Device Tree 中有提供两种方法对预留内存进行配置:memreserve 和 reserved-memory。

      memreserve

      memreserve 的使用方法比较简单,如下所示,会将从地址 0x40000000 开始共 1MB 的内存空间预留出来:

      /memreserve/ 0x40000000 0x00100000;
      

      使用 memreserve 预留出来的内存一般无法再被 Linux 系统使用(当然,也可以通过特殊方法让代码固定访问该地址,但这种并非标准用法,在此不展开描述)。

      reserved-memory

      reserved-memory 框架提供了更多样的使用方法,并且与内核的 DMA API 和 CMA 框架紧密联系。

      推荐先阅读一下内核自带的文档 Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt,里面有其详细的语法说明和注意事项(例如 reserved-memory 节点中的 #address-cells 和 #size-cells 的值需要与根节点的保持一致)。

      下面对几种常见的使用方法进行举例说明:

      通过 memremap/ioremap 来使用
      在 Device Tree 配置如下,然后通过“memory-region”参数可将该预留内存分配给特定的设备驱动使用:

      reserved-memory {
         #address-cells = <2>;
         #size-cells = <2>;
         ranges;
       
         foobar_reserved: foobar@70000000 {
            no-map;
            reg = <0x0 0x70000000 0x0 0x10000000>;
         };
      };
       
      foobar_driver: foobar_driver@0 {
         memory-region = <&foobar_reserved>;
      };
      

      在设备驱动程序中,可解析 Device Tree 节点获得预留内存的物理地址和大小,然后通过 memremap/ioremap 映射这片内存空间来使用:

      /* Get reserved memory region from Device-tree */
      np = of_parse_phandle(dev->of_node, "memory-region", 0);
      if (!np) {
        dev_err(dev, "No %s specified\n", "memory-region");
        goto error1;
      }
        
      rc = of_address_to_resource(np, 0, &r);
      if (rc) {
        dev_err(dev, "No memory address assigned to the region\n");
        goto error1;
      }
        
      lp->paddr = r.start;
      lp->vaddr = memremap(r.start, resource_size(&r), MEMREMAP_WB);
      dev_info(dev, "Allocated reserved memory, vaddr: 0x%0llX, paddr: 0x%0llX\n", (u64)lp->vaddr, lp->paddr);
      

      通过 DMA API 来使用

      设置“shared-dma-pool”属性后,可让设备驱动通过 DMA API 来使用预留内存:

      reserved-memory {
         #address-cells = <2>;
         #size-cells = <2>;
         ranges;
       
         foobar_reserved: foobar@70000000 {
            compatible = "shared-dma-pool";
            no-map;
            reg = <0x0 0x70000000 0x0 0x10000000>;
         };
      };
       
      foobar_driver: foobar_driver@0 {
         memory-region = <&foobar_reserved>;
      };
      

      设备驱动程序中可类似常规地使用 DMA API,它申请的内存不是来源于默认的 CMA 内存池,而是来源于该预留内存:

      /* Initialize reserved memory resources */
        rc = of_reserved_mem_device_init(dev);
        if(rc) {
          dev_err(dev, "Could not get reserved memory\n");
          goto error1;
        }
        
        /* Allocate memory */
        dma_set_coherent_mask(dev, 0xFFFFFFFF);
        lp->vaddr = dma_alloc_coherent(dev, ALLOC_SIZE, &lp->paddr, GFP_KERNEL);
        dev_info(dev, "Allocated coherent memory, vaddr: 0x%0llX, paddr: 0x%0llX\n", (u64)lp->vaddr, lp->paddr);
      

      给 CMA 预留内存

      有时我们不需要将预留内存分配给特定的设备驱动,而只是想给默认 CMA 内存池分配一片固定的内存区域,这时我们可配置上“reusable”和“linux,cma-default”:

      reserved-memory {
            #address-cells = <2>;
            #size-cells = <2>;
            ranges;
        
            linux,cma {
               compatible = "shared-dma-pool";
               reusable;
               reg = <0x0 0x70000000 0x0 0x10000000>;
               linux,cma-default;
            };
         };
      

      由此可见,不同于 memreserve,通过 reserved-memory 预留的内存有可能进入系统 CMA,这需要满足以下几个条件:

      • compatible 需要为“shared-dma-pool”
      • 没有定义“no-map”属性
      • 定义了“reusable”属性
      1 Reply Last reply Reply Quote Share 0
      • Referenced by  q1215200171 q1215200171 
      • Referenced by  q1215200171 q1215200171 
      • Referenced by  q1215200171 q1215200171 
      • Referenced by  q1215200171 q1215200171 
      • Referenced by  q1215200171 q1215200171 
      • Referenced by  q1215200171 q1215200171 
      • Referenced by  q1215200171 q1215200171 
      • Referenced by  q1215200171 q1215200171 
      • 1 / 1
      • First post
        Last post

      Copyright © 2022 深圳全志在线有限公司 粤ICP备2021084185号 粤公网安备44030502007680号

      行为准则 | 用户协议 | 隐私权政策