thunderx: Calculate TCR dynamically

Based on the memory map we can determine a lot of hard coded fields of
TCR, like the maximum VA and max PA we want to support. Calculate those
dynamically to reduce the chance for pit falls.

Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
Alexander Graf 2016-03-04 01:09:45 +01:00 committed by Tom Rini
parent dcac8843a8
commit 0691484ac1
3 changed files with 59 additions and 9 deletions

View file

@ -38,6 +38,58 @@ static struct mm_region mem_map[] = CONFIG_SYS_MEM_MAP;
#define PTL1_ENTRIES CONFIG_SYS_PTL1_ENTRIES
#define PTL2_ENTRIES CONFIG_SYS_PTL2_ENTRIES
static u64 get_tcr(int el, u64 *pips, u64 *pva_bits)
{
u64 max_addr = 0;
u64 ips, va_bits;
u64 tcr;
int i;
/* Find the largest address we need to support */
for (i = 0; i < ARRAY_SIZE(mem_map); i++)
max_addr = max(max_addr, mem_map[i].base + mem_map[i].size);
/* Calculate the maximum physical (and thus virtual) address */
if (max_addr > (1ULL << 44)) {
ips = 5;
va_bits = 48;
} else if (max_addr > (1ULL << 42)) {
ips = 4;
va_bits = 44;
} else if (max_addr > (1ULL << 40)) {
ips = 3;
va_bits = 42;
} else if (max_addr > (1ULL << 36)) {
ips = 2;
va_bits = 40;
} else if (max_addr > (1ULL << 32)) {
ips = 1;
va_bits = 36;
} else {
ips = 0;
va_bits = 32;
}
if (el == 1) {
tcr = TCR_EL1_RSVD | (ips << 32);
} else if (el == 2) {
tcr = TCR_EL2_RSVD | (ips << 16);
} else {
tcr = TCR_EL3_RSVD | (ips << 16);
}
/* PTWs cacheable, inner/outer WBWA and inner shareable */
tcr |= TCR_TG0_64K | TCR_SHARED_INNER | TCR_ORGN_WBWA | TCR_IRGN_WBWA;
tcr |= TCR_T0SZ(VA_BITS);
if (pips)
*pips = ips;
if (pva_bits)
*pva_bits = va_bits;
return tcr;
}
static void setup_pgtables(void)
{
int l1_e, l2_e;
@ -110,6 +162,10 @@ __weak void mmu_setup(void)
/* Set up page tables only on BSP */
if (coreid == BSP_COREID)
setup_pgtables();
el = current_el();
set_ttbr_tcr_mair(el, gd->arch.tlb_addr, get_tcr(el, NULL, NULL),
MEMORY_ATTRIBUTES);
#else
/* Setup an identity-mapping for all spaces */
for (i = 0; i < (PGTABLE_SIZE >> 3); i++) {
@ -128,7 +184,6 @@ __weak void mmu_setup(void)
}
}
#endif
/* load TTBR0 */
el = current_el();
if (el == 1) {
@ -144,6 +199,8 @@ __weak void mmu_setup(void)
TCR_EL3_RSVD | TCR_FLAGS | TCR_EL3_IPS_BITS,
MEMORY_ATTRIBUTES);
}
#endif
/* enable the mmu */
set_sctlr(get_sctlr() | CR_M);
}

View file

@ -159,11 +159,6 @@
#define TCR_EL1_IPS_BITS (UL(3) << 32) /* 42 bits physical address */
#define TCR_EL2_IPS_BITS (3 << 16) /* 42 bits physical address */
#define TCR_EL3_IPS_BITS (3 << 16) /* 42 bits physical address */
#else
#define TCR_EL1_IPS_BITS CONFIG_SYS_TCR_EL1_IPS_BITS
#define TCR_EL2_IPS_BITS CONFIG_SYS_TCR_EL2_IPS_BITS
#define TCR_EL3_IPS_BITS CONFIG_SYS_TCR_EL3_IPS_BITS
#endif
/* PTWs cacheable, inner/outer WBWA and inner shareable */
#define TCR_FLAGS (TCR_TG0_64K | \
@ -171,6 +166,7 @@
TCR_ORGN_WBWA | \
TCR_IRGN_WBWA | \
TCR_T0SZ(VA_BITS))
#endif
#define TCR_EL1_RSVD (1 << 31)
#define TCR_EL2_RSVD (1 << 31 | 1 << 23)

View file

@ -50,9 +50,6 @@
#define CONFIG_SYS_PGTABLE_SIZE \
((CONFIG_SYS_PTL1_ENTRIES + \
CONFIG_SYS_MEM_MAP_SIZE * CONFIG_SYS_PTL2_ENTRIES) * 8)
#define CONFIG_SYS_TCR_EL1_IPS_BITS (5UL << 32)
#define CONFIG_SYS_TCR_EL2_IPS_BITS (5 << 16)
#define CONFIG_SYS_TCR_EL3_IPS_BITS (5 << 16)
/* Link Definitions */
#define CONFIG_SYS_TEXT_BASE 0x00500000