]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
remoteproc: pru: Fix loading of GNU Binutils ELF
authorDimitar Dimitrov <dimitar@dinux.eu>
Wed, 30 Dec 2020 10:50:05 +0000 (12:50 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 21 Apr 2021 11:13:18 +0000 (13:13 +0200)
[ Upstream commit e6d9423d31b2f9bdd0220fd0584e3bb6ed2c4e52 ]

PRU port of GNU Binutils lacks support for separate address spaces.
PRU IRAM addresses are marked with artificial offset to differentiate
them from DRAM addresses. Hence remoteproc must mask IRAM addresses
coming from GNU ELF in order to get the true hardware address.

PRU firmware used for testing was the example in:
  https://github.com/dinuxbg/pru-gcc-examples/tree/master/blinking-led/pru

Signed-off-by: Dimitar Dimitrov <dimitar@dinux.eu>
Link: https://lore.kernel.org/r/20201230105005.30492-1-dimitar@dinux.eu
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/remoteproc/pru_rproc.c

index 16979c1cd2f4b3beacacaba33ad41f06d23c25e5..dcb380e868dfdb746201beaeb2037864205f7f87 100644 (file)
@@ -450,6 +450,24 @@ static void *pru_i_da_to_va(struct pru_rproc *pru, u32 da, size_t len)
        if (len == 0)
                return NULL;
 
+       /*
+        * GNU binutils do not support multiple address spaces. The GNU
+        * linker's default linker script places IRAM at an arbitrary high
+        * offset, in order to differentiate it from DRAM. Hence we need to
+        * strip the artificial offset in the IRAM addresses coming from the
+        * ELF file.
+        *
+        * The TI proprietary linker would never set those higher IRAM address
+        * bits anyway. PRU architecture limits the program counter to 16-bit
+        * word-address range. This in turn corresponds to 18-bit IRAM
+        * byte-address range for ELF.
+        *
+        * Two more bits are added just in case to make the final 20-bit mask.
+        * Idea is to have a safeguard in case TI decides to add banking
+        * in future SoCs.
+        */
+       da &= 0xfffff;
+
        if (da >= PRU_IRAM_DA &&
            da + len <= PRU_IRAM_DA + pru->mem_regions[PRU_IOMEM_IRAM].size) {
                offset = da - PRU_IRAM_DA;