diff --git a/arch/arm/mach-mvebu/cpu.c b/arch/arm/mach-mvebu/cpu.c
index 38e15aa7b67b07a9b6e97e9b20deffa88a557c7c..1c5f4c3da3de81af64ec819784c9058667d21eb3 100644
--- a/arch/arm/mach-mvebu/cpu.c
+++ b/arch/arm/mach-mvebu/cpu.c
@@ -179,6 +179,46 @@ static void set_cbar(u32 addr)
 	asm("mcr p15, 4, %0, c15, c0" : : "r" (addr));
 }
 
+#define MV_USB_PHY_BASE			(MVEBU_AXP_USB_BASE + 0x800)
+#define MV_USB_PHY_PLL_REG(reg)		(MV_USB_PHY_BASE | (((reg) & 0xF) << 2))
+#define MV_USB_X3_BASE(addr)		(MVEBU_AXP_USB_BASE | BIT(11) | \
+					 (((addr) & 0xF) << 6))
+#define MV_USB_X3_PHY_CHANNEL(dev, reg)	(MV_USB_X3_BASE((dev) + 1) |	\
+					 (((reg) & 0xF) << 2))
+
+static void setup_usb_phys(void)
+{
+	int dev;
+
+	/*
+	 * USB PLL init
+	 */
+
+	/* Setup PLL frequency */
+	/* USB REF frequency = 25 MHz */
+	clrsetbits_le32(MV_USB_PHY_PLL_REG(1), 0x3ff, 0x605);
+
+	/* Power up PLL and PHY channel */
+	clrsetbits_le32(MV_USB_PHY_PLL_REG(2), 0, BIT(9));
+
+	/* Assert VCOCAL_START */
+	clrsetbits_le32(MV_USB_PHY_PLL_REG(1), 0, BIT(21));
+
+	mdelay(1);
+
+	/*
+	 * USB PHY init (change from defaults) specific for 40nm (78X30 78X60)
+	 */
+
+	for (dev = 0; dev < 3; dev++) {
+		clrsetbits_le32(MV_USB_X3_PHY_CHANNEL(dev, 3), 0, BIT(15));
+
+		/* Assert REG_RCAL_START in channel REG 1 */
+		clrsetbits_le32(MV_USB_X3_PHY_CHANNEL(dev, 1), 0, BIT(12));
+		udelay(40);
+		clrsetbits_le32(MV_USB_X3_PHY_CHANNEL(dev, 1), BIT(12), 0);
+	}
+}
 
 int arch_cpu_init(void)
 {
@@ -246,6 +286,9 @@ int arch_cpu_init(void)
 		clrsetbits_le32(ARMADA_XP_PUP_ENABLE, 0,
 				GE0_PUP_EN | GE1_PUP_EN | LCD_PUP_EN |
 				NAND_PUP_EN | SPI_PUP_EN);
+
+		/* Configure USB PLL and PHYs on AXP */
+		setup_usb_phys();
 	}
 
 	/* Enable NAND and NAND arbiter */
diff --git a/arch/arm/mach-mvebu/include/mach/soc.h b/arch/arm/mach-mvebu/include/mach/soc.h
index 6115d6e58dcd4128c5217bd879149c985d18acf8..a8a6b27d802b7c4e4dc9caa512e49b9daaf72c87 100644
--- a/arch/arm/mach-mvebu/include/mach/soc.h
+++ b/arch/arm/mach-mvebu/include/mach/soc.h
@@ -65,6 +65,7 @@
 #define MVEBU_EGIGA2_BASE	(MVEBU_REGISTER(0x30000))
 #define MVEBU_EGIGA3_BASE	(MVEBU_REGISTER(0x34000))
 #define MVEBU_REG_PCIE_BASE	(MVEBU_REGISTER(0x40000))
+#define MVEBU_AXP_USB_BASE      (MVEBU_REGISTER(0x50000))
 #define MVEBU_USB20_BASE	(MVEBU_REGISTER(0x58000))
 #define MVEBU_EGIGA0_BASE	(MVEBU_REGISTER(0x70000))
 #define MVEBU_EGIGA1_BASE	(MVEBU_REGISTER(0x74000))
diff --git a/drivers/usb/host/ehci-marvell.c b/drivers/usb/host/ehci-marvell.c
index 3a9f60f169d893917374c92bc5e3b3b9b5516ca7..fda812e94c50c61bb0b7e9c5d10d52216d1d9cb0 100644
--- a/drivers/usb/host/ehci-marvell.c
+++ b/drivers/usb/host/ehci-marvell.c
@@ -30,7 +30,14 @@ DECLARE_GLOBAL_DATA_PTR;
  */
 #ifdef CONFIG_ARMADA_XP
 
-#define MVUSB0_BASE		MVEBU_USB20_BASE
+/*
+ * Armada XP and Armada 38x have different base addresses for
+ * the USB 2.0 EHCI host controller. So we need to provide
+ * a mechnism to support both here.
+ */
+#define MVUSB0_BASE					\
+	(mvebu_soc_family() == MVEBU_SOC_A38X ?		\
+	 MVEBU_USB20_BASE : MVEBU_AXP_USB_BASE)
 
 /*
  * Once all the older Marvell SoC's (Orion, Kirkwood) are converted