diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index c33364758bdb17f4aa415a9fd124d8d498d22e9d..9426302b38c92f524ab9e6c4b524dd2a45f57fc6 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -74,6 +74,7 @@ config TARGET_AT91SAM9X5EK
 config TARGET_SAMA5D2_XPLAINED
 	bool "SAMA5D2 Xplained board"
 	select CPU_V7
+	select SUPPORT_SPL
 
 config TARGET_SAMA5D3_XPLAINED
 	bool "SAMA5D3 Xplained board"
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index 5b89617623e7ed7771124e6b1ab399d9f7b47f9e..abd1d13da7e1a860f5f264ab35f48e996cac1f1e 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_AT91SAM9G20) += sdram.o spl_at91.o
 obj-$(CONFIG_AT91SAM9M10G45) += mpddrc.o spl_at91.o
 obj-$(CONFIG_AT91SAM9N12) += mpddrc.o spl_at91.o
 obj-$(CONFIG_AT91SAM9X5) += mpddrc.o spl_at91.o
+obj-$(CONFIG_SAMA5D2) += mpddrc.o spl_atmel.o matrix.o atmel_sfr.o
 obj-$(CONFIG_SAMA5D3) += mpddrc.o spl_atmel.o
 obj-$(CONFIG_SAMA5D4) += mpddrc.o spl_atmel.o matrix.o atmel_sfr.o
 obj-y += spl.o
diff --git a/arch/arm/mach-at91/include/mach/atmel_mpddrc.h b/arch/arm/mach-at91/include/mach/atmel_mpddrc.h
index c6c8dda803e9ac1499f86e7a11894ec449351147..d37d9082cdbbe7bb8c6c587cfb301c53a32fecf8 100644
--- a/arch/arm/mach-at91/include/mach/atmel_mpddrc.h
+++ b/arch/arm/mach-at91/include/mach/atmel_mpddrc.h
@@ -2,31 +2,69 @@
  * Copyright (C) 2013 Atmel Corporation
  *		      Bo Shen <voice.shen@atmel.com>
  *
+ * Copyright (C) 2015 Atmel Corporation
+ *		      Wenyou Yang <wenyou.yang@atmel.com>
+ *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
 #ifndef __ATMEL_MPDDRC_H__
 #define __ATMEL_MPDDRC_H__
 
-/*
- * Only define the needed register in mpddr
- * If other register needed, will add them later
- */
-struct atmel_mpddr {
+struct atmel_mpddrc_config {
 	u32 mr;
 	u32 rtr;
 	u32 cr;
 	u32 tpr0;
 	u32 tpr1;
 	u32 tpr2;
-	u32 reserved[2];
 	u32 md;
 };
 
+/*
+ * Only define the needed register in mpddr
+ * If other register needed, will add them later
+ */
+struct atmel_mpddr {
+	u32 mr;			/* 0x00: Mode Register */
+	u32 rtr;		/* 0x04: Refresh Timer Register */
+	u32 cr;			/* 0x08: Configuration Register */
+	u32 tpr0;		/* 0x0c: Timing Parameter 0 Register */
+	u32 tpr1;		/* 0x10: Timing Parameter 1 Register */
+	u32 tpr2;		/* 0x14: Timing Parameter 2 Register */
+	u32 reserved;		/* 0x18: Reserved */
+	u32 lpr;		/* 0x1c: Low-power Register */
+	u32 md;			/* 0x20: Memory Device Register */
+	u32 reserved1;		/* 0x24: Reserved */
+	u32 lpddr23_lpr;	/* 0x28: LPDDR2-LPDDR3 Low-power Register*/
+	u32 cal_mr4;		/* 0x2c: Calibration and MR4 Register */
+	u32 tim_cal;		/* 0x30: Timing Calibration Register */
+	u32 io_calibr;		/* 0x34: IO Calibration */
+	u32 ocms;		/* 0x38: OCMS Register */
+	u32 ocms_key1;		/* 0x3c: OCMS KEY1 Register */
+	u32 ocms_key2;		/* 0x40: OCMS KEY2 Register */
+	u32 conf_arbiter;	/* 0x44: Configuration Arbiter Register */
+	u32 timeout;		/* 0x48: Timeout Port 0/1/2/3 Register */
+	u32 req_port0123;	/* 0x4c: Request Port 0/1/2/3 Register */
+	u32 req_port4567;	/* 0x50: Request Port 4/5/6/7 Register */
+	u32 bdw_port0123;	/* 0x54: Bandwidth Port 0/1/2/3 Register */
+	u32 bdw_port4567;	/* 0x58: Bandwidth Port 4/5/6/7 Register */
+	u32 rd_data_path;	/* 0x5c: Read Datapath Register */
+	u32 reserved2[33];
+	u32 wpmr;		/* 0xe4: Write Protection Mode Register */
+	u32 wpsr;		/* 0xe8: Write Protection Status Register */
+	u32 reserved3[4];
+	u32 version;		/* 0xfc: IP version */
+};
+
 
 int ddr2_init(const unsigned int base,
 	      const unsigned int ram_address,
-	      const struct atmel_mpddr *mpddr);
+	      const struct atmel_mpddrc_config *mpddr_value);
+
+int ddr3_init(const unsigned int base,
+	      const unsigned int ram_address,
+	      const struct atmel_mpddrc_config *mpddr_value);
 
 /* Bit field in mode register */
 #define ATMEL_MPDDRC_MR_MODE_NORMAL_CMD		0x0
@@ -110,9 +148,51 @@ int ddr2_init(const unsigned int base,
 
 /* Bit field in Memory Device Register */
 #define ATMEL_MPDDRC_MD_LPDDR_SDRAM	0x3
+#define ATMEL_MPDDRC_MD_DDR3_SDRAM	0x4
+#define ATMEL_MPDDRC_MD_LPDDR3_SDRAM	0x5
 #define ATMEL_MPDDRC_MD_DDR2_SDRAM	0x6
 #define ATMEL_MPDDRC_MD_DBW_MASK	(0x1 << 4)
 #define ATMEL_MPDDRC_MD_DBW_32_BITS	(0x0 << 4)
 #define ATMEL_MPDDRC_MD_DBW_16_BITS	(0x1 << 4)
 
+/* Bit field in I/O Calibration Register */
+#define ATMEL_MPDDRC_IO_CALIBR_RDIV		0x7
+
+#define ATMEL_MPDDRC_IO_CALIBR_LPDDR2_RZQ_34_3	0x1
+#define ATMEL_MPDDRC_IO_CALIBR_LPDDR2_RZQ_40	0x2
+#define ATMEL_MPDDRC_IO_CALIBR_LPDDR2_RZQ_48	0x3
+#define ATMEL_MPDDRC_IO_CALIBR_LPDDR2_RZQ_60	0x4
+#define ATMEL_MPDDRC_IO_CALIBR_LPDDR2_RZQ_80	0x6
+#define ATMEL_MPDDRC_IO_CALIBR_LPDDR2_RZQ_120	0x7
+
+#define ATMEL_MPDDRC_IO_CALIBR_DDR2_RZQ_35	0x2
+#define ATMEL_MPDDRC_IO_CALIBR_DDR2_RZQ_43	0x3
+#define ATMEL_MPDDRC_IO_CALIBR_DDR2_RZQ_52	0x4
+#define ATMEL_MPDDRC_IO_CALIBR_DDR2_RZQ_70	0x6
+#define ATMEL_MPDDRC_IO_CALIBR_DDR2_RZQ_105	0x7
+
+#define ATMEL_MPDDRC_IO_CALIBR_DDR3_RZQ_37	0x2
+#define ATMEL_MPDDRC_IO_CALIBR_DDR3_RZQ_44	0x3
+#define ATMEL_MPDDRC_IO_CALIBR_DDR3_RZQ_55	0x4
+#define ATMEL_MPDDRC_IO_CALIBR_DDR3_RZQ_73	0x6
+#define ATMEL_MPDDRC_IO_CALIBR_DDR3_RZQ_110	0x7
+
+#define ATMEL_MPDDRC_IO_CALIBR_DDR3_RZQ_37	0x2
+#define ATMEL_MPDDRC_IO_CALIBR_DDR3_RZQ_44	0x3
+#define ATMEL_MPDDRC_IO_CALIBR_DDR3_RZQ_55	0x4
+#define ATMEL_MPDDRC_IO_CALIBR_DDR3_RZQ_73	0x6
+#define ATMEL_MPDDRC_IO_CALIBR_DDR3_RZQ_110	0x7
+
+#define ATMEL_MPDDRC_IO_CALIBR_TZQIO		0x7f
+#define ATMEL_MPDDRC_IO_CALIBR_TZQIO_(x)	(((x) & 0x7f) << 8)
+
+#define ATMEL_MPDDRC_IO_CALIBR_EN_CALIB		(0x1 << 4)
+
+/* Bit field in Read Data Path Register */
+#define ATMEL_MPDDRC_RD_DATA_PATH_SHIFT_SAMPLING	0x3
+#define ATMEL_MPDDRC_RD_DATA_PATH_NO_SHIFT		0x0
+#define ATMEL_MPDDRC_RD_DATA_PATH_SHIFT_ONE_CYCLE	0x1
+#define ATMEL_MPDDRC_RD_DATA_PATH_SHIFT_TWO_CYCLE	0x2
+#define ATMEL_MPDDRC_RD_DATA_PATH_SHIFT_THREE_CYCLE	0x3
+
 #endif
diff --git a/arch/arm/mach-at91/include/mach/sama5d2.h b/arch/arm/mach-at91/include/mach/sama5d2.h
index c85571c999eda4cc35da828e9a4fe63f5aceab3c..dd5a2a7523d8a61bed53314b8afe29f9cc6c2976 100644
--- a/arch/arm/mach-at91/include/mach/sama5d2.h
+++ b/arch/arm/mach-at91/include/mach/sama5d2.h
@@ -106,6 +106,7 @@
 #define ATMEL_BASE_MPDDRC	0xf000c000
 #define ATMEL_BASE_XDMAC0	0xf0010000
 #define ATMEL_BASE_PMC		0xf0014000
+#define ATMEL_BASE_MATRIX0	0xf0018000
 #define ATMEL_BASE_QSPI0	0xf0020000
 #define ATMEL_BASE_QSPI1	0xf0024000
 #define ATMEL_BASE_SPI0		0xf8000000
@@ -117,6 +118,7 @@
 #define ATMEL_BASE_UART1	0xf8020000
 #define ATMEL_BASE_UART2	0xf8024000
 #define ATMEL_BASE_TWI0		0xf8028000
+#define ATMEL_BASE_SFR		0xf8030000
 #define ATMEL_BASE_SYSC		0xf8048000
 #define ATMEL_BASE_SPI1		0xfc000000
 #define ATMEL_BASE_UART3	0xfc008000
@@ -125,6 +127,7 @@
 #define ATMEL_BASE_UDPHS	0xfc02c000
 
 #define ATMEL_BASE_PIOA		0xfc038000
+#define ATMEL_BASE_MATRIX1	0xfc03c000
 
 #define ATMEL_CHIPID_CIDR	0xfc069000
 #define ATMEL_CHIPID_EXID	0xfc069004
@@ -171,6 +174,35 @@
 #define CPU_HAS_PCR
 #define CPU_HAS_H32MXDIV
 
+/* AICREDIR Unlock Key */
+#define ATMEL_SFR_AICREDIR_KEY		0xB6D81C4D
+
+/* MATRIX0(H64MX) slave id definitions */
+#define H64MX_SLAVE_AXIMX_BRIDGE	0	/* Bridge from H64MX to AXIMX */
+#define H64MX_SLAVE_PERIPH_BRIDGE	1	/* H64MX Peripheral Bridge */
+#define H64MX_SLAVE_DDRC_PORT0		2	/* DDR2 Port0-AESOTF */
+#define H64MX_SLAVE_DDRC_PORT1		3	/* DDR2 Port1 */
+#define H64MX_SLAVE_DDRC_PORT2		4	/* DDR2 Port2 */
+#define H64MX_SLAVE_DDRC_PORT3		5	/* DDR2 Port3 */
+#define H64MX_SLAVE_DDRC_PORT4		6	/* DDR2 Port4 */
+#define H64MX_SLAVE_DDRC_PORT5		7	/* DDR2 Port5 */
+#define H64MX_SLAVE_DDRC_PORT6		8	/* DDR2 Port6 */
+#define H64MX_SLAVE_DDRC_PORT7		9	/* DDR2 Port7 */
+#define H64MX_SLAVE_SRAM		10	/* Internal SRAM 128K */
+#define H64MX_SLAVE_CACHE_L2		11	/* Internal SRAM 128K(L2) */
+#define H64MX_SLAVE_QSPI0		12	/* QSPI0 */
+#define H64MX_SLAVE_QSPI1		13	/* QSPI1 */
+#define H64MX_SLAVE_AESB		14	/* AESB */
+
+/* MATRIX1(H32MX) slave id definitions */
+#define H32MX_SLAVE_H64MX_BRIDGE	0	/* Bridge from H32MX to H64MX */
+#define H32MX_SLAVE_PERIPH_BRIDGE0	1	/* H32MX Peripheral Bridge 0 */
+#define H32MX_SLAVE_PERIPH_BRIDGE1	2	/* H32MX Peripheral Bridge 1 */
+#define H32MX_SLAVE_EBI			3	/* External Bus Interface */
+#define H32MX_SLAVE_NFC_CMD		3	/* NFC command Register */
+#define H32MX_SLAVE_NFC_SRAM		4	/* NFC SRAM */
+#define H32MX_SLAVE_USB			5	/* USB Device & Host */
+
 /* SAMA5D2 series chip id definitions */
 #define ARCH_ID_SAMA5D2		0x8a5c08c0
 #define ARCH_EXID_SAMA5D21CU	0x0000005a
diff --git a/arch/arm/mach-at91/mpddrc.c b/arch/arm/mach-at91/mpddrc.c
index 47e6e5a3cdc4290265b020fdcebab73d06aae9a7..16e089c3a0c3e0d254240955b8bdf8b95ec3a167 100644
--- a/arch/arm/mach-at91/mpddrc.c
+++ b/arch/arm/mach-at91/mpddrc.c
@@ -2,6 +2,9 @@
  * Copyright (C) 2013 Atmel Corporation
  *		      Bo Shen <voice.shen@atmel.com>
  *
+ * Copyright (C) 2015 Atmel Corporation
+ *		      Wenyou Yang <wenyou.yang@atmel.com>
+ *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
@@ -9,6 +12,8 @@
 #include <asm/io.h>
 #include <asm/arch/atmel_mpddrc.h>
 
+#define SAMA5D3_MPDDRC_VERSION		0x140
+
 static inline void atmel_mpddr_op(const struct atmel_mpddr *mpddr,
 	      int mode,
 	      u32 ram_address)
@@ -17,20 +22,22 @@ static inline void atmel_mpddr_op(const struct atmel_mpddr *mpddr,
 	writel(0, ram_address);
 }
 
-static int ddr2_decodtype_is_seq(u32 cr)
+static int ddr2_decodtype_is_seq(const unsigned int base, u32 cr)
 {
-#if defined(CONFIG_SAMA5D3) || defined(CONFIG_SAMA5D4) || \
-	defined(CONFIG_AT91SAM9X5) || defined(CONFIG_AT91SAM9N12)
-	if (cr & ATMEL_MPDDRC_CR_DECOD_INTERLEAVED)
+	struct atmel_mpddr *mpddr = (struct atmel_mpddr *)base;
+	u16 version = readl(&mpddr->version) & 0xffff;
+
+	if ((version >= SAMA5D3_MPDDRC_VERSION) &&
+	    (cr & ATMEL_MPDDRC_CR_DECOD_INTERLEAVED))
 		return 0;
-#endif
+
 	return 1;
 }
 
 
 int ddr2_init(const unsigned int base,
 	      const unsigned int ram_address,
-	      const struct atmel_mpddr *mpddr_value)
+	      const struct atmel_mpddrc_config *mpddr_value)
 {
 	const struct atmel_mpddr *mpddr = (struct atmel_mpddr *)base;
 
@@ -38,7 +45,7 @@ int ddr2_init(const unsigned int base,
 
 	/* Compute bank offset according to NC in configuration register */
 	ba_off = (mpddr_value->cr & ATMEL_MPDDRC_CR_NC_MASK) + 9;
-	if (ddr2_decodtype_is_seq(mpddr_value->cr))
+	if (ddr2_decodtype_is_seq(base, mpddr_value->cr))
 		ba_off += ((mpddr_value->cr & ATMEL_MPDDRC_CR_NR_MASK) >> 2) + 11;
 
 	ba_off += (mpddr_value->md & ATMEL_MPDDRC_MD_DBW_MASK) ? 1 : 2;
@@ -135,3 +142,89 @@ int ddr2_init(const unsigned int base,
 
 	return 0;
 }
+
+int ddr3_init(const unsigned int base,
+	      const unsigned int ram_address,
+	      const struct atmel_mpddrc_config *mpddr_value)
+{
+	struct atmel_mpddr *mpddr = (struct atmel_mpddr *)base;
+	u32 ba_off;
+
+	/* Compute bank offset according to NC in configuration register */
+	ba_off = (mpddr_value->cr & ATMEL_MPDDRC_CR_NC_MASK) + 9;
+	if (ddr2_decodtype_is_seq(base, mpddr_value->cr))
+		ba_off += ((mpddr_value->cr &
+			   ATMEL_MPDDRC_CR_NR_MASK) >> 2) + 11;
+
+	ba_off += (mpddr_value->md & ATMEL_MPDDRC_MD_DBW_MASK) ? 1 : 2;
+
+	/* Program the memory device type */
+	writel(mpddr_value->md, &mpddr->md);
+
+	/*
+	 * Program features of the DDR3-SDRAM device and timing parameters
+	 */
+	writel(mpddr_value->cr, &mpddr->cr);
+
+	writel(mpddr_value->tpr0, &mpddr->tpr0);
+	writel(mpddr_value->tpr1, &mpddr->tpr1);
+	writel(mpddr_value->tpr2, &mpddr->tpr2);
+
+	/* A NOP command is issued to the DDR3-SRAM */
+	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address);
+
+	/* A pause of at least 500us must be observed before a single toggle. */
+	udelay(500);
+
+	/* A NOP command is issued to the DDR3-SDRAM */
+	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address);
+
+	/*
+	 * An Extended Mode Register Set (EMRS2) cycle is issued to choose
+	 * between commercial or high temperature operations.
+	 */
+	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
+		       ram_address + (0x2 << ba_off));
+	/*
+	 * Step 7: An Extended Mode Register Set (EMRS3) cycle is issued to set
+	 * the Extended Mode Register to 0.
+	 */
+	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
+		       ram_address + (0x3 << ba_off));
+	/*
+	 * An Extended Mode Register Set (EMRS1) cycle is issued to disable and
+	 * to program O.D.S. (Output Driver Strength).
+	 */
+	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
+		       ram_address + (0x1 << ba_off));
+
+	/*
+	 * Write a one to the DLL bit (enable DLL reset) in the MPDDRC
+	 * Configuration Register.
+	 */
+
+	/* A Mode Register Set (MRS) cycle is issued to reset DLL. */
+	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_LMR_CMD, ram_address);
+
+	udelay(50);
+
+	/*
+	 * A Calibration command (MRS) is issued to calibrate RTT and RON
+	 * values for the Process Voltage Temperature (PVT).
+	 */
+	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_DEEP_CMD, ram_address);
+
+	/* A Normal Mode command is provided. */
+	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NORMAL_CMD, ram_address);
+
+	/* Perform a write access to any DDR3-SDRAM address. */
+	writel(0, ram_address);
+
+	/*
+	 * Write the refresh rate into the COUNT field in the MPDDRC
+	 * Refresh Timer Register (MPDDRC_RTR):
+	 */
+	writel(mpddr_value->rtr, &mpddr->rtr);
+
+	return 0;
+}
diff --git a/board/atmel/at91sam9m10g45ek/at91sam9m10g45ek.c b/board/atmel/at91sam9m10g45ek/at91sam9m10g45ek.c
index 2fea56ffe757f85e9a77cb5face384c90908525e..0a51fcd9aa59e3685f47713c1ba05ff34c7d4dd0 100644
--- a/board/atmel/at91sam9m10g45ek/at91sam9m10g45ek.c
+++ b/board/atmel/at91sam9m10g45ek/at91sam9m10g45ek.c
@@ -97,7 +97,7 @@ void at91_spl_board_init(void)
 }
 
 #include <asm/arch/atmel_mpddrc.h>
-static void ddr2_conf(struct atmel_mpddr *ddr2)
+static void ddr2_conf(struct atmel_mpddrc_config *ddr2)
 {
 	ddr2->md = (ATMEL_MPDDRC_MD_DBW_16_BITS | ATMEL_MPDDRC_MD_DDR2_SDRAM);
 
@@ -131,7 +131,7 @@ static void ddr2_conf(struct atmel_mpddr *ddr2)
 void mem_init(void)
 {
 	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
-	struct atmel_mpddr ddr2;
+	struct atmel_mpddrc_config ddr2;
 
 	ddr2_conf(&ddr2);
 
diff --git a/board/atmel/at91sam9n12ek/at91sam9n12ek.c b/board/atmel/at91sam9n12ek/at91sam9n12ek.c
index 59bc5350ded30826c97185d61cbe0baa64fca92c..0b0177df2b06d84ac78c80ffb3c79aa745e3e81c 100644
--- a/board/atmel/at91sam9n12ek/at91sam9n12ek.c
+++ b/board/atmel/at91sam9n12ek/at91sam9n12ek.c
@@ -274,7 +274,7 @@ void at91_spl_board_init(void)
 }
 
 #include <asm/arch/atmel_mpddrc.h>
-static void ddr2_conf(struct atmel_mpddr *ddr2)
+static void ddr2_conf(struct atmel_mpddrc_config *ddr2)
 {
 	ddr2->md = (ATMEL_MPDDRC_MD_DBW_16_BITS | ATMEL_MPDDRC_MD_DDR2_SDRAM);
 
@@ -310,7 +310,7 @@ void mem_init(void)
 {
 	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
 	struct at91_matrix *matrix = (struct at91_matrix *)ATMEL_BASE_MATRIX;
-	struct atmel_mpddr ddr2;
+	struct atmel_mpddrc_config ddr2;
 	unsigned long csa;
 
 	ddr2_conf(&ddr2);
diff --git a/board/atmel/at91sam9x5ek/at91sam9x5ek.c b/board/atmel/at91sam9x5ek/at91sam9x5ek.c
index 1738a2b3096baf7a5bd033b6ff29b92ac26146de..833e38335a24d151cbd888b30813d895575a747b 100644
--- a/board/atmel/at91sam9x5ek/at91sam9x5ek.c
+++ b/board/atmel/at91sam9x5ek/at91sam9x5ek.c
@@ -310,7 +310,7 @@ void at91_spl_board_init(void)
 }
 
 #include <asm/arch/atmel_mpddrc.h>
-static void ddr2_conf(struct atmel_mpddr *ddr2)
+static void ddr2_conf(struct atmel_mpddrc_config *ddr2)
 {
 	ddr2->md = (ATMEL_MPDDRC_MD_DBW_16_BITS | ATMEL_MPDDRC_MD_DDR2_SDRAM);
 
@@ -347,7 +347,7 @@ void mem_init(void)
 {
 	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
 	struct at91_matrix *matrix = (struct at91_matrix *)ATMEL_BASE_MATRIX;
-	struct atmel_mpddr ddr2;
+	struct atmel_mpddrc_config ddr2;
 	unsigned long csa;
 
 	ddr2_conf(&ddr2);
diff --git a/board/atmel/sama5d2_xplained/sama5d2_xplained.c b/board/atmel/sama5d2_xplained/sama5d2_xplained.c
index 0b3397fa0905a1af7893fa77223c20b0e4db429a..8ed01ddbea8753889bdea524f57f93283fae96f3 100644
--- a/board/atmel/sama5d2_xplained/sama5d2_xplained.c
+++ b/board/atmel/sama5d2_xplained/sama5d2_xplained.c
@@ -17,6 +17,7 @@
 #include <asm/arch/at91_common.h>
 #include <asm/arch/at91_pmc.h>
 #include <asm/arch/atmel_pio4.h>
+#include <asm/arch/atmel_mpddrc.h>
 #include <asm/arch/atmel_usba_udc.h>
 #include <asm/arch/atmel_sdhci.h>
 #include <asm/arch/clk.h>
@@ -281,3 +282,105 @@ int board_eth_init(bd_t *bis)
 
 	return rc;
 }
+
+/* SPL */
+#ifdef CONFIG_SPL_BUILD
+void spl_board_init(void)
+{
+#ifdef CONFIG_SYS_USE_SERIALFLASH
+	board_spi0_hw_init();
+#endif
+#ifdef CONFIG_ATMEL_SDHCI
+#ifdef CONFIG_ATMEL_SDHCI0
+	board_sdhci0_hw_init();
+#endif
+#ifdef CONFIG_ATMEL_SDHCI1
+	board_sdhci1_hw_init();
+#endif
+#endif
+}
+
+static void ddrc_conf(struct atmel_mpddrc_config *ddrc)
+{
+	ddrc->md = (ATMEL_MPDDRC_MD_DBW_32_BITS | ATMEL_MPDDRC_MD_DDR3_SDRAM);
+
+	ddrc->cr = (ATMEL_MPDDRC_CR_NC_COL_10 |
+		    ATMEL_MPDDRC_CR_NR_ROW_14 |
+		    ATMEL_MPDDRC_CR_CAS_DDR_CAS5 |
+		    ATMEL_MPDDRC_CR_DIC_DS |
+		    ATMEL_MPDDRC_CR_DIS_DLL |
+		    ATMEL_MPDDRC_CR_NB_8BANKS |
+		    ATMEL_MPDDRC_CR_DECOD_INTERLEAVED |
+		    ATMEL_MPDDRC_CR_UNAL_SUPPORTED);
+
+	ddrc->rtr = 0x511;
+
+	ddrc->tpr0 = (6 << ATMEL_MPDDRC_TPR0_TRAS_OFFSET |
+		      3 << ATMEL_MPDDRC_TPR0_TRCD_OFFSET |
+		      4 << ATMEL_MPDDRC_TPR0_TWR_OFFSET |
+		      9 << ATMEL_MPDDRC_TPR0_TRC_OFFSET |
+		      3 << ATMEL_MPDDRC_TPR0_TRP_OFFSET |
+		      4 << ATMEL_MPDDRC_TPR0_TRRD_OFFSET |
+		      4 << ATMEL_MPDDRC_TPR0_TWTR_OFFSET |
+		      4 << ATMEL_MPDDRC_TPR0_TMRD_OFFSET);
+
+	ddrc->tpr1 = (27 << ATMEL_MPDDRC_TPR1_TRFC_OFFSET |
+		      29 << ATMEL_MPDDRC_TPR1_TXSNR_OFFSET |
+		      0 << ATMEL_MPDDRC_TPR1_TXSRD_OFFSET |
+		      3 << ATMEL_MPDDRC_TPR1_TXP_OFFSET);
+
+	ddrc->tpr2 = (0 << ATMEL_MPDDRC_TPR2_TXARD_OFFSET |
+		      0 << ATMEL_MPDDRC_TPR2_TXARDS_OFFSET |
+		      0 << ATMEL_MPDDRC_TPR2_TRPA_OFFSET |
+		      4 << ATMEL_MPDDRC_TPR2_TRTP_OFFSET |
+		      7 << ATMEL_MPDDRC_TPR2_TFAW_OFFSET);
+}
+
+void mem_init(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+	struct atmel_mpddr *mpddrc = (struct atmel_mpddr *)ATMEL_BASE_MPDDRC;
+	struct atmel_mpddrc_config ddrc_config;
+	u32 reg;
+
+	ddrc_conf(&ddrc_config);
+
+	at91_periph_clk_enable(ATMEL_ID_MPDDRC);
+	writel(AT91_PMC_DDR, &pmc->scer);
+
+	reg = readl(&mpddrc->io_calibr);
+	reg &= ~ATMEL_MPDDRC_IO_CALIBR_RDIV;
+	reg |= ATMEL_MPDDRC_IO_CALIBR_DDR3_RZQ_55;
+	reg &= ~ATMEL_MPDDRC_IO_CALIBR_TZQIO;
+	reg |= ATMEL_MPDDRC_IO_CALIBR_TZQIO_(100);
+	writel(reg, &mpddrc->io_calibr);
+
+	writel(ATMEL_MPDDRC_RD_DATA_PATH_SHIFT_TWO_CYCLE,
+	       &mpddrc->rd_data_path);
+
+	ddr3_init(ATMEL_BASE_MPDDRC, ATMEL_BASE_DDRCS, &ddrc_config);
+
+	writel(0x3, &mpddrc->cal_mr4);
+	writel(64, &mpddrc->tim_cal);
+}
+
+void at91_pmc_init(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+	u32 tmp;
+
+	tmp = AT91_PMC_PLLAR_29 |
+	      AT91_PMC_PLLXR_PLLCOUNT(0x3f) |
+	      AT91_PMC_PLLXR_MUL(82) |
+	      AT91_PMC_PLLXR_DIV(1);
+	at91_plla_init(tmp);
+
+	writel(0x0 << 8, &pmc->pllicpr);
+
+	tmp = AT91_PMC_MCKR_H32MXDIV |
+	      AT91_PMC_MCKR_PLLADIV_2 |
+	      AT91_PMC_MCKR_MDIV_3 |
+	      AT91_PMC_MCKR_CSS_PLLA;
+	at91_mck_init(tmp);
+}
+#endif
diff --git a/board/atmel/sama5d3_xplained/sama5d3_xplained.c b/board/atmel/sama5d3_xplained/sama5d3_xplained.c
index 7a01149e11238f972b442cf3c8b916f7b1cfe78a..7acb8d09748aa713eb5e98d61ca2be0cd4628b9d 100644
--- a/board/atmel/sama5d3_xplained/sama5d3_xplained.c
+++ b/board/atmel/sama5d3_xplained/sama5d3_xplained.c
@@ -143,7 +143,7 @@ void spl_board_init(void)
 #endif
 }
 
-static void ddr2_conf(struct atmel_mpddr *ddr2)
+static void ddr2_conf(struct atmel_mpddrc_config *ddr2)
 {
 	ddr2->md = (ATMEL_MPDDRC_MD_DBW_32_BITS | ATMEL_MPDDRC_MD_DDR2_SDRAM);
 
@@ -185,7 +185,7 @@ static void ddr2_conf(struct atmel_mpddr *ddr2)
 void mem_init(void)
 {
 	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
-	struct atmel_mpddr ddr2;
+	struct atmel_mpddrc_config ddr2;
 
 	ddr2_conf(&ddr2);
 
diff --git a/board/atmel/sama5d3xek/sama5d3xek.c b/board/atmel/sama5d3xek/sama5d3xek.c
index 7c95f33590ed87596ca269b576171ba9bc48cb2c..0d824fc0ba16e3c62c79d0a564083df4a3999917 100644
--- a/board/atmel/sama5d3xek/sama5d3xek.c
+++ b/board/atmel/sama5d3xek/sama5d3xek.c
@@ -402,7 +402,7 @@ void spl_board_init(void)
 #endif
 }
 
-static void ddr2_conf(struct atmel_mpddr *ddr2)
+static void ddr2_conf(struct atmel_mpddrc_config *ddr2)
 {
 	ddr2->md = (ATMEL_MPDDRC_MD_DBW_32_BITS | ATMEL_MPDDRC_MD_DDR2_SDRAM);
 
@@ -444,7 +444,7 @@ static void ddr2_conf(struct atmel_mpddr *ddr2)
 void mem_init(void)
 {
 	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
-	struct atmel_mpddr ddr2;
+	struct atmel_mpddrc_config ddr2;
 
 	ddr2_conf(&ddr2);
 
diff --git a/board/atmel/sama5d4_xplained/sama5d4_xplained.c b/board/atmel/sama5d4_xplained/sama5d4_xplained.c
index db4533148049a6ffce22cff1a92e82dc5cab3d19..e2f33a3e8b3570c12f4f2766f725b60e4e2af244 100644
--- a/board/atmel/sama5d4_xplained/sama5d4_xplained.c
+++ b/board/atmel/sama5d4_xplained/sama5d4_xplained.c
@@ -346,7 +346,7 @@ void spl_board_init(void)
 #endif
 }
 
-static void ddr2_conf(struct atmel_mpddr *ddr2)
+static void ddr2_conf(struct atmel_mpddrc_config *ddr2)
 {
 	ddr2->md = (ATMEL_MPDDRC_MD_DBW_32_BITS | ATMEL_MPDDRC_MD_DDR2_SDRAM);
 
@@ -384,7 +384,7 @@ static void ddr2_conf(struct atmel_mpddr *ddr2)
 void mem_init(void)
 {
 	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
-	struct atmel_mpddr ddr2;
+	struct atmel_mpddrc_config ddr2;
 
 	ddr2_conf(&ddr2);
 
diff --git a/board/atmel/sama5d4ek/sama5d4ek.c b/board/atmel/sama5d4ek/sama5d4ek.c
index 357b223e1b0cee5a17d65318d20de019b0ced342..1799059f87ed236c1965ec8b6436646227df369a 100644
--- a/board/atmel/sama5d4ek/sama5d4ek.c
+++ b/board/atmel/sama5d4ek/sama5d4ek.c
@@ -342,7 +342,7 @@ void spl_board_init(void)
 #endif
 }
 
-static void ddr2_conf(struct atmel_mpddr *ddr2)
+static void ddr2_conf(struct atmel_mpddrc_config *ddr2)
 {
 	ddr2->md = (ATMEL_MPDDRC_MD_DBW_32_BITS | ATMEL_MPDDRC_MD_DDR2_SDRAM);
 
@@ -380,7 +380,7 @@ static void ddr2_conf(struct atmel_mpddr *ddr2)
 void mem_init(void)
 {
 	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
-	struct atmel_mpddr ddr2;
+	struct atmel_mpddrc_config ddr2;
 
 	ddr2_conf(&ddr2);
 
diff --git a/board/mini-box/picosam9g45/picosam9g45.c b/board/mini-box/picosam9g45/picosam9g45.c
index afbd6ce59988a09a99c79557790e765b11443144..193f14d75a91d7b8be1db4791b2348a78081dc1e 100644
--- a/board/mini-box/picosam9g45/picosam9g45.c
+++ b/board/mini-box/picosam9g45/picosam9g45.c
@@ -47,7 +47,7 @@ void at91_spl_board_init(void)
 }
 
 #include <asm/arch/atmel_mpddrc.h>
-static void ddr2_conf(struct atmel_mpddr *ddr2)
+static void ddr2_conf(struct atmel_mpddrc_config *ddr2)
 {
 	ddr2->md = (ATMEL_MPDDRC_MD_DBW_16_BITS | ATMEL_MPDDRC_MD_DDR2_SDRAM);
 
@@ -82,7 +82,7 @@ void mem_init(void)
 {
 	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
 	struct at91_matrix *mat = (struct at91_matrix *)ATMEL_BASE_MATRIX;
-	struct atmel_mpddr ddr2;
+	struct atmel_mpddrc_config ddr2;
 	unsigned long csa;
 
 	ddr2_conf(&ddr2);
diff --git a/board/siemens/corvus/board.c b/board/siemens/corvus/board.c
index 28985b8b08c5fd34009a2975ce6837b33cf16c1a..38c0ca3aaeb40822b5b37702929f6755826befea 100644
--- a/board/siemens/corvus/board.c
+++ b/board/siemens/corvus/board.c
@@ -114,7 +114,7 @@ void spl_board_init(void)
 }
 
 #include <asm/arch/atmel_mpddrc.h>
-static void ddr2_conf(struct atmel_mpddr *ddr2)
+static void ddr2_conf(struct atmel_mpddrc_config *ddr2)
 {
 	ddr2->md = (ATMEL_MPDDRC_MD_DBW_16_BITS | ATMEL_MPDDRC_MD_DDR2_SDRAM);
 
@@ -148,7 +148,7 @@ static void ddr2_conf(struct atmel_mpddr *ddr2)
 void mem_init(void)
 {
 	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
-	struct atmel_mpddr ddr2;
+	struct atmel_mpddrc_config ddr2;
 
 	ddr2_conf(&ddr2);
 
diff --git a/configs/sama5d2_xplained_mmc_defconfig b/configs/sama5d2_xplained_mmc_defconfig
index c1dcbefcc311b7149c49cbddc2da90351f59ce8d..75b17131beebbd50a5f84cad5c9ac2959be5de84 100644
--- a/configs/sama5d2_xplained_mmc_defconfig
+++ b/configs/sama5d2_xplained_mmc_defconfig
@@ -1,6 +1,7 @@
 CONFIG_ARM=y
 CONFIG_ARCH_AT91=y
 CONFIG_TARGET_SAMA5D2_XPLAINED=y
+CONFIG_SPL=y
 CONFIG_SYS_EXTRA_OPTIONS="SAMA5D2,SYS_USE_MMC"
 # CONFIG_CMD_IMI is not set
 # CONFIG_CMD_IMLS is not set
diff --git a/configs/sama5d2_xplained_spiflash_defconfig b/configs/sama5d2_xplained_spiflash_defconfig
index 0271e8ef8d5c15a32b1f492c67476d6cc9775710..6d61a7eb233fa7e1b7547da9e5bbb576a76ea616 100644
--- a/configs/sama5d2_xplained_spiflash_defconfig
+++ b/configs/sama5d2_xplained_spiflash_defconfig
@@ -1,6 +1,7 @@
 CONFIG_ARM=y
 CONFIG_ARCH_AT91=y
 CONFIG_TARGET_SAMA5D2_XPLAINED=y
+CONFIG_SPL=y
 CONFIG_SYS_EXTRA_OPTIONS="SAMA5D2,SYS_USE_SERIALFLASH"
 # CONFIG_CMD_IMI is not set
 # CONFIG_CMD_IMLS is not set
diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c
index da870c646ebbac06734ca1b7a840bd7b01a23806..0474a15484348917c8834a554c5b5fe9188330c5 100644
--- a/drivers/mmc/gen_atmel_mci.c
+++ b/drivers/mmc/gen_atmel_mci.c
@@ -36,6 +36,7 @@ struct atmel_mci_priv {
 	struct mmc_config	cfg;
 	struct atmel_mci	*mci;
 	unsigned int		initialized:1;
+	unsigned int		curr_clk;
 };
 
 /* Read Atmel MCI IP version */
@@ -91,7 +92,10 @@ static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen)
 
 		}
 	}
-
+	if (version >= 0x500)
+		priv->curr_clk = bus_hz / (clkdiv * 2 + clkodd + 2);
+	else
+		priv->curr_clk = (bus_hz / (clkdiv + 1)) / 2;
 	blklen &= 0xfffc;
 
 	mr = MMCI_BF(CLKDIV, clkdiv);
@@ -118,8 +122,6 @@ static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen)
 	if (mmc->card_caps & mmc->cfg->host_caps & MMC_MODE_HS)
 		writel(MMCI_BIT(HSMODE), &mci->cfg);
 
-	udelay(50);
-
 	priv->initialized = 1;
 }
 
@@ -323,6 +325,13 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 		}
 	}
 
+	/*
+	 * After the switch command, wait for 8 clocks before the next
+	 * command
+	 */
+	if (cmd->cmdidx == MMC_CMD_SWITCH)
+		udelay(8*1000000 / priv->curr_clk); /* 8 clk in us */
+
 	return 0;
 }
 
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 0d4f327ed71e2196b01e88eeaab1486f7ae0229f..7cc1de03134c52fed826ce2e51336d6e986a33d3 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -80,6 +80,7 @@ static struct nand_ecclayout atmel_pmecc_oobinfo;
  *                8-bits                13-bytes                 14-bytes
  *               12-bits                20-bytes                 21-bytes
  *               24-bits                39-bytes                 42-bytes
+ *               32-bits                52-bytes                 56-bytes
  */
 static int pmecc_get_ecc_bytes(int cap, int sector_size)
 {
@@ -638,6 +639,9 @@ static void atmel_pmecc_core_init(struct mtd_info *mtd)
 	case 24:
 		val = PMECC_CFG_BCH_ERR24;
 		break;
+	case 32:
+		val = PMECC_CFG_BCH_ERR32;
+		break;
 	}
 
 	if (host->pmecc_sector_size == 512)
@@ -676,34 +680,6 @@ static void atmel_pmecc_core_init(struct mtd_info *mtd)
 }
 
 #ifdef CONFIG_SYS_NAND_ONFI_DETECTION
-/*
- * get_onfi_ecc_param - Get ECC requirement from ONFI parameters
- * @ecc_bits: store the ONFI ECC correct bits capbility
- * @sector_size: in how many bytes that ONFI require to correct @ecc_bits
- *
- * Returns -1 if ONFI parameters is not supported. In this case @ecc_bits,
- * @sector_size are initialize to 0.
- * Return 0 if success to get the ECC requirement.
- */
-static int get_onfi_ecc_param(struct nand_chip *chip,
-		int *ecc_bits, int *sector_size)
-{
-	*ecc_bits = *sector_size = 0;
-
-	if (chip->onfi_params.ecc_bits == 0xff)
-		/* TODO: the sector_size and ecc_bits need to be find in
-		 * extended ecc parameter, currently we don't support it.
-		 */
-		return -1;
-
-	*ecc_bits = chip->onfi_params.ecc_bits;
-
-	/* The default sector size (ecc codeword size) is 512 */
-	*sector_size = 512;
-
-	return 0;
-}
-
 /*
  * pmecc_choose_ecc - Get ecc requirement from ONFI parameters. If
  *                    pmecc_corr_cap or pmecc_sector_size is 0, then set it as
@@ -724,17 +700,15 @@ static int pmecc_choose_ecc(struct atmel_nand_host *host,
 	/* Get ECC requirement from ONFI parameters */
 	*cap = *sector_size = 0;
 	if (chip->onfi_version) {
-		if (!get_onfi_ecc_param(chip, cap, sector_size)) {
-			MTDDEBUG(MTD_DEBUG_LEVEL1, "ONFI params, minimum required ECC: %d bits in %d bytes\n",
-				*cap, *sector_size);
-		} else {
-			dev_info(host->dev, "NAND chip ECC reqirement is in Extended ONFI parameter, we don't support yet.\n");
-		}
-	} else {
-		dev_info(host->dev, "NAND chip is not ONFI compliant, assume ecc_bits is 2 in 512 bytes");
+		*cap = chip->ecc_strength_ds;
+		*sector_size = chip->ecc_step_ds;
+		MTDDEBUG(MTD_DEBUG_LEVEL1, "ONFI params, minimum required ECC: %d bits in %d bytes\n",
+			 *cap, *sector_size);
 	}
+
 	if (*cap == 0 && *sector_size == 0) {
-		/* Non-ONFI compliant or use extended ONFI parameters */
+		/* Non-ONFI compliant */
+		dev_info(host->dev, "NAND chip is not ONFI compliant, assume ecc_bits is 2 in 512 bytes\n");
 		*cap = 2;
 		*sector_size = 512;
 	}
@@ -753,7 +727,11 @@ static int pmecc_choose_ecc(struct atmel_nand_host *host,
 		else if (*cap <= 24)
 			host->pmecc_corr_cap = 24;
 		else
-			return -EINVAL;
+#ifdef CONFIG_SAMA5D2
+			host->pmecc_corr_cap = 32;
+#else
+			host->pmecc_corr_cap = 24;
+#endif
 	}
 	if (host->pmecc_sector_size == 0) {
 		/* use the most fitable sector size (the near smaller one ) */
@@ -851,8 +829,8 @@ static int atmel_pmecc_nand_init_params(struct nand_chip *nand,
 	 * from ONFI.
 	 */
 	if (pmecc_choose_ecc(host, nand, &cap, &sector_size)) {
-		dev_err(host->dev, "The NAND flash's ECC requirement(ecc_bits: %d, sector_size: %d) are not support!",
-				cap, sector_size);
+		dev_err(host->dev, "Required ECC %d bits in %d bytes not supported!\n",
+			cap, sector_size);
 		return -EINVAL;
 	}
 
@@ -931,7 +909,7 @@ static int atmel_pmecc_nand_init_params(struct nand_chip *nand,
 			return -EINVAL;
 		}
 
-		if (nand->ecc.bytes > mtd->oobsize - 2) {
+		if (nand->ecc.bytes > mtd->oobsize - PMECC_OOB_RESERVED_BYTES) {
 			dev_err(host->dev, "No room for ECC bytes\n");
 			return -EINVAL;
 		}
diff --git a/drivers/mtd/nand/atmel_nand_ecc.h b/drivers/mtd/nand/atmel_nand_ecc.h
index 79e399489eac9604c5e69814b6ff6013ca9a28cf..e13f38503fa9478d7ecaea12d9c715445005a954 100644
--- a/drivers/mtd/nand/atmel_nand_ecc.h
+++ b/drivers/mtd/nand/atmel_nand_ecc.h
@@ -58,14 +58,23 @@ struct pmecc_regs {
 
 	/* 0x40 + sector_num * (0x40), Redundancy Registers */
 	struct {
+#ifdef CONFIG_SAMA5D2
+		u8 ecc[56];	/* PMECC Generated Redundancy Byte Per Sector */
+		u32 reserved1[2];
+#else
 		u8 ecc[44];	/* PMECC Generated Redundancy Byte Per Sector */
 		u32 reserved1[5];
+#endif
 	} ecc_port[PMECC_MAX_SECTOR_NUM];
 
 	/* 0x240 + sector_num * (0x40) Remainder Registers */
 	struct {
+#ifdef CONFIG_SAMA5D2
+		u32 rem[16];
+#else
 		u32 rem[12];
 		u32 reserved2[4];
+#endif
 	} rem_port[PMECC_MAX_SECTOR_NUM];
 	u32 reserved3[16];	/* 0x440-0x47C Reserved */
 };
@@ -76,6 +85,7 @@ struct pmecc_regs {
 #define		PMECC_CFG_BCH_ERR8		(2 << 0)
 #define		PMECC_CFG_BCH_ERR12		(3 << 0)
 #define		PMECC_CFG_BCH_ERR24		(4 << 0)
+#define		PMECC_CFG_BCH_ERR32		(5 << 0)
 
 #define		PMECC_CFG_SECTOR512		(0 << 4)
 #define		PMECC_CFG_SECTOR1024		(1 << 4)
@@ -120,19 +130,31 @@ struct pmecc_errloc_regs {
 	u32 elimr;	/* 0x0C Error Location Interrupt Mask Register */
 	u32 elisr;	/* 0x20 Error Location Interrupt Status Register */
 	u32 reserved0;	/* 0x24 Reserved */
+#ifdef CONFIG_SAMA5D2
+	u32 sigma[33];	/* 0x28-0xA8 Error Location Sigma Registers */
+	u32 el[32];	/* 0xAC-0x128 Error Location Registers */
+
+	/*
+	 * 0x12C-0x1FC:
+	 *   Reserved for SAMA5D2.
+	 */
+	u32 reserved1[53];
+#else
 	u32 sigma[25];	/* 0x28-0x88 Error Location Sigma Registers */
 	u32 el[24];	/* 0x8C-0xE8 Error Location Registers */
 	u32 reserved1[5];	/* 0xEC-0xFC Reserved */
+#endif
 
 	/*
-	 * 0x100-0x1F8:
-	 *   Reserved for AT91SAM9X5, AT91SAM9N12.
-	 *   HSMC registers for SAMA5D3, SAMA5D4.
+	 * SAMA5 chip HSMC registers start here. But for 9X5 chip it is just
+	 * reserved.
+	 *
+	 * Offset 0x00-0xF8:
 	 */
 	u32 reserved2[63];
 
 	/*
-	 * 0x1FC:
+	 * Offset 0xFC:
 	 *   PMECC version for AT91SAM9X5, AT91SAM9N12.
 	 *   HSMC version for SAMA5D3, SAMA5D4. Can refer as PMECC version.
 	 */
@@ -148,10 +170,16 @@ struct pmecc_errloc_regs {
 #define		PMERRLOC_DISABLE		(1 << 0)
 
 /* For Error Location Interrupt Status Register */
+#ifdef CONFIG_SAMA5D2
+#define		PMERRLOC_ERR_NUM_MASK		(0x3f << 8)
+#else
 #define		PMERRLOC_ERR_NUM_MASK		(0x1f << 8)
+#endif
+
 #define		PMERRLOC_CALC_DONE		(1 << 0)
 
 /* PMECC IP version */
+#define PMECC_VERSION_SAMA5D2			0x210
 #define PMECC_VERSION_SAMA5D4			0x113
 #define PMECC_VERSION_SAMA5D3			0x112
 #define PMECC_VERSION_AT91SAM9N12		0x102
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index a5c188066ca5822627f44e6fbc3473242d99b299..be0659a52c820165d7f7451d0fabc2f34b0c63a5 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -109,6 +109,23 @@ static int macb_is_gem(struct macb_device *macb)
 	return MACB_BFEXT(IDNUM, macb_readl(macb, MID)) == 0x2;
 }
 
+#ifndef cpu_is_sama5d2
+#define cpu_is_sama5d2() 0
+#endif
+
+#ifndef cpu_is_sama5d4
+#define cpu_is_sama5d4() 0
+#endif
+
+static int gem_is_gigabit_capable(struct macb_device *macb)
+{
+	/*
+	 * The GEM controllers embeded in SAMA5D2 and SAMA5D4 are
+	 * configured to support only 10/100.
+	 */
+	return macb_is_gem(macb) && !cpu_is_sama5d2() && !cpu_is_sama5d4();
+}
+
 static void macb_mdio_write(struct macb_device *macb, u8 reg, u16 value)
 {
 	unsigned long netctl;
@@ -480,8 +497,8 @@ static int macb_phy_init(struct macb_device *macb)
 		return 0;
 	}
 
-	/* First check for GMAC */
-	if (macb_is_gem(macb)) {
+	/* First check for GMAC and that it is GiB capable */
+	if (gem_is_gigabit_capable(macb)) {
 		lpa = macb_mdio_read(macb, MII_STAT1000);
 
 		if (lpa & (LPA_1000FULL | LPA_1000HALF)) {
diff --git a/include/configs/sama5d2_xplained.h b/include/configs/sama5d2_xplained.h
index ae5ba3dd5746baa0b84d139103830f8c7a0d75bd..272257ea0edd4f770fdcac7d6578c1eebcab0e54 100644
--- a/include/configs/sama5d2_xplained.h
+++ b/include/configs/sama5d2_xplained.h
@@ -25,8 +25,12 @@
 #define CONFIG_SYS_SDRAM_BASE           ATMEL_BASE_DDRCS
 #define CONFIG_SYS_SDRAM_SIZE		0x20000000
 
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SYS_INIT_SP_ADDR		0x210000
+#else
 #define CONFIG_SYS_INIT_SP_ADDR \
 	(CONFIG_SYS_SDRAM_BASE + 4 * 1024 - GENERATED_GBL_DATA_SIZE)
+#endif
 
 #define CONFIG_SYS_LOAD_ADDR		0x22000000 /* load address */
 
@@ -119,4 +123,39 @@
 
 #endif
 
+/* SPL */
+#define CONFIG_SPL_FRAMEWORK
+#define CONFIG_SPL_TEXT_BASE		0x200000
+#define CONFIG_SPL_MAX_SIZE		0x10000
+#define CONFIG_SPL_BSS_START_ADDR	0x20000000
+#define CONFIG_SPL_BSS_MAX_SIZE		0x80000
+#define CONFIG_SYS_SPL_MALLOC_START	0x20080000
+#define CONFIG_SYS_SPL_MALLOC_SIZE	0x80000
+
+#define CONFIG_SPL_LIBCOMMON_SUPPORT
+#define CONFIG_SPL_LIBGENERIC_SUPPORT
+#define CONFIG_SPL_GPIO_SUPPORT
+#define CONFIG_SPL_SERIAL_SUPPORT
+
+#define CONFIG_SPL_BOARD_INIT
+#define CONFIG_SYS_MONITOR_LEN		(512 << 10)
+
+#ifdef CONFIG_SYS_USE_MMC
+#define CONFIG_SPL_LDSCRIPT		arch/arm/mach-at91/armv7/u-boot-spl.lds
+#define CONFIG_SPL_MMC_SUPPORT
+#define CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS	0x400
+#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 0x200
+#define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION	1
+#define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME		"u-boot.img"
+#define CONFIG_SPL_FAT_SUPPORT
+#define CONFIG_SPL_LIBDISK_SUPPORT
+
+#elif CONFIG_SYS_USE_SERIALFLASH
+#define CONFIG_SPL_SPI_SUPPORT
+#define CONFIG_SPL_SPI_FLASH_SUPPORT
+#define CONFIG_SPL_SPI_LOAD
+#define CONFIG_SYS_SPI_U_BOOT_OFFS	0x8000
+
+#endif
+
 #endif