The BROM in newer SoC variants doesn't enable MMU by default anymore. So in order to benefit from e4b3da2b17ee9d7c5cab9b80e708b3a309fc4c96 ("fel: Faster USB transfers via 'fel write' to DRAM"), we need to be able to enable it from the 'sunxi-fel' tool.
Signed-off-by: Siarhei Siamashka <siarhei.siamas...@gmail.com> --- fel.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/fel.c b/fel.c index e9f6450..916afdf 100644 --- a/fel.c +++ b/fel.c @@ -388,6 +388,18 @@ typedef struct { * Note: the entries in the 'swap_buffers' tables need to be sorted by 'buf1' * addresses. And the 'buf1' addresses are the BROM data buffers, while 'buf2' * addresses are the intended backup locations. + * + * Also for performance reasons, we want to have MMU enabled with optimal + * section attributes configured (the code from the BROM should use I-cache, + * writing data to the DRAM area should use write combining). The reason is + * that the BROM FEL protocol implementation relies on a memcpy loop somewhere + * on the perfromance critical path when transferring data over USB. The older + * SoC variants (A10/A13/A20/A31/A23) already have MMU enabled and we only need + * to adjust section attributes. The BROM in newer SoC variants (A33/A83T/H3) + * doesn't enable MMU anymore, so we need to find some 16K of spare space in + * SRAM to place the translation table there and specify it as the 'mmu_tt_addr' + * field in the 'soc_sram_info' structure. This is only an optional performance + * feature. */ typedef struct { uint32_t soc_id; /* ID of the SoC */ @@ -396,6 +408,7 @@ typedef struct { uint32_t thunk_addr; /* Address of the thunk code */ uint32_t thunk_size; /* Maximal size of the thunk code */ uint32_t needs_l2en; /* Set the L2EN bit */ + uint32_t mmu_tt_addr; /* MMU translation table address */ sram_swap_buffers *swap_buffers; } soc_sram_info; @@ -600,6 +613,21 @@ uint32_t aw_get_ttbr0(libusb_device_handle *usb, soc_sram_info *sram_info) return ttbr0; } +void aw_set_ttbr0(libusb_device_handle *usb, soc_sram_info *sram_info, + uint32_t ttbr0) +{ + uint32_t arm_code[] = { + htole32(0xe59f200c), /* ldr r2, [pc, #12] */ + htole32(0xee022f10), /* mcr 15, 0, r2, cr2, cr0, {0} */ + htole32(0xe12fff1e), /* bx lr */ + }; + + ttbr0 = htole32(ttbr0); + aw_fel_write(usb, arm_code, sram_info->scratch_addr, sizeof(arm_code)); + aw_fel_write(usb, &ttbr0, sram_info->scratch_addr + 0x14, sizeof(ttbr0)); + aw_fel_execute(usb, sram_info->scratch_addr); +} + uint32_t aw_get_sctlr(libusb_device_handle *usb, soc_sram_info *sram_info) { uint32_t sctlr = 0; @@ -616,6 +644,20 @@ uint32_t aw_get_sctlr(libusb_device_handle *usb, soc_sram_info *sram_info) return sctlr; } +uint32_t *aw_generate_mmu_translation_table(void) +{ + uint32_t *tt = malloc(16 * 1024); + uint32_t i; + + /* The same MMU translation table as used by the A20 BROM */ + for (i = 0; i < 4096; i++) + tt[i] = 0x00000DE2 | (i << 20); + tt[0x000] |= 0x1000; + tt[0xFFF] |= 0x1000; + + return tt; +} + uint32_t *aw_backup_and_disable_mmu(libusb_device_handle *usb, soc_sram_info *sram_info) { @@ -786,6 +828,12 @@ void aw_fel_write_and_execute_spl(libusb_device_handle *usb, pr_info("Stack pointers: sp_irq=0x%08X, sp=0x%08X\n", sp_irq, sp); tt = aw_backup_and_disable_mmu(usb, sram_info); + if (!tt && sram_info->mmu_tt_addr) { + pr_info("Generating the new MMU translation table at 0x%08X\n", + sram_info->mmu_tt_addr); + tt = aw_generate_mmu_translation_table(); + aw_set_ttbr0(usb, sram_info, sram_info->mmu_tt_addr); + } swap_buffers = sram_info->swap_buffers; for (i = 0; swap_buffers[i].size; i++) { -- 2.4.10 -- You received this message because you are subscribed to the Google Groups "linux-sunxi" group. To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.