
From: Chris Morgan macromorgan@hotmail.com
Allow RK3568 and RK3588 based boards to get the RAM bank configuration from the ROCKCHIP_TPL stage instead of the current logic. This fixes both an issue where 256MB of RAM is blocked for devices with >= 4GB of RAM and where memory holes need to be defined for devices with
= 16GB of RAM. In the event that neither SOC is used and the
ROCKCHIP_TPL stage is not used, fall back to existing logic.
Signed-off-by: Chris Morgan macromorgan@hotmail.com --- arch/arm/mach-rockchip/sdram.c | 100 +++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+)
diff --git a/arch/arm/mach-rockchip/sdram.c b/arch/arm/mach-rockchip/sdram.c index 0d9a0aef6f..e02fb03c5f 100644 --- a/arch/arm/mach-rockchip/sdram.c +++ b/arch/arm/mach-rockchip/sdram.c @@ -12,6 +12,7 @@ #include <asm/io.h> #include <asm/arch-rockchip/sdram.h> #include <dm/uclass-internal.h> +#include <linux/errno.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -35,11 +36,110 @@ struct tos_parameter_t { s64 reserve[8]; };
+/* Tag magic */ +#define ATAGS_CORE_MAGIC 0x54410001 +#define ATAGS_DDR_MEM_MAGIC 0x54410052 + +/* Tag size and offset */ +#define ATAGS_SIZE SZ_8K +#define ATAGS_OFFSET (SZ_2M - ATAGS_SIZE) +#define ATAGS_PHYS_BASE (CFG_SYS_SDRAM_BASE + ATAGS_OFFSET) + +/* ATAGS memory structure. */ +struct tag_ddr_mem { + u32 count; + u32 version; + u64 bank[20]; + u32 flags; + u32 data[2]; + u32 hash; +} __packed; + +/** + * rockchip_dram_init_banksize() - Get RAM banks from Rockchip TPL + * + * Iterate through the defined ATAGS memory location to first find a + * valid core header, then find a valid ddr_info header. Sanity check + * the number of banks found. Then, iterate through the data to add + * each individual memory bank. Perform fixups on memory banks that + * overlap with a reserved space. If an error condition is received, + * it is expected that memory bank setup will fall back on existing + * logic. If ROCKCHIP_EXTERNAL_TPL is false then immediately return, + * and if neither ROCKCHIP_RK3588 or ROCKCHIP_RK3568 is enabled + * immediately return. + * + * Return number of banks found on success or negative on error. + */ +__weak int rockchip_dram_init_banksize(void) +{ + struct tag_ddr_mem *ddr_info; + size_t val; + size_t addr = ATAGS_PHYS_BASE; + int i; + + if (!IS_ENABLED(CONFIG_ROCKCHIP_EXTERNAL_TPL)) + return 0; + if (!IS_ENABLED(CONFIG_ROCKCHIP_RK3588) && + !IS_ENABLED(CONFIG_ROCKCHIP_RK3568)) + return 0; + + if (!IS_ENABLED(CONFIG_ROCKCHIP_EXTERNAL_TPL)) + return -EPERM; + + while (addr < (ATAGS_PHYS_BASE + ATAGS_SIZE)) { + val = readl(addr); + if (val == ATAGS_CORE_MAGIC) + break; + addr += 4; + } + if (addr >= (ATAGS_PHYS_BASE + ATAGS_SIZE)) + return -ENODATA; + + while (addr < (ATAGS_PHYS_BASE + ATAGS_SIZE)) { + val = readl(addr); + if (val == ATAGS_DDR_MEM_MAGIC) + break; + addr += 4; + } + if (addr >= (ATAGS_PHYS_BASE + ATAGS_SIZE)) + return -ENODATA; + + ddr_info = (void *)addr + 4; + if (!ddr_info->count || ddr_info->count > CONFIG_NR_DRAM_BANKS) + return -ENODATA; + + for (i = 0; i < (ddr_info->count); i++) { + size_t start_addr = ddr_info->bank[i]; + size_t size = ddr_info->bank[(i + ddr_info->count)]; + size_t tmp; + + if (start_addr < SZ_2M) { + tmp = SZ_2M - start_addr; + start_addr = SZ_2M; + size = size - tmp; + } + + if (start_addr >= SDRAM_MAX_SIZE && start_addr < SZ_4G) + start_addr = SZ_4G; + + tmp = start_addr + size; + if (tmp > SDRAM_MAX_SIZE && tmp < SZ_4G) + size = SDRAM_MAX_SIZE - start_addr; + + gd->bd->bi_dram[i].start = start_addr; + gd->bd->bi_dram[i].size = size; + } + + return i; +} + int dram_init_banksize(void) { size_t ram_top = (unsigned long)(gd->ram_size + CFG_SYS_SDRAM_BASE); size_t top = min((unsigned long)ram_top, (unsigned long)(gd->ram_top));
+ if (rockchip_dram_init_banksize() > 0) + return 0; #ifdef CONFIG_ARM64 /* Reserve 0x200000 for ATF bl31 */ gd->bd->bi_dram[0].start = 0x200000;