diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 7a76924..33a17c7 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -373,6 +373,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 118d631..5912fa1 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,9M";
+		bootargs = "console=ttyS0,115200n8 debug earlyprintk lpj=50000 rdinit=/bin/ash rw root=/dev/ram0 initrd=0x805000000,9M";
 	};
 
 	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 5f71e66..8ea3b96 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 7c78b1e..a5f7a1a 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 a4eed57..e8aee85 100644
--- a/arch/arm/mach-keystone/keystone.c
+++ b/arch/arm/mach-keystone/keystone.c
@@ -74,6 +74,39 @@ 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 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",
+		      (u64)KEYSTONE_HIGH_PHYS_START,
+		      (u64)KEYSTONE_HIGH_PHYS_END);
+	}
+
+	set_phys_offset(KEYSTONE_HIGH_PHYS_START);
+}
+
 DT_MACHINE_START(KEYSTONE, "Keystone")
 	smp_ops(keystone_smp_ops)
 	.map_io		= keystone_map_io,
@@ -82,4 +115,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 dbe7601..b7f0724 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,30 @@ 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);
+
+	ptr = IS_ENABLED(CONFIG_ARM_LPAE) ?
+		phys_to_virt(KEYSTONE_HIGH_PHYS_START + 0x1f0) :
+		phys_to_virt(KEYSTONE_LOW_PHYS_START + 0x1f0);
+
 	ptr[cpu] = virt_to_idmap(&secondary_startup);
 	__cpuc_flush_dcache_area(ptr, sizeof(ptr) * 4);
 
