diff --git a/arch/arm/mach-mvebu/board-v7.c b/arch/arm/mach-mvebu/board-v7.c
index afee908..e5911de 100644
--- a/arch/arm/mach-mvebu/board-v7.c
+++ b/arch/arm/mach-mvebu/board-v7.c
@@ -230,6 +230,7 @@ DT_MACHINE_START(ARMADA_38X_DT, "Marvell Armada 380/385 (Device Tree)")
 	.l2c_aux_mask	= ~0,
 	.init_irq       = mvebu_init_irq,
 	.restart	= mvebu_restart,
+	.reserve        = mvebu_memblock_reserve,
 	.dt_compat	= armada_38x_dt_compat,
 MACHINE_END
 
diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c
index 44eedf3..caf4769 100644
--- a/arch/arm/mach-mvebu/coherency.c
+++ b/arch/arm/mach-mvebu/coherency.c
@@ -31,9 +31,11 @@
 #include <linux/mbus.h>
 #include <linux/pci.h>
 #include <asm/smp_plat.h>
+#include <asm/smp_scu.h>
 #include <asm/cacheflush.h>
 #include <asm/mach/map.h>
 #include <asm/dma-mapping.h>
+#include "common.h"
 #include "coherency.h"
 #include "mvebu-soc-id.h"
 
@@ -206,6 +208,8 @@ int set_cpu_coherent(void)
 		}
 		ll_add_cpu_to_smp_group();
 		return ll_enable_coherency();
+	} else if (type == COHERENCY_FABRIC_TYPE_ARMADA_380) {
+		scu_enable(mvebu_get_scu_base());
 	}
 
 	return 0;
diff --git a/arch/arm/mach-mvebu/pm-board.c b/arch/arm/mach-mvebu/pm-board.c
index b8c26cb..0f471fa 100644
--- a/arch/arm/mach-mvebu/pm-board.c
+++ b/arch/arm/mach-mvebu/pm-board.c
@@ -82,7 +82,8 @@ static int mvebu_armada_pm_init(void)
 	struct device_node *gpio_ctrl_np;
 	int ret = 0, i;
 
-	if (!of_machine_is_compatible("marvell,axp-gp"))
+	if (!of_machine_is_compatible("marvell,axp-gp") &&
+	    !of_machine_is_compatible("marvell,a388-gp"))
 		return -ENODEV;
 
 	np = of_find_node_by_name(NULL, "pm_pic");
diff --git a/arch/arm/mach-mvebu/pm.c b/arch/arm/mach-mvebu/pm.c
index 02fdf67..90d85ef 100644
--- a/arch/arm/mach-mvebu/pm.c
+++ b/arch/arm/mach-mvebu/pm.c
@@ -149,6 +149,45 @@ static void mvebu_pm_store_armadaxp_bootinfo(u32 *store_addr)
 	writel(BOOT_MAGIC_LIST_END, store_addr);
 }
 
+static void mvebu_pm_store_armada38x_bootinfo(u32 *store_addr)
+{
+	phys_addr_t resume_pc;
+	extern unsigned char armada_38x_mem_resume_data;
+	void *armada_38x_mem_resume_datap =
+		&armada_38x_mem_resume_data;
+
+	/*
+	 * Provide the internal register address to the resume code in
+	 * assembly. The value must be given in the native endianness
+	 * of the system, hence the usage of the raw variant.
+	 */
+	__raw_writel(mvebu_internal_reg_base(),
+		     armada_38x_mem_resume_datap);
+
+	resume_pc = virt_to_phys(armada_38x_mem_resume);
+
+	/*
+	 * The bootloader expects the first two words to be a magic
+	 * value (BOOT_MAGIC_WORD), followed by the address of the
+	 * resume code to jump to. Then, it expects a sequence of
+	 * (address, value) pairs, which can be used to restore the
+	 * value of certain registers. This sequence must end with the
+	 * BOOT_MAGIC_LIST_END magic value.
+	 */
+
+	writel(BOOT_MAGIC_WORD, store_addr++);
+	writel(resume_pc, store_addr++);
+
+	/*
+	 * We don't restore much registers here compared to Armada XP,
+	 * because we're getting out of the bootloader with MMU
+	 * enabled, so we have to disable it first in
+	 * armada_38x_mem_resume before being able to restore things.
+	 */
+
+	writel(BOOT_MAGIC_LIST_END, store_addr);
+}
+
 static int mvebu_pm_store_bootinfo(void)
 {
 	u32 *store_addr;
@@ -157,6 +196,8 @@ static int mvebu_pm_store_bootinfo(void)
 
 	if (of_machine_is_compatible("marvell,armadaxp"))
 		mvebu_pm_store_armadaxp_bootinfo(store_addr);
+	else if (of_machine_is_compatible("marvell,armada380"))
+		mvebu_pm_store_armada38x_bootinfo(store_addr);
 	else
 		return -ENODEV;
 
diff --git a/arch/arm/mach-mvebu/pmsu.h b/arch/arm/mach-mvebu/pmsu.h
index ea79269..9166e94 100644
--- a/arch/arm/mach-mvebu/pmsu.h
+++ b/arch/arm/mach-mvebu/pmsu.h
@@ -18,6 +18,7 @@ int mvebu_setup_boot_addr_wa(unsigned int crypto_eng_target,
 
 void mvebu_v7_pmsu_idle_exit(void);
 void armada_370_xp_cpu_resume(void);
+void armada_38x_mem_resume(void);
 
 int armada_370_xp_pmsu_idle_enter(unsigned long deepidle);
 int armada_38x_do_cpu_suspend(unsigned long deepidle);
diff --git a/arch/arm/mach-mvebu/pmsu_ll.S b/arch/arm/mach-mvebu/pmsu_ll.S
index 8865122..6305d80 100644
--- a/arch/arm/mach-mvebu/pmsu_ll.S
+++ b/arch/arm/mach-mvebu/pmsu_ll.S
@@ -51,6 +51,49 @@ ARM_BE8(setend	be )			@ go BE8 if entered LE
 	b	cpu_resume
 ENDPROC(armada_38x_cpu_resume)
 
+.global armada_38x_mem_resume_data
+
+#define MBUS_INTERNAL_REG_ADDRESS 0xd0020080
+
+ENTRY(armada_38x_mem_resume)
+ARM_BE8(setend	be )			@ go BE8 if entered LE
+	/* MMU disable, left enabled by the bootloader */
+	mrc	p15, 0, r1, c1, c0, 0
+	bic	r1, #1
+	mcr	p15, 0, r1, c1, c0, 0
+
+	bl      v7_invalidate_l1
+
+	/*
+	 * Load the internal register base address, we keep the value
+	 * unmodified in r1 throughout this function.
+	 */
+	adr	r1, armada_38x_mem_resume_data
+	ldr	r1, [r1]
+
+	/* Restore internal register address */
+	mov	r2, r1
+ARM_BE8(rev	r2, r2)
+	ldr	r3, =MBUS_INTERNAL_REG_ADDRESS
+	str	r2, [r3]
+
+	/* Update SCU offset CP15 register */
+	add	r2, r1, #0xC000
+	mcr  	p15, 4, r2, c15, c0, 0
+
+	/*
+	 * Disable L2 cache, left enabled by the bootloader,
+	 * it will be re-enabled later by the resume logic
+	 */
+	add	r2, r1, #0x8100
+	ldr  	r3, =0x0
+	str  	r3, [r2]
+
+	b 	cpu_resume
+armada_38x_mem_resume_data:
+	.long	.
+ENDPROC(armada_38x_mem_resume)
+
 .global mvebu_boot_wa_start
 .global mvebu_boot_wa_end
 
