aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCyril Chemparathy <cyril@ti.com>2012-07-22 09:54:19 -0400
committerCyril Chemparathy <cyril@ti.com>2012-09-21 10:44:18 -0400
commitf815603baf99ea03f945cb84a16645d2f2a7e24b (patch)
tree66a1de3d61d103c4e7aa437e75634aebd589141e
parent4bde64d1d4c51bf44078002ab2bc223ad342f58c (diff)
downloadlinux-keystone-f815603baf99ea03f945cb84a16645d2f2a7e24b.tar.gz
ARM: keystone: add switch over to high physical address range
Keystone platforms have their physical memory mapped at an address outside the 32-bit physical range. A Keystone machine with 16G of RAM would find its memory at 0x0800000000 - 0x0bffffffff. For boot purposes, the interconnect supports a limited alias of some of this memory within the 32-bit addressable space (0x80000000 - 0xffffffff). This aliasing is implemented in hardware, and is not intended to be used much beyond boot. For instance, DMA coherence does not work when running out of this aliased address space. Therefore, we've taken the approach of booting out of the low physical address range, and subsequently we switch over to the high range once we're safely inside machine specific territory. This patch implements this switch over mechanism, which involves rewiring the TTBRs and page tables to point to the new physical address space. Signed-off-by: Vitaly Andrianov <vitalya@ti.com> Signed-off-by: Cyril Chemparathy <cyril@ti.com>
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/boot/dts/keystone-sim.dts8
-rw-r--r--arch/arm/configs/keystone_defconfig1
-rw-r--r--arch/arm/mach-keystone/include/mach/memory.h25
-rw-r--r--arch/arm/mach-keystone/keystone.c39
-rw-r--r--arch/arm/mach-keystone/platsmp.c16
6 files changed, 83 insertions, 7 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 953be107e05028..7abf18d82cffb7 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -411,6 +411,7 @@ config ARCH_KEYSTONE
select NEED_MACH_MEMORY_H
select HAVE_SCHED_CLOCK
select HAVE_SMP
+ select ZONE_DMA if ARM_LPAE
help
Support for boards based on the Texas Instruments Keystone family of
SoCs.
diff --git a/arch/arm/boot/dts/keystone-sim.dts b/arch/arm/boot/dts/keystone-sim.dts
index acec30f8e61015..17ee47385edf65 100644
--- a/arch/arm/boot/dts/keystone-sim.dts
+++ b/arch/arm/boot/dts/keystone-sim.dts
@@ -4,8 +4,8 @@
/ {
model = "Texas Instruments Keystone 2 SoC";
compatible = "ti,keystone-evm";
- #address-cells = <1>;
- #size-cells = <1>;
+ #address-cells = <2>;
+ #size-cells = <2>;
interrupt-parent = <&gic>;
aliases {
@@ -13,11 +13,11 @@
};
chosen {
- bootargs = "console=ttyS0,115200n8 debug earlyprintk lpj=50000 rdinit=/bin/ash rw root=/dev/ram0 initrd=0x85000000,2M";
+ bootargs = "console=ttyS0,115200n8 debug earlyprintk lpj=50000 rdinit=/bin/ash rw root=/dev/ram0 initrd=0x805000000,2M";
};
memory {
- reg = <0x80000000 0x8000000>;
+ reg = <0x00000008 0x00000000 0x00000000 0x8000000>;
};
cpus {
diff --git a/arch/arm/configs/keystone_defconfig b/arch/arm/configs/keystone_defconfig
index 5f71e66666bbd4..8ea3b96630730f 100644
--- a/arch/arm/configs/keystone_defconfig
+++ b/arch/arm/configs/keystone_defconfig
@@ -1,6 +1,7 @@
CONFIG_EXPERIMENTAL=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_ARCH_KEYSTONE=y
+CONFIG_ARM_LPAE=y
CONFIG_SMP=y
CONFIG_ARM_ARCH_TIMER=y
CONFIG_NR_CPUS=4
diff --git a/arch/arm/mach-keystone/include/mach/memory.h b/arch/arm/mach-keystone/include/mach/memory.h
index 7c78b1e0a6166b..a5f7a1ac75f83e 100644
--- a/arch/arm/mach-keystone/include/mach/memory.h
+++ b/arch/arm/mach-keystone/include/mach/memory.h
@@ -19,4 +19,29 @@
#define MAX_PHYSMEM_BITS 36
#define SECTION_SIZE_BITS 34
+#define KEYSTONE_LOW_PHYS_START 0x80000000ULL
+#define KEYSTONE_LOW_PHYS_SIZE 0x80000000ULL /* 2G */
+#define KEYSTONE_LOW_PHYS_END (KEYSTONE_LOW_PHYS_START + \
+ KEYSTONE_LOW_PHYS_SIZE - 1)
+
+#define KEYSTONE_HIGH_PHYS_START 0x800000000ULL
+#define KEYSTONE_HIGH_PHYS_SIZE 0x400000000ULL /* 16G */
+#define KEYSTONE_HIGH_PHYS_END (KEYSTONE_HIGH_PHYS_START + \
+ KEYSTONE_HIGH_PHYS_SIZE - 1)
+#ifdef CONFIG_ARM_LPAE
+
+#ifndef __ASSEMBLY__
+
+static inline phys_addr_t __virt_to_idmap(unsigned long x)
+{
+ return (phys_addr_t)(x) - CONFIG_PAGE_OFFSET +
+ KEYSTONE_LOW_PHYS_START;
+}
+
+#define virt_to_idmap(x) __virt_to_idmap((unsigned long)(x))
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* CONFIG_ARM_LPAE */
+
#endif /* __ASM_MACH_MEMORY_H */
diff --git a/arch/arm/mach-keystone/keystone.c b/arch/arm/mach-keystone/keystone.c
index 6a8ece98540f2a..c4be7a7ec0c2da 100644
--- a/arch/arm/mach-keystone/keystone.c
+++ b/arch/arm/mach-keystone/keystone.c
@@ -74,6 +74,41 @@ static const char *keystone_match[] __initconst = {
NULL,
};
+static void __init keystone_init_meminfo(void)
+{
+ bool lpae = IS_ENABLED(CONFIG_ARM_LPAE);
+ bool pvpatch = IS_ENABLED(CONFIG_ARM_PATCH_PHYS_VIRT);
+ phys_addr_t offset = PHYS_OFFSET - KEYSTONE_LOW_PHYS_START;
+ phys_addr_t mem_start, mem_end;
+
+ BUG_ON(meminfo.nr_banks < 1);
+ mem_start = meminfo.bank[0].start;
+ mem_end = mem_start + meminfo.bank[0].size - 1;
+
+ /* nothing to do if we are running out of the <32-bit space */
+ if (mem_start >= KEYSTONE_LOW_PHYS_START &&
+ mem_end <= KEYSTONE_LOW_PHYS_END)
+ return;
+
+ if (!lpae || !pvpatch) {
+ panic("Enable %s%s%s to run outside 32-bit space\n",
+ !lpae ? __stringify(CONFIG_ARM_LPAE) : "",
+ (!lpae && !pvpatch) ? " and " : "",
+ !pvpatch ? __stringify(CONFIG_ARM_PATCH_PHYS_VIRT) : "");
+ }
+
+ if (mem_start < KEYSTONE_HIGH_PHYS_START ||
+ mem_end > KEYSTONE_HIGH_PHYS_END) {
+ panic("Invalid address space for memory (%08llx-%08llx)\n",
+ mem_start, mem_end);
+ }
+
+ offset += KEYSTONE_HIGH_PHYS_START;
+ pr_info("switching to high address space at 0x%llx\n", offset);
+ __pv_phys_offset = offset;
+ __pv_offset = offset - PAGE_OFFSET;
+}
+
DT_MACHINE_START(KEYSTONE, "Keystone")
smp_ops(keystone_smp_ops)
.map_io = keystone_map_io,
@@ -82,4 +117,8 @@ DT_MACHINE_START(KEYSTONE, "Keystone")
.handle_irq = gic_handle_irq,
.init_machine = keystone_init,
.dt_compat = keystone_match,
+ .init_meminfo = keystone_init_meminfo,
+#ifdef CONFIG_ZONE_DMA
+ .dma_zone_size = SZ_2G,
+#endif
MACHINE_END
diff --git a/arch/arm/mach-keystone/platsmp.c b/arch/arm/mach-keystone/platsmp.c
index dbe7601171e359..015190657d5bde 100644
--- a/arch/arm/mach-keystone/platsmp.c
+++ b/arch/arm/mach-keystone/platsmp.c
@@ -24,6 +24,7 @@
#include <asm/smp_ops.h>
#include <asm/hardware/gic.h>
#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
#include <asm/memory.h>
#include "keystone.h"
@@ -51,17 +52,26 @@ static void __init keystone_smp_prepare_cpus(unsigned int max_cpus)
/* nothing for now */
}
+static void __cpuinit keystone_secondary_initmem(void)
+{
+#ifdef CONFIG_ARM_LPAE
+ pgd_t *pgd0 = pgd_offset_k(0);
+ cpu_set_ttbr(1, __pa(pgd0) + TTBR1_OFFSET);
+ local_flush_tlb_all();
+#endif
+}
+
static void __cpuinit keystone_secondary_init(unsigned int cpu)
{
gic_secondary_init(0);
+ keystone_secondary_initmem();
}
static int __cpuinit
keystone_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
- unsigned long *ptr;
-
- ptr = phys_to_virt(0x800001f0);
+ unsigned long *ptr = (unsigned long *)(PAGE_OFFSET + 0x1f0);
+
ptr[cpu] = virt_to_idmap(&secondary_startup);
__cpuc_flush_dcache_area(ptr, sizeof(ptr) * 4);