[U-Boot] [PATCH] keystone2: add high memory test

Keystone2 SOC physical DDR3 address range is outside the first 4GB and cannot be entirely accessible without MMU enabled. Only first 2GB of the physical memory have 32-bits aliased addresses. This patch adds u-boot shell command that allows to enable/disable MMU and map the 1GB of 36bits physical memory to the first 4GB address range.
Signed-off-by: Vitaly Andrianov vitalya@ti.com --- arch/arm/mach-keystone/Makefile | 3 +- arch/arm/mach-keystone/highmem.c | 162 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-keystone/highmem.c
diff --git a/arch/arm/mach-keystone/Makefile b/arch/arm/mach-keystone/Makefile index ed030db..56b6457 100644 --- a/arch/arm/mach-keystone/Makefile +++ b/arch/arm/mach-keystone/Makefile @@ -1,5 +1,5 @@ # -# (C) Copyright 2012-2014 +# (C) Copyright 2012-2015 # Texas Instruments Incorporated, <www.ti.com> # # SPDX-License-Identifier: GPL-2.0+ @@ -16,3 +16,4 @@ obj-y += cmd_mon.o obj-y += msmc.o obj-y += ddr3.o cmd_ddr3.o obj-y += keystone.o +obj-y += highmem.o diff --git a/arch/arm/mach-keystone/highmem.c b/arch/arm/mach-keystone/highmem.c new file mode 100644 index 0000000..d024e04 --- /dev/null +++ b/arch/arm/mach-keystone/highmem.c @@ -0,0 +1,162 @@ +/* + * Keystone2: High Memory Test + * + * (C) Copyright 2013-2015 + * Texas Instruments Incorporated, <www.ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +/* + * Keysone2 systems which have more then 2GB of DDR2A memory + * cannot access that memory without MMU enable. In order to test + * the entire memory we need to create MMU translation table, + * enable MMU and test the memory in portions. After the test + * we need to disable MMU. + * + * We assume that the memory size >= 2GB and u-boot code is relocated + * to the upper GB of the PA address range and the 0x80000000-0xbfffffff + * address range is available to use for testing. + * + * The code will create simple 1 level page table with 4 entries of + * 1GB blocks. The block with VA 0x80000000-0xbfffffff will be used + * to map different portions of the DDR3a. + * + */ + +#include <common.h> +#include <asm/armv7.h> + +static unsigned long long pgd_table[4] __aligned(0x1000); +static unsigned long sctlr_save; +static int mmu_enabled; + +/* Invalidate TLB */ +void my_v7_inval_tlb(void) +{ + /* Invalidate entire unified TLB */ + asm volatile ("mcr p15, 0, %0, c8, c7, 0" : : "r" (0)); + /* Invalidate entire data TLB */ + asm volatile ("mcr p15, 0, %0, c8, c6, 0" : : "r" (0)); + /* Invalidate entire instruction TLB */ + asm volatile ("mcr p15, 0, %0, c8, c5, 0" : : "r" (0)); + /* Full system DSB - make sure that the invalidation is complete */ + CP15DSB; + /* Full system ISB - make sure the instruction stream sees it */ + CP15ISB; +} + +static unsigned long enable_mmu(unsigned long long *ttbr0) +{ + unsigned long ret; + asm ( + "stmfd r13!, {r10, r11}\n" + /* set ttbr0 */ + "mov r10, %1\n" + "mov r11, #0\n" + "mcrr p15, 0, r10, r11, c2\n" + /* ttbcr = 0x80000000 */ + "mov r10, #0\n" + "orr r10, r10, #(1 << 31)\n" + "mcr p15, 0, r10, c2, c0, 2\n" + /* save current SCTLR value */ + "mrc p15, #0, r10, c1, c0, #0\n" + "mov %0, r10\n" + /* disable cache */ + "bic r10, r10,#(1 << 12)\n" + "bic r10, r10,#(1 << 2)\n" + "mcr p15, #0, r10, c1, c0, #0\n" + "isb\n" + "dsb\n" + "bl invalidate_dcache_all\n" + "bl my_v7_inval_tlb\n" + /* enable mmu */ + "mrc p15, #0, r10, c1, c0, #0\n" + "orr r10, r10,#1\n" + "mcr p15, #0, r10, c1, c0, #0\n" + "ldmfd r13!, {r10, r11}\n" + : "=r" (ret) : "r" (ttbr0) : "r10", "r11", "cc" + ); + + return ret; +} + +static void disable_mmu(unsigned long sctlr_old) +{ + asm volatile ( + "mov r10, %0\n" + "bic r10, r10,#1\n" + "mcr p15, #0, r10, c1, c0, #0\n" + : : "r" (sctlr_old) : "r10", "cc" + ); +} + + +static void pgd_table_init(void) +{ + /* + * we create identical mapping for the whole 4GB address range + * this table maps 0x0-0xffffffff VA to aliased PA range + * 0x0_0000_0000 - 0x0_ffff_ffff; + */ + + pgd_table[0] = 0x000000000000071dULL; + pgd_table[1] = 0x000000004000071dULL; + pgd_table[2] = 0x000000008000071dULL; + pgd_table[3] = 0x00000000c000071dULL; +} + +int do_highmem_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + unsigned long pgd2_pa; + unsigned long long pgd_val; + int j; + + if (argc < 2) + goto highmem_cmd_usage; + + if (strcmp(argv[1], "mmuon") == 0) { + if (mmu_enabled) { + printf("MMU already enabled\n"); + } else { + pgd_table_init(); + sctlr_save = enable_mmu(pgd_table); + mmu_enabled = 1; + printf("MMU enabled\n"); + } + } else if (strcmp(argv[1], "mmuoff") == 0) { + if (mmu_enabled == 0) { + printf("MMU already disabled\n"); + } else { + disable_mmu(sctlr_save); + mmu_enabled = 0; + printf("MMU disabled\n"); + } + } else if (strcmp(argv[1], "pgd2") == 0) { + if (argc == 3) { + pgd2_pa = simple_strtoul(argv[2], NULL, 16); + pgd_val = pgd2_pa; + pgd_val <<= 4; + pgd_val |= 0x71dull; + pgd_table[2] = pgd_val; + my_v7_inval_tlb(); + } + for (j = 0; j < 4; j++) + printf("pgd%d - 0x%016llX\n", j, pgd_table[j]); + } else { + goto highmem_cmd_usage; + } + + return 0; + +highmem_cmd_usage: + return cmd_usage(cmdtp); +} + +U_BOOT_CMD( + highmem, 3, 0, do_highmem_cmd, + "highmem test", + "highmem <mmuon|mmuoff|pgd2> [<pgd2_pa >> 4> in hex]\n" +); +

On Wed, Jul 08, 2015 at 11:51:39AM -0400, Vitaly Andrianov wrote:
Keystone2 SOC physical DDR3 address range is outside the first 4GB and cannot be entirely accessible without MMU enabled. Only first 2GB of the physical memory have 32-bits aliased addresses. This patch adds u-boot shell command that allows to enable/disable MMU and map the 1GB of 36bits physical memory to the first 4GB address range.
Signed-off-by: Vitaly Andrianov vitalya@ti.com
arch/arm/mach-keystone/Makefile | 3 +- arch/arm/mach-keystone/highmem.c | 162 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-keystone/highmem.c
The code looks reasonable. But why do we need this? Thanks.

On 07/21/2015 05:28 PM, Tom Rini wrote:
On Wed, Jul 08, 2015 at 11:51:39AM -0400, Vitaly Andrianov wrote:
Keystone2 SOC physical DDR3 address range is outside the first 4GB and cannot be entirely accessible without MMU enabled. Only first 2GB of the physical memory have 32-bits aliased addresses. This patch adds u-boot shell command that allows to enable/disable MMU and map the 1GB of 36bits physical memory to the first 4GB address range.
Signed-off-by: Vitaly Andrianov vitalya@ti.com
arch/arm/mach-keystone/Makefile | 3 +- arch/arm/mach-keystone/highmem.c | 162 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-keystone/highmem.c
The code looks reasonable. But why do we need this? Thanks.
Tom,
I added this code to test DDR3 configuration. Probably you are right. After configuration is done we don't need this code.
Thanks, -Vitaly
participants (2)
-
Tom Rini
-
Vitaly Andrianov