From f2ccf7f7aacf75bd9c521459d1d20df07d1ebe41 Mon Sep 17 00:00:00 2001 From: York Sun Date: Mon, 6 Mar 2017 09:02:24 -0800 Subject: armv8: Add global variable resv_ram Use gd->arch.resv_ram to track reserved memory allocation. Signed-off-by: York Sun Reviewed-by: Simon Glass --- arch/arm/cpu/armv8/fsl-layerscape/Kconfig | 10 ++++++++++ arch/arm/include/asm/global_data.h | 7 +++++++ 2 files changed, 17 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig index b5609ff7a6..b8b9cd58c4 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig +++ b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig @@ -277,6 +277,16 @@ config SYS_FSL_SDHC_CLK_DIV clock, in another word SDHC_clk = Platform_clk / this_divider. endmenu +config RESV_RAM + bool + help + Reserve memory from the top, tracked by gd->arch.resv_ram. This + reserved RAM can be used by special driver that resides in memory + after U-Boot exits. It's up to implementation to allocate and allow + access to this reserved memory. For example, the reserved RAM can + be at the high end of physical memory. The reserve RAM may be + excluded from memory bank(s) passed to OS, or marked as reserved. + config SYS_FSL_ERRATUM_A008336 bool diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h index aee87cdcbf..dfcbcceba3 100644 --- a/arch/arm/include/asm/global_data.h +++ b/arch/arm/include/asm/global_data.h @@ -59,6 +59,13 @@ struct arch_global_data { phys_addr_t secure_ram; unsigned long tlb_allocated; #endif +#ifdef CONFIG_RESV_RAM + /* + * Reserved RAM for memory resident, eg. Management Complex (MC) + * driver which continues to run after U-Boot exits. + */ + phys_addr_t resv_ram; +#endif #ifdef CONFIG_ARCH_OMAP2 u32 omap_boot_device; -- cgit From e243b6e1fa37376278488c374052040f04a833ea Mon Sep 17 00:00:00 2001 From: York Sun Date: Mon, 6 Mar 2017 09:02:25 -0800 Subject: armv8: ls2080a: Move CONFIG_FSL_MC_ENET to Kconfig Use Kconfig option instead of config macro in header file. Clean up existing usage. Signed-off-by: York Sun --- arch/arm/cpu/armv8/fsl-layerscape/Kconfig | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig index b8b9cd58c4..1a8a345dcc 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig +++ b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig @@ -89,6 +89,14 @@ config FSL_LSCH3 select SYS_FSL_SRDS_1 select SYS_HAS_SERDES +config FSL_MC_ENET + bool "Management Complex network" + depends on ARCH_LS2080A + default y + select RESV_RAM + help + Enable Management Complex (MC) network + menu "Layerscape architecture" depends on FSL_LSCH2 || FSL_LSCH3 -- cgit From f692d4eef4999f5c8b9287a0faa7bd6eee809532 Mon Sep 17 00:00:00 2001 From: York Sun Date: Mon, 6 Mar 2017 09:02:26 -0800 Subject: armv8: ls2080a: Move CONFIG_SYS_MC_RSV_MEM_ALIGN to Kconfig Use Kconfig option instead of config macro in header file. Signed-off-by: York Sun --- arch/arm/cpu/armv8/fsl-layerscape/Kconfig | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig index 1a8a345dcc..a99b1c6a99 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig +++ b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig @@ -315,3 +315,11 @@ config SYS_FSL_ERRATUM_A009660 config SYS_FSL_ERRATUM_A009929 bool + +config SYS_MC_RSV_MEM_ALIGN + hex "Management Complex reserved memory alignment" + depends on RESV_RAM + default 0x20000000 + help + Reserved memory needs to be aligned for MC to use. Default value + is 512MB. -- cgit From 36cc0de0b919c0e185739142742e0a76a7c5c30a Mon Sep 17 00:00:00 2001 From: York Sun Date: Mon, 6 Mar 2017 09:02:28 -0800 Subject: armv8: layerscape: Rewrite memory reservation For ARMv8 Layerscape SoCs, secure memory and MC memorey are reserved at the end of DDR. DDR is spit into two or three banks. This patch reverts commit aabd7ddb and simplifies the calculation of reserved memory, and moves the code into common SoC file. Secure memory is carved out first. DDR bank size is reduced. Reserved memory is then allocated on the top of available memory. U-Boot still has access to reserved memory as data transferring is needed. Device tree is fixed with reduced memory size to hide the reserved memory from OS. The same region is reserved for efi_loader. Signed-off-by: York Sun --- arch/arm/cpu/armv8/fsl-layerscape/cpu.c | 198 +++++++++++++++++++++- arch/arm/include/asm/arch-fsl-layerscape/config.h | 4 +- 2 files changed, 194 insertions(+), 8 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c index 335f225181..d0be335b2f 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c @@ -524,15 +524,201 @@ phys_size_t board_reserve_ram_top(phys_size_t ram_size) { phys_size_t ram_top = ram_size; -#ifdef CONFIG_SYS_MEM_TOP_HIDE -#error CONFIG_SYS_MEM_TOP_HIDE not to be used together with this function -#endif - -/* Carve the MC private DRAM block from the end of DRAM */ #ifdef CONFIG_FSL_MC_ENET + /* The start address of MC reserved memory needs to be aligned. */ ram_top -= mc_get_dram_block_size(); ram_top &= ~(CONFIG_SYS_MC_RSV_MEM_ALIGN - 1); #endif - return ram_top; + return ram_size - ram_top; +} + +phys_size_t get_effective_memsize(void) +{ + phys_size_t ea_size, rem = 0; + + /* + * For ARMv8 SoCs, DDR memory is split into two or three regions. The + * first region is 2GB space at 0x8000_0000. If the memory extends to + * the second region (or the third region if applicable), the secure + * memory and Management Complex (MC) memory should be put into the + * highest region, i.e. the end of DDR memory. CONFIG_MAX_MEM_MAPPED + * is set to the size of first region so U-Boot doesn't relocate itself + * into higher address. Should DDR be configured to skip the first + * region, this function needs to be adjusted. + */ + if (gd->ram_size > CONFIG_MAX_MEM_MAPPED) { + ea_size = CONFIG_MAX_MEM_MAPPED; + rem = gd->ram_size - ea_size; + } else { + ea_size = gd->ram_size; + } + +#ifdef CONFIG_SYS_MEM_RESERVE_SECURE + /* Check if we have enough space for secure memory */ + if (rem > CONFIG_SYS_MEM_RESERVE_SECURE) { + rem -= CONFIG_SYS_MEM_RESERVE_SECURE; + } else { + if (ea_size > CONFIG_SYS_MEM_RESERVE_SECURE) { + ea_size -= CONFIG_SYS_MEM_RESERVE_SECURE; + rem = 0; /* Presume MC requires more memory */ + } else { + printf("Error: No enough space for secure memory.\n"); + } + } +#endif + /* Check if we have enough memory for MC */ + if (rem < board_reserve_ram_top(rem)) { + /* Not enough memory in high region to reserve */ + if (ea_size > board_reserve_ram_top(rem)) + ea_size -= board_reserve_ram_top(rem); + else + printf("Error: No enough space for reserved memory.\n"); + } + + return ea_size; +} + +void dram_init_banksize(void) +{ +#ifdef CONFIG_SYS_DP_DDR_BASE_PHY + phys_size_t dp_ddr_size; +#endif + + /* + * gd->ram_size has the total size of DDR memory, less reserved secure + * memory. The DDR extends from low region to high region(s) presuming + * no hole is created with DDR configuration. gd->arch.secure_ram tracks + * the location of secure memory. gd->arch.resv_ram tracks the location + * of reserved memory for Management Complex (MC). + */ + gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; + if (gd->ram_size > CONFIG_SYS_DDR_BLOCK1_SIZE) { + gd->bd->bi_dram[0].size = CONFIG_SYS_DDR_BLOCK1_SIZE; + gd->bd->bi_dram[1].start = CONFIG_SYS_DDR_BLOCK2_BASE; + gd->bd->bi_dram[1].size = gd->ram_size - + CONFIG_SYS_DDR_BLOCK1_SIZE; +#ifdef CONFIG_SYS_DDR_BLOCK3_BASE + if (gd->bi_dram[1].size > CONFIG_SYS_DDR_BLOCK2_SIZE) { + gd->bd->bi_dram[2].start = CONFIG_SYS_DDR_BLOCK3_BASE; + gd->bd->bi_dram[2].size = gd->bd->bi_dram[1].size - + CONFIG_SYS_DDR_BLOCK2_SIZE; + gd->bd->bi_dram[1].size = CONFIG_SYS_DDR_BLOCK2_SIZE; + } +#endif + } else { + gd->bd->bi_dram[0].size = gd->ram_size; + } +#ifdef CONFIG_SYS_MEM_RESERVE_SECURE +#ifdef CONFIG_SYS_DDR_BLOCK3_BASE + if (gd->bd->bi_dram[2].size >= CONFIG_SYS_MEM_RESERVE_SECURE) { + gd->bd->bi_dram[2].size -= CONFIG_SYS_MEM_RESERVE_SECURE; + gd->arch.secure_ram = gd->bd->bi_dram[2].start + + gd->bd->bi_dram[2].size; + gd->arch.secure_ram |= MEM_RESERVE_SECURE_MAINTAINED; + gd->ram_size -= CONFIG_SYS_MEM_RESERVE_SECURE; + } else +#endif + { + if (gd->bd->bi_dram[1].size >= CONFIG_SYS_MEM_RESERVE_SECURE) { + gd->bd->bi_dram[1].size -= + CONFIG_SYS_MEM_RESERVE_SECURE; + gd->arch.secure_ram = gd->bd->bi_dram[1].start + + gd->bd->bi_dram[1].size; + gd->arch.secure_ram |= MEM_RESERVE_SECURE_MAINTAINED; + gd->ram_size -= CONFIG_SYS_MEM_RESERVE_SECURE; + } else if (gd->bd->bi_dram[0].size > + CONFIG_SYS_MEM_RESERVE_SECURE) { + gd->bd->bi_dram[0].size -= + CONFIG_SYS_MEM_RESERVE_SECURE; + gd->arch.secure_ram = gd->bd->bi_dram[0].start + + gd->bd->bi_dram[0].size; + gd->arch.secure_ram |= MEM_RESERVE_SECURE_MAINTAINED; + gd->ram_size -= CONFIG_SYS_MEM_RESERVE_SECURE; + } + } +#endif /* CONFIG_SYS_MEM_RESERVE_SECURE */ + +#ifdef CONFIG_FSL_MC_ENET + /* Assign memory for MC */ +#ifdef CONFIG_SYS_DDR_BLOCK3_BASE + if (gd->bd->bi_dram[2].size >= + board_reserve_ram_top(gd->bd->bi_dram[2].size)) { + gd->arch.resv_ram = gd->bd->bi_dram[2].start + + gd->bd->bi_dram[2].size - + board_reserve_ram_top(gd->bd->bi_dram[2].size); + } else +#endif + { + if (gd->bd->bi_dram[1].size >= + board_reserve_ram_top(gd->bd->bi_dram[1].size)) { + gd->arch.resv_ram = gd->bd->bi_dram[1].start + + gd->bd->bi_dram[1].size - + board_reserve_ram_top(gd->bd->bi_dram[1].size); + } else if (gd->bd->bi_dram[0].size > + board_reserve_ram_top(gd->bd->bi_dram[0].size)) { + gd->arch.resv_ram = gd->bd->bi_dram[0].start + + gd->bd->bi_dram[0].size - + board_reserve_ram_top(gd->bd->bi_dram[0].size); + } + } +#endif /* CONFIG_FSL_MC_ENET */ + +#ifdef CONFIG_SYS_DP_DDR_BASE_PHY +#ifdef CONFIG_SYS_DDR_BLOCK3_BASE +#error "This SoC shouldn't have DP DDR" +#endif + if (soc_has_dp_ddr()) { + /* initialize DP-DDR here */ + puts("DP-DDR: "); + /* + * DDR controller use 0 as the base address for binding. + * It is mapped to CONFIG_SYS_DP_DDR_BASE for core to access. + */ + dp_ddr_size = fsl_other_ddr_sdram(CONFIG_SYS_DP_DDR_BASE_PHY, + CONFIG_DP_DDR_CTRL, + CONFIG_DP_DDR_NUM_CTRLS, + CONFIG_DP_DDR_DIMM_SLOTS_PER_CTLR, + NULL, NULL, NULL); + if (dp_ddr_size) { + gd->bd->bi_dram[2].start = CONFIG_SYS_DP_DDR_BASE; + gd->bd->bi_dram[2].size = dp_ddr_size; + } else { + puts("Not detected"); + } + } +#endif +} + +#if defined(CONFIG_EFI_LOADER) && !defined(CONFIG_SPL_BUILD) +void efi_add_known_memory(void) +{ + int i; + phys_addr_t ram_start, start; + phys_size_t ram_size; + u64 pages; + + /* Add RAM */ + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { +#ifdef CONFIG_SYS_DP_DDR_BASE_PHY +#ifdef CONFIG_SYS_DDR_BLOCK3_BASE +#error "This SoC shouldn't have DP DDR" +#endif + if (i == 2) + continue; /* skip DP-DDR */ +#endif + ram_start = gd->bd->bi_dram[i].start; + ram_size = gd->bd->bi_dram[i].size; +#ifdef CONFIG_RESV_RAM + if (gd->arch.resv_ram >= ram_start && + gd->arch.resv_ram < ram_start + ram_size) + ram_size = gd->arch.resv_ram - ram_start; +#endif + start = (ram_start + EFI_PAGE_MASK) & ~EFI_PAGE_MASK; + pages = (ram_size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT; + + efi_add_memory_map(start, pages, EFI_CONVENTIONAL_MEMORY, + false); + } } +#endif diff --git a/arch/arm/include/asm/arch-fsl-layerscape/config.h b/arch/arm/include/asm/arch-fsl-layerscape/config.h index 586ce17215..b5b08aae23 100644 --- a/arch/arm/include/asm/arch-fsl-layerscape/config.h +++ b/arch/arm/include/asm/arch-fsl-layerscape/config.h @@ -33,8 +33,8 @@ #define CONFIG_SYS_FSL_OCRAM_SIZE 0x00020000 /* Real size 128K */ /* DDR */ -#define CONFIG_SYS_LS2_DDR_BLOCK1_SIZE ((phys_size_t)2 << 30) -#define CONFIG_MAX_MEM_MAPPED CONFIG_SYS_LS2_DDR_BLOCK1_SIZE +#define CONFIG_SYS_DDR_BLOCK1_SIZE ((phys_size_t)2 << 30) +#define CONFIG_MAX_MEM_MAPPED CONFIG_SYS_DDR_BLOCK1_SIZE #define CONFIG_SYS_FSL_CCSR_GUR_LE #define CONFIG_SYS_FSL_CCSR_SCFG_LE -- cgit From 24f55496a40fc2903a3737563c52b952d9a25332 Mon Sep 17 00:00:00 2001 From: York Sun Date: Mon, 6 Mar 2017 09:02:30 -0800 Subject: armv8: layerscape: Update MMU mapping with actual DDR size Update mapping with actual DDR size. Non-existing memory should not be mapped as "normal" memory to avoid speculative access. Signed-off-by: York Sun --- arch/arm/cpu/armv8/fsl-layerscape/cpu.c | 42 +++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c index d0be335b2f..368bdcdb88 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c @@ -101,12 +101,50 @@ static inline void final_mmu_setup(void) { u64 tlb_addr_save = gd->arch.tlb_addr; unsigned int el = current_el(); -#ifdef CONFIG_SYS_MEM_RESERVE_SECURE int index; -#endif mem_map = final_map; + /* Update mapping for DDR to actual size */ + for (index = 0; index < ARRAY_SIZE(final_map) - 2; index++) { + /* + * Find the entry for DDR mapping and update the address and + * size. Zero-sized mapping will be skipped when creating MMU + * table. + */ + switch (final_map[index].virt) { + case CONFIG_SYS_FSL_DRAM_BASE1: + final_map[index].virt = gd->bd->bi_dram[0].start; + final_map[index].phys = gd->bd->bi_dram[0].start; + final_map[index].size = gd->bd->bi_dram[0].size; + break; +#ifdef CONFIG_SYS_FSL_DRAM_BASE2 + case CONFIG_SYS_FSL_DRAM_BASE2: +#if (CONFIG_NR_DRAM_BANKS >= 2) + final_map[index].virt = gd->bd->bi_dram[1].start; + final_map[index].phys = gd->bd->bi_dram[1].start; + final_map[index].size = gd->bd->bi_dram[1].size; +#else + final_map[index].size = 0; +#endif + break; +#endif +#ifdef CONFIG_SYS_FSL_DRAM_BASE3 + case CONFIG_SYS_FSL_DRAM_BASE3: +#if (CONFIG_NR_DRAM_BANKS >= 3) + final_map[index].virt = gd->bd->bi_dram[2].start; + final_map[index].phys = gd->bd->bi_dram[2].start; + final_map[index].size = gd->bd->bi_dram[2].size; +#else + final_map[index].size = 0; +#endif + break; +#endif + default: + break; + } + } + #ifdef CONFIG_SYS_MEM_RESERVE_SECURE if (gd->arch.secure_ram & MEM_RESERVE_SECURE_MAINTAINED) { if (el == 3) { -- cgit From a045a0c33330f4b38b198651901c96829619e60b Mon Sep 17 00:00:00 2001 From: York Sun Date: Mon, 6 Mar 2017 09:02:31 -0800 Subject: armv8: layerscape: Fix the sequence of changing MMU table This patch follows the break-before-make process when making changes to MMU table. MMU is disabled before changing TTBR to avoid any potential race condition. Signed-off-by: York Sun --- arch/arm/cpu/armv8/fsl-layerscape/cpu.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c index 368bdcdb88..d82f6d1b82 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c @@ -181,21 +181,14 @@ static inline void final_mmu_setup(void) setup_pgtables(); gd->arch.tlb_addr = tlb_addr_save; - /* flush new MMU table */ - flush_dcache_range(gd->arch.tlb_addr, - gd->arch.tlb_addr + gd->arch.tlb_size); + /* Disable cache and MMU */ + dcache_disable(); /* TLBs are invalidated */ + invalidate_icache_all(); /* point TTBR to the new table */ set_ttbr_tcr_mair(el, gd->arch.tlb_addr, get_tcr(el, NULL, NULL), MEMORY_ATTRIBUTES); - /* - * EL3 MMU is already enabled, just need to invalidate TLB to load the - * new table. The new table is compatible with the current table, if - * MMU somehow walks through the new table before invalidation TLB, - * it still works. So we don't need to turn off MMU here. - * When EL2 MMU table is created by calling this function, MMU needs - * to be enabled. - */ + set_sctlr(get_sctlr() | CR_M); } -- cgit From f539c8a4a7a590e1933a7e21d5771528db1d88b7 Mon Sep 17 00:00:00 2001 From: York Sun Date: Mon, 6 Mar 2017 09:02:32 -0800 Subject: armv8: ls2080a: Drop early MMU for SPL build Early MMU improves performance especially on emulators. However, the early MMU is left enabled after the first stage of SPL boot. Instead of flushing D-cache and dealing with re-enabling MMU for the second stage U-Boot, disabling it for SPL build simplifies the process. The performance penalty is unnoticeable on the real hardware. As of now, SPL boot is not supported by existing emulators. So this should have no impact on emulators. Signed-off-by: York Sun --- arch/arm/cpu/armv8/fsl-layerscape/spl.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/cpu/armv8/fsl-layerscape/spl.c b/arch/arm/cpu/armv8/fsl-layerscape/spl.c index 1dabdbb305..73a8680741 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/spl.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/spl.c @@ -45,9 +45,6 @@ void board_init_f(ulong dummy) { /* Clear global data */ memset((void *)gd, 0, sizeof(gd_t)); -#ifdef CONFIG_LS2080A - arch_cpu_init(); -#endif board_early_init_f(); timer_init(); #ifdef CONFIG_LS2080A -- cgit From 7f9b9f318ff152bd8d2e8b573708e2bdc088c1b1 Mon Sep 17 00:00:00 2001 From: York Sun Date: Mon, 6 Mar 2017 09:02:33 -0800 Subject: armv8: mmu: Add a function to change mapping attributes Function mmu_change_region_attr() is added to change existing mapping with updated PXN, UXN and memory type. This is a break-before-make process during which the mapping becomes fault (invalid) before final attributres are set. Signed-off-by: York Sun --- arch/arm/cpu/armv8/cache_v8.c | 72 +++++++++++++++++++++++++++++++++++++--- arch/arm/include/asm/armv8/mmu.h | 5 +++ arch/arm/include/asm/system.h | 1 + 3 files changed, 74 insertions(+), 4 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c index 6c5630c0a8..bd1c3e0335 100644 --- a/arch/arm/cpu/armv8/cache_v8.c +++ b/arch/arm/cpu/armv8/cache_v8.c @@ -501,7 +501,8 @@ static bool is_aligned(u64 addr, u64 size, u64 align) return !(addr & (align - 1)) && !(size & (align - 1)); } -static u64 set_one_region(u64 start, u64 size, u64 attrs, int level) +/* Use flag to indicate if attrs has more than d-cache attributes */ +static u64 set_one_region(u64 start, u64 size, u64 attrs, bool flag, int level) { int levelshift = level2shift(level); u64 levelsize = 1ULL << levelshift; @@ -509,8 +510,13 @@ static u64 set_one_region(u64 start, u64 size, u64 attrs, int level) /* Can we can just modify the current level block PTE? */ if (is_aligned(start, size, levelsize)) { - *pte &= ~PMD_ATTRINDX_MASK; - *pte |= attrs; + if (flag) { + *pte &= ~PMD_ATTRMASK; + *pte |= attrs & PMD_ATTRMASK; + } else { + *pte &= ~PMD_ATTRINDX_MASK; + *pte |= attrs & PMD_ATTRINDX_MASK; + } debug("Set attrs=%llx pte=%p level=%d\n", attrs, pte, level); return levelsize; @@ -560,7 +566,8 @@ void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size, u64 r; for (level = 1; level < 4; level++) { - r = set_one_region(start, size, attrs, level); + /* Set d-cache attributes only */ + r = set_one_region(start, size, attrs, false, level); if (r) { /* PTE successfully replaced */ size -= r; @@ -581,6 +588,63 @@ void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size, flush_dcache_range(real_start, real_start + real_size); } +/* + * Modify MMU table for a region with updated PXN/UXN/Memory type/valid bits. + * The procecess is break-before-make. The target region will be marked as + * invalid during the process of changing. + */ +void mmu_change_region_attr(phys_addr_t addr, size_t siz, u64 attrs) +{ + int level; + u64 r, size, start; + + start = addr; + size = siz; + /* + * Loop through the address range until we find a page granule that fits + * our alignment constraints, then set it to "invalid". + */ + while (size > 0) { + for (level = 1; level < 4; level++) { + /* Set PTE to fault */ + r = set_one_region(start, size, PTE_TYPE_FAULT, true, + level); + if (r) { + /* PTE successfully invalidated */ + size -= r; + start += r; + break; + } + } + } + + flush_dcache_range(gd->arch.tlb_addr, + gd->arch.tlb_addr + gd->arch.tlb_size); + __asm_invalidate_tlb_all(); + + /* + * Loop through the address range until we find a page granule that fits + * our alignment constraints, then set it to the new cache attributes + */ + start = addr; + size = siz; + while (size > 0) { + for (level = 1; level < 4; level++) { + /* Set PTE to new attributes */ + r = set_one_region(start, size, attrs, true, level); + if (r) { + /* PTE successfully updated */ + size -= r; + start += r; + break; + } + } + } + flush_dcache_range(gd->arch.tlb_addr, + gd->arch.tlb_addr + gd->arch.tlb_size); + __asm_invalidate_tlb_all(); +} + #else /* CONFIG_SYS_DCACHE_OFF */ /* diff --git a/arch/arm/include/asm/armv8/mmu.h b/arch/arm/include/asm/armv8/mmu.h index e9b4cdbbcd..a34990368e 100644 --- a/arch/arm/include/asm/armv8/mmu.h +++ b/arch/arm/include/asm/armv8/mmu.h @@ -53,6 +53,7 @@ #define PTE_TYPE_FAULT (0 << 0) #define PTE_TYPE_TABLE (3 << 0) #define PTE_TYPE_BLOCK (1 << 0) +#define PTE_TYPE_VALID (1 << 0) #define PTE_TABLE_PXN (1UL << 59) #define PTE_TABLE_XN (1UL << 60) @@ -77,6 +78,10 @@ */ #define PMD_ATTRINDX(t) ((t) << 2) #define PMD_ATTRINDX_MASK (7 << 2) +#define PMD_ATTRMASK (PTE_BLOCK_PXN | \ + PTE_BLOCK_UXN | \ + PMD_ATTRINDX_MASK | \ + PTE_TYPE_VALID) /* * TCR flags. diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 766e929d46..9c3261c884 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -226,6 +226,7 @@ void protect_secure_region(void); void smp_kick_all_cpus(void); void flush_l3_cache(void); +void mmu_change_region_attr(phys_addr_t start, size_t size, u64 attrs); /* *Issue a secure monitor call in accordance with ARM "SMC Calling convention", -- cgit From 4961eafc25d0bfa7ac5f88ec78a7f7501c202fbb Mon Sep 17 00:00:00 2001 From: York Sun Date: Mon, 6 Mar 2017 09:02:34 -0800 Subject: armv8: layerscape: Update early MMU for DDR after initialization In early MMU table, DDR has to be mapped as device memory to avoid speculative access. After DDR is initialized, it needs to be updated to normal memory to allow code execution. To simplify the code, dram_init() is moved into a common file as a weak function. Signed-off-by: York Sun --- arch/arm/cpu/armv8/fsl-layerscape/cpu.c | 76 ++++++++++++++++++++++++++ arch/arm/include/asm/arch-fsl-layerscape/cpu.h | 12 +++- arch/arm/include/asm/arch-fsl-layerscape/mmu.h | 2 +- 3 files changed, 87 insertions(+), 3 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c index d82f6d1b82..7e66ee08b5 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c @@ -753,3 +753,79 @@ void efi_add_known_memory(void) } } #endif + +/* + * Before DDR size is known, early MMU table have DDR mapped as device memory + * to avoid speculative access. To relocate U-Boot to DDR, "normal memory" + * needs to be set for these mappings. + * If a special case configures DDR with holes in the mapping, the holes need + * to be marked as invalid. This is not implemented in this function. + */ +void update_early_mmu_table(void) +{ + if (!gd->arch.tlb_addr) + return; + + if (gd->ram_size <= CONFIG_SYS_FSL_DRAM_SIZE1) { + mmu_change_region_attr( + CONFIG_SYS_SDRAM_BASE, + gd->ram_size, + PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_OUTER_SHARE | + PTE_BLOCK_NS | + PTE_TYPE_VALID); + } else { + mmu_change_region_attr( + CONFIG_SYS_SDRAM_BASE, + CONFIG_SYS_DDR_BLOCK1_SIZE, + PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_OUTER_SHARE | + PTE_BLOCK_NS | + PTE_TYPE_VALID); +#ifdef CONFIG_SYS_DDR_BLOCK3_BASE +#ifndef CONFIG_SYS_DDR_BLOCK2_SIZE +#error "Missing CONFIG_SYS_DDR_BLOCK2_SIZE" +#endif + if (gd->ram_size - CONFIG_SYS_DDR_BLOCK1_SIZE > + CONFIG_SYS_DDR_BLOCK2_SIZE) { + mmu_change_region_attr( + CONFIG_SYS_DDR_BLOCK2_BASE, + CONFIG_SYS_DDR_BLOCK2_SIZE, + PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_OUTER_SHARE | + PTE_BLOCK_NS | + PTE_TYPE_VALID); + mmu_change_region_attr( + CONFIG_SYS_DDR_BLOCK3_BASE, + gd->ram_size - + CONFIG_SYS_DDR_BLOCK1_SIZE - + CONFIG_SYS_DDR_BLOCK2_SIZE, + PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_OUTER_SHARE | + PTE_BLOCK_NS | + PTE_TYPE_VALID); + } else +#endif + { + mmu_change_region_attr( + CONFIG_SYS_DDR_BLOCK2_BASE, + gd->ram_size - + CONFIG_SYS_DDR_BLOCK1_SIZE, + PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_OUTER_SHARE | + PTE_BLOCK_NS | + PTE_TYPE_VALID); + } + } +} + +__weak int dram_init(void) +{ + gd->ram_size = initdram(0); +#if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD) + /* This will break-before-make MMU for DDR */ + update_early_mmu_table(); +#endif + + return 0; +} diff --git a/arch/arm/include/asm/arch-fsl-layerscape/cpu.h b/arch/arm/include/asm/arch-fsl-layerscape/cpu.h index 4ea4aeaf4c..bcf3e3863e 100644 --- a/arch/arm/include/asm/arch-fsl-layerscape/cpu.h +++ b/arch/arm/include/asm/arch-fsl-layerscape/cpu.h @@ -115,7 +115,11 @@ static struct mm_region early_map[] = { }, { CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_SIZE1, +#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD) PTE_BLOCK_MEMTYPE(MT_NORMAL) | +#else /* Start with nGnRnE and PXN and UXN to prevent speculative access */ + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_PXN | PTE_BLOCK_UXN | +#endif PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS }, /* Map IFC region #2 up to CONFIG_SYS_FLASH_BASE for NAND boot */ @@ -130,7 +134,7 @@ static struct mm_region early_map[] = { }, { CONFIG_SYS_FSL_DRAM_BASE2, CONFIG_SYS_FSL_DRAM_BASE2, CONFIG_SYS_FSL_DRAM_SIZE2, - PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_PXN | PTE_BLOCK_UXN | PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS }, #elif defined(CONFIG_FSL_LSCH2) @@ -158,12 +162,16 @@ static struct mm_region early_map[] = { }, { CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_SIZE1, +#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD) PTE_BLOCK_MEMTYPE(MT_NORMAL) | +#else /* Start with nGnRnE and PXN and UXN to prevent speculative access */ + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_PXN | PTE_BLOCK_UXN | +#endif PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS }, { CONFIG_SYS_FSL_DRAM_BASE2, CONFIG_SYS_FSL_DRAM_BASE2, CONFIG_SYS_FSL_DRAM_SIZE2, - PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_PXN | PTE_BLOCK_UXN | PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS }, #endif diff --git a/arch/arm/include/asm/arch-fsl-layerscape/mmu.h b/arch/arm/include/asm/arch-fsl-layerscape/mmu.h index d54eacd4a0..d232bec1e4 100644 --- a/arch/arm/include/asm/arch-fsl-layerscape/mmu.h +++ b/arch/arm/include/asm/arch-fsl-layerscape/mmu.h @@ -6,5 +6,5 @@ #ifndef _ASM_ARMV8_FSL_LAYERSCAPE_MMU_H_ #define _ASM_ARMV8_FSL_LAYERSCAPE_MMU_H_ -#include +void update_early_mmu_table(void); #endif /* _ASM_ARMV8_FSL_LAYERSCAPE_MMU_H_ */ -- cgit From dffb4931fdba5d98133a80b719622bacc8524655 Mon Sep 17 00:00:00 2001 From: Tang Yuantian Date: Tue, 7 Feb 2017 14:18:59 +0800 Subject: armv8: fsl-lsch2: add workaround for erratum A-010635 Read DMA operations causes CRC error on armv8 chassis 2 platforms due to the erratum A-010635. In order to support sata on these platforms, ECC needs to be disabled. Signed-off-by: Tang Yuantian Reviewed-by: York Sun --- arch/arm/cpu/armv8/fsl-layerscape/soc.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/cpu/armv8/fsl-layerscape/soc.c b/arch/arm/cpu/armv8/fsl-layerscape/soc.c index 9489f85c64..b54a937971 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/soc.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/soc.c @@ -233,10 +233,8 @@ int sata_init(void) { struct ccsr_ahci __iomem *ccsr_ahci = (void *)CONFIG_SYS_SATA; -#ifdef CONFIG_ARCH_LS1046A /* Disable SATA ECC */ out_le32((void *)CONFIG_SYS_DCSR_DCFG_ADDR + 0x520, 0x80000000); -#endif out_le32(&ccsr_ahci->ppcfg, AHCI_PORT_PHY_1_CFG); out_le32(&ccsr_ahci->ptc, AHCI_PORT_TRANS_CFG); out_le32(&ccsr_ahci->axicc, AHCI_PORT_AXICC_CFG); -- cgit From 27f133bbcf2c06b9b74e8694fb08a8cf7249496d Mon Sep 17 00:00:00 2001 From: Priyanka Jain Date: Thu, 19 Jan 2017 11:12:26 +0530 Subject: armv8: fsl-layerscape: Updates DCFG register map Based on latest hardware documentation, update ccsr_gur structure (represents DCFG register map) Signed-off-by: Priyanka Jain Signed-off-by: Arpit Goel Reviewed-by: York Sun --- .../include/asm/arch-fsl-layerscape/immap_lsch3.h | 65 +++++++++++++++------- 1 file changed, 46 insertions(+), 19 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h b/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h index 43ae686a29..9e6b5e3c19 100644 --- a/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h +++ b/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h @@ -177,21 +177,23 @@ struct ccsr_gur { u8 res_008[0x20-0x8]; u32 gpporcr1; /* General-purpose POR configuration */ u32 gpporcr2; /* General-purpose POR configuration 2 */ + u32 gpporcr3; + u32 gpporcr4; + u8 res_030[0x60-0x30]; #define FSL_CHASSIS3_DCFG_FUSESR_VID_SHIFT 25 #define FSL_CHASSIS3_DCFG_FUSESR_VID_MASK 0x1F #define FSL_CHASSIS3_DCFG_FUSESR_ALTVID_SHIFT 20 #define FSL_CHASSIS3_DCFG_FUSESR_ALTVID_MASK 0x1F u32 dcfg_fusesr; /* Fuse status register */ - u32 gpporcr3; - u32 gpporcr4; - u8 res_034[0x70-0x34]; - u32 devdisr; /* Device disable control */ + u8 res_064[0x70-0x64]; + u32 devdisr; /* Device disable control 1 */ u32 devdisr2; /* Device disable control 2 */ u32 devdisr3; /* Device disable control 3 */ u32 devdisr4; /* Device disable control 4 */ u32 devdisr5; /* Device disable control 5 */ u32 devdisr6; /* Device disable control 6 */ - u32 devdisr7; /* Device disable control 7 */ + u8 res_088[0x94-0x88]; + u32 coredisr; /* Device disable control 7 */ #define FSL_CHASSIS3_DEVDISR2_DPMAC1 0x00000001 #define FSL_CHASSIS3_DEVDISR2_DPMAC2 0x00000002 #define FSL_CHASSIS3_DEVDISR2_DPMAC3 0x00000004 @@ -216,15 +218,11 @@ struct ccsr_gur { #define FSL_CHASSIS3_DEVDISR2_DPMAC22 0x00200000 #define FSL_CHASSIS3_DEVDISR2_DPMAC23 0x00400000 #define FSL_CHASSIS3_DEVDISR2_DPMAC24 0x00800000 - u8 res_08c[0x90-0x8c]; - u32 coredisru; /* uppper portion for support of 64 cores */ - u32 coredisrl; /* lower portion for support of 64 cores */ u8 res_098[0xa0-0x98]; u32 pvr; /* Processor version */ u32 svr; /* System version */ - u32 mvr; /* Manufacturing version */ - u8 res_0ac[0x100-0xac]; - u32 rcwsr[32]; /* Reset control word status */ + u8 res_0a8[0x100-0xa8]; + u32 rcwsr[30]; /* Reset control word status */ #define FSL_CHASSIS3_RCWSR0_SYS_PLL_RAT_SHIFT 2 #define FSL_CHASSIS3_RCWSR0_SYS_PLL_RAT_MASK 0x1f @@ -239,24 +237,53 @@ struct ccsr_gur { #define RCW_SB_EN_REG_INDEX 9 #define RCW_SB_EN_MASK 0x00000400 - u8 res_180[0x200-0x180]; - u32 scratchrw[32]; /* Scratch Read/Write */ - u8 res_280[0x300-0x280]; + u8 res_178[0x200-0x178]; + u32 scratchrw[16]; /* Scratch Read/Write */ + u8 res_240[0x300-0x240]; u32 scratchw1r[4]; /* Scratch Read (Write once) */ u8 res_310[0x400-0x310]; u32 bootlocptrl; /* Boot location pointer low-order addr */ u32 bootlocptrh; /* Boot location pointer high-order addr */ - u8 res_408[0x500-0x408]; - u8 res_500[0x740-0x500]; /* add more registers when needed */ + u8 res_408[0x520-0x408]; + u32 usb1_amqr; + u32 usb2_amqr; + u8 res_528[0x530-0x528]; /* add more registers when needed */ + u32 sdmm1_amqr; + u8 res_534[0x550-0x534]; /* add more registers when needed */ + u32 sata1_amqr; + u32 sata2_amqr; + u8 res_558[0x570-0x558]; /* add more registers when needed */ + u32 misc1_amqr; + u8 res_574[0x590-0x574]; /* add more registers when needed */ + u32 spare1_amqr; + u32 spare2_amqr; + u8 res_598[0x620-0x598]; /* add more registers when needed */ + u32 gencr[7]; /* General Control Registers */ + u8 res_63c[0x640-0x63c]; /* add more registers when needed */ + u32 cgensr1; /* Core General Status Register */ + u8 res_644[0x660-0x644]; /* add more registers when needed */ + u32 cgencr1; /* Core General Control Register */ + u8 res_664[0x740-0x664]; /* add more registers when needed */ u32 tp_ityp[64]; /* Topology Initiator Type Register */ struct { u32 upper; u32 lower; - } tp_cluster[3]; /* Core Cluster n Topology Register */ - u8 res_858[0x1000-0x858]; + } tp_cluster[4]; /* Core cluster n Topology Register */ + u8 res_864[0x920-0x864]; /* add more registers when needed */ + u32 ioqoscr[8]; /*I/O Quality of Services Register */ + u32 uccr; + u8 res_944[0x960-0x944]; /* add more registers when needed */ + u32 ftmcr; + u8 res_964[0x990-0x964]; /* add more registers when needed */ + u32 coredisablesr; + u8 res_994[0xa00-0x994]; /* add more registers when needed */ + u32 sdbgcr; /*Secure Debug Confifuration Register */ + u8 res_a04[0xbf8-0xa04]; /* add more registers when needed */ + u32 ipbrr1; + u32 ipbrr2; + u8 res_858[0x1000-0xc00]; }; - struct ccsr_clk_cluster_group { struct { u8 res_00[0x10]; -- cgit From 29ca713cc1cfb84b6d1b485859479e81a1479188 Mon Sep 17 00:00:00 2001 From: Priyanka Jain Date: Thu, 19 Jan 2017 11:12:27 +0530 Subject: armv8: fsl-lsch3: Update VID support VID support in NXP layerscape Chassis-3 (lsch3) compilant SoCs like LS2088A, LS2080A differs from existing logic. -VDD voltage array is different -Registers are different -VDD calculation logic is different Add new function adjust_vdd() for LSCH3 compliant SoCs Signed-off-by: Priyanka Jain Signed-off-by: Arpit Goel Reviewed-by: York Sun --- arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h b/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h index 9e6b5e3c19..08ea8fb8ef 100644 --- a/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h +++ b/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h @@ -180,9 +180,9 @@ struct ccsr_gur { u32 gpporcr3; u32 gpporcr4; u8 res_030[0x60-0x30]; -#define FSL_CHASSIS3_DCFG_FUSESR_VID_SHIFT 25 +#define FSL_CHASSIS3_DCFG_FUSESR_VID_SHIFT 2 #define FSL_CHASSIS3_DCFG_FUSESR_VID_MASK 0x1F -#define FSL_CHASSIS3_DCFG_FUSESR_ALTVID_SHIFT 20 +#define FSL_CHASSIS3_DCFG_FUSESR_ALTVID_SHIFT 7 #define FSL_CHASSIS3_DCFG_FUSESR_ALTVID_MASK 0x1F u32 dcfg_fusesr; /* Fuse status register */ u8 res_064[0x70-0x64]; -- cgit From 9b6639fa85bddd90df4c371f25a89c791a6ee6ef Mon Sep 17 00:00:00 2001 From: Vinitha Pillai Date: Wed, 1 Feb 2017 18:28:53 +0530 Subject: LS1021ATWR: Modify u-boot size for sd secure boot Raw uboot image is used in place of FIT image in secure boot. The maximum allocated size of raw u-boot bin is 1MB in memory map. Hence , CONFIG_SYS_MONITOR_LEN has been modified to 1 MB. The bootscript (BS_ADDR) and its header (BS_HDR_ADDR) offset on MMC have also been modified to accommodate the increase in uboot size. Signed-off-by: Vinitha Pillai-B57223 Reviewed-by: Sumit Garg Reviewed-by: Ruchika Gupta Reviewed-by: Prabhakar Kushwaha Reviewed-by: York Sun --- arch/arm/include/asm/fsl_secure_boot.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/include/asm/fsl_secure_boot.h b/arch/arm/include/asm/fsl_secure_boot.h index ccb513fba2..fd627c0874 100644 --- a/arch/arm/include/asm/fsl_secure_boot.h +++ b/arch/arm/include/asm/fsl_secure_boot.h @@ -86,8 +86,8 @@ /* For SD boot address and size are assigned in terms of sector * offset and no. of sectors respectively. */ -#define CONFIG_BS_HDR_ADDR_DEVICE 0x00000800 -#define CONFIG_BS_ADDR_DEVICE 0x00000840 +#define CONFIG_BS_HDR_ADDR_DEVICE 0x00000900 +#define CONFIG_BS_ADDR_DEVICE 0x00000940 #define CONFIG_BS_HDR_SIZE 0x00000010 #define CONFIG_BS_SIZE 0x00000008 #else -- cgit