lkml.org 
[lkml]   [2020]   [Jul]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 06/10] remoteproc: imx_rproc: add load hook
    Date
    To i.MX8, we not able to see the correct data written into TCM when
    using ioremap_wc, so use ioremap.

    However common elf loader using memset.

    To arm64, "dc zva, dst" is used in memset.
    Per ARM DDI 0487A.j, chapter C5.3.8 DC ZVA, Data Cache Zero by VA,

    "If the memory region being zeroed is any type of Device memory,
    this instruction can give an alignment fault which is prioritized
    in the same way as other alignment faults that are determined
    by the memory type."

    On i.MX platforms, when elf is loaded to onchip TCM area, the region
    is ioremapped, so "dc zva, dst" will trigger abort.

    So add i.MX specific loader to address the TCM write issue.

    The change not impact i.MX6/7 function.

    Signed-off-by: Peng Fan <peng.fan@nxp.com>
    ---
    drivers/remoteproc/imx_rproc.c | 76 ++++++++++++++++++++++++++++++++++++++++++
    1 file changed, 76 insertions(+)

    diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
    index aee790efbf7b..c23726091228 100644
    --- a/drivers/remoteproc/imx_rproc.c
    +++ b/drivers/remoteproc/imx_rproc.c
    @@ -4,6 +4,7 @@
    */

    #include <linux/clk.h>
    +#include <linux/elf.h>
    #include <linux/err.h>
    #include <linux/interrupt.h>
    #include <linux/kernel.h>
    @@ -15,6 +16,9 @@
    #include <linux/regmap.h>
    #include <linux/remoteproc.h>

    +#include "remoteproc_internal.h"
    +#include "remoteproc_elf_helpers.h"
    +
    #define IMX7D_SRC_SCR 0x0C
    #define IMX7D_ENABLE_M4 BIT(3)
    #define IMX7D_SW_M4P_RST BIT(2)
    @@ -247,10 +251,82 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
    return va;
    }

    +static int imx_rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
    +{
    + struct device *dev = &rproc->dev;
    + const void *ehdr, *phdr;
    + int i, ret = 0;
    + u16 phnum;
    + const u8 *elf_data = fw->data;
    + u8 class = fw_elf_get_class(fw);
    + u32 elf_phdr_get_size = elf_size_of_phdr(class);
    +
    + ehdr = elf_data;
    + phnum = elf_hdr_get_e_phnum(class, ehdr);
    + phdr = elf_data + elf_hdr_get_e_phoff(class, ehdr);
    +
    + /* go through the available ELF segments */
    + for (i = 0; i < phnum; i++, phdr += elf_phdr_get_size) {
    + u64 da = elf_phdr_get_p_paddr(class, phdr);
    + u64 memsz = elf_phdr_get_p_memsz(class, phdr);
    + u64 filesz = elf_phdr_get_p_filesz(class, phdr);
    + u64 offset = elf_phdr_get_p_offset(class, phdr);
    + u32 type = elf_phdr_get_p_type(class, phdr);
    + void *ptr;
    +
    + if (type != PT_LOAD)
    + continue;
    +
    + dev_dbg(dev, "phdr: type %d da 0x%llx memsz 0x%llx filesz 0x%llx\n",
    + type, da, memsz, filesz);
    +
    + if (filesz > memsz) {
    + dev_err(dev, "bad phdr filesz 0x%llx memsz 0x%llx\n",
    + filesz, memsz);
    + ret = -EINVAL;
    + break;
    + }
    +
    + if (offset + filesz > fw->size) {
    + dev_err(dev, "truncated fw: need 0x%llx avail 0x%zx\n",
    + offset + filesz, fw->size);
    + ret = -EINVAL;
    + break;
    + }
    +
    + if (!rproc_u64_fit_in_size_t(memsz)) {
    + dev_err(dev, "size (%llx) does not fit in size_t type\n",
    + memsz);
    + ret = -EOVERFLOW;
    + break;
    + }
    +
    + /* grab the kernel address for this device address */
    + ptr = rproc_da_to_va(rproc, da, memsz);
    + if (!ptr) {
    + dev_err(dev, "bad phdr da 0x%llx mem 0x%llx\n", da,
    + memsz);
    + ret = -EINVAL;
    + break;
    + }
    +
    + /* put the segment where the remote processor expects it */
    + if (filesz)
    + memcpy_toio(ptr, elf_data + offset, filesz);
    + }
    +
    + return ret;
    +}
    +
    static const struct rproc_ops imx_rproc_ops = {
    .start = imx_rproc_start,
    .stop = imx_rproc_stop,
    .da_to_va = imx_rproc_da_to_va,
    + .load = imx_rproc_elf_load_segments,
    + .parse_fw = rproc_elf_load_rsc_table,
    + .find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table,
    + .sanity_check = rproc_elf_sanity_check,
    + .get_boot_addr = rproc_elf_get_boot_addr,
    };

    static int imx_rproc_addr_init(struct imx_rproc *priv,
    --
    2.16.4
    \
     
     \ /
      Last update: 2020-07-24 09:45    [W:4.954 / U:0.056 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site