@@ -417,6 +417,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.
@@ -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 {
@@ -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
@@ -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 */
@@ -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
@@ -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);