[U-Boot] [PATCH] arm/da850 : [RFC] add bootdsp to cmd_elf

On platform with a DSP co-processor, add a command to boot an elf on it.
* Test *
This patch has been tested on an OMAP-L138 EVM with DSP code generated with TI's code generation tools 7.4.6 with the --abi=eabi option.
* Bugs *
Some elf generated with older TI's cgt have mis-aligned header sections that lead to u-boot freeze. This point can be checked with readelf (see "Start of program headers" and/or "Start of section headers") if you experience such problem.
* Discussion *
Our first question is about the interest of the u-boot community for this feature ?
For the implementation, we tried to separate platform specific code (dsp's reset and entry point) from the elf generic code (check and load elf in memory). We would like to have your opinion on this design.
Signed-off-by: Paul Chavent paul.chavent@onera.fr Cc: Tom Rini trini@ti.com --- board/davinci/da8xxevm/da850evm.c | 43 ++++++++++++++++++++++++++ common/cmd_elf.c | 65 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+)
diff --git a/board/davinci/da8xxevm/da850evm.c b/board/davinci/da8xxevm/da850evm.c index 85b4830..3d361b6 100644 --- a/board/davinci/da8xxevm/da850evm.c +++ b/board/davinci/da8xxevm/da850evm.c @@ -121,6 +121,49 @@ static void dspwake(void) writel(val, (PSC0_MDCTL + (15 * 4))); }
+void dsp_reset_assert(void) +{ + unsigned int id = DAVINCI_LPSC_GEM; + dv_reg_p mdstat, mdctl; + struct davinci_psc_regs *psc_regs; + + psc_regs = davinci_psc0_regs; + mdstat = &psc_regs->psc0.mdstat[id]; + mdctl = &psc_regs->psc0.mdctl[id]; + + if ((*mdstat & 0x100) == 0x000) + return; + + *mdctl &= ~0x100; + + while ((*mdstat & 0x100) != 0x000) + ; +} + +void dsp_entry_point(unsigned long addr) +{ + writel(addr, HOST1CFG); +} + +void dsp_reset_deassert(void) +{ + unsigned int id = DAVINCI_LPSC_GEM; + dv_reg_p mdstat, mdctl; + struct davinci_psc_regs *psc_regs; + + psc_regs = davinci_psc0_regs; + mdstat = &psc_regs->psc0.mdstat[id]; + mdctl = &psc_regs->psc0.mdctl[id]; + + if ((*mdstat & 0x100) == 0x100) + return; + + *mdctl |= 0x100; + + while ((*mdstat & 0x100) != 0x100) + ; +} + int misc_init_r(void) { dspwake(); diff --git a/common/cmd_elf.c b/common/cmd_elf.c index ab9c7e3..ae7b6e1 100644 --- a/common/cmd_elf.c +++ b/common/cmd_elf.c @@ -24,6 +24,12 @@ DECLARE_GLOBAL_DATA_PTR; #endif
+#if defined(CONFIG_MACH_DAVINCI_DA850_EVM) +extern void dsp_reset_assert(void); +extern void dsp_entry_point(unsigned long addr); +extern void dsp_reset_deassert(void); +#endif + static unsigned long load_elf_image_phdr(unsigned long addr); static unsigned long load_elf_image_shdr(unsigned long addr);
@@ -269,6 +275,55 @@ int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 1; }
+#if defined(CONFIG_MACH_DAVINCI_DA850_EVM) +/* ====================================================================== + * Interpreter command to boot the companion dsp with an arbitrary ELF + * image from memory. Can be improved to bring bootargs + * ====================================================================== */ +int do_bootdsp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + unsigned long addr; /* Address of the ELF image */ + char *sload, *saddr; + + sload = saddr = NULL; + if (argc == 3) { + sload = argv[1]; + saddr = argv[2]; + } else if (argc == 2) { + if (argv[1][0] == '-') + sload = argv[1]; + else + saddr = argv[1]; + } + + if (saddr) + addr = simple_strtoul(saddr, NULL, 16); + else + addr = load_addr; + + if (!valid_elf_image(addr)) + return 1; + + /* hold the reset */ + dsp_reset_assert(); + + if (sload && sload[1] == 'p') + addr = load_elf_image_phdr(addr); + else + addr = load_elf_image_shdr(addr); + + printf("## Starting dsp's application at 0x%08lx ...\n", addr); + + /* setup the DSP reset vector */ + dsp_entry_point(addr); + + /* release the reset */ + dsp_reset_deassert(); + + return 0; +} +#endif /* defined(CONFIG_MACH_DAVINCI_DA850_EVM) */ + /* ====================================================================== * A very simple elf loader, assumes the image is valid, returns the * entry point address. @@ -367,3 +422,13 @@ U_BOOT_CMD( "Boot vxWorks from an ELF image", " [address] - load address of vxWorks ELF image." ); + +#if defined(CONFIG_MACH_DAVINCI_DA850_EVM) +U_BOOT_CMD( + bootdsp, 3, 0, do_bootdsp, + "Boot dsp from an ELF image in memory", + "[-p|-s] [address]\n" + "\t- load ELF image at [address] via program headers (-p)\n" + "\t or via section headers (-s)" +); +#endif /* defined(CONFIG_MACH_DAVINCI_DA850_EVM) */

On Mon, Jan 27, 2014 at 05:28:22PM +0100, Paul Chavent wrote:
On platform with a DSP co-processor, add a command to boot an elf on it.
- Test *
This patch has been tested on an OMAP-L138 EVM with DSP code generated with TI's code generation tools 7.4.6 with the --abi=eabi option.
- Bugs *
Some elf generated with older TI's cgt have mis-aligned header sections that lead to u-boot freeze. This point can be checked with readelf (see "Start of program headers" and/or "Start of section headers") if you experience such problem.
- Discussion *
Our first question is about the interest of the u-boot community for this feature ?
For the implementation, we tried to separate platform specific code (dsp's reset and entry point) from the elf generic code (check and load elf in memory). We would like to have your opinion on this design.
This seems like the right direction to take for things. The question I have first is, are we talking about loading something into the DSP and then letting it go, or are we talking about getting a result back from the DSP in Linux? I assume the first case.

On 01/29/2014 11:37 PM, Tom Rini wrote:
On Mon, Jan 27, 2014 at 05:28:22PM +0100, Paul Chavent wrote:
On platform with a DSP co-processor, add a command to boot an elf on it.
- Test *
This patch has been tested on an OMAP-L138 EVM with DSP code generated with TI's code generation tools 7.4.6 with the --abi=eabi option.
- Bugs *
Some elf generated with older TI's cgt have mis-aligned header sections that lead to u-boot freeze. This point can be checked with readelf (see "Start of program headers" and/or "Start of section headers") if you experience such problem.
- Discussion *
Our first question is about the interest of the u-boot community for this feature ?
For the implementation, we tried to separate platform specific code (dsp's reset and entry point) from the elf generic code (check and load elf in memory). We would like to have your opinion on this design.
This seems like the right direction to take for things. The question I have first is, are we talking about loading something into the DSP and then letting it go, or are we talking about getting a result back from the DSP in Linux? I assume the first case.
Thank you for having considered the patch.
Indeed, this is about loading something into the DSP and then letting it go without worrying about the result.
In our use case however, later, the ARM run some programs (under Linux) that will use services provided by the DSP through its L2 cache used as shared memory. Ideally, we would like to be able to soft reset the ARM without killing the DSP that will run the critical code that should survive to hight level apps failures...
I wait for your advices to improve the patch integration (I'm not sure that the "extern" declarations on top of cmd_elf.c will be integrated like that). Moreover, i wonder if we should begin to think about a more generic "boot_companion" function that would introduce a framework in order to boot companion cpu... but perhaps it's a bit premature.
Regards.
Paul Chavent.
participants (2)
-
Paul Chavent
-
Tom Rini