From 1d09cf29cded007e7cb3c55a78f6a0a5a3845a12 Mon Sep 17 00:00:00 2001 From: Joseph Chen Date: Thu, 12 Dec 2019 11:51:31 +0800 Subject: [PATCH] lib: bidram: add 4GB+ memory size support - On ARMv7: LPAE seems to be not friendly that brings a lot of compile errors. - On ARMv8: MMU translate table is static defined by mem_map[] and max 4GB as usual. It is not created dynamically according to real memory size, that is different from ARMv7. - 4GB memory is enough for U-Boot on both ARMv7 an ARMv8. Considering all that, we decide to make max 4GB size to be visiable for U-Boot, but still pass the real available memory size to kernel by bidram_fixup() called at late before fixup "/memory" node. Signed-off-by: Joseph Chen Change-Id: Idd5fa769e940b0618446909f8f9edc39f596f072 --- include/bidram.h | 17 +++++++++++ include/memblk.h | 3 ++ lib/bidram.c | 75 +++++++++++++++++++++++++++++++++++++----------- 3 files changed, 79 insertions(+), 16 deletions(-) diff --git a/include/bidram.h b/include/bidram.h index 4eb9ed9c75..7ba0497389 100644 --- a/include/bidram.h +++ b/include/bidram.h @@ -14,6 +14,9 @@ struct bidram { struct lmb lmb; struct list_head reserved_head; bool has_init; + bool fixup; + u64 base_u64[MEM_RESV_COUNT]; /* 4GB+ */ + u64 size_u64[MEM_RESV_COUNT]; }; /** @@ -64,6 +67,20 @@ int bidram_reserve_by_name(const char *name, phys_addr_t base, phys_size_t size) */ void bidram_dump(void); +/** + * bidram_fixup() - Fixup bi_dram[] for 4GB+ memory + * + * @return 0 on success, otherwise error + */ +int bidram_fixup(void); + +/** + * bidram_append_size() - Append 4GB+ memory + * + * @return 4GB+ size + */ +u64 bidram_append_size(void); + /** * bidram_reserved_is_overlap() - Check outside memory is overlap with reserved * diff --git a/include/memblk.h b/include/memblk.h index 15accdb17b..8254fb7a4b 100644 --- a/include/memblk.h +++ b/include/memblk.h @@ -7,6 +7,7 @@ #define _MEMBLK_H #define ALIAS_COUNT_MAX 2 +#define MEM_RESV_COUNT 3 enum memblk_id { MEMBLK_ID_UNK, @@ -47,6 +48,8 @@ struct memblk_attr { struct memblock { phys_addr_t base; phys_size_t size; + u64 base_u64; /* 4GB+ */ + u64 size_u64; phys_addr_t orig_base; struct memblk_attr attr; struct list_head node; diff --git a/lib/bidram.c b/lib/bidram.c index 5f6fac8a0a..ec563ee8b9 100644 --- a/lib/bidram.c +++ b/lib/bidram.c @@ -119,6 +119,7 @@ static int bidram_add(phys_addr_t base, phys_size_t size) void bidram_gen_gd_bi_dram(void) { + struct bidram *bidram = &plat_bidram; struct lmb *lmb = &plat_bidram.lmb; struct lmb_property *mem_rgn = lmb->memory.region; struct lmb_property *res_rgn = lmb->reserved.region; @@ -168,12 +169,48 @@ void bidram_gen_gd_bi_dram(void) gd->bd->bi_dram[idx].start; } done: - for (i = 0; i < idx; i++) { - BIDRAM_D("gd bi_dram[%d]: start=0x%08lx, end=0x%08lx\n", - i, (ulong)gd->bd->bi_dram[i].start, - (ulong)gd->bd->bi_dram[i].start + - (ulong)gd->bd->bi_dram[i].size); + /* Append 4GB+ memory blocks */ + if (bidram->fixup) { + for (i = 0; i < MEM_RESV_COUNT; i++) { + if (!bidram->size_u64[i]) + continue; + gd->bd->bi_dram[idx].start = bidram->base_u64[i]; + gd->bd->bi_dram[idx].size = bidram->size_u64[i]; + BIDRAM_D("FIXUP: gd->bi_dram[%d]: start=0x%llx, size=0x%llx\n", + idx, bidram->base_u64[i], bidram->size_u64[i]); + idx++; + } } + + for (i = 0; i < idx; i++) { + BIDRAM_D("GEN: gd->bi_dram[%d]: start=0x%llx, end=0x%llx\n", + i, (u64)gd->bd->bi_dram[i].start, + (u64)gd->bd->bi_dram[i].start + + (u64)gd->bd->bi_dram[i].size); + } +} + +int bidram_fixup(void) +{ + struct bidram *bidram = &plat_bidram; + + bidram->fixup = true; + bidram_gen_gd_bi_dram(); + + return 0; +} + +u64 bidram_append_size(void) +{ + struct bidram *bidram = &plat_bidram; + u64 size = 0; + int i; + + /* 4GB+ */ + for (i = 0; i < MEM_RESV_COUNT; i++) + size += bidram->size_u64[i]; + + return size; } static int bidram_is_overlap(phys_addr_t base1, phys_size_t size1, @@ -341,7 +378,7 @@ phys_size_t bidram_get_ram_size(void) phys_addr_t end_addr; parse_fn_t parse_fn; int i, count, ret; - int bad_cnt = 0; + int bad_cnt = 0, n = 0; char bad_name[12]; parse_fn = board_bidram_parse_fn(); @@ -373,19 +410,18 @@ phys_size_t bidram_get_ram_size(void) i, (ulong)list[i].base, (ulong)list[i].base + (ulong)list[i].size); - if (!list[i].size) + if (!list[i].size) { + /* handle 4GB+ */ + if (list[i].size_u64 && n < MEM_RESV_COUNT) { + bidram->base_u64[n] = list[i].base_u64; + bidram->size_u64[n] = list[i].size_u64; + n++; + } continue; + } /* We assume the last block gives the ram addr end */ - if (i == count - 1) { - ram_addr_end = list[i].base + list[i].size; - ret = bidram_add(CONFIG_SYS_SDRAM_BASE, - ram_addr_end - CONFIG_SYS_SDRAM_BASE); - if (ret) { - BIDRAM_E("Failed to add bidram from bi_dram[%d]\n", i); - return 0; - } - } + ram_addr_end = list[i].base + list[i].size; /* This is a bad dram bank? record it */ if (i > 0) { @@ -405,6 +441,13 @@ phys_size_t bidram_get_ram_size(void) } } + ret = bidram_add(CONFIG_SYS_SDRAM_BASE, + ram_addr_end - CONFIG_SYS_SDRAM_BASE); + if (ret) { + BIDRAM_E("Failed to add bidram from bi_dram[%d]\n", i); + return 0; + } + /* Reserve bad dram bank after bidram_add(), treat as reserved region */ for (i = 0; i < bad_cnt; i++) { if (gd->flags & GD_FLG_RELOC)