diff --git a/arch/arm/dts/sama5d2.dtsi b/arch/arm/dts/sama5d2.dtsi
index 19feb6609dbf8205110c3903c9257d11b63cb6c8..a881d9e05c071772b6b00c54f87e0f728fc73c8e 100644
--- a/arch/arm/dts/sama5d2.dtsi
+++ b/arch/arm/dts/sama5d2.dtsi
@@ -79,7 +79,7 @@
 					#clock-cells = <0>;
 				};
 
-				plla: pllack {
+				plla: pllack@0 {
 					compatible = "atmel,sama5d3-clk-pll";
 					#clock-cells = <0>;
 					clocks = <&main>;
@@ -146,17 +146,17 @@
 					interrupt-parent = <&pmc>;
 					clocks = <&main>, <&plladiv>, <&utmi>, <&mck>;
 
-					prog0: prog0 {
+					prog0: prog@0 {
 						#clock-cells = <0>;
 						reg = <0>;
 					};
 
-					prog1: prog1 {
+					prog1: prog@1 {
 						#clock-cells = <0>;
 						reg = <1>;
 					};
 
-					prog2: prog2 {
+					prog2: prog@2 {
 						#clock-cells = <0>;
 						reg = <2>;
 					};
@@ -167,49 +167,49 @@
 					#address-cells = <1>;
 					#size-cells = <0>;
 
-					ddrck: ddrck {
+					ddrck: ddrck@2 {
 						#clock-cells = <0>;
 						reg = <2>;
 						clocks = <&mck>;
 					};
 
-					lcdck: lcdck {
+					lcdck: lcdck@3 {
 						#clock-cells = <0>;
 						reg = <3>;
 						clocks = <&mck>;
 					};
 
-					uhpck: uhpck {
+					uhpck: uhpck@6 {
 						#clock-cells = <0>;
 						reg = <6>;
 						clocks = <&usb>;
 					};
 
-					udpck: udpck {
+					udpck: udpck@7 {
 						#clock-cells = <0>;
 						reg = <7>;
 						clocks = <&usb>;
 					};
 
-					pck0: pck0 {
+					pck0: pck0@8 {
 						#clock-cells = <0>;
 						reg = <8>;
 						clocks = <&prog0>;
 					};
 
-					pck1: pck1 {
+					pck1: pck1@9 {
 						#clock-cells = <0>;
 						reg = <9>;
 						clocks = <&prog1>;
 					};
 
-					pck2: pck2 {
+					pck2: pck2@10 {
 						#clock-cells = <0>;
 						reg = <10>;
 						clocks = <&prog2>;
 					};
 
-					iscck: iscck {
+					iscck: iscck@18 {
 						#clock-cells = <0>;
 						reg = <18>;
 						clocks = <&mck>;
@@ -222,203 +222,203 @@
 					#size-cells = <0>;
 					clocks = <&h32ck>;
 
-					macb0_clk: macb0_clk {
+					macb0_clk: macb0_clk@5 {
 						#clock-cells = <0>;
 						reg = <5>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					tdes_clk: tdes_clk {
+					tdes_clk: tdes_clk@11 {
 						#clock-cells = <0>;
 						reg = <11>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					matrix1_clk: matrix1_clk {
+					matrix1_clk: matrix1_clk@14 {
 						#clock-cells = <0>;
 						reg = <14>;
 					};
 
-					hsmc_clk: hsmc_clk {
+					hsmc_clk: hsmc_clk@17 {
 						#clock-cells = <0>;
 						reg = <17>;
 					};
 
-					pioA_clk: pioA_clk {
+					pioA_clk: pioA_clk@18 {
 						#clock-cells = <0>;
 						reg = <18>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					flx0_clk: flx0_clk {
+					flx0_clk: flx0_clk@19 {
 						#clock-cells = <0>;
 						reg = <19>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					flx1_clk: flx1_clk {
+					flx1_clk: flx1_clk@20 {
 						#clock-cells = <0>;
 						reg = <20>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					flx2_clk: flx2_clk {
+					flx2_clk: flx2_clk@21 {
 						#clock-cells = <0>;
 						reg = <21>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					flx3_clk: flx3_clk {
+					flx3_clk: flx3_clk@22 {
 						#clock-cells = <0>;
 						reg = <22>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					flx4_clk: flx4_clk {
+					flx4_clk: flx4_clk@23 {
 						#clock-cells = <0>;
 						reg = <23>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					uart0_clk: uart0_clk {
+					uart0_clk: uart0_clk@24 {
 						#clock-cells = <0>;
 						reg = <24>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					uart1_clk: uart1_clk {
+					uart1_clk: uart1_clk@25 {
 						#clock-cells = <0>;
 						reg = <25>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					uart2_clk: uart2_clk {
+					uart2_clk: uart2_clk@26 {
 						#clock-cells = <0>;
 						reg = <26>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					uart3_clk: uart3_clk {
+					uart3_clk: uart3_clk@27 {
 						#clock-cells = <0>;
 						reg = <27>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					uart4_clk: uart4_clk {
+					uart4_clk: uart4_clk@28 {
 						#clock-cells = <0>;
 						reg = <28>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					twi0_clk: twi0_clk {
+					twi0_clk: twi0_clk@29 {
 						reg = <29>;
 						#clock-cells = <0>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					twi1_clk: twi1_clk {
+					twi1_clk: twi1_clk@30 {
 						#clock-cells = <0>;
 						reg = <30>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					spi0_clk: spi0_clk {
+					spi0_clk: spi0_clk@33 {
 						#clock-cells = <0>;
 						reg = <33>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					spi1_clk: spi1_clk {
+					spi1_clk: spi1_clk@34 {
 						#clock-cells = <0>;
 						reg = <34>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					tcb0_clk: tcb0_clk {
+					tcb0_clk: tcb0_clk@35 {
 						#clock-cells = <0>;
 						reg = <35>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					tcb1_clk: tcb1_clk {
+					tcb1_clk: tcb1_clk@36 {
 						#clock-cells = <0>;
 						reg = <36>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					pwm_clk: pwm_clk {
+					pwm_clk: pwm_clk@38 {
 						#clock-cells = <0>;
 						reg = <38>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					adc_clk: adc_clk {
+					adc_clk: adc_clk@40 {
 						#clock-cells = <0>;
 						reg = <40>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					uhphs_clk: uhphs_clk {
+					uhphs_clk: uhphs_clk@41 {
 						#clock-cells = <0>;
 						reg = <41>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					udphs_clk: udphs_clk {
+					udphs_clk: udphs_clk@42 {
 						#clock-cells = <0>;
 						reg = <42>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					ssc0_clk: ssc0_clk {
+					ssc0_clk: ssc0_clk@43 {
 						#clock-cells = <0>;
 						reg = <43>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					ssc1_clk: ssc1_clk {
+					ssc1_clk: ssc1_clk@44 {
 						#clock-cells = <0>;
 						reg = <44>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					trng_clk: trng_clk {
+					trng_clk: trng_clk@47 {
 						#clock-cells = <0>;
 						reg = <47>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					pdmic_clk: pdmic_clk {
+					pdmic_clk: pdmic_clk@48 {
 						#clock-cells = <0>;
 						reg = <48>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					i2s0_clk: i2s0_clk {
+					i2s0_clk: i2s0_clk@54 {
 						#clock-cells = <0>;
 						reg = <54>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					i2s1_clk: i2s1_clk {
+					i2s1_clk: i2s1_clk@55 {
 						#clock-cells = <0>;
 						reg = <55>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					can0_clk: can0_clk {
+					can0_clk: can0_clk@56 {
 						#clock-cells = <0>;
 						reg = <56>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					can1_clk: can1_clk {
+					can1_clk: can1_clk@57 {
 						#clock-cells = <0>;
 						reg = <57>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					classd_clk: classd_clk {
+					classd_clk: classd_clk@59 {
 						#clock-cells = <0>;
 						reg = <59>;
 						atmel,clk-output-range = <0 83000000>;
@@ -431,67 +431,67 @@
 					#size-cells = <0>;
 					clocks = <&mck>;
 
-					dma0_clk: dma0_clk {
+					dma0_clk: dma0_clk@6 {
 						#clock-cells = <0>;
 						reg = <6>;
 					};
 
-					dma1_clk: dma1_clk {
+					dma1_clk: dma1_clk@7 {
 						#clock-cells = <0>;
 						reg = <7>;
 					};
 
-					aes_clk: aes_clk {
+					aes_clk: aes_clk@9 {
 						#clock-cells = <0>;
 						reg = <9>;
 					};
 
-					aesb_clk: aesb_clk {
+					aesb_clk: aesb_clk@10 {
 						#clock-cells = <0>;
 						reg = <10>;
 					};
 
-					sha_clk: sha_clk {
+					sha_clk: sha_clk@12 {
 						#clock-cells = <0>;
 						reg = <12>;
 					};
 
-					mpddr_clk: mpddr_clk {
+					mpddr_clk: mpddr_clk@13 {
 						#clock-cells = <0>;
 						reg = <13>;
 					};
 
-					matrix0_clk: matrix0_clk {
+					matrix0_clk: matrix0_clk@15 {
 						#clock-cells = <0>;
 						reg = <15>;
 					};
 
-					sdmmc0_hclk: sdmmc0_hclk {
+					sdmmc0_hclk: sdmmc0_hclk@31 {
 						#clock-cells = <0>;
 						reg = <31>;
 					};
 
-					sdmmc1_hclk: sdmmc1_hclk {
+					sdmmc1_hclk: sdmmc1_hclk@32 {
 						#clock-cells = <0>;
 						reg = <32>;
 					};
 
-					lcdc_clk: lcdc_clk {
+					lcdc_clk: lcdc_clk@45 {
 						#clock-cells = <0>;
 						reg = <45>;
 					};
 
-					isc_clk: isc_clk {
+					isc_clk: isc_clk@46 {
 						#clock-cells = <0>;
 						reg = <46>;
 					};
 
-					qspi0_clk: qspi0_clk {
+					qspi0_clk: qspi0_clk@52 {
 						#clock-cells = <0>;
 						reg = <52>;
 					};
 
-					qspi1_clk: qspi1_clk {
+					qspi1_clk: qspi1_clk@53 {
 						#clock-cells = <0>;
 						reg = <53>;
 					};
@@ -504,62 +504,62 @@
 					interrupt-parent = <&pmc>;
 					clocks = <&main>, <&plla>, <&utmi>, <&mck>;
 
-					sdmmc0_gclk: sdmmc0_gclk {
+					sdmmc0_gclk: sdmmc0_gclk@31 {
 						#clock-cells = <0>;
 						reg = <31>;
 					};
 
-					sdmmc1_gclk: sdmmc1_gclk {
+					sdmmc1_gclk: sdmmc1_gclk@32 {
 						#clock-cells = <0>;
 						reg = <32>;
 					};
 
-					tcb0_gclk: tcb0_gclk {
+					tcb0_gclk: tcb0_gclk@35 {
 						#clock-cells = <0>;
 						reg = <35>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					tcb1_gclk: tcb1_gclk {
+					tcb1_gclk: tcb1_gclk@36 {
 						#clock-cells = <0>;
 						reg = <36>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					pwm_gclk: pwm_gclk {
+					pwm_gclk: pwm_gclk@38 {
 						#clock-cells = <0>;
 						reg = <38>;
 						atmel,clk-output-range = <0 83000000>;
 					};
 
-					pdmic_gclk: pdmic_gclk {
+					pdmic_gclk: pdmic_gclk@48 {
 						#clock-cells = <0>;
 						reg = <48>;
 					};
 
-					i2s0_gclk: i2s0_gclk {
+					i2s0_gclk: i2s0_gclk@54 {
 						#clock-cells = <0>;
 						reg = <54>;
 					};
 
-					i2s1_gclk: i2s1_gclk {
+					i2s1_gclk: i2s1_gclk@55 {
 						#clock-cells = <0>;
 						reg = <55>;
 					};
 
-					can0_gclk: can0_gclk {
+					can0_gclk: can0_gclk@56 {
 						#clock-cells = <0>;
 						reg = <56>;
 						atmel,clk-output-range = <0 80000000>;
 					};
 
-					can1_gclk: can1_gclk {
+					can1_gclk: can1_gclk@57 {
 						#clock-cells = <0>;
 						reg = <57>;
 						atmel,clk-output-range = <0 80000000>;
 					};
 
-					classd_gclk: classd_gclk {
+					classd_gclk: classd_gclk@59 {
 						#clock-cells = <0>;
 						reg = <59>;
 						atmel,clk-output-range = <0 100000000>;
diff --git a/arch/arm/mach-at91/arm926ejs/Makefile b/arch/arm/mach-at91/arm926ejs/Makefile
index ddc323f6415dd5c16093754ca3a0c9e070bbaf54..d36e15a51cc04d667a0e0e9f6874e9c8f4dd3adf 100644
--- a/arch/arm/mach-at91/arm926ejs/Makefile
+++ b/arch/arm/mach-at91/arm926ejs/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_AT91SAM9N12)	+= at91sam9n12_devices.o
 obj-$(CONFIG_AT91SAM9X5)	+= at91sam9x5_devices.o
 obj-$(CONFIG_AT91_EFLASH)	+= eflash.o
 obj-$(CONFIG_AT91_LED)	+= led.o
+obj-y += cache.o
 obj-y += clock.o
 obj-y += cpu.o
 obj-y	+= reset.o
diff --git a/arch/arm/mach-at91/arm926ejs/cache.c b/arch/arm/mach-at91/arm926ejs/cache.c
new file mode 100644
index 0000000000000000000000000000000000000000..8813706232e1b073e7d8ec661fd87b43b4923ec5
--- /dev/null
+++ b/arch/arm/mach-at91/arm926ejs/cache.c
@@ -0,0 +1,29 @@
+/*
+ * (C) Copyright 2016
+ * Heiko Schocher, DENX Software Engineering, hs@denx.de.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#include <linux/types.h>
+#include <common.h>
+
+void enable_caches(void)
+{
+#ifndef CONFIG_SYS_ICACHE_OFF
+	icache_enable();
+#endif
+}
+
+#ifndef CONFIG_SYS_ICACHE_OFF
+/* Invalidate entire I-cache and branch predictor array */
+void invalidate_icache_all(void)
+{
+	unsigned long i = 0;
+
+	asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (i));
+}
+#else
+void invalidate_icache_all(void)
+{
+}
+#endif
diff --git a/arch/arm/mach-at91/arm926ejs/clock.c b/arch/arm/mach-at91/arm926ejs/clock.c
index c8d24ae826508d2cd254c8717cbbad7eaa5125e1..e3181fab84feaa0c5cdf8e98dc508fd62bf9270d 100644
--- a/arch/arm/mach-at91/arm926ejs/clock.c
+++ b/arch/arm/mach-at91/arm926ejs/clock.c
@@ -162,7 +162,13 @@ int at91_clock_init(unsigned long main_clock)
 	gd->arch.mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK);
 	freq = gd->arch.mck_rate_hz;
 
+#if defined(CONFIG_AT91SAM9X5)
+	/* different in prescale on at91sam9x5 */
+	freq /= (1 << ((mckr & AT91_PMC_MCKR_PRES_MASK) >> 4));
+#else
 	freq /= (1 << ((mckr & AT91_PMC_MCKR_PRES_MASK) >> 2));	/* prescale */
+#endif
+
 #if defined(CONFIG_AT91SAM9G20)
 	/* mdiv ; (x >> 7) = ((x >> 8) * 2) */
 	gd->arch.mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) ?
diff --git a/arch/arm/mach-at91/include/mach/atmel_mpddrc.h b/arch/arm/mach-at91/include/mach/atmel_mpddrc.h
index d37d9082cdbbe7bb8c6c587cfb301c53a32fecf8..f6bcecda383832a630cf117923cfa6d96661bbff 100644
--- a/arch/arm/mach-at91/include/mach/atmel_mpddrc.h
+++ b/arch/arm/mach-at91/include/mach/atmel_mpddrc.h
@@ -147,6 +147,9 @@ int ddr3_init(const unsigned int base,
 #define ATMEL_MPDDRC_TPR2_TFAW_MASK		0xf
 
 /* Bit field in Memory Device Register */
+#define ATMEL_MPDDRC_MD_SDR_SDRAM	0x0
+#define ATMEL_MPDDRC_MD_LP_SDR_SDRAM	0x1
+#define ATMEL_MPDDRC_MD_DDR_SDRAM	0x2
 #define ATMEL_MPDDRC_MD_LPDDR_SDRAM	0x3
 #define ATMEL_MPDDRC_MD_DDR3_SDRAM	0x4
 #define ATMEL_MPDDRC_MD_LPDDR3_SDRAM	0x5
diff --git a/board/atmel/sama5d2_xplained/sama5d2_xplained.c b/board/atmel/sama5d2_xplained/sama5d2_xplained.c
index 93df7ba32a8fad9f306d6b0b6beece55be008f64..c5337af4de6fa16e6e22d0aa48f19f3be8b69891 100644
--- a/board/atmel/sama5d2_xplained/sama5d2_xplained.c
+++ b/board/atmel/sama5d2_xplained/sama5d2_xplained.c
@@ -7,6 +7,9 @@
 
 #include <common.h>
 #include <atmel_hlcdc.h>
+#include <debug_uart.h>
+#include <dm.h>
+#include <i2c.h>
 #include <lcd.h>
 #include <mmc.h>
 #include <net.h>
@@ -25,32 +28,6 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-int spi_cs_is_valid(unsigned int bus, unsigned int cs)
-{
-	return bus == 0 && cs == 0;
-}
-
-void spi_cs_activate(struct spi_slave *slave)
-{
-	atmel_pio4_set_pio_output(AT91_PIO_PORTA, 17, 0);
-}
-
-void spi_cs_deactivate(struct spi_slave *slave)
-{
-	atmel_pio4_set_pio_output(AT91_PIO_PORTA, 17, 1);
-}
-
-static void board_spi0_hw_init(void)
-{
-	atmel_pio4_set_a_periph(AT91_PIO_PORTA, 14, 0);
-	atmel_pio4_set_a_periph(AT91_PIO_PORTA, 15, 0);
-	atmel_pio4_set_a_periph(AT91_PIO_PORTA, 16, 0);
-
-	atmel_pio4_set_pio_output(AT91_PIO_PORTA, 17, 1);
-
-	at91_periph_clk_enable(ATMEL_ID_SPI0);
-}
-
 static void board_usb_hw_init(void)
 {
 	atmel_pio4_set_pio_output(AT91_PIO_PORTB, 10, 1);
@@ -157,55 +134,6 @@ static void board_gmac_hw_init(void)
 	at91_periph_clk_enable(ATMEL_ID_GMAC);
 }
 
-static void board_sdhci0_hw_init(void)
-{
-	atmel_pio4_set_a_periph(AT91_PIO_PORTA, 0, 0);	/* SDMMC0_CK */
-	atmel_pio4_set_a_periph(AT91_PIO_PORTA, 1, 0);	/* SDMMC0_CMD */
-	atmel_pio4_set_a_periph(AT91_PIO_PORTA, 2, 0);	/* SDMMC0_DAT0 */
-	atmel_pio4_set_a_periph(AT91_PIO_PORTA, 3, 0);	/* SDMMC0_DAT1 */
-	atmel_pio4_set_a_periph(AT91_PIO_PORTA, 4, 0);	/* SDMMC0_DAT2 */
-	atmel_pio4_set_a_periph(AT91_PIO_PORTA, 5, 0);	/* SDMMC0_DAT3 */
-	atmel_pio4_set_a_periph(AT91_PIO_PORTA, 6, 0);	/* SDMMC0_DAT4 */
-	atmel_pio4_set_a_periph(AT91_PIO_PORTA, 7, 0);	/* SDMMC0_DAT5 */
-	atmel_pio4_set_a_periph(AT91_PIO_PORTA, 8, 0);	/* SDMMC0_DAT6 */
-	atmel_pio4_set_a_periph(AT91_PIO_PORTA, 9, 0);	/* SDMMC0_DAT7 */
-	atmel_pio4_set_a_periph(AT91_PIO_PORTA, 10, 0);	/* SDMMC0_RSTN */
-	atmel_pio4_set_a_periph(AT91_PIO_PORTA, 11, 0);	/* SDMMC0_VDDSEL */
-	atmel_pio4_set_a_periph(AT91_PIO_PORTA, 13, 0);	/* SDMMC0_CD */
-
-	at91_periph_clk_enable(ATMEL_ID_SDMMC0);
-	at91_enable_periph_generated_clk(ATMEL_ID_SDMMC0,
-					 GCK_CSS_UPLL_CLK, 1);
-}
-
-static void board_sdhci1_hw_init(void)
-{
-	atmel_pio4_set_e_periph(AT91_PIO_PORTA, 18, 0);	/* SDMMC1_DAT0 */
-	atmel_pio4_set_e_periph(AT91_PIO_PORTA, 19, 0);	/* SDMMC1_DAT1 */
-	atmel_pio4_set_e_periph(AT91_PIO_PORTA, 20, 0);	/* SDMMC1_DAT2 */
-	atmel_pio4_set_e_periph(AT91_PIO_PORTA, 21, 0);	/* SDMMC1_DAT3 */
-	atmel_pio4_set_e_periph(AT91_PIO_PORTA, 22, 0);	/* SDMMC1_CK */
-	atmel_pio4_set_e_periph(AT91_PIO_PORTA, 27, 0);	/* SDMMC1_RSTN */
-	atmel_pio4_set_e_periph(AT91_PIO_PORTA, 28, 0);	/* SDMMC1_CMD */
-	atmel_pio4_set_e_periph(AT91_PIO_PORTA, 30, 0);	/* SDMMC1_CD */
-
-	at91_periph_clk_enable(ATMEL_ID_SDMMC1);
-	at91_enable_periph_generated_clk(ATMEL_ID_SDMMC1,
-					 GCK_CSS_UPLL_CLK, 1);
-}
-
-int board_mmc_init(bd_t *bis)
-{
-#ifdef CONFIG_ATMEL_SDHCI0
-	atmel_sdhci_init((void *)ATMEL_BASE_SDMMC0, ATMEL_ID_SDMMC0);
-#endif
-#ifdef CONFIG_ATMEL_SDHCI1
-	atmel_sdhci_init((void *)ATMEL_BASE_SDMMC1, ATMEL_ID_SDMMC1);
-#endif
-
-	return 0;
-}
-
 static void board_uart1_hw_init(void)
 {
 	atmel_pio4_set_a_periph(AT91_PIO_PORTD, 2, 1);	/* URXD1 */
@@ -214,34 +142,31 @@ static void board_uart1_hw_init(void)
 	at91_periph_clk_enable(ATMEL_ID_UART1);
 }
 
-int board_early_init_f(void)
+#ifdef CONFIG_DEBUG_UART_BOARD_INIT
+void board_debug_uart_init(void)
 {
-	at91_periph_clk_enable(ATMEL_ID_PIOA);
-	at91_periph_clk_enable(ATMEL_ID_PIOB);
-	at91_periph_clk_enable(ATMEL_ID_PIOC);
-	at91_periph_clk_enable(ATMEL_ID_PIOD);
+	board_uart1_hw_init();
+}
+#endif
 
+#ifdef CONFIG_BOARD_EARLY_INIT_F
+int board_early_init_f(void)
+{
+#ifdef CONFIG_DEBUG_UART
+	debug_uart_init();
+#else
 	board_uart1_hw_init();
+#endif
 
 	return 0;
 }
+#endif
 
 int board_init(void)
 {
 	/* address of boot parameters */
 	gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
 
-#ifdef CONFIG_ATMEL_SPI
-	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
 #ifdef CONFIG_MACB
 	board_gmac_hw_init();
 #endif
@@ -283,21 +208,59 @@ int board_eth_init(bd_t *bis)
 	return rc;
 }
 
+#ifdef CONFIG_CMD_I2C
+static int set_ethaddr_from_eeprom(void)
+{
+	const int ETH_ADDR_LEN = 6;
+	unsigned char ethaddr[ETH_ADDR_LEN];
+	const char *ETHADDR_NAME = "ethaddr";
+	struct udevice *bus, *dev;
+
+	if (getenv(ETHADDR_NAME))
+		return 0;
+
+	if (uclass_get_device_by_seq(UCLASS_I2C, 1, &bus)) {
+		printf("Cannot find I2C bus 1\n");
+		return -1;
+	}
+
+	if (dm_i2c_probe(bus, AT24MAC_ADDR, 0, &dev)) {
+		printf("Failed to probe I2C chip\n");
+		return -1;
+	}
+
+	if (dm_i2c_read(dev, AT24MAC_REG, ethaddr, ETH_ADDR_LEN)) {
+		printf("Failed to read ethernet address from EEPROM\n");
+		return -1;
+	}
+
+	if (!is_valid_ethaddr(ethaddr)) {
+		printf("The ethernet address read from EEPROM is not valid!\n");
+		return -1;
+	}
+
+	return eth_setenv_enetaddr(ETHADDR_NAME, ethaddr);
+}
+#else
+static int set_ethaddr_from_eeprom(void)
+{
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_MISC_INIT_R
+int misc_init_r(void)
+{
+	set_ethaddr_from_eeprom();
+
+	return 0;
+}
+#endif
+
 /* 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)
diff --git a/board/bluewater/gurnard/gurnard.c b/board/bluewater/gurnard/gurnard.c
index 2a36d29788c631a57b91e126ced45b666796142c..08b1401372c9fb2034db9e2f47d44b9bc3a88c56 100644
--- a/board/bluewater/gurnard/gurnard.c
+++ b/board/bluewater/gurnard/gurnard.c
@@ -414,12 +414,6 @@ void reset_phy(void)
 {
 }
 
-/* This breaks the Ethernet MAC at present */
-void enable_caches(void)
-{
-	dcache_enable();
-}
-
 /* SPI chip select control - only used for FPGA programming */
 #ifdef CONFIG_ATMEL_SPI
 
diff --git a/configs/sama5d2_xplained_mmc_defconfig b/configs/sama5d2_xplained_mmc_defconfig
index 23ab4d6d34d3fd00a888b55336474b8350d41eed..8a786f1a062d664824f3ae4948484c6a770a34a6 100644
--- a/configs/sama5d2_xplained_mmc_defconfig
+++ b/configs/sama5d2_xplained_mmc_defconfig
@@ -8,6 +8,9 @@ CONFIG_SPL_FAT_SUPPORT=y
 CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_SPL_MMC_SUPPORT=y
 CONFIG_SPL_SERIAL_SUPPORT=y
+CONFIG_DM_GPIO=y
+CONFIG_DM_SERIAL=y
+CONFIG_DEFAULT_DEVICE_TREE="at91-sama5d2_xplained"
 CONFIG_FIT=y
 CONFIG_SYS_EXTRA_OPTIONS="SAMA5D2,SYS_USE_MMC"
 CONFIG_BOOTDELAY=3
@@ -21,14 +24,46 @@ CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_MMC=y
 CONFIG_CMD_SF=y
+CONFIG_CMD_I2C=y
 CONFIG_CMD_USB=y
 # CONFIG_CMD_FPGA is not set
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_PING=y
 CONFIG_CMD_FAT=y
+CONFIG_OF_CONTROL=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_DM=y
+CONFIG_SPL_DM=y
+CONFIG_BLK=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_CLK_AT91=y
+CONFIG_AT91_UTMI=y
+CONFIG_AT91_H32MX=y
+CONFIG_AT91_GENERIC_CLK=y
+CONFIG_ATMEL_PIO4=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_AT91=y
+CONFIG_DM_MMC=y
+CONFIG_DM_MMC_OPS=y
+CONFIG_ATMEL_SDHCI=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_ATMEL=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_AT91PIO4=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_ATMEL=y
+CONFIG_DEBUG_UART_BASE=0xf8020000
+CONFIG_DEBUG_UART_CLOCK=0
+CONFIG_DEBUG_UART_BOARD_INIT=y
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_ATMEL_USART=y
+CONFIG_DM_SPI=y
+CONFIG_ATMEL_SPI=y
 CONFIG_USB=y
 CONFIG_USB_STORAGE=y
+CONFIG_DM_USB=y
+CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_ATMEL_USBA=y
-CONFIG_OF_LIBFDT=y
diff --git a/configs/sama5d2_xplained_spiflash_defconfig b/configs/sama5d2_xplained_spiflash_defconfig
index f208dc2473f01b48a21b29d3ee95f7f105e73006..51594e71f71678aaff168f6adc86a1798dcab24a 100644
--- a/configs/sama5d2_xplained_spiflash_defconfig
+++ b/configs/sama5d2_xplained_spiflash_defconfig
@@ -7,6 +7,9 @@ CONFIG_SPL_LIBGENERIC_SUPPORT=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_SPI_FLASH_SUPPORT=y
 CONFIG_SPL_SPI_SUPPORT=y
+CONFIG_DM_GPIO=y
+CONFIG_DM_SERIAL=y
+CONFIG_DEFAULT_DEVICE_TREE="at91-sama5d2_xplained"
 CONFIG_FIT=y
 CONFIG_SYS_EXTRA_OPTIONS="SAMA5D2,SYS_USE_SERIALFLASH"
 CONFIG_BOOTDELAY=3
@@ -20,14 +23,46 @@ CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_MMC=y
 CONFIG_CMD_SF=y
+CONFIG_CMD_I2C=y
 CONFIG_CMD_USB=y
 # CONFIG_CMD_FPGA is not set
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_PING=y
 CONFIG_CMD_FAT=y
+CONFIG_OF_CONTROL=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_DM=y
+CONFIG_SPL_DM=y
+CONFIG_BLK=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_CLK_AT91=y
+CONFIG_AT91_UTMI=y
+CONFIG_AT91_H32MX=y
+CONFIG_AT91_GENERIC_CLK=y
+CONFIG_ATMEL_PIO4=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_AT91=y
+CONFIG_DM_MMC=y
+CONFIG_DM_MMC_OPS=y
+CONFIG_ATMEL_SDHCI=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_ATMEL=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_AT91PIO4=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_ATMEL=y
+CONFIG_DEBUG_UART_BASE=0xf8020000
+CONFIG_DEBUG_UART_CLOCK=0
+CONFIG_DEBUG_UART_BOARD_INIT=y
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_ATMEL_USART=y
+CONFIG_DM_SPI=y
+CONFIG_ATMEL_SPI=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_ATMEL_USBA=y
-CONFIG_OF_LIBFDT=y
diff --git a/drivers/clk/at91/Kconfig b/drivers/clk/at91/Kconfig
index 10050d8a44216adc93ced1ddf121b6bf4eaac02a..904ed48e51e0f071629afb9b41042d7765891cbb 100644
--- a/drivers/clk/at91/Kconfig
+++ b/drivers/clk/at91/Kconfig
@@ -1,6 +1,7 @@
 config CLK_AT91
 	bool "AT91 clock drivers"
 	depends on CLK
+	select MISC
 	help
 	  This option is used to enable the AT91 clock driver.
 	  The driver supports the AT91 clock generator, including
diff --git a/drivers/clk/at91/clk-generated.c b/drivers/clk/at91/clk-generated.c
index f6164cc8ca1c8ac1b5430502710d911bc832e3f6..d36f64ffdf81b7df371b67f77c70cb356ef210d9 100644
--- a/drivers/clk/at91/clk-generated.c
+++ b/drivers/clk/at91/clk-generated.c
@@ -17,15 +17,41 @@ DECLARE_GLOBAL_DATA_PTR;
 #define GENERATED_SOURCE_MAX	6
 #define GENERATED_MAX_DIV	255
 
-struct generated_clk_priv {
+/**
+ * generated_clk_bind() - for the generated clock driver
+ * Recursively bind its children as clk devices.
+ *
+ * @return: 0 on success, or negative error code on failure
+ */
+static int generated_clk_bind(struct udevice *dev)
+{
+	return at91_clk_sub_device_bind(dev, "generic-clk");
+}
+
+static const struct udevice_id generated_clk_match[] = {
+	{ .compatible = "atmel,sama5d2-clk-generated" },
+	{}
+};
+
+U_BOOT_DRIVER(generated_clk) = {
+	.name = "generated-clk",
+	.id = UCLASS_MISC,
+	.of_match = generated_clk_match,
+	.bind = generated_clk_bind,
+};
+
+/*-------------------------------------------------------------*/
+
+struct generic_clk_priv {
 	u32 num_parents;
 };
 
-static ulong generated_clk_get_rate(struct clk *clk)
+static ulong generic_clk_get_rate(struct clk *clk)
 {
 	struct pmc_platdata *plat = dev_get_platdata(clk->dev);
 	struct at91_pmc *pmc = plat->reg_base;
 	struct clk parent;
+	ulong clk_rate;
 	u32 tmp, gckdiv;
 	u8 parent_id;
 	int ret;
@@ -36,18 +62,22 @@ static ulong generated_clk_get_rate(struct clk *clk)
 		    AT91_PMC_PCR_GCKCSS_MASK;
 	gckdiv = (tmp >> AT91_PMC_PCR_GCKDIV_OFFSET) & AT91_PMC_PCR_GCKDIV_MASK;
 
-	ret = clk_get_by_index(clk->dev, parent_id, &parent);
+	ret = clk_get_by_index(dev_get_parent(clk->dev), parent_id, &parent);
 	if (ret)
 		return 0;
 
-	return clk_get_rate(&parent) / (gckdiv + 1);
+	clk_rate = clk_get_rate(&parent) / (gckdiv + 1);
+
+	clk_free(&parent);
+
+	return clk_rate;
 }
 
-static ulong generated_clk_set_rate(struct clk *clk, ulong rate)
+static ulong generic_clk_set_rate(struct clk *clk, ulong rate)
 {
 	struct pmc_platdata *plat = dev_get_platdata(clk->dev);
 	struct at91_pmc *pmc = plat->reg_base;
-	struct generated_clk_priv *priv = dev_get_priv(clk->dev);
+	struct generic_clk_priv *priv = dev_get_priv(clk->dev);
 	struct clk parent, best_parent;
 	ulong tmp_rate, best_rate = rate, parent_rate;
 	int tmp_diff, best_diff = -1;
@@ -58,7 +88,7 @@ static ulong generated_clk_set_rate(struct clk *clk, ulong rate)
 	int ret;
 
 	for (i = 0; i < priv->num_parents; i++) {
-		ret = clk_get_by_index(clk->dev, i, &parent);
+		ret = clk_get_by_index(dev_get_parent(clk->dev), i, &parent);
 		if (ret)
 			return ret;
 
@@ -111,18 +141,20 @@ static ulong generated_clk_set_rate(struct clk *clk, ulong rate)
 	return 0;
 }
 
-static struct clk_ops generated_clk_ops = {
-	.get_rate = generated_clk_get_rate,
-	.set_rate = generated_clk_set_rate,
+static struct clk_ops generic_clk_ops = {
+	.of_xlate = at91_clk_of_xlate,
+	.get_rate = generic_clk_get_rate,
+	.set_rate = generic_clk_set_rate,
 };
 
-static int generated_clk_ofdata_to_platdata(struct udevice *dev)
+static int generic_clk_ofdata_to_platdata(struct udevice *dev)
 {
-	struct generated_clk_priv *priv = dev_get_priv(dev);
+	struct generic_clk_priv *priv = dev_get_priv(dev);
 	u32 cells[GENERATED_SOURCE_MAX];
 	u32 num_parents;
 
-	num_parents = fdtdec_get_int_array_count(gd->fdt_blob, dev->of_offset,
+	num_parents = fdtdec_get_int_array_count(gd->fdt_blob,
+						 dev_get_parent(dev)->of_offset,
 						 "clocks", cells,
 						 GENERATED_SOURCE_MAX);
 
@@ -134,29 +166,12 @@ static int generated_clk_ofdata_to_platdata(struct udevice *dev)
 	return 0;
 }
 
-static int generated_clk_bind(struct udevice *dev)
-{
-	return at91_pmc_clk_node_bind(dev);
-}
-
-static int generated_clk_probe(struct udevice *dev)
-{
-	return at91_pmc_core_probe(dev);
-}
-
-static const struct udevice_id generated_clk_match[] = {
-	{ .compatible = "atmel,sama5d2-clk-generated" },
-	{}
-};
-
-U_BOOT_DRIVER(generated_clk) = {
-	.name = "generated-clk",
+U_BOOT_DRIVER(generic_clk) = {
+	.name = "generic-clk",
 	.id = UCLASS_CLK,
-	.of_match = generated_clk_match,
-	.bind = generated_clk_bind,
-	.probe = generated_clk_probe,
-	.ofdata_to_platdata = generated_clk_ofdata_to_platdata,
-	.priv_auto_alloc_size = sizeof(struct generated_clk_priv),
+	.probe = at91_clk_probe,
+	.ofdata_to_platdata = generic_clk_ofdata_to_platdata,
+	.priv_auto_alloc_size = sizeof(struct generic_clk_priv),
 	.platdata_auto_alloc_size = sizeof(struct pmc_platdata),
-	.ops = &generated_clk_ops,
+	.ops = &generic_clk_ops,
 };
diff --git a/drivers/clk/at91/clk-peripheral.c b/drivers/clk/at91/clk-peripheral.c
index 16688e90b417fc1ed9a3996f848f7be606eb822c..e1ed447133e077201c5b7f638ef23b5e6d0850b8 100644
--- a/drivers/clk/at91/clk-peripheral.c
+++ b/drivers/clk/at91/clk-peripheral.c
@@ -16,7 +16,32 @@
 #define PERIPHERAL_ID_MAX	31
 #define PERIPHERAL_MASK(id)	(1 << ((id) & PERIPHERAL_ID_MAX))
 
-static int sam9x5_periph_clk_enable(struct clk *clk)
+/**
+ * sam9x5_periph_clk_bind() - for the periph clock driver
+ * Recursively bind its children as clk devices.
+ *
+ * @return: 0 on success, or negative error code on failure
+ */
+static int sam9x5_periph_clk_bind(struct udevice *dev)
+{
+	return at91_clk_sub_device_bind(dev, "periph-clk");
+}
+
+static const struct udevice_id sam9x5_periph_clk_match[] = {
+	{ .compatible = "atmel,at91sam9x5-clk-peripheral" },
+	{}
+};
+
+U_BOOT_DRIVER(sam9x5_periph_clk) = {
+	.name = "sam9x5-periph-clk",
+	.id = UCLASS_MISC,
+	.of_match = sam9x5_periph_clk_match,
+	.bind = sam9x5_periph_clk_bind,
+};
+
+/*---------------------------------------------------------*/
+
+static int periph_clk_enable(struct clk *clk)
 {
 	struct pmc_platdata *plat = dev_get_platdata(clk->dev);
 	struct at91_pmc *pmc = plat->reg_base;
@@ -30,31 +55,36 @@ static int sam9x5_periph_clk_enable(struct clk *clk)
 	return 0;
 }
 
-static struct clk_ops sam9x5_periph_clk_ops = {
-	.enable = sam9x5_periph_clk_enable,
-};
-
-static int sam9x5_periph_clk_bind(struct udevice *dev)
+static ulong periph_get_rate(struct clk *clk)
 {
-	return at91_pmc_clk_node_bind(dev);
-}
+	struct udevice *dev;
+	struct clk clk_dev;
+	ulong clk_rate;
+	int ret;
 
-static int sam9x5_periph_clk_probe(struct udevice *dev)
-{
-	return at91_pmc_core_probe(dev);
+	dev = dev_get_parent(clk->dev);
+
+	ret = clk_get_by_index(dev, 0, &clk_dev);
+	if (ret)
+		return ret;
+
+	clk_rate = clk_get_rate(&clk_dev);
+
+	clk_free(&clk_dev);
+
+	return clk_rate;
 }
 
-static const struct udevice_id sam9x5_periph_clk_match[] = {
-	{ .compatible = "atmel,at91sam9x5-clk-peripheral" },
-	{}
+static struct clk_ops periph_clk_ops = {
+	.of_xlate = at91_clk_of_xlate,
+	.enable = periph_clk_enable,
+	.get_rate = periph_get_rate,
 };
 
-U_BOOT_DRIVER(sam9x5_periph_clk) = {
-	.name = "sam9x5-periph-clk",
-	.id = UCLASS_CLK,
-	.of_match = sam9x5_periph_clk_match,
-	.bind = sam9x5_periph_clk_bind,
-	.probe = sam9x5_periph_clk_probe,
+U_BOOT_DRIVER(clk_periph) = {
+	.name	= "periph-clk",
+	.id	= UCLASS_CLK,
 	.platdata_auto_alloc_size = sizeof(struct pmc_platdata),
-	.ops = &sam9x5_periph_clk_ops,
+	.probe = at91_clk_probe,
+	.ops	= &periph_clk_ops,
 };
diff --git a/drivers/clk/at91/clk-system.c b/drivers/clk/at91/clk-system.c
index fa80bade7a91e80bc530cbfee1163165b06d846a..5b59a0c85204fda795ca6877732bbf66a0e43f39 100644
--- a/drivers/clk/at91/clk-system.c
+++ b/drivers/clk/at91/clk-system.c
@@ -14,12 +14,37 @@
 
 #define SYSTEM_MAX_ID		31
 
+/**
+ * at91_system_clk_bind() - for the system clock driver
+ * Recursively bind its children as clk devices.
+ *
+ * @return: 0 on success, or negative error code on failure
+ */
+static int at91_system_clk_bind(struct udevice *dev)
+{
+	return at91_clk_sub_device_bind(dev, "system-clk");
+}
+
+static const struct udevice_id at91_system_clk_match[] = {
+	{ .compatible = "atmel,at91rm9200-clk-system" },
+	{}
+};
+
+U_BOOT_DRIVER(at91_system_clk) = {
+	.name = "at91-system-clk",
+	.id = UCLASS_MISC,
+	.of_match = at91_system_clk_match,
+	.bind = at91_system_clk_bind,
+};
+
+/*----------------------------------------------------------*/
+
 static inline int is_pck(int id)
 {
 	return (id >= 8) && (id <= 15);
 }
 
-static int at91_system_clk_enable(struct clk *clk)
+static int system_clk_enable(struct clk *clk)
 {
 	struct pmc_platdata *plat = dev_get_platdata(clk->dev);
 	struct at91_pmc *pmc = plat->reg_base;
@@ -46,31 +71,15 @@ static int at91_system_clk_enable(struct clk *clk)
 	return 0;
 }
 
-static struct clk_ops at91_system_clk_ops = {
-	.enable = at91_system_clk_enable,
+static struct clk_ops system_clk_ops = {
+	.of_xlate = at91_clk_of_xlate,
+	.enable = system_clk_enable,
 };
 
-static int at91_system_clk_bind(struct udevice *dev)
-{
-	return at91_pmc_clk_node_bind(dev);
-}
-
-static int at91_system_clk_probe(struct udevice *dev)
-{
-	return at91_pmc_core_probe(dev);
-}
-
-static const struct udevice_id at91_system_clk_match[] = {
-	{ .compatible = "atmel,at91rm9200-clk-system" },
-	{}
-};
-
-U_BOOT_DRIVER(at91_system_clk) = {
-	.name = "at91-system-clk",
+U_BOOT_DRIVER(system_clk) = {
+	.name = "system-clk",
 	.id = UCLASS_CLK,
-	.of_match = at91_system_clk_match,
-	.bind = at91_system_clk_bind,
-	.probe = at91_system_clk_probe,
+	.probe = at91_clk_probe,
 	.platdata_auto_alloc_size = sizeof(struct pmc_platdata),
-	.ops = &at91_system_clk_ops,
+	.ops = &system_clk_ops,
 };
diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
index a08d7e82eb3462bf825116ec5a1645abb9c81137..76ba91af81209296585eae984e6143b3719c0db0 100644
--- a/drivers/clk/at91/pmc.c
+++ b/drivers/clk/at91/pmc.c
@@ -14,23 +14,19 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-static int at91_pmc_bind(struct udevice *dev)
-{
-	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
-}
-
 static const struct udevice_id at91_pmc_match[] = {
 	{ .compatible = "atmel,sama5d2-pmc" },
 	{}
 };
 
 U_BOOT_DRIVER(at91_pmc) = {
-	.name = "at91-pmc-core",
-	.id = UCLASS_CLK,
+	.name = "at91-pmc",
+	.id = UCLASS_SIMPLE_BUS,
 	.of_match = at91_pmc_match,
-	.bind = at91_pmc_bind,
 };
 
+/*---------------------------------------------------------*/
+
 int at91_pmc_core_probe(struct udevice *dev)
 {
 	struct pmc_platdata *plat = dev_get_platdata(dev);
@@ -42,21 +38,41 @@ int at91_pmc_core_probe(struct udevice *dev)
 	return 0;
 }
 
-int at91_pmc_clk_node_bind(struct udevice *dev)
+/**
+ * at91_clk_sub_device_bind() - for the at91 clock driver
+ * Recursively bind its children as clk devices.
+ *
+ * @return: 0 on success, or negative error code on failure
+ */
+int at91_clk_sub_device_bind(struct udevice *dev, const char *drv_name)
 {
 	const void *fdt = gd->fdt_blob;
 	int offset = dev->of_offset;
+	bool pre_reloc_only = !(gd->flags & GD_FLG_RELOC);
 	const char *name;
 	int ret;
 
 	for (offset = fdt_first_subnode(fdt, offset);
 	     offset > 0;
 	     offset = fdt_next_subnode(fdt, offset)) {
+		if (pre_reloc_only &&
+		    !fdt_getprop(fdt, offset, "u-boot,dm-pre-reloc", NULL))
+			continue;
+		/*
+		 * If this node has "compatible" property, this is not
+		 * a clock sub-node, but a normal device. skip.
+		 */
+		fdt_get_property(fdt, offset, "compatible", &ret);
+		if (ret >= 0)
+			continue;
+
+		if (ret != -FDT_ERR_NOTFOUND)
+			return ret;
+
 		name = fdt_get_name(fdt, offset, NULL);
 		if (!name)
 			return -EINVAL;
-
-		ret = device_bind_driver_to_node(dev, "clk", name,
+		ret = device_bind_driver_to_node(dev, drv_name, name,
 						 offset, NULL);
 		if (ret)
 			return ret;
@@ -65,7 +81,33 @@ int at91_pmc_clk_node_bind(struct udevice *dev)
 	return 0;
 }
 
-U_BOOT_DRIVER(clk_generic) = {
-	.id	= UCLASS_CLK,
-	.name	= "clk",
-};
+int at91_clk_of_xlate(struct clk *clk, struct fdtdec_phandle_args *args)
+{
+	int periph;
+
+	if (args->args_count) {
+		debug("Invalid args_count: %d\n", args->args_count);
+		return -EINVAL;
+	}
+
+	periph = fdtdec_get_uint(gd->fdt_blob, clk->dev->of_offset, "reg", -1);
+	if (periph < 0)
+		return -EINVAL;
+
+	clk->id = periph;
+
+	return 0;
+}
+
+int at91_clk_probe(struct udevice *dev)
+{
+	struct udevice *dev_periph_container, *dev_pmc;
+	struct pmc_platdata *plat = dev_get_platdata(dev);
+
+	dev_periph_container = dev_get_parent(dev);
+	dev_pmc = dev_get_parent(dev_periph_container);
+
+	plat->reg_base = (struct at91_pmc *)dev_get_addr_ptr(dev_pmc);
+
+	return 0;
+}
diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h
index 5444c84db66cc76dabc5f165ddb14bf13f6f7a7e..f222fce11f427aef09625993994c97fe0f44a89b 100644
--- a/drivers/clk/at91/pmc.h
+++ b/drivers/clk/at91/pmc.h
@@ -13,6 +13,9 @@ struct pmc_platdata {
 };
 
 int at91_pmc_core_probe(struct udevice *dev);
-int at91_pmc_clk_node_bind(struct udevice *dev);
+int at91_clk_sub_device_bind(struct udevice *dev, const char *drv_name);
+
+int at91_clk_of_xlate(struct clk *clk, struct fdtdec_phandle_args *args);
+int at91_clk_probe(struct udevice *dev);
 
 #endif
diff --git a/drivers/clk/at91/sckc.c b/drivers/clk/at91/sckc.c
index b207611de1cd9799ab908036332c9136223d8d41..6035e2095996469a7ca26f07d7c71c29dcad0c0e 100644
--- a/drivers/clk/at91/sckc.c
+++ b/drivers/clk/at91/sckc.c
@@ -6,25 +6,18 @@
  */
 
 #include <common.h>
-#include <clk-uclass.h>
 #include <dm/device.h>
 #include <dm/root.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
-static int at91_sckc_clk_bind(struct udevice *dev)
-{
-	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
-}
-
-static const struct udevice_id at91_sckc_clk_match[] = {
+static const struct udevice_id at91_sckc_match[] = {
 	{ .compatible = "atmel,at91sam9x5-sckc" },
 	{}
 };
 
-U_BOOT_DRIVER(at91_sckc_clk) = {
-	.name = "at91_sckc_clk",
-	.id = UCLASS_CLK,
-	.of_match = at91_sckc_clk_match,
-	.bind = at91_sckc_clk_bind,
+U_BOOT_DRIVER(at91_sckc) = {
+	.name = "at91-sckc",
+	.id = UCLASS_SIMPLE_BUS,
+	.of_match = at91_sckc_match,
 };
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index c42fff6ec2908ba801d8420011b7e55f4346da9a..153ceba702d621158c238322e1345516125fc31f 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -80,6 +80,9 @@ int clk_get_by_index(struct udevice *dev, int index, struct clk *clk)
 		      __func__, ret);
 		return ret;
 	}
+
+	clk->dev = dev_clk;
+
 	ops = clk_dev_ops(dev_clk);
 
 	if (ops->of_xlate)
diff --git a/drivers/gpio/atmel_pio4.c b/drivers/gpio/atmel_pio4.c
index 7adea885650fde7c4e6869a7a9762cd3e2bdbc76..cb90b0241a2bdc7b120f73ca817e7bf9aa5522aa 100644
--- a/drivers/gpio/atmel_pio4.c
+++ b/drivers/gpio/atmel_pio4.c
@@ -284,27 +284,15 @@ static int atmel_pio4_probe(struct udevice *dev)
 	struct atmel_pio4_platdata *plat = dev_get_platdata(dev);
 	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 	struct atmel_pioctrl_data *pioctrl_data;
-	struct udevice *dev_clk;
 	struct clk clk;
 	fdt_addr_t addr_base;
 	u32 nbanks;
-	int periph;
 	int ret;
 
 	ret = clk_get_by_index(dev, 0, &clk);
 	if (ret)
 		return ret;
 
-	periph = fdtdec_get_uint(gd->fdt_blob, clk.dev->of_offset, "reg", -1);
-	if (periph < 0)
-		return -EINVAL;
-
-	dev_clk = dev_get_parent(clk.dev);
-	ret = clk_request(dev_clk, &clk);
-	if (ret)
-		return ret;
-
-	clk.id = periph;
 	ret = clk_enable(&clk);
 	if (ret)
 		return ret;
diff --git a/drivers/i2c/at91_i2c.c b/drivers/i2c/at91_i2c.c
index d71f75c5faa97eb2e1c99052324c6c74a64575f5..4bc54eea596eb6b2a63bae682de7feb6550f9b25 100644
--- a/drivers/i2c/at91_i2c.c
+++ b/drivers/i2c/at91_i2c.c
@@ -176,37 +176,21 @@ static void at91_calc_i2c_clock(struct udevice *dev, int i2c_clk)
 static int at91_i2c_enable_clk(struct udevice *dev)
 {
 	struct at91_i2c_bus *bus = dev_get_priv(dev);
-	struct udevice *dev_clk;
 	struct clk clk;
 	ulong clk_rate;
-	int periph;
 	int ret;
 
 	ret = clk_get_by_index(dev, 0, &clk);
 	if (ret)
 		return -EINVAL;
 
-	periph = fdtdec_get_uint(gd->fdt_blob, clk.dev->of_offset, "reg", -1);
-	if (periph < 0)
-		return -EINVAL;
-
-	dev_clk = dev_get_parent(clk.dev);
-	ret = clk_request(dev_clk, &clk);
-	if (ret)
-		return ret;
-
-	clk.id = periph;
 	ret = clk_enable(&clk);
 	if (ret)
 		return ret;
 
-	ret = clk_get_by_index(dev_clk, 0, &clk);
-	if (ret)
-		return ret;
-
 	clk_rate = clk_get_rate(&clk);
 	if (!clk_rate)
-		return -ENODEV;
+		return -EINVAL;
 
 	bus->bus_clk_rate = clk_rate;
 
diff --git a/drivers/mmc/atmel_sdhci.c b/drivers/mmc/atmel_sdhci.c
index 20bba1a2797481830d7fde7a3d47d0f63c936f1f..6654b542788e6eec57da661311b6c7cc91f15598 100644
--- a/drivers/mmc/atmel_sdhci.c
+++ b/drivers/mmc/atmel_sdhci.c
@@ -50,29 +50,6 @@ struct atmel_sdhci_plat {
 	struct mmc mmc;
 };
 
-static int atmel_sdhci_get_clk(struct udevice *dev, int index, struct clk *clk)
-{
-	struct udevice *dev_clk;
-	int periph, ret;
-
-	ret = clk_get_by_index(dev, index, clk);
-	if (ret)
-		return ret;
-
-	periph = fdtdec_get_uint(gd->fdt_blob, clk->dev->of_offset, "reg", -1);
-	if (periph < 0)
-		return -EINVAL;
-
-	dev_clk = dev_get_parent(clk->dev);
-	ret = clk_request(dev_clk, clk);
-	if (ret)
-		return ret;
-
-	clk->id = periph;
-
-	return 0;
-}
-
 static int atmel_sdhci_probe(struct udevice *dev)
 {
 	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
@@ -85,7 +62,7 @@ static int atmel_sdhci_probe(struct udevice *dev)
 	struct clk clk;
 	int ret;
 
-	ret = atmel_sdhci_get_clk(dev, 0, &clk);
+	ret = clk_get_by_index(dev, 0, &clk);
 	if (ret)
 		return ret;
 
@@ -106,7 +83,7 @@ static int atmel_sdhci_probe(struct udevice *dev)
 	clk_mul = (caps_1 & SDHCI_CLOCK_MUL_MASK) >> SDHCI_CLOCK_MUL_SHIFT;
 	gck_rate = clk_base * 1000000 * (clk_mul + 1);
 
-	ret = atmel_sdhci_get_clk(dev, 1, &clk);
+	ret = clk_get_by_index(dev, 1, &clk);
 	if (ret)
 		return ret;
 
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 317d15849d34323fde33efb2d55fc98df7d1bdc2..56c024f97a140c87121e3c228ef25e28c2691fed 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -98,6 +98,13 @@ config DEBUG_UART_AR933X
 	  driver will be available until the real driver model serial is
 	  running.
 
+config DEBUG_UART_ATMEL
+	bool "Atmel USART"
+	help
+	  Select this to enable a debug UART using the atmel usart driver. You
+	  will need to provide parameters to make this work. The driver will
+	  be available until the real driver-model serial is running.
+
 config DEBUG_UART_NS16550
 	bool "ns16550"
 	help
@@ -296,6 +303,13 @@ config AR933X_UART
 	  tree binding to operate, please refer to the document at
 	  doc/device-tree-bindings/serial/qca,ar9330-uart.txt.
 
+config ATMEL_USART
+	bool "Atmel USART support"
+	help
+	  Select this to enable USART support for Atmel SoCs. It can be
+	  configured in the device tree, and input clock frequency can
+	  be got from the clk node.
+
 config FSL_LPUART
 	bool "Freescale LPUART support"
 	help
diff --git a/drivers/serial/atmel_usart.c b/drivers/serial/atmel_usart.c
index e450135c75745e7231fd83bf5f35bd4d98bb7591..7674f97e8dde04dbf5bf4112874cdb91847d7e4d 100644
--- a/drivers/serial/atmel_usart.c
+++ b/drivers/serial/atmel_usart.c
@@ -11,6 +11,7 @@
 #include <errno.h>
 #include <watchdog.h>
 #include <serial.h>
+#include <debug_uart.h>
 #include <linux/compiler.h>
 
 #include <asm/io.h>
@@ -226,3 +227,24 @@ U_BOOT_DRIVER(serial_atmel) = {
 	.priv_auto_alloc_size	= sizeof(struct atmel_serial_priv),
 };
 #endif
+
+#ifdef CONFIG_DEBUG_UART_ATMEL
+static inline void _debug_uart_init(void)
+{
+	atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_DEBUG_UART_BASE;
+
+	atmel_serial_setbrg_internal(usart, 0, CONFIG_BAUDRATE);
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+	atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_DEBUG_UART_BASE;
+
+	while (!(readl(&usart->csr) & USART3_BIT(TXRDY)))
+		;
+
+	writel(ch, &usart->thr);
+}
+
+DEBUG_UART_FUNCS
+#endif
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 8724f87c4987d098115ddcfd67b0a8913df2f6d1..0f51b3a21b87ae08a2a96b622a3e92c5afc04c41 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -32,6 +32,14 @@ config ATH79_SPI
 	  uses driver model and requires a device tree binding to operate.
 	  please refer to doc/device-tree-bindings/spi/spi-ath79.txt.
 
+config ATMEL_SPI
+	bool "Atmel SPI driver"
+	depends on ARCH_AT91
+	help
+	  This enables driver for the Atmel SPI Controller, present on
+	  many AT32 (AVR32) and AT91 (ARM) chips. This driver can be
+	  used to access the SPI Flash, such as AT25DF321.
+
 config CADENCE_QSPI
 	bool "Cadence QSPI driver"
 	help
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index ed6278b86fdef4eac9851a7e1dc3802658c27fc6..76491142318342da1c7cf222fac7fe531230c5a4 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -4,16 +4,30 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 #include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <fdtdec.h>
 #include <spi.h>
 #include <malloc.h>
+#include <wait_bit.h>
 
 #include <asm/io.h>
 
 #include <asm/arch/clk.h>
 #include <asm/arch/hardware.h>
+#ifdef CONFIG_DM_SPI
+#include <asm/arch/at91_spi.h>
+#endif
+#ifdef CONFIG_DM_GPIO
+#include <asm/gpio.h>
+#endif
 
 #include "atmel_spi.h"
 
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifndef CONFIG_DM_SPI
+
 static int spi_has_wdrbt(struct atmel_spi_slave *slave)
 {
 	unsigned int ver;
@@ -209,3 +223,277 @@ out:
 
 	return 0;
 }
+
+#else
+
+#define MAX_CS_COUNT	4
+
+struct atmel_spi_platdata {
+	struct at91_spi *regs;
+};
+
+struct atmel_spi_priv {
+	unsigned int freq;		/* Default frequency */
+	unsigned int mode;
+	ulong bus_clk_rate;
+	struct gpio_desc cs_gpios[MAX_CS_COUNT];
+};
+
+static int atmel_spi_claim_bus(struct udevice *dev)
+{
+	struct udevice *bus = dev_get_parent(dev);
+	struct atmel_spi_platdata *bus_plat = dev_get_platdata(bus);
+	struct atmel_spi_priv *priv = dev_get_priv(bus);
+	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
+	struct at91_spi *reg_base = bus_plat->regs;
+	u32 cs = slave_plat->cs;
+	u32 freq = priv->freq;
+	u32 scbr, csrx, mode;
+
+	scbr = (priv->bus_clk_rate + freq - 1) / freq;
+	if (scbr > ATMEL_SPI_CSRx_SCBR_MAX)
+		return -EINVAL;
+
+	if (scbr < 1)
+		scbr = 1;
+
+	csrx = ATMEL_SPI_CSRx_SCBR(scbr);
+	csrx |= ATMEL_SPI_CSRx_BITS(ATMEL_SPI_BITS_8);
+
+	if (!(priv->mode & SPI_CPHA))
+		csrx |= ATMEL_SPI_CSRx_NCPHA;
+	if (priv->mode & SPI_CPOL)
+		csrx |= ATMEL_SPI_CSRx_CPOL;
+
+	writel(csrx, &reg_base->csr[cs]);
+
+	mode = ATMEL_SPI_MR_MSTR |
+	       ATMEL_SPI_MR_MODFDIS |
+	       ATMEL_SPI_MR_WDRBT |
+	       ATMEL_SPI_MR_PCS(~(1 << cs));
+
+	writel(mode, &reg_base->mr);
+
+	writel(ATMEL_SPI_CR_SPIEN, &reg_base->cr);
+
+	return 0;
+}
+
+static int atmel_spi_release_bus(struct udevice *dev)
+{
+	struct udevice *bus = dev_get_parent(dev);
+	struct atmel_spi_platdata *bus_plat = dev_get_platdata(bus);
+
+	writel(ATMEL_SPI_CR_SPIDIS, &bus_plat->regs->cr);
+
+	return 0;
+}
+
+static void atmel_spi_cs_activate(struct udevice *dev)
+{
+	struct udevice *bus = dev_get_parent(dev);
+	struct atmel_spi_priv *priv = dev_get_priv(bus);
+	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
+	u32 cs = slave_plat->cs;
+
+	dm_gpio_set_value(&priv->cs_gpios[cs], 0);
+}
+
+static void atmel_spi_cs_deactivate(struct udevice *dev)
+{
+	struct udevice *bus = dev_get_parent(dev);
+	struct atmel_spi_priv *priv = dev_get_priv(bus);
+	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
+	u32 cs = slave_plat->cs;
+
+	dm_gpio_set_value(&priv->cs_gpios[cs], 1);
+}
+
+static int atmel_spi_xfer(struct udevice *dev, unsigned int bitlen,
+			  const void *dout, void *din, unsigned long flags)
+{
+	struct udevice *bus = dev_get_parent(dev);
+	struct atmel_spi_platdata *bus_plat = dev_get_platdata(bus);
+	struct at91_spi *reg_base = bus_plat->regs;
+
+	u32 len_tx, len_rx, len;
+	u32 status;
+	const u8 *txp = dout;
+	u8 *rxp = din;
+	u8 value;
+
+	if (bitlen == 0)
+		goto out;
+
+	/*
+	 * The controller can do non-multiple-of-8 bit
+	 * transfers, but this driver currently doesn't support it.
+	 *
+	 * It's also not clear how such transfers are supposed to be
+	 * represented as a stream of bytes...this is a limitation of
+	 * the current SPI interface.
+	 */
+	if (bitlen % 8) {
+		/* Errors always terminate an ongoing transfer */
+		flags |= SPI_XFER_END;
+		goto out;
+	}
+
+	len = bitlen / 8;
+
+	/*
+	 * The controller can do automatic CS control, but it is
+	 * somewhat quirky, and it doesn't really buy us much anyway
+	 * in the context of U-Boot.
+	 */
+	if (flags & SPI_XFER_BEGIN) {
+		atmel_spi_cs_activate(dev);
+
+		/*
+		 * sometimes the RDR is not empty when we get here,
+		 * in theory that should not happen, but it DOES happen.
+		 * Read it here to be on the safe side.
+		 * That also clears the OVRES flag. Required if the
+		 * following loop exits due to OVRES!
+		 */
+		readl(&reg_base->rdr);
+	}
+
+	for (len_tx = 0, len_rx = 0; len_rx < len; ) {
+		status = readl(&reg_base->sr);
+
+		if (status & ATMEL_SPI_SR_OVRES)
+			return -1;
+
+		if ((len_tx < len) && (status & ATMEL_SPI_SR_TDRE)) {
+			if (txp)
+				value = *txp++;
+			else
+				value = 0;
+			writel(value, &reg_base->tdr);
+			len_tx++;
+		}
+
+		if (status & ATMEL_SPI_SR_RDRF) {
+			value = readl(&reg_base->rdr);
+			if (rxp)
+				*rxp++ = value;
+			len_rx++;
+		}
+	}
+
+out:
+	if (flags & SPI_XFER_END) {
+		/*
+		 * Wait until the transfer is completely done before
+		 * we deactivate CS.
+		 */
+		wait_for_bit(__func__, &reg_base->sr,
+			     ATMEL_SPI_SR_TXEMPTY, true, 1000, false);
+
+		atmel_spi_cs_deactivate(dev);
+	}
+
+	return 0;
+}
+
+static int atmel_spi_set_speed(struct udevice *bus, uint speed)
+{
+	struct atmel_spi_priv *priv = dev_get_priv(bus);
+
+	priv->freq = speed;
+
+	return 0;
+}
+
+static int atmel_spi_set_mode(struct udevice *bus, uint mode)
+{
+	struct atmel_spi_priv *priv = dev_get_priv(bus);
+
+	priv->mode = mode;
+
+	return 0;
+}
+
+static const struct dm_spi_ops atmel_spi_ops = {
+	.claim_bus	= atmel_spi_claim_bus,
+	.release_bus	= atmel_spi_release_bus,
+	.xfer		= atmel_spi_xfer,
+	.set_speed	= atmel_spi_set_speed,
+	.set_mode	= atmel_spi_set_mode,
+	/*
+	 * cs_info is not needed, since we require all chip selects to be
+	 * in the device tree explicitly
+	 */
+};
+
+static int atmel_spi_enable_clk(struct udevice *bus)
+{
+	struct atmel_spi_priv *priv = dev_get_priv(bus);
+	struct clk clk;
+	ulong clk_rate;
+	int ret;
+
+	ret = clk_get_by_index(bus, 0, &clk);
+	if (ret)
+		return -EINVAL;
+
+	ret = clk_enable(&clk);
+	if (ret)
+		return ret;
+
+	clk_rate = clk_get_rate(&clk);
+	if (!clk_rate)
+		return -EINVAL;
+
+	priv->bus_clk_rate = clk_rate;
+
+	clk_free(&clk);
+
+	return 0;
+}
+
+static int atmel_spi_probe(struct udevice *bus)
+{
+	struct atmel_spi_platdata *bus_plat = dev_get_platdata(bus);
+	struct atmel_spi_priv *priv = dev_get_priv(bus);
+	int i, ret;
+
+	ret = atmel_spi_enable_clk(bus);
+	if (ret)
+		return ret;
+
+	bus_plat->regs = (struct at91_spi *)dev_get_addr(bus);
+
+	ret = gpio_request_list_by_name(bus, "cs-gpios", priv->cs_gpios,
+					ARRAY_SIZE(priv->cs_gpios), 0);
+	if (ret < 0) {
+		error("Can't get %s gpios! Error: %d", bus->name, ret);
+		return ret;
+	}
+
+	for(i = 0; i < ARRAY_SIZE(priv->cs_gpios); i++) {
+		dm_gpio_set_dir_flags(&priv->cs_gpios[i],
+				      GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
+	}
+
+	writel(ATMEL_SPI_CR_SWRST, &bus_plat->regs->cr);
+
+	return 0;
+}
+
+static const struct udevice_id atmel_spi_ids[] = {
+	{ .compatible = "atmel,at91rm9200-spi" },
+	{ }
+};
+
+U_BOOT_DRIVER(atmel_spi) = {
+	.name	= "atmel_spi",
+	.id	= UCLASS_SPI,
+	.of_match = atmel_spi_ids,
+	.ops	= &atmel_spi_ops,
+	.platdata_auto_alloc_size = sizeof(struct atmel_spi_platdata),
+	.priv_auto_alloc_size = sizeof(struct atmel_spi_priv),
+	.probe	= atmel_spi_probe,
+};
+#endif
diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
index 2b138c515355f97481cb362490b495665b7e4c24..a5c6d349747ff247139bca0278f4ad37de6c2e23 100644
--- a/drivers/usb/host/ehci-atmel.c
+++ b/drivers/usb/host/ehci-atmel.c
@@ -56,9 +56,7 @@ struct ehci_atmel_priv {
 
 static int ehci_atmel_enable_clk(struct udevice *dev)
 {
-	struct udevice *dev_clk;
 	struct clk clk;
-	int periph;
 	int ret;
 
 	ret = clk_get_by_index(dev, 0, &clk);
@@ -73,19 +71,6 @@ static int ehci_atmel_enable_clk(struct udevice *dev)
 	if (ret)
 		return -EINVAL;
 
-	periph = fdtdec_get_uint(gd->fdt_blob, clk.dev->of_offset, "reg", -1);
-	if (periph < 0)
-		return -EINVAL;
-
-	dev_clk = dev_get_parent(clk.dev);
-	if (!dev_clk)
-		return -ENODEV;
-
-	ret = clk_request(dev_clk, &clk);
-	if (ret)
-		return ret;
-
-	clk.id = periph;
 	ret = clk_enable(&clk);
 	if (ret)
 		return ret;
diff --git a/include/configs/at91-sama5_common.h b/include/configs/at91-sama5_common.h
index b09ef33e574a379556d61543def8d9c0cebfec16..13140bae1f82a841402e6500f3f7b7f1a3415400 100644
--- a/include/configs/at91-sama5_common.h
+++ b/include/configs/at91-sama5_common.h
@@ -74,7 +74,7 @@
 #define CONFIG_BOOTARGS							\
 	"console=ttyS0,115200 earlyprintk "				\
 	"mtdparts=atmel_nand:256k(bootstrap)ro,512k(uboot)ro,"		\
-	"256K(env),256k(env_redundent),256k(spare),"			\
+	"256K(env),256k(env_redundant),256k(spare),"			\
 	"512k(dtb),6M(kernel)ro,-(rootfs) "				\
 	"rootfstype=ubifs ubi.mtd=7 root=ubi0:rootfs"
 
diff --git a/include/configs/at91sam9rlek.h b/include/configs/at91sam9rlek.h
index 5b3a3d1b481a65ebcdfacf18adeb23b485cba892..23184ceba00086f1275c5a42a01904e191ff0da6 100644
--- a/include/configs/at91sam9rlek.h
+++ b/include/configs/at91sam9rlek.h
@@ -148,7 +148,7 @@
 #define CONFIG_BOOTARGS		\
 				"console=ttyS0,115200 earlyprintk "				\
 				"mtdparts=atmel_nand:256k(bootstrap)ro,512k(uboot)ro,"		\
-				"256K(env),256k(env_redundent),256k(spare),"			\
+				"256K(env),256k(env_redundant),256k(spare),"			\
 				"512k(dtb),6M(kernel)ro,-(rootfs) "				\
 				"rootfstype=ubifs ubi.mtd=7 root=ubi0:rootfs"
 
diff --git a/include/configs/sama5d2_xplained.h b/include/configs/sama5d2_xplained.h
index 30fb9a4dfb652f0de2919adedd2ee0e4c347ee15..f6946453e5df9c584c198022810d2e2ff3eaf94f 100644
--- a/include/configs/sama5d2_xplained.h
+++ b/include/configs/sama5d2_xplained.h
@@ -15,10 +15,9 @@
 
 #include "at91-sama5_common.h"
 
-/* serial console */
-#define CONFIG_ATMEL_USART
-#define CONFIG_USART_BASE		ATMEL_BASE_UART1
-#define CONFIG_USART_ID			ATMEL_ID_UART1
+#define CONFIG_BOARD_EARLY_INIT_F
+
+#define CONFIG_MISC_INIT_R
 
 /* SDRAM */
 #define CONFIG_NR_DRAM_BANKS		1
@@ -34,14 +33,8 @@
 
 #define CONFIG_SYS_LOAD_ADDR		0x22000000 /* load address */
 
-#undef CONFIG_AT91_GPIO
-#define CONFIG_ATMEL_PIO4
-
 /* SerialFlash */
 #ifdef CONFIG_CMD_SF
-#define CONFIG_ATMEL_SPI
-#define CONFIG_ATMEL_SPI0
-#define CONFIG_SPI_FLASH_ATMEL
 #define CONFIG_SF_DEFAULT_BUS		0
 #define CONFIG_SF_DEFAULT_CS		0
 #define CONFIG_SF_DEFAULT_SPEED		30000000
@@ -51,23 +44,9 @@
 #undef CONFIG_CMD_NAND
 
 /* MMC */
-
 #ifdef CONFIG_CMD_MMC
-#define CONFIG_MMC
 #define CONFIG_GENERIC_MMC
 #define CONFIG_SDHCI
-#define CONFIG_ATMEL_SDHCI
-#define CONFIG_ATMEL_SDHCI0
-#define CONFIG_ATMEL_SDHCI1
-#define CONFIG_SUPPORT_EMMC_BOOT
-#endif
-
-/* USB */
-
-#ifdef CONFIG_CMD_USB
-#define CONFIG_USB_EHCI
-#define CONFIG_USB_EHCI_ATMEL
-#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS	3
 #endif
 
 /* USB device */
@@ -79,6 +58,10 @@
 #define CONFIG_DOS_PARTITION
 #endif
 
+/* I2C */
+#define AT24MAC_ADDR		0x5c
+#define AT24MAC_REG		0x9a
+
 /* Ethernet Hardware */
 #define CONFIG_MACB
 #define CONFIG_RMII