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 <chenjh@rock-chips.com>
Change-Id: Idd5fa769e940b0618446909f8f9edc39f596f072
This commit is contained in:
Joseph Chen 2019-12-12 11:51:31 +08:00
parent 36d452911c
commit 1d09cf29cd
3 changed files with 79 additions and 16 deletions

View File

@ -14,6 +14,9 @@ struct bidram {
struct lmb lmb; struct lmb lmb;
struct list_head reserved_head; struct list_head reserved_head;
bool has_init; 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); 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 * bidram_reserved_is_overlap() - Check outside memory is overlap with reserved
* *

View File

@ -7,6 +7,7 @@
#define _MEMBLK_H #define _MEMBLK_H
#define ALIAS_COUNT_MAX 2 #define ALIAS_COUNT_MAX 2
#define MEM_RESV_COUNT 3
enum memblk_id { enum memblk_id {
MEMBLK_ID_UNK, MEMBLK_ID_UNK,
@ -47,6 +48,8 @@ struct memblk_attr {
struct memblock { struct memblock {
phys_addr_t base; phys_addr_t base;
phys_size_t size; phys_size_t size;
u64 base_u64; /* 4GB+ */
u64 size_u64;
phys_addr_t orig_base; phys_addr_t orig_base;
struct memblk_attr attr; struct memblk_attr attr;
struct list_head node; struct list_head node;

View File

@ -119,6 +119,7 @@ static int bidram_add(phys_addr_t base, phys_size_t size)
void bidram_gen_gd_bi_dram(void) void bidram_gen_gd_bi_dram(void)
{ {
struct bidram *bidram = &plat_bidram;
struct lmb *lmb = &plat_bidram.lmb; struct lmb *lmb = &plat_bidram.lmb;
struct lmb_property *mem_rgn = lmb->memory.region; struct lmb_property *mem_rgn = lmb->memory.region;
struct lmb_property *res_rgn = lmb->reserved.region; struct lmb_property *res_rgn = lmb->reserved.region;
@ -168,14 +169,50 @@ void bidram_gen_gd_bi_dram(void)
gd->bd->bi_dram[idx].start; gd->bd->bi_dram[idx].start;
} }
done: done:
for (i = 0; i < idx; i++) { /* Append 4GB+ memory blocks */
BIDRAM_D("gd bi_dram[%d]: start=0x%08lx, end=0x%08lx\n", if (bidram->fixup) {
i, (ulong)gd->bd->bi_dram[i].start, for (i = 0; i < MEM_RESV_COUNT; i++) {
(ulong)gd->bd->bi_dram[i].start + if (!bidram->size_u64[i])
(ulong)gd->bd->bi_dram[i].size); 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, static int bidram_is_overlap(phys_addr_t base1, phys_size_t size1,
phys_addr_t base2, phys_size_t size2) phys_addr_t base2, phys_size_t size2)
{ {
@ -341,7 +378,7 @@ phys_size_t bidram_get_ram_size(void)
phys_addr_t end_addr; phys_addr_t end_addr;
parse_fn_t parse_fn; parse_fn_t parse_fn;
int i, count, ret; int i, count, ret;
int bad_cnt = 0; int bad_cnt = 0, n = 0;
char bad_name[12]; char bad_name[12];
parse_fn = board_bidram_parse_fn(); parse_fn = board_bidram_parse_fn();
@ -373,19 +410,18 @@ phys_size_t bidram_get_ram_size(void)
i, (ulong)list[i].base, i, (ulong)list[i].base,
(ulong)list[i].base + (ulong)list[i].size); (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; continue;
}
/* We assume the last block gives the ram addr end */ /* We assume the last block gives the ram addr end */
if (i == count - 1) {
ram_addr_end = list[i].base + list[i].size; 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;
}
}
/* This is a bad dram bank? record it */ /* This is a bad dram bank? record it */
if (i > 0) { 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 */ /* Reserve bad dram bank after bidram_add(), treat as reserved region */
for (i = 0; i < bad_cnt; i++) { for (i = 0; i < bad_cnt; i++) {
if (gd->flags & GD_FLG_RELOC) if (gd->flags & GD_FLG_RELOC)