Merge git://git.denx.de/u-boot-x86
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 0d055e3a..9db56f2 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -427,6 +427,9 @@
 	logicpd-torpedo-37xx-devkit.dtb \
 	logicpd-som-lv-37xx-devkit.dtb
 
+dtb-$(CONFIG_TARGET_SAMA5D2_PTC_EK) += \
+	at91-sama5d2_ptc_ek.dtb
+
 dtb-$(CONFIG_TARGET_SAMA5D2_XPLAINED) += \
 	at91-sama5d2_xplained.dtb
 
diff --git a/arch/arm/dts/at91-sama5d2_ptc_ek.dts b/arch/arm/dts/at91-sama5d2_ptc_ek.dts
new file mode 100644
index 0000000..ab5ab21
--- /dev/null
+++ b/arch/arm/dts/at91-sama5d2_ptc_ek.dts
@@ -0,0 +1,215 @@
+/*
+ * at91-sama5d2_ptc_ek.dts - Device Tree file for SAMA5D2 PTC EK board
+ *
+ *  Copyright (C) 2017 Microchip Technology Inc,
+ *		       Ludovic Desroches <ludovic.desroches@microchip.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include "sama5d2.dtsi"
+#include "sama5d2-pinfunc.h"
+
+/ {
+	model = "Atmel SAMA5D2 PTC EK";
+	compatible = "atmel,sama5d2-ptc_ek", "atmel,sama5d2", "atmel,sama5";
+
+	chosen {
+		u-boot,dm-pre-reloc;
+		stdout-path = &uart0;
+	};
+
+	ahb {
+		usb0: gadget@00300000 {
+			atmel,vbus-gpio = <&pioA PIN_PA27 GPIO_ACTIVE_HIGH>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_usba_vbus>;
+			status = "okay";
+		};
+
+		usb1: ohci@00400000 {
+			num-ports = <3>;
+			atmel,vbus-gpio = <0
+					   &pioA PIN_PB12 GPIO_ACTIVE_HIGH
+					   0
+					  >;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_usb_default>;
+			status = "okay";
+		};
+
+		usb2: ehci@00500000 {
+			status = "okay";
+		};
+
+		sdmmc0: sdio-host@a0000000 {
+			bus-width = <8>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_sdmmc0_cmd_dat_default &pinctrl_sdmmc0_ck_cd_default>;
+			status = "okay";
+			u-boot,dm-pre-reloc;
+		};
+
+		sdmmc1: sdio-host@b0000000 {
+			bus-width = <4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_sdmmc1_cmd_dat_default &pinctrl_sdmmc1_ck_cd_default>;
+			status = "disabled"; /* conflicts with nand and qspi0*/
+			u-boot,dm-pre-reloc;
+		};
+
+		apb {
+			macb0: ethernet@f8008000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_macb0_rmii &pinctrl_macb0_phy_irq>;
+				phy-mode = "rmii";
+				status = "okay";
+
+				ethernet-phy@1 {
+					reg = <0x1>;
+				};
+			};
+
+			uart0: serial@f801c000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_uart0_default>;
+				status = "okay";
+				u-boot,dm-pre-reloc;
+			};
+
+			i2c1: i2c@fc028000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_i2c1_default>;
+				status = "okay";
+
+				i2c_eeprom: i2c_eeprom@50 {
+					compatible = "atmel,24mac402";
+					reg = <0x50>;
+				};
+			};
+
+			pioA: gpio@fc038000 {
+				pinctrl {
+					pinctrl_i2c1_default: i2c1_default {
+						pinmux = <PIN_PC6__TWD1>,
+							 <PIN_PC7__TWCK1>;
+						bias-disable;
+					};
+
+					pinctrl_macb0_phy_irq: macb0_phy_irq {
+						pinmux = <PIN_PB24__GPIO>;
+						bias-disable;
+					};
+
+					pinctrl_macb0_rmii: macb0_rmii {
+						pinmux = <PIN_PB14__GTXCK>,
+							 <PIN_PB15__GTXEN>,
+							 <PIN_PB16__GRXDV>,
+							 <PIN_PB17__GRXER>,
+							 <PIN_PB18__GRX0>,
+							 <PIN_PB19__GRX1>,
+							 <PIN_PB20__GTX0>,
+							 <PIN_PB21__GTX1>,
+							 <PIN_PB22__GMDC>,
+							 <PIN_PB23__GMDIO>;
+						bias-disable;
+					};
+
+					pinctrl_sdmmc0_cmd_dat_default: sdmmc0_cmd_dat_default {
+						pinmux = <PIN_PA1__SDMMC0_CMD>,
+							 <PIN_PA2__SDMMC0_DAT0>,
+							 <PIN_PA3__SDMMC0_DAT1>,
+							 <PIN_PA4__SDMMC0_DAT2>,
+							 <PIN_PA5__SDMMC0_DAT3>,
+							 <PIN_PA6__SDMMC0_DAT4>,
+							 <PIN_PA7__SDMMC0_DAT5>,
+							 <PIN_PA8__SDMMC0_DAT6>,
+							 <PIN_PA9__SDMMC0_DAT7>;
+						bias-pull-up;
+						u-boot,dm-pre-reloc;
+					};
+
+					pinctrl_sdmmc0_ck_cd_default: sdmmc0_ck_cd_default {
+						pinmux = <PIN_PA0__SDMMC0_CK>,
+							 <PIN_PA10__SDMMC0_RSTN>,
+							 <PIN_PA11__SDMMC0_VDDSEL>,
+							 <PIN_PA13__SDMMC0_CD>;
+						bias-disable;
+						u-boot,dm-pre-reloc;
+					};
+
+					pinctrl_sdmmc1_cmd_dat_default: sdmmc1_cmd_dat_default {
+						pinmux = <PIN_PA28__SDMMC1_CMD>,
+							 <PIN_PA18__SDMMC1_DAT0>,
+							 <PIN_PA19__SDMMC1_DAT1>,
+							 <PIN_PA20__SDMMC1_DAT2>,
+							 <PIN_PA21__SDMMC1_DAT3>;
+						bias-pull-up;
+						u-boot,dm-pre-reloc;
+					};
+
+					pinctrl_sdmmc1_ck_cd_default: sdmmc1_ck_cd_default {
+						pinmux = <PIN_PA22__SDMMC1_CK>,
+							 <PIN_PA30__SDMMC1_CD>;
+						bias-disable;
+						u-boot,dm-pre-reloc;
+					};
+
+					pinctrl_uart0_default: uart0_default {
+						pinmux = <PIN_PB26__URXD0>,
+							 <PIN_PB27__UTXD0>;
+						bias-disable;
+						u-boot,dm-pre-reloc;
+					};
+
+					pinctrl_usb_default: usb_default {
+						pinmux = <PIN_PB12__GPIO>;
+						bias-disable;
+					};
+
+					pinctrl_usba_vbus: usba_vbus {
+						pinmux = <PIN_PB11__GPIO>;
+						bias-disable;
+					};
+				};
+			};
+		};
+	};
+};
diff --git a/arch/arm/dts/logicpd-torpedo-37xx-devkit-u-boot.dtsi b/arch/arm/dts/logicpd-torpedo-37xx-devkit-u-boot.dtsi
index 85cb548..d46ecdb 100644
--- a/arch/arm/dts/logicpd-torpedo-37xx-devkit-u-boot.dtsi
+++ b/arch/arm/dts/logicpd-torpedo-37xx-devkit-u-boot.dtsi
@@ -6,6 +6,8 @@
  */
 
 / {
+	model = "LogicPD Zoom OMAP3 Development Kit";
+
 	chosen {
 		stdout-path = &uart1;
 	};
diff --git a/arch/arm/dts/sama5d2.dtsi b/arch/arm/dts/sama5d2.dtsi
index 7520446..6645a55 100644
--- a/arch/arm/dts/sama5d2.dtsi
+++ b/arch/arm/dts/sama5d2.dtsi
@@ -302,6 +302,7 @@
 						#clock-cells = <0>;
 						reg = <24>;
 						atmel,clk-output-range = <0 83000000>;
+						u-boot,dm-pre-reloc;
 					};
 
 					uart1_clk: uart1_clk@25 {
@@ -315,6 +316,7 @@
 						#clock-cells = <0>;
 						reg = <26>;
 						atmel,clk-output-range = <0 83000000>;
+						u-boot,dm-pre-reloc;
 					};
 
 					uart3_clk: uart3_clk@27 {
@@ -635,6 +637,14 @@
 				status = "disabled";
 			};
 
+			uart0: serial@f801c000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xf801c000 0x100>;
+				clocks = <&uart0_clk>;
+				clock-names = "usart";
+				status = "disabled";
+			};
+
 			uart1: serial@f8020000 {
 				compatible = "atmel,at91sam9260-usart";
 				reg = <0xf8020000 0x100>;
@@ -643,6 +653,14 @@
 				status = "disabled";
 			};
 
+			uart2: serial@f8024000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xf8024000 0x100>;
+				clocks = <&uart2_clk>;
+				clock-names = "usart";
+				status = "disabled";
+			};
+
 			i2c0: i2c@f8028000 {
 				compatible = "atmel,sama5d2-i2c";
 				reg = <0xf8028000 0x100>;
diff --git a/arch/arm/dts/stm32f7-u-boot.dtsi b/arch/arm/dts/stm32f7-u-boot.dtsi
index 5f77f57..a56ae93 100644
--- a/arch/arm/dts/stm32f7-u-boot.dtsi
+++ b/arch/arm/dts/stm32f7-u-boot.dtsi
@@ -22,3 +22,7 @@
 		 u-boot,dm-pre-reloc;
 	};
 };
+
+&pwrcfg {
+	u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/stm32f746.dtsi b/arch/arm/dts/stm32f746.dtsi
index 783d4e7..f62360f 100644
--- a/arch/arm/dts/stm32f746.dtsi
+++ b/arch/arm/dts/stm32f746.dtsi
@@ -99,12 +99,19 @@
 			status = "disabled";
 			u-boot,dm-pre-reloc;
 		};
+
+		pwrcfg: power-config@58024800 {
+			compatible = "syscon";
+			reg = <0x40007000 0x400>;
+		};
+
 		rcc: rcc@40023810 {
 			#reset-cells = <1>;
 			#clock-cells = <2>;
-			compatible = "st,stm32f42xx-rcc", "st,stm32-rcc";
+			compatible = "st,stm32f746-rcc", "st,stm32-rcc";
 			reg = <0x40023800 0x400>;
 			clocks = <&clk_hse>;
+			st,syscfg = <&pwrcfg>;
 			u-boot,dm-pre-reloc;
 		};
 
diff --git a/arch/arm/include/asm/arch-stm32f4/stm32.h b/arch/arm/include/asm/arch-stm32f4/stm32.h
index 6cc1966..e9f3aab 100644
--- a/arch/arm/include/asm/arch-stm32f4/stm32.h
+++ b/arch/arm/include/asm/arch-stm32f4/stm32.h
@@ -42,41 +42,6 @@
 	u32 u_id_high;
 };
 
-struct stm32_rcc_regs {
-	u32 cr;		/* RCC clock control */
-	u32 pllcfgr;	/* RCC PLL configuration */
-	u32 cfgr;	/* RCC clock configuration */
-	u32 cir;	/* RCC clock interrupt */
-	u32 ahb1rstr;	/* RCC AHB1 peripheral reset */
-	u32 ahb2rstr;	/* RCC AHB2 peripheral reset */
-	u32 ahb3rstr;	/* RCC AHB3 peripheral reset */
-	u32 rsv0;
-	u32 apb1rstr;	/* RCC APB1 peripheral reset */
-	u32 apb2rstr;	/* RCC APB2 peripheral reset */
-	u32 rsv1[2];
-	u32 ahb1enr;	/* RCC AHB1 peripheral clock enable */
-	u32 ahb2enr;	/* RCC AHB2 peripheral clock enable */
-	u32 ahb3enr;	/* RCC AHB3 peripheral clock enable */
-	u32 rsv2;
-	u32 apb1enr;	/* RCC APB1 peripheral clock enable */
-	u32 apb2enr;	/* RCC APB2 peripheral clock enable */
-	u32 rsv3[2];
-	u32 ahb1lpenr;	/* RCC AHB1 periph clk enable in low pwr mode */
-	u32 ahb2lpenr;	/* RCC AHB2 periph clk enable in low pwr mode */
-	u32 ahb3lpenr;	/* RCC AHB3 periph clk enable in low pwr mode */
-	u32 rsv4;
-	u32 apb1lpenr;	/* RCC APB1 periph clk enable in low pwr mode */
-	u32 apb2lpenr;	/* RCC APB2 periph clk enable in low pwr mode */
-	u32 rsv5[2];
-	u32 bdcr;	/* RCC Backup domain control */
-	u32 csr;	/* RCC clock control & status */
-	u32 rsv6[2];
-	u32 sscgr;	/* RCC spread spectrum clock generation */
-	u32 plli2scfgr;	/* RCC PLLI2S configuration */
-	u32 pllsaicfgr;
-	u32 dckcfgr;
-};
-
 struct stm32_pwr_regs {
 	u32 cr;
 	u32 csr;
diff --git a/arch/arm/include/asm/arch-stm32f4/stm32_pwr.h b/arch/arm/include/asm/arch-stm32f4/stm32_pwr.h
new file mode 100644
index 0000000..bfe5469
--- /dev/null
+++ b/arch/arm/include/asm/arch-stm32f4/stm32_pwr.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
+ * Author(s): Patrice Chotard, <patrice.chotard@st.com> for STMicroelectronics.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __STM32_PWR_H_
+
+/*
+ * Offsets of some PWR registers
+ */
+#define PWR_CR1_ODEN			BIT(16)
+#define PWR_CR1_ODSWEN			BIT(17)
+#define PWR_CSR1_ODRDY			BIT(16)
+#define PWR_CSR1_ODSWRDY		BIT(17)
+
+struct stm32_pwr_regs {
+	u32 cr1;   /* power control register 1 */
+	u32 csr1;  /* power control/status register 2 */
+};
+
+#endif /* __STM32_PWR_H_ */
diff --git a/arch/arm/include/asm/arch-stm32f7/rcc.h b/arch/arm/include/asm/arch-stm32f7/rcc.h
deleted file mode 100644
index 6475f9d..0000000
--- a/arch/arm/include/asm/arch-stm32f7/rcc.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
- * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics.
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#ifndef _STM32_RCC_H
-#define _STM32_RCC_H
-
-#include <dt-bindings/mfd/stm32f7-rcc.h>
-
-/*
- * RCC AHB1ENR specific definitions
- */
-#define RCC_AHB1ENR_ETHMAC_EN		BIT(25)
-#define RCC_AHB1ENR_ETHMAC_TX_EN	BIT(26)
-#define RCC_AHB1ENR_ETHMAC_RX_EN	BIT(27)
-
-/*
- * RCC APB1ENR specific definitions
- */
-#define RCC_APB1ENR_TIM2EN		BIT(0)
-#define RCC_APB1ENR_PWREN		BIT(28)
-
-/*
- * RCC APB2ENR specific definitions
- */
-#define RCC_APB2ENR_SYSCFGEN		BIT(14)
-
-#endif
diff --git a/arch/arm/include/asm/arch-stm32f7/stm32.h b/arch/arm/include/asm/arch-stm32f7/stm32.h
index d6412a0..f54e6f1 100644
--- a/arch/arm/include/asm/arch-stm32f7/stm32.h
+++ b/arch/arm/include/asm/arch-stm32f7/stm32.h
@@ -59,49 +59,8 @@
 
 #define STM32_BUS_MASK		GENMASK(31, 16)
 
-struct stm32_rcc_regs {
-	u32 cr;		/* RCC clock control */
-	u32 pllcfgr;	/* RCC PLL configuration */
-	u32 cfgr;	/* RCC clock configuration */
-	u32 cir;	/* RCC clock interrupt */
-	u32 ahb1rstr;	/* RCC AHB1 peripheral reset */
-	u32 ahb2rstr;	/* RCC AHB2 peripheral reset */
-	u32 ahb3rstr;	/* RCC AHB3 peripheral reset */
-	u32 rsv0;
-	u32 apb1rstr;	/* RCC APB1 peripheral reset */
-	u32 apb2rstr;	/* RCC APB2 peripheral reset */
-	u32 rsv1[2];
-	u32 ahb1enr;	/* RCC AHB1 peripheral clock enable */
-	u32 ahb2enr;	/* RCC AHB2 peripheral clock enable */
-	u32 ahb3enr;	/* RCC AHB3 peripheral clock enable */
-	u32 rsv2;
-	u32 apb1enr;	/* RCC APB1 peripheral clock enable */
-	u32 apb2enr;	/* RCC APB2 peripheral clock enable */
-	u32 rsv3[2];
-	u32 ahb1lpenr;	/* RCC AHB1 periph clk enable in low pwr mode */
-	u32 ahb2lpenr;	/* RCC AHB2 periph clk enable in low pwr mode */
-	u32 ahb3lpenr;	/* RCC AHB3 periph clk enable in low pwr mode */
-	u32 rsv4;
-	u32 apb1lpenr;	/* RCC APB1 periph clk enable in low pwr mode */
-	u32 apb2lpenr;	/* RCC APB2 periph clk enable in low pwr mode */
-	u32 rsv5[2];
-	u32 bdcr;	/* RCC Backup domain control */
-	u32 csr;	/* RCC clock control & status */
-	u32 rsv6[2];
-	u32 sscgr;	/* RCC spread spectrum clock generation */
-	u32 plli2scfgr;	/* RCC PLLI2S configuration */
-	u32 pllsaicfgr;	/* PLLSAI configuration */
-	u32 dckcfgr;	/* dedicated clocks configuration register */
-};
 #define STM32_RCC		((struct stm32_rcc_regs *)RCC_BASE)
 
-struct stm32_pwr_regs {
-	u32 cr1;   /* power control register 1 */
-	u32 csr1;  /* power control/status register 2 */
-	u32 cr2;   /* power control register 2 */
-	u32 csr2;  /* power control/status register 2 */
-};
-#define STM32_PWR		((struct stm32_pwr_regs *)PWR_BASE)
 
 void stm32_flash_latency_cfg(int latency);
 
diff --git a/arch/arm/include/asm/arch-stm32f7/stm32_pwr.h b/arch/arm/include/asm/arch-stm32f7/stm32_pwr.h
new file mode 100644
index 0000000..917dd46
--- /dev/null
+++ b/arch/arm/include/asm/arch-stm32f7/stm32_pwr.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
+ * Author(s): Patrice Chotard, <patrice.chotard@st.com> for STMicroelectronics.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __STM32_PWR_H_
+
+/*
+ * Offsets of some PWR registers
+ */
+#define PWR_CR1_ODEN			BIT(16)
+#define PWR_CR1_ODSWEN			BIT(17)
+#define PWR_CSR1_ODRDY			BIT(16)
+#define PWR_CSR1_ODSWRDY		BIT(17)
+
+struct stm32_pwr_regs {
+	u32 cr1;   /* power control register 1 */
+	u32 csr1;  /* power control/status register 2 */
+	u32 cr2;   /* power control register 2 */
+	u32 csr2;  /* power control/status register 2 */
+};
+
+#endif /* __STM32_PWR_H_ */
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index 7e85b69..6907263 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -143,10 +143,9 @@
 	select BOARD_EARLY_INIT_F
 	select BOARD_LATE_INIT
 
-config TARGET_SAMA5D2_PTC
-	bool "SAMA5D2 PTC board"
+config TARGET_SAMA5D2_PTC_EK
+	bool "SAMA5D2 PTC EK board"
 	select SAMA5D2
-	select SUPPORT_SPL
 	select BOARD_EARLY_INIT_F
 
 config TARGET_SAMA5D2_XPLAINED
@@ -236,6 +235,18 @@
 	bool "Support VINCO"
 	select SAMA5D4
 	select SUPPORT_SPL
+
+config TARGET_WB45N
+	bool "Support Laird WB45N"
+	select CPU_ARM926EJS
+	select SUPPORT_SPL
+
+config TARGET_WB50N
+	bool "Support Laird WB50N"
+	select BOARD_LATE_INIT
+	select CPU_V7
+	select SUPPORT_SPL
+	select BOARD_EARLY_INIT_F
 
 endchoice
 
@@ -251,7 +262,7 @@
 source "board/atmel/at91sam9n12ek/Kconfig"
 source "board/atmel/at91sam9rlek/Kconfig"
 source "board/atmel/at91sam9x5ek/Kconfig"
-source "board/atmel/sama5d2_ptc/Kconfig"
+source "board/atmel/sama5d2_ptc_ek/Kconfig"
 source "board/atmel/sama5d2_xplained/Kconfig"
 source "board/atmel/sama5d27_som1_ek/Kconfig"
 source "board/atmel/sama5d3_xplained/Kconfig"
@@ -271,6 +282,8 @@
 source "board/siemens/corvus/Kconfig"
 source "board/siemens/taurus/Kconfig"
 source "board/siemens/smartweb/Kconfig"
+source "board/laird/wb45n/Kconfig"
+source "board/laird/wb50n/Kconfig"
 
 config SPL_LDSCRIPT
 	default "arch/arm/mach-at91/arm926ejs/u-boot-spl.lds" if CPU_ARM926EJS
diff --git a/arch/arm/mach-at91/include/mach/gpio.h b/arch/arm/mach-at91/include/mach/gpio.h
index df0f719..e206316 100644
--- a/arch/arm/mach-at91/include/mach/gpio.h
+++ b/arch/arm/mach-at91/include/mach/gpio.h
@@ -219,6 +219,8 @@
 	at91_set_a_periph((x - PIN_BASE) / 32,(x % 32), y)
 #define at91_set_B_periph(x, y) \
 	at91_set_b_periph((x - PIN_BASE) / 32,(x % 32), y)
+#define at91_set_gpio_deglitch(x, y) \
+	at91_set_pio_deglitch((x - PIN_BASE) / 32,(x % 32), y)
 #define at91_set_gpio_output(x, y) \
 	at91_set_pio_output((x - PIN_BASE) / 32,(x % 32), y)
 #define at91_set_gpio_input(x, y) \
diff --git a/arch/arm/mach-at91/include/mach/sama5d2_smc.h b/arch/arm/mach-at91/include/mach/sama5d2_smc.h
new file mode 100644
index 0000000..7ddb728
--- /dev/null
+++ b/arch/arm/mach-at91/include/mach/sama5d2_smc.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2017 Microchip Corporation.
+ *
+ * Static Memory Controllers (SMC) - System peripherals registers.
+ * Based on SAMA5D2 datasheet.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef SAMA5D2_SMC_H
+#define SAMA5D2_SMC_H
+
+#ifdef __ASSEMBLY__
+#define AT91_ASM_SMC_SETUP0	(ATMEL_BASE_SMC + 0x700)
+#define AT91_ASM_SMC_PULSE0	(ATMEL_BASE_SMC + 0x704)
+#define AT91_ASM_SMC_CYCLE0	(ATMEL_BASE_SMC + 0x708)
+#define AT91_ASM_SMC_TIMINGS0	(ATMEL_BASE_SMC + 0x70c)
+#define AT91_ASM_SMC_MODE0	(ATMEL_BASE_SMC + 0x710)
+#else
+struct at91_cs {
+	u32	setup;		/* 0x600 SMC Setup Register */
+	u32	pulse;		/* 0x604 SMC Pulse Register */
+	u32	cycle;		/* 0x608 SMC Cycle Register */
+	u32	timings;	/* 0x60C SMC Cycle Register */
+	u32	mode;		/* 0x610 SMC Mode Register */
+};
+
+struct at91_smc {
+	struct at91_cs cs[4];
+};
+#endif /*  __ASSEMBLY__ */
+
+#define AT91_SMC_SETUP_NWE(x)		(x & 0x3f)
+#define AT91_SMC_SETUP_NCS_WR(x)	((x & 0x3f) << 8)
+#define AT91_SMC_SETUP_NRD(x)		((x & 0x3f) << 16)
+#define AT91_SMC_SETUP_NCS_RD(x)	((x & 0x3f) << 24)
+
+#define AT91_SMC_PULSE_NWE(x)		(x & 0x7f)
+#define AT91_SMC_PULSE_NCS_WR(x)	((x & 0x7f) << 8)
+#define AT91_SMC_PULSE_NRD(x)		((x & 0x7f) << 16)
+#define AT91_SMC_PULSE_NCS_RD(x)	((x & 0x7f) << 24)
+
+#define AT91_SMC_CYCLE_NWE(x)		(x & 0x1ff)
+#define AT91_SMC_CYCLE_NRD(x)		((x & 0x1ff) << 16)
+
+#define AT91_SMC_TIMINGS_TCLR(x)	(x & 0xf)
+#define AT91_SMC_TIMINGS_TADL(x)	((x & 0xf) << 4)
+#define AT91_SMC_TIMINGS_TAR(x)		((x & 0xf) << 8)
+#define AT91_SMC_TIMINGS_OCMS(x)	((x & 0x1) << 12)
+#define AT91_SMC_TIMINGS_TRR(x)		((x & 0xf) << 16)
+#define AT91_SMC_TIMINGS_TWB(x)		((x & 0xf) << 24)
+#define AT91_SMC_TIMINGS_RBNSEL(x)	((x & 0xf) << 28)
+#define AT91_SMC_TIMINGS_NFSEL(x)	((x & 0x1) << 31)
+
+#define AT91_SMC_MODE_RM_NCS		0x00000000
+#define AT91_SMC_MODE_RM_NRD		0x00000001
+#define AT91_SMC_MODE_WM_NCS		0x00000000
+#define AT91_SMC_MODE_WM_NWE		0x00000002
+
+#define AT91_SMC_MODE_EXNW_DISABLE	0x00000000
+#define AT91_SMC_MODE_EXNW_FROZEN	0x00000020
+#define AT91_SMC_MODE_EXNW_READY	0x00000030
+
+#define AT91_SMC_MODE_BAT		0x00000100
+#define AT91_SMC_MODE_DBW_8		0x00000000
+#define AT91_SMC_MODE_DBW_16		0x00001000
+#define AT91_SMC_MODE_DBW_32		0x00002000
+#define AT91_SMC_MODE_TDF_CYCLE(x)	((x & 0xf) << 16)
+#define AT91_SMC_MODE_TDF		0x00100000
+#define AT91_SMC_MODE_PMEN		0x01000000
+#define AT91_SMC_MODE_PS_4		0x00000000
+#define AT91_SMC_MODE_PS_8		0x10000000
+#define AT91_SMC_MODE_PS_16		0x20000000
+#define AT91_SMC_MODE_PS_32		0x30000000
+
+#endif
diff --git a/arch/arm/mach-stm32/Makefile b/arch/arm/mach-stm32/Makefile
index 0f5ac37..c2806af 100644
--- a/arch/arm/mach-stm32/Makefile
+++ b/arch/arm/mach-stm32/Makefile
@@ -4,7 +4,6 @@
 #
 # SPDX-License-Identifier:	GPL-2.0+
 #
-
+obj-y += soc.o
 obj-$(CONFIG_STM32F4) += stm32f4/
 obj-$(CONFIG_STM32F7) += stm32f7/
-obj-$(CONFIG_STM32H7) += stm32h7/
diff --git a/arch/arm/mach-stm32/stm32h7/soc.c b/arch/arm/mach-stm32/soc.c
similarity index 75%
rename from arch/arm/mach-stm32/stm32h7/soc.c
rename to arch/arm/mach-stm32/soc.c
index 692dbcc..df20d54 100644
--- a/arch/arm/mach-stm32/stm32h7/soc.c
+++ b/arch/arm/mach-stm32/soc.c
@@ -9,11 +9,6 @@
 #include <asm/io.h>
 #include <asm/armv7m_mpu.h>
 
-u32 get_cpu_rev(void)
-{
-	return 0;
-}
-
 int arch_cpu_init(void)
 {
 	int i;
@@ -30,11 +25,11 @@
 		{ 0x00000000, REGION_0, XN_DIS, PRIV_RW_USR_RW,
 		O_I_WB_RD_WR_ALLOC, REGION_4GB },
 
-		/* Code area, executable & strongly ordered */
-		{ 0xD0000000, REGION_1, XN_EN, PRIV_RW_USR_RW,
-		STRONG_ORDER, REGION_8MB },
+		/* armv7m code area */
+		{ 0x00000000, REGION_1, XN_DIS, PRIV_RW_USR_RW,
+		STRONG_ORDER, REGION_512MB },
 
-		/* Device area in all H7 : Not executable */
+		/* Device area : Not executable */
 		{ 0x40000000, REGION_2, XN_EN, PRIV_RW_USR_RW,
 		DEVICE_NON_SHARED, REGION_512MB },
 
@@ -42,8 +37,14 @@
 		 * Armv7m fixed configuration: strongly ordered & not
 		 * executable, not cacheable
 		 */
-		{ 0xE0000000, REGION_4, XN_EN, PRIV_RW_USR_RW,
+		{ 0xE0000000, REGION_3, XN_EN, PRIV_RW_USR_RW,
 		STRONG_ORDER, REGION_512MB },
+
+#if !defined(CONFIG_STM32H7)
+		/* Device area : Not executable */
+		{ 0xA0000000, REGION_4, XN_EN, PRIV_RW_USR_RW,
+		DEVICE_NON_SHARED, REGION_512MB },
+#endif
 	};
 
 	disable_mpu();
@@ -53,7 +54,3 @@
 
 	return 0;
 }
-
-void s_init(void)
-{
-}
diff --git a/arch/arm/mach-stm32/stm32f4/Makefile b/arch/arm/mach-stm32/stm32f4/Makefile
index 020e783..63db820 100644
--- a/arch/arm/mach-stm32/stm32f4/Makefile
+++ b/arch/arm/mach-stm32/stm32f4/Makefile
@@ -8,4 +8,4 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-obj-y += soc.o clock.o timer.o
+obj-y += clock.o timer.o
diff --git a/arch/arm/mach-stm32/stm32f4/clock.c b/arch/arm/mach-stm32/stm32f4/clock.c
index 15fcadb..774591d 100644
--- a/arch/arm/mach-stm32/stm32f4/clock.c
+++ b/arch/arm/mach-stm32/stm32f4/clock.c
@@ -9,6 +9,7 @@
  */
 
 #include <common.h>
+#include <stm32_rcc.h>
 #include <asm/io.h>
 #include <asm/arch/stm32.h>
 #include <asm/arch/stm32_periph.h>
@@ -81,32 +82,6 @@
 #define RCC_ENR_GPIO_J_EN	(1 << 9)
 #define RCC_ENR_GPIO_K_EN	(1 << 10)
 
-struct pll_psc {
-	u8	pll_m;
-	u16	pll_n;
-	u8	pll_p;
-	u8	pll_q;
-	u8	ahb_psc;
-	u8	apb1_psc;
-	u8	apb2_psc;
-};
-
-#define AHB_PSC_1		0
-#define AHB_PSC_2		0x8
-#define AHB_PSC_4		0x9
-#define AHB_PSC_8		0xA
-#define AHB_PSC_16		0xB
-#define AHB_PSC_64		0xC
-#define AHB_PSC_128		0xD
-#define AHB_PSC_256		0xE
-#define AHB_PSC_512		0xF
-
-#define APB_PSC_1		0
-#define APB_PSC_2		0x4
-#define APB_PSC_4		0x5
-#define APB_PSC_8		0x6
-#define APB_PSC_16		0x7
-
 #if !defined(CONFIG_STM32_HSE_HZ)
 #error "CONFIG_STM32_HSE_HZ not defined!"
 #else
diff --git a/arch/arm/mach-stm32/stm32f4/soc.c b/arch/arm/mach-stm32/stm32f4/soc.c
deleted file mode 100644
index 9eb655a..0000000
--- a/arch/arm/mach-stm32/stm32f4/soc.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * (C) Copyright 2015
- * Kamil Lulko, <kamil.lulko@gmail.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <asm/armv7m_mpu.h>
-#include <asm/arch/stm32.h>
-
-u32 get_cpu_rev(void)
-{
-	return 0;
-}
-
-int arch_cpu_init(void)
-{
-	struct mpu_region_config stm32_region_config[] = {
-		{ 0x00000000, REGION_0, XN_DIS, PRIV_RW_USR_RW,
-		STRONG_ORDER, REGION_4GB },
-	};
-	int i;
-
-	configure_clocks();
-	/*
-	 * Configure the memory protection unit (MPU) to allow full access to
-	 * the whole 4GB address space.
-	 */
-	disable_mpu();
-	for (i = 0; i < ARRAY_SIZE(stm32_region_config); i++)
-		mpu_config(&stm32_region_config[i]);
-	enable_mpu();
-
-	return 0;
-}
-
-void s_init(void)
-{
-}
diff --git a/arch/arm/mach-stm32/stm32f4/timer.c b/arch/arm/mach-stm32/stm32f4/timer.c
index 1dee190..163f461 100644
--- a/arch/arm/mach-stm32/stm32f4/timer.c
+++ b/arch/arm/mach-stm32/stm32f4/timer.c
@@ -6,6 +6,7 @@
  */
 
 #include <common.h>
+#include <stm32_rcc.h>
 #include <asm/io.h>
 #include <asm/armv7m.h>
 #include <asm/arch/stm32.h>
diff --git a/arch/arm/mach-stm32/stm32f7/Makefile b/arch/arm/mach-stm32/stm32f7/Makefile
index 6696b26..8132c13 100644
--- a/arch/arm/mach-stm32/stm32f7/Makefile
+++ b/arch/arm/mach-stm32/stm32f7/Makefile
@@ -5,4 +5,4 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-obj-y += timer.o soc.o
+obj-y += timer.o
diff --git a/arch/arm/mach-stm32/stm32f7/soc.c b/arch/arm/mach-stm32/stm32f7/soc.c
deleted file mode 100644
index a960cc1..0000000
--- a/arch/arm/mach-stm32/stm32f7/soc.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * (C) Copyright 2015
- * Kamil Lulko, <kamil.lulko@gmail.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <asm/armv7m_mpu.h>
-#include <asm/arch/stm32.h>
-
-u32 get_cpu_rev(void)
-{
-	return 0;
-}
-
-int arch_cpu_init(void)
-{
-	int i;
-
-	struct mpu_region_config stm32_region_config[] = {
-		{ 0x00000000, REGION_0, XN_DIS, PRIV_RW_USR_RW,
-		O_I_WB_RD_WR_ALLOC, REGION_4GB },
-
-		{ 0x00000000, REGION_1, XN_DIS, PRIV_RW_USR_RW,
-		STRONG_ORDER, REGION_512MB },
-
-		{ 0x40000000, REGION_2, XN_EN, PRIV_RW_USR_RW,
-		DEVICE_NON_SHARED, REGION_512MB },
-
-		{ 0xA0000000, REGION_3, XN_EN, PRIV_RW_USR_RW,
-		DEVICE_NON_SHARED, REGION_512MB },
-
-		{ 0xE0000000, REGION_4, XN_EN, PRIV_RW_USR_RW,
-		STRONG_ORDER, REGION_512MB },
-	};
-
-	disable_mpu();
-	for (i = 0; i < ARRAY_SIZE(stm32_region_config); i++)
-		mpu_config(&stm32_region_config[i]);
-	enable_mpu();
-
-	return 0;
-}
-
-void s_init(void)
-{
-}
diff --git a/arch/arm/mach-stm32/stm32f7/timer.c b/arch/arm/mach-stm32/stm32f7/timer.c
index 0521c24..69d37a7 100644
--- a/arch/arm/mach-stm32/stm32f7/timer.c
+++ b/arch/arm/mach-stm32/stm32f7/timer.c
@@ -6,6 +6,7 @@
  */
 
 #include <common.h>
+#include <stm32_rcc.h>
 #include <asm/io.h>
 #include <asm/arch/stm32.h>
 #include <asm/arch/stm32_defs.h>
diff --git a/arch/arm/mach-stm32/stm32h7/Makefile b/arch/arm/mach-stm32/stm32h7/Makefile
deleted file mode 100644
index cba2e3b..0000000
--- a/arch/arm/mach-stm32/stm32h7/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Copyright (C) 2017, STMicroelectronics - All Rights Reserved
-# Author(s): Patrice CHOTARD, <patrice.chotard@st.com> for STMicroelectronics.
-#
-# SPDX-License-Identifier:	GPL-2.0+
-#
-
-obj-y += soc.o
diff --git a/arch/nds32/dts/ae3xx.dts b/arch/nds32/dts/ae3xx.dts
index fbe6d74..b19ba98 100644
--- a/arch/nds32/dts/ae3xx.dts
+++ b/arch/nds32/dts/ae3xx.dts
@@ -69,6 +69,14 @@
 		interrupts = <25 4>;
 	};
 
+	mmc0: mmc@f0e00000 {
+		compatible = "andestech,atsdc010";
+		max-frequency = <100000000>;
+		fifo-depth = <0x10>;
+		reg = <0xf0e00000 0x1000>;
+		interrupts = <17 4>;
+	};
+
 	nor@0,0 {
 		compatible = "cfi-flash";
 		reg = <0x88000000 0x1000>;
diff --git a/arch/nds32/dts/ag101p.dts b/arch/nds32/dts/ag101p.dts
index 99cde2f..19dc36f 100644
--- a/arch/nds32/dts/ag101p.dts
+++ b/arch/nds32/dts/ag101p.dts
@@ -60,4 +60,12 @@
 		reg = <0x90900000 0x1000>;
 		interrupts = <25 4>;
 	};
+
+	mmc0: mmc@98e00000 {
+		compatible = "andestech,atsdc010";
+		max-frequency = <30000000>;
+		fifo-depth = <0x10>;
+		reg = <0x98e00000 0x1000>;
+		interrupts = <5 4>;
+	};
 };
diff --git a/board/AndesTech/adp-ag101p/adp-ag101p.c b/board/AndesTech/adp-ag101p/adp-ag101p.c
index 79608f4..f918c63 100644
--- a/board/AndesTech/adp-ag101p/adp-ag101p.c
+++ b/board/AndesTech/adp-ag101p/adp-ag101p.c
@@ -85,8 +85,10 @@
 
 int board_mmc_init(bd_t *bis)
 {
+#ifndef CONFIG_DM_MMC
 #ifdef CONFIG_FTSDC010
 	ftsdc010_mmc_init(0);
 #endif
+#endif
 	return 0;
 }
diff --git a/board/atmel/sama5d2_ptc/MAINTAINERS b/board/atmel/sama5d2_ptc/MAINTAINERS
deleted file mode 100644
index 7ab03d6..0000000
--- a/board/atmel/sama5d2_ptc/MAINTAINERS
+++ /dev/null
@@ -1,7 +0,0 @@
-SAMA5D2 PTC Engineering BOARD
-M:	Wenyou Yang <wenyou.yang@atmel.com>
-S:	Maintained
-F:	board/atmel/sama5d2_ptc/
-F:	include/configs/sama5d2_ptc.h
-F:	configs/sama5d2_ptc_spiflash_defconfig
-F:	configs/sama5d2_ptc_nandflash_defconfig
diff --git a/board/atmel/sama5d2_ptc/Makefile b/board/atmel/sama5d2_ptc/Makefile
deleted file mode 100644
index 1fe0392..0000000
--- a/board/atmel/sama5d2_ptc/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Copyright (C) 2016 Atmel
-#		     Wenyou Yang <wenyou.yang@atmel.com>
-#
-# SPDX-License-Identifier:	GPL-2.0+
-#
-
-obj-y += sama5d2_ptc.o
diff --git a/board/atmel/sama5d2_ptc/sama5d2_ptc.c b/board/atmel/sama5d2_ptc/sama5d2_ptc.c
deleted file mode 100644
index c441e69..0000000
--- a/board/atmel/sama5d2_ptc/sama5d2_ptc.c
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * Copyright (C) 2016 Atmel
- *		      Wenyou.Yang <wenyou.yang@atmel.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <atmel_hlcdc.h>
-#include <lcd.h>
-#include <mmc.h>
-#include <net.h>
-#include <netdev.h>
-#include <spi.h>
-#include <version.h>
-#include <asm/io.h>
-#include <asm/arch/at91_common.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>
-#include <asm/arch/gpio.h>
-#include <asm/arch/sama5_sfr.h>
-#include <asm/arch/sama5d2.h>
-#include <asm/arch/sama5d3_smc.h>
-
-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_nand_hw_init(void)
-{
-	struct at91_smc *smc = (struct at91_smc *)ATMEL_BASE_SMC;
-	struct atmel_sfr *sfr = (struct atmel_sfr *)ATMEL_BASE_SFR;
-
-	at91_periph_clk_enable(ATMEL_ID_HSMC);
-
-	writel(AT91_SFR_EBICFG_DRIVE0_HIGH |
-	       AT91_SFR_EBICFG_PULL0_NONE |
-	       AT91_SFR_EBICFG_DRIVE1_HIGH |
-	       AT91_SFR_EBICFG_PULL1_NONE, &sfr->ebicfg);
-
-	/* Configure SMC CS3 for NAND */
-	writel(AT91_SMC_SETUP_NWE(1) | AT91_SMC_SETUP_NCS_WR(1) |
-	       AT91_SMC_SETUP_NRD(1) | AT91_SMC_SETUP_NCS_RD(1),
-	       &smc->cs[3].setup);
-	writel(AT91_SMC_PULSE_NWE(2) | AT91_SMC_PULSE_NCS_WR(3) |
-	       AT91_SMC_PULSE_NRD(2) | AT91_SMC_PULSE_NCS_RD(3),
-	       &smc->cs[3].pulse);
-	writel(AT91_SMC_CYCLE_NWE(5) | AT91_SMC_CYCLE_NRD(5),
-	       &smc->cs[3].cycle);
-	writel(AT91_SMC_TIMINGS_TCLR(2) | AT91_SMC_TIMINGS_TADL(7) |
-	       AT91_SMC_TIMINGS_TAR(2)  | AT91_SMC_TIMINGS_TRR(3)   |
-	       AT91_SMC_TIMINGS_TWB(7)  | AT91_SMC_TIMINGS_RBNSEL(3) |
-	       AT91_SMC_TIMINGS_NFSEL(1), &smc->cs[3].timings);
-	writel(AT91_SMC_MODE_RM_NRD | AT91_SMC_MODE_WM_NWE |
-	       AT91_SMC_MODE_EXNW_DISABLE |
-	       AT91_SMC_MODE_DBW_8 |
-	       AT91_SMC_MODE_TDF_CYCLE(3),
-	       &smc->cs[3].mode);
-
-	atmel_pio4_set_f_periph(AT91_PIO_PORTA, 0, 0);	/* D0 */
-	atmel_pio4_set_f_periph(AT91_PIO_PORTA, 1, 0);	/* D1 */
-	atmel_pio4_set_f_periph(AT91_PIO_PORTA, 2, 0);	/* D2 */
-	atmel_pio4_set_f_periph(AT91_PIO_PORTA, 3, 0);	/* D3 */
-	atmel_pio4_set_f_periph(AT91_PIO_PORTA, 4, 0);	/* D4 */
-	atmel_pio4_set_f_periph(AT91_PIO_PORTA, 5, 0);	/* D5 */
-	atmel_pio4_set_f_periph(AT91_PIO_PORTA, 6, 0);	/* D6 */
-	atmel_pio4_set_f_periph(AT91_PIO_PORTA, 7, 0);	/* D7 */
-	atmel_pio4_set_f_periph(AT91_PIO_PORTA, 12, 0);	/* RE */
-	atmel_pio4_set_f_periph(AT91_PIO_PORTA, 8, 0);	/* WE */
-	atmel_pio4_set_f_periph(AT91_PIO_PORTA, 9, 1);	/* NCS */
-	atmel_pio4_set_f_periph(AT91_PIO_PORTA, 21, 1);	/* RDY */
-	atmel_pio4_set_f_periph(AT91_PIO_PORTA, 10, 1);	/* ALE */
-	atmel_pio4_set_f_periph(AT91_PIO_PORTA, 11, 1);	/* CLE */
-}
-
-static void board_usb_hw_init(void)
-{
-	atmel_pio4_set_pio_output(AT91_PIO_PORTA, 28, 1);
-}
-
-static void board_gmac_hw_init(void)
-{
-	atmel_pio4_set_f_periph(AT91_PIO_PORTB, 14, 0);	/* GTXCK */
-	atmel_pio4_set_f_periph(AT91_PIO_PORTB, 15, 0);	/* GTXEN */
-	atmel_pio4_set_f_periph(AT91_PIO_PORTB, 16, 0);	/* GRXDV */
-	atmel_pio4_set_f_periph(AT91_PIO_PORTB, 17, 0);	/* GRXER */
-	atmel_pio4_set_f_periph(AT91_PIO_PORTB, 18, 0);	/* GRX0 */
-	atmel_pio4_set_f_periph(AT91_PIO_PORTB, 19, 0);	/* GRX1 */
-	atmel_pio4_set_f_periph(AT91_PIO_PORTB, 20, 0);	/* GTX0 */
-	atmel_pio4_set_f_periph(AT91_PIO_PORTB, 21, 0);	/* GTX1 */
-	atmel_pio4_set_f_periph(AT91_PIO_PORTB, 22, 0);	/* GMDC */
-	atmel_pio4_set_f_periph(AT91_PIO_PORTB, 23, 0);	/* GMDIO */
-
-	at91_periph_clk_enable(ATMEL_ID_GMAC);
-}
-
-static void board_uart0_hw_init(void)
-{
-	atmel_pio4_set_c_periph(AT91_PIO_PORTB, 26, 1);	/* URXD0 */
-	atmel_pio4_set_c_periph(AT91_PIO_PORTB, 27, 0);	/* UTXD0 */
-
-	at91_periph_clk_enable(CONFIG_USART_ID);
-}
-
-int board_early_init_f(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_uart0_hw_init();
-
-	return 0;
-}
-
-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_NAND_ATMEL
-	board_nand_hw_init();
-#endif
-#ifdef CONFIG_MACB
-	board_gmac_hw_init();
-#endif
-#ifdef CONFIG_CMD_USB
-	board_usb_hw_init();
-#endif
-#ifdef CONFIG_USB_GADGET_ATMEL_USBA
-	at91_udp_hw_init();
-#endif
-
-	return 0;
-}
-
-int dram_init(void)
-{
-	gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE,
-				    CONFIG_SYS_SDRAM_SIZE);
-	return 0;
-}
-
-int board_eth_init(bd_t *bis)
-{
-	int rc = 0;
-
-#ifdef CONFIG_MACB
-	rc = macb_eth_initialize(0, (void *)ATMEL_BASE_GMAC, 0x00);
-	if (rc)
-		printf("GMAC register failed\n");
-#endif
-
-#ifdef CONFIG_USB_GADGET_ATMEL_USBA
-	usba_udc_probe(&pdata);
-#ifdef CONFIG_USB_ETH_RNDIS
-	usb_eth_initialize(bis);
-#endif
-#endif
-
-	return rc;
-}
-
-/* SPL */
-#ifdef CONFIG_SPL_BUILD
-void spl_board_init(void)
-{
-#ifdef CONFIG_SPI_BOOT
-	board_spi0_hw_init();
-#endif
-
-#ifdef CONFIG_NAND_BOOT
-	board_nand_hw_init();
-#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 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);
-	at91_system_clk_enable(AT91_PMC_DDR);
-
-	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)
-{
-	at91_plla_init(AT91_PMC_PLLAR_29 |
-		       AT91_PMC_PLLXR_PLLCOUNT(0x3f) |
-		       AT91_PMC_PLLXR_MUL(82) |
-		       AT91_PMC_PLLXR_DIV(1));
-
-	at91_pllicpr_init(0);
-
-	at91_mck_init(AT91_PMC_MCKR_H32MXDIV |
-		      AT91_PMC_MCKR_PLLADIV_2 |
-		      AT91_PMC_MCKR_MDIV_3 |
-		      AT91_PMC_MCKR_CSS_PLLA);
-}
-#endif
diff --git a/board/atmel/sama5d2_ptc/Kconfig b/board/atmel/sama5d2_ptc_ek/Kconfig
similarity index 60%
rename from board/atmel/sama5d2_ptc/Kconfig
rename to board/atmel/sama5d2_ptc_ek/Kconfig
index d2661c6..8b202d6 100644
--- a/board/atmel/sama5d2_ptc/Kconfig
+++ b/board/atmel/sama5d2_ptc_ek/Kconfig
@@ -1,7 +1,7 @@
-if TARGET_SAMA5D2_PTC
+if TARGET_SAMA5D2_PTC_EK
 
 config SYS_BOARD
-	default "sama5d2_ptc"
+	default "sama5d2_ptc_ek"
 
 config SYS_VENDOR
 	default "atmel"
@@ -10,6 +10,6 @@
 	default "at91"
 
 config SYS_CONFIG_NAME
-	default "sama5d2_ptc"
+	default "sama5d2_ptc_ek"
 
 endif
diff --git a/board/atmel/sama5d2_ptc_ek/MAINTAINERS b/board/atmel/sama5d2_ptc_ek/MAINTAINERS
new file mode 100644
index 0000000..3c7b7f5
--- /dev/null
+++ b/board/atmel/sama5d2_ptc_ek/MAINTAINERS
@@ -0,0 +1,8 @@
+SAMA5D2 PTC EK BOARD
+M:	Wenyou Yang <wenyou.yang@microchip.com>
+M:	Ludovic Desroches <ludovic.desroches@microchip.com>
+S:	Maintained
+F:	board/atmel/sama5d2_ptc_ek/
+F:	include/configs/sama5d2_ptc_ek.h
+F:	configs/sama5d2_ptc_ek_mmc_defconfig
+F:	configs/sama5d2_ptc_ek_nandflash_defconfig
diff --git a/board/atmel/sama5d2_ptc_ek/Makefile b/board/atmel/sama5d2_ptc_ek/Makefile
new file mode 100644
index 0000000..9fe4b41
--- /dev/null
+++ b/board/atmel/sama5d2_ptc_ek/Makefile
@@ -0,0 +1,8 @@
+#
+# Copyright (C) 2017 Microchip Corporation
+#		     Wenyou Yang <wenyou.yang@microchip.com>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y += sama5d2_ptc_ek.o
diff --git a/board/atmel/sama5d2_ptc_ek/sama5d2_ptc_ek.c b/board/atmel/sama5d2_ptc_ek/sama5d2_ptc_ek.c
new file mode 100644
index 0000000..4c2e209
--- /dev/null
+++ b/board/atmel/sama5d2_ptc_ek/sama5d2_ptc_ek.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2017 Microchip Corporation
+ *		      Wenyou Yang <wenyou.yang@microchip.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <dm.h>
+#include <i2c.h>
+#include <nand.h>
+#include <version.h>
+#include <asm/io.h>
+#include <asm/arch/at91_common.h>
+#include <asm/arch/atmel_pio4.h>
+#include <asm/arch/atmel_mpddrc.h>
+#include <asm/arch/atmel_sdhci.h>
+#include <asm/arch/clk.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/sama5d2.h>
+#include <asm/arch/sama5d2_smc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_NAND_ATMEL
+static void board_nand_hw_init(void)
+{
+	struct at91_smc *smc = (struct at91_smc *)ATMEL_BASE_SMC;
+
+	at91_periph_clk_enable(ATMEL_ID_HSMC);
+
+	/* Configure SMC CS3 for NAND */
+	writel(AT91_SMC_SETUP_NWE(1) | AT91_SMC_SETUP_NCS_WR(1) |
+	       AT91_SMC_SETUP_NRD(1) | AT91_SMC_SETUP_NCS_RD(1),
+	       &smc->cs[3].setup);
+	writel(AT91_SMC_PULSE_NWE(2) | AT91_SMC_PULSE_NCS_WR(3) |
+	       AT91_SMC_PULSE_NRD(2) | AT91_SMC_PULSE_NCS_RD(3),
+	       &smc->cs[3].pulse);
+	writel(AT91_SMC_CYCLE_NWE(5) | AT91_SMC_CYCLE_NRD(5),
+	       &smc->cs[3].cycle);
+	writel(AT91_SMC_TIMINGS_TCLR(2) | AT91_SMC_TIMINGS_TADL(7) |
+	       AT91_SMC_TIMINGS_TAR(2)  | AT91_SMC_TIMINGS_TRR(3)   |
+	       AT91_SMC_TIMINGS_TWB(7)  | AT91_SMC_TIMINGS_RBNSEL(3) |
+	       AT91_SMC_TIMINGS_NFSEL(1), &smc->cs[3].timings);
+	writel(AT91_SMC_MODE_RM_NRD | AT91_SMC_MODE_WM_NWE |
+	       AT91_SMC_MODE_EXNW_DISABLE |
+	       AT91_SMC_MODE_DBW_8 |
+	       AT91_SMC_MODE_TDF_CYCLE(3),
+	       &smc->cs[3].mode);
+
+	atmel_pio4_set_b_periph(AT91_PIO_PORTA, 22, 0);	/* D0 */
+	atmel_pio4_set_b_periph(AT91_PIO_PORTA, 23, 0);	/* D1 */
+	atmel_pio4_set_b_periph(AT91_PIO_PORTA, 24, 0);	/* D2 */
+	atmel_pio4_set_b_periph(AT91_PIO_PORTA, 25, 0);	/* D3 */
+	atmel_pio4_set_b_periph(AT91_PIO_PORTA, 26, 0);	/* D4 */
+	atmel_pio4_set_b_periph(AT91_PIO_PORTA, 27, 0);	/* D5 */
+	atmel_pio4_set_b_periph(AT91_PIO_PORTA, 28, 0);	/* D6 */
+	atmel_pio4_set_b_periph(AT91_PIO_PORTA, 29, 0);	/* D7 */
+	atmel_pio4_set_b_periph(AT91_PIO_PORTB, 2, 0);	/* RE */
+	atmel_pio4_set_b_periph(AT91_PIO_PORTA, 30, 0);	/* WE */
+	atmel_pio4_set_b_periph(AT91_PIO_PORTA, 31, 1);	/* NCS */
+	atmel_pio4_set_b_periph(AT91_PIO_PORTC, 8, 1);	/* RDY */
+	atmel_pio4_set_b_periph(AT91_PIO_PORTB, 0, 1);	/* ALE */
+	atmel_pio4_set_b_periph(AT91_PIO_PORTB, 1, 1);	/* CLE */
+}
+#endif
+
+static void board_usb_hw_init(void)
+{
+	atmel_pio4_set_pio_output(AT91_PIO_PORTB, 12, 1);
+}
+
+#ifdef CONFIG_DEBUG_UART_BOARD_INIT
+static void board_uart0_hw_init(void)
+{
+	atmel_pio4_set_c_periph(AT91_PIO_PORTB, 26, 1);	/* URXD0 */
+	atmel_pio4_set_c_periph(AT91_PIO_PORTB, 27, 0);	/* UTXD0 */
+
+	at91_periph_clk_enable(ATMEL_ID_UART0);
+}
+
+void board_debug_uart_init(void)
+{
+	board_uart0_hw_init();
+}
+#endif
+
+#ifdef CONFIG_BOARD_EARLY_INIT_F
+int board_early_init_f(void)
+{
+#ifdef CONFIG_DEBUG_UART
+	debug_uart_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_NAND_ATMEL
+	board_nand_hw_init();
+#endif
+#ifdef CONFIG_CMD_USB
+	board_usb_hw_init();
+#endif
+	return 0;
+}
+
+int dram_init(void)
+{
+	gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE,
+				    CONFIG_SYS_SDRAM_SIZE);
+	return 0;
+}
+
+#define AT24MAC_MAC_OFFSET	0xfa
+
+#ifdef CONFIG_MISC_INIT_R
+int misc_init_r(void)
+{
+#ifdef CONFIG_I2C_EEPROM
+	at91_set_ethaddr(AT24MAC_MAC_OFFSET);
+#endif
+	return 0;
+}
+#endif
diff --git a/board/laird/wb45n/Kconfig b/board/laird/wb45n/Kconfig
new file mode 100644
index 0000000..2a67337
--- /dev/null
+++ b/board/laird/wb45n/Kconfig
@@ -0,0 +1,12 @@
+if TARGET_WB45N
+
+config SYS_BOARD
+	default "wb45n"
+
+config SYS_VENDOR
+	default "laird"
+
+config SYS_CONFIG_NAME
+	default "wb45n"
+
+endif
diff --git a/board/laird/wb45n/MAINTAINERS b/board/laird/wb45n/MAINTAINERS
new file mode 100644
index 0000000..60bb563
--- /dev/null
+++ b/board/laird/wb45n/MAINTAINERS
@@ -0,0 +1,6 @@
+WB45N CPU MODULE
+M:	Ben Whitten <ben.whitten@lairdtech.com>
+S:	Maintained
+F:	board/laird/wb45n/
+F:	include/configs/wb45n.h
+F:	configs/wb45n_defconfig
diff --git a/board/laird/wb45n/Makefile b/board/laird/wb45n/Makefile
new file mode 100644
index 0000000..fc645dd
--- /dev/null
+++ b/board/laird/wb45n/Makefile
@@ -0,0 +1,6 @@
+#
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y += wb45n.o
diff --git a/board/laird/wb45n/wb45n.c b/board/laird/wb45n/wb45n.c
new file mode 100644
index 0000000..5914071
--- /dev/null
+++ b/board/laird/wb45n/wb45n.c
@@ -0,0 +1,199 @@
+/*
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/at91sam9x5_matrix.h>
+#include <asm/arch/at91sam9_smc.h>
+#include <asm/arch/at91_common.h>
+#include <asm/arch/at91_rstc.h>
+#include <asm/arch/clk.h>
+#include <asm/arch/gpio.h>
+#include <net.h>
+#include <netdev.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Miscelaneous platform dependent initialisations
+ */
+static void wb45n_nand_hw_init(void)
+{
+	struct at91_smc *smc = (struct at91_smc *)ATMEL_BASE_SMC;
+	struct at91_matrix *matrix = (struct at91_matrix *)ATMEL_BASE_MATRIX;
+	unsigned long csa;
+
+	csa = readl(&matrix->ebicsa);
+	/* Enable CS3 */
+	csa |= AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA;
+	/* NAND flash on D0 */
+	csa &= ~AT91_MATRIX_NFD0_ON_D16;
+	writel(csa, &matrix->ebicsa);
+
+	/* Configure SMC CS3 for NAND/SmartMedia */
+	writel(AT91_SMC_SETUP_NWE(1) | AT91_SMC_SETUP_NCS_WR(0) |
+	       AT91_SMC_SETUP_NRD(1) | AT91_SMC_SETUP_NCS_RD(0),
+	       &smc->cs[3].setup);
+	writel(AT91_SMC_PULSE_NWE(3) | AT91_SMC_PULSE_NCS_WR(5) |
+	       AT91_SMC_PULSE_NRD(4) | AT91_SMC_PULSE_NCS_RD(6),
+	       &smc->cs[3].pulse);
+	writel(AT91_SMC_CYCLE_NWE(5) | AT91_SMC_CYCLE_NRD(6),
+	       &smc->cs[3].cycle);
+	writel(AT91_SMC_MODE_RM_NRD | AT91_SMC_MODE_WM_NWE |
+	       AT91_SMC_MODE_EXNW_DISABLE |
+	       AT91_SMC_MODE_DBW_8 |
+	       AT91_SMC_MODE_TDF_CYCLE(1), &smc->cs[3].mode);
+
+	at91_periph_clk_enable(ATMEL_ID_PIOCD);
+
+	/* Configure RDY/BSY */
+	at91_set_gpio_input(CONFIG_SYS_NAND_READY_PIN, 1);
+	/* Enable NandFlash */
+	at91_set_gpio_output(CONFIG_SYS_NAND_ENABLE_PIN, 1);
+	/* Disable Flash Write Protect Line */
+	at91_set_gpio_output(AT91_PIN_PD10, 1);
+
+	at91_set_a_periph(AT91_PIO_PORTD, 0, 1);	/* NAND OE */
+	at91_set_a_periph(AT91_PIO_PORTD, 1, 1);	/* NAND WE */
+	at91_set_a_periph(AT91_PIO_PORTD, 2, 1);	/* NAND ALE */
+	at91_set_a_periph(AT91_PIO_PORTD, 3, 1);	/* NAND CLE */
+}
+
+static void wb45n_gpio_hw_init(void)
+{
+
+	/* Configure wifi gpio CHIP_PWD_L */
+	at91_set_gpio_output(AT91_PIN_PA28, 0);
+
+	/* Setup USB pins */
+	at91_set_gpio_input(AT91_PIN_PB11, 0);
+	at91_set_gpio_output(AT91_PIN_PB12, 0);
+
+	/* IRQ pin, pullup, deglitch */
+	at91_set_gpio_input(AT91_PIN_PB18, 1);
+	at91_set_gpio_deglitch(AT91_PIN_PB18, 1);
+}
+
+int board_eth_init(bd_t *bis)
+{
+	int rc = 0;
+
+	if (has_emac0())
+		rc = macb_eth_initialize(0, (void *)ATMEL_BASE_EMAC0, 0x00);
+
+	return rc;
+}
+
+int board_early_init_f(void)
+{
+	at91_seriald_hw_init();
+	return 0;
+}
+
+int board_init(void)
+{
+	/* address of boot parameters */
+	gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
+
+	wb45n_gpio_hw_init();
+
+	wb45n_nand_hw_init();
+
+	at91_macb_hw_init();
+
+	return 0;
+}
+
+int dram_init(void)
+{
+	gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE,
+	                            CONFIG_SYS_SDRAM_SIZE);
+	return 0;
+}
+
+#if defined(CONFIG_SPL_BUILD)
+#include <spl.h>
+#include <nand.h>
+
+void at91_spl_board_init(void)
+{
+	/* Setup GPIO first */
+	wb45n_gpio_hw_init();
+
+	/* Bring up NAND */
+	wb45n_nand_hw_init();
+}
+
+void matrix_init(void)
+{
+	struct at91_matrix *matrix = (struct at91_matrix *)ATMEL_BASE_MATRIX;
+	unsigned long csa;
+
+	csa = readl(&matrix->ebicsa);
+	/* Pull ups on D0 - D16 */
+	csa &= ~AT91_MATRIX_EBI_DBPU_OFF;
+	csa |= AT91_MATRIX_EBI_DBPD_OFF;
+	/* Normal drive strength */
+	csa |= AT91_MATRIX_EBI_EBI_IOSR_NORMAL;
+	/* Multi-port off */
+	csa &= ~AT91_MATRIX_MP_ON;
+	writel(csa, &matrix->ebicsa);
+}
+
+#include <asm/arch/atmel_mpddrc.h>
+static void ddr2_conf(struct atmel_mpddrc_config *ddr2)
+{
+	ddr2->md = (ATMEL_MPDDRC_MD_DBW_16_BITS | ATMEL_MPDDRC_MD_LPDDR_SDRAM);
+
+	ddr2->cr = (ATMEL_MPDDRC_CR_NC_COL_10 |
+	            ATMEL_MPDDRC_CR_NR_ROW_13 |
+	            ATMEL_MPDDRC_CR_CAS_DDR_CAS3 |
+	            ATMEL_MPDDRC_CR_DECOD_INTERLEAVED |
+	            ATMEL_MPDDRC_CR_DQMS_SHARED);
+
+	ddr2->rtr = 0x411;
+
+	ddr2->tpr0 = (6 << ATMEL_MPDDRC_TPR0_TRAS_OFFSET |
+	              2 << ATMEL_MPDDRC_TPR0_TRCD_OFFSET |
+	              2 << ATMEL_MPDDRC_TPR0_TWR_OFFSET |
+	              8 << ATMEL_MPDDRC_TPR0_TRC_OFFSET |
+	              2 << ATMEL_MPDDRC_TPR0_TRP_OFFSET |
+	              2 << ATMEL_MPDDRC_TPR0_TRRD_OFFSET |
+	              2 << ATMEL_MPDDRC_TPR0_TWTR_OFFSET |
+	              2 << ATMEL_MPDDRC_TPR0_TMRD_OFFSET);
+
+	ddr2->tpr1 = (2 << ATMEL_MPDDRC_TPR1_TXP_OFFSET |
+	              200 << ATMEL_MPDDRC_TPR1_TXSRD_OFFSET |
+	              19 << ATMEL_MPDDRC_TPR1_TXSNR_OFFSET |
+	              18 << ATMEL_MPDDRC_TPR1_TRFC_OFFSET);
+
+	ddr2->tpr2 = (7 << ATMEL_MPDDRC_TPR2_TFAW_OFFSET |
+	              2 << ATMEL_MPDDRC_TPR2_TRTP_OFFSET |
+	              3 << ATMEL_MPDDRC_TPR2_TRPA_OFFSET |
+	              7 << ATMEL_MPDDRC_TPR2_TXARDS_OFFSET |
+	              2 << ATMEL_MPDDRC_TPR2_TXARD_OFFSET);
+}
+
+void mem_init(void)
+{
+	struct at91_matrix *matrix = (struct at91_matrix *)ATMEL_BASE_MATRIX;
+	struct atmel_mpddrc_config ddr2;
+	unsigned long csa;
+
+	ddr2_conf(&ddr2);
+
+	/* enable DDR2 clock */
+	at91_system_clk_enable(AT91_PMC_DDR);
+
+	/* Chip select 1 is for DDR2/SDRAM */
+	csa = readl(&matrix->ebicsa);
+	csa |= AT91_MATRIX_EBI_CS1A_SDRAMC;
+	writel(csa, &matrix->ebicsa);
+
+	/* DDRAM2 Controller initialize */
+	ddr2_init(ATMEL_BASE_DDRSDRC, ATMEL_BASE_CS1, &ddr2);
+}
+#endif
diff --git a/board/laird/wb50n/Kconfig b/board/laird/wb50n/Kconfig
new file mode 100644
index 0000000..2e7090e
--- /dev/null
+++ b/board/laird/wb50n/Kconfig
@@ -0,0 +1,12 @@
+if TARGET_WB50N
+
+config SYS_BOARD
+	default "wb50n"
+
+config SYS_VENDOR
+	default "laird"
+
+config SYS_CONFIG_NAME
+	default "wb50n"
+
+endif
diff --git a/board/laird/wb50n/MAINTAINERS b/board/laird/wb50n/MAINTAINERS
new file mode 100644
index 0000000..3d38fc4
--- /dev/null
+++ b/board/laird/wb50n/MAINTAINERS
@@ -0,0 +1,6 @@
+WB50N CPU MODULE
+M:	Ben Whitten <ben.whitten@lairdtech.com>
+S:	Maintained
+F:	board/laird/wb50n/
+F:	include/configs/wb50n.h
+F:	configs/wb50n_defconfig
diff --git a/board/laird/wb50n/Makefile b/board/laird/wb50n/Makefile
new file mode 100644
index 0000000..d1b6cfa
--- /dev/null
+++ b/board/laird/wb50n/Makefile
@@ -0,0 +1,6 @@
+#
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y += wb50n.o
diff --git a/board/laird/wb50n/wb50n.c b/board/laird/wb50n/wb50n.c
new file mode 100644
index 0000000..8896e62
--- /dev/null
+++ b/board/laird/wb50n/wb50n.c
@@ -0,0 +1,206 @@
+/*
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/sama5_sfr.h>
+#include <asm/arch/sama5d3_smc.h>
+#include <asm/arch/at91_common.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_rstc.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/clk.h>
+#include <micrel.h>
+#include <net.h>
+#include <netdev.h>
+#include <spl.h>
+#include <asm/arch/atmel_mpddrc.h>
+#include <asm/arch/at91_wdt.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Miscelaneous platform dependent initialisations
+ */
+
+void wb50n_nand_hw_init(void)
+{
+	struct at91_smc *smc = (struct at91_smc *)ATMEL_BASE_SMC;
+
+	at91_periph_clk_enable(ATMEL_ID_SMC);
+
+	/* Configure SMC CS3 for NAND/SmartMedia */
+	writel(AT91_SMC_SETUP_NWE(2) | AT91_SMC_SETUP_NCS_WR(1) |
+	       AT91_SMC_SETUP_NRD(2) | AT91_SMC_SETUP_NCS_RD(1),
+	       &smc->cs[3].setup);
+	writel(AT91_SMC_PULSE_NWE(3) | AT91_SMC_PULSE_NCS_WR(5) |
+	       AT91_SMC_PULSE_NRD(3) | AT91_SMC_PULSE_NCS_RD(5),
+	       &smc->cs[3].pulse);
+	writel(AT91_SMC_CYCLE_NWE(8) | AT91_SMC_CYCLE_NRD(8),
+	       &smc->cs[3].cycle);
+	writel(AT91_SMC_TIMINGS_TCLR(3) | AT91_SMC_TIMINGS_TADL(10) |
+	       AT91_SMC_TIMINGS_TAR(3) | AT91_SMC_TIMINGS_TRR(4) |
+	       AT91_SMC_TIMINGS_TWB(5) | AT91_SMC_TIMINGS_RBNSEL(3) |
+	       AT91_SMC_TIMINGS_NFSEL(1), &smc->cs[3].timings);
+	writel(AT91_SMC_MODE_RM_NRD | AT91_SMC_MODE_WM_NWE |
+	       AT91_SMC_MODE_EXNW_DISABLE |
+	       AT91_SMC_MODE_DBW_8 |
+	       AT91_SMC_MODE_TDF_CYCLE(3), &smc->cs[3].mode);
+
+	/* Disable Flash Write Protect Line */
+	at91_set_pio_output(AT91_PIO_PORTE, 14, 1);
+}
+
+int board_early_init_f(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);
+	at91_periph_clk_enable(ATMEL_ID_PIOE);
+
+	at91_seriald_hw_init();
+
+	return 0;
+}
+
+int board_init(void)
+{
+	/* adress of boot parameters */
+	gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
+
+	wb50n_nand_hw_init();
+
+	at91_macb_hw_init();
+
+	return 0;
+}
+
+int dram_init(void)
+{
+	gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE,
+	                            CONFIG_SYS_SDRAM_SIZE);
+	return 0;
+}
+
+int board_phy_config(struct phy_device *phydev)
+{
+	/* rx data delay */
+	ksz9021_phy_extended_write(phydev,
+	                           MII_KSZ9021_EXT_RGMII_RX_DATA_SKEW, 0x2222);
+	/* tx data delay */
+	ksz9021_phy_extended_write(phydev,
+	                           MII_KSZ9021_EXT_RGMII_TX_DATA_SKEW, 0x2222);
+	/* rx/tx clock delay */
+	ksz9021_phy_extended_write(phydev,
+	                           MII_KSZ9021_EXT_RGMII_CLOCK_SKEW, 0xf2f4);
+
+	return 0;
+}
+
+int board_eth_init(bd_t *bis)
+{
+	int rc = 0;
+
+	rc = macb_eth_initialize(0, (void *)ATMEL_BASE_EMAC, 0x00);
+
+	return rc;
+}
+
+#ifdef CONFIG_BOARD_LATE_INIT
+#include <linux/ctype.h>
+int board_late_init(void)
+{
+#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
+	const char *LAIRD_NAME = "lrd_name";
+	char name[32], *p;
+
+	strcpy(name, get_cpu_name());
+	for (p = name; *p != '\0'; *p = tolower(*p), p++)
+		;
+	strcat(name, "-wb50n");
+	env_set(LAIRD_NAME, name);
+
+#endif
+
+	return 0;
+}
+#endif
+
+/* SPL */
+#ifdef CONFIG_SPL_BUILD
+void spl_board_init(void)
+{
+	wb50n_nand_hw_init();
+}
+
+static void ddr2_conf(struct atmel_mpddrc_config *ddr2)
+{
+	ddr2->md = (ATMEL_MPDDRC_MD_DBW_32_BITS | ATMEL_MPDDRC_MD_LPDDR_SDRAM);
+
+	ddr2->cr = (ATMEL_MPDDRC_CR_NC_COL_9 |
+	            ATMEL_MPDDRC_CR_NR_ROW_13 |
+	            ATMEL_MPDDRC_CR_CAS_DDR_CAS3 |
+	            ATMEL_MPDDRC_CR_NDQS_DISABLED |
+	            ATMEL_MPDDRC_CR_DECOD_INTERLEAVED |
+	            ATMEL_MPDDRC_CR_UNAL_SUPPORTED);
+
+	ddr2->rtr = 0x411;
+
+	ddr2->tpr0 = (6 << ATMEL_MPDDRC_TPR0_TRAS_OFFSET |
+	              2 << ATMEL_MPDDRC_TPR0_TRCD_OFFSET |
+	              2 << ATMEL_MPDDRC_TPR0_TWR_OFFSET |
+	              8 << ATMEL_MPDDRC_TPR0_TRC_OFFSET |
+	              2 << ATMEL_MPDDRC_TPR0_TRP_OFFSET |
+	              2 << ATMEL_MPDDRC_TPR0_TRRD_OFFSET |
+	              2 << ATMEL_MPDDRC_TPR0_TWTR_OFFSET |
+	              2 << ATMEL_MPDDRC_TPR0_TMRD_OFFSET);
+
+	ddr2->tpr1 = (2 << ATMEL_MPDDRC_TPR1_TXP_OFFSET |
+	              200 << ATMEL_MPDDRC_TPR1_TXSRD_OFFSET |
+	              19 << ATMEL_MPDDRC_TPR1_TXSNR_OFFSET |
+	              18 << ATMEL_MPDDRC_TPR1_TRFC_OFFSET);
+
+	ddr2->tpr2 = (7 << ATMEL_MPDDRC_TPR2_TFAW_OFFSET |
+	              2 << ATMEL_MPDDRC_TPR2_TRTP_OFFSET |
+	              3 << ATMEL_MPDDRC_TPR2_TRPA_OFFSET |
+	              7 << ATMEL_MPDDRC_TPR2_TXARDS_OFFSET |
+	              2 << ATMEL_MPDDRC_TPR2_TXARD_OFFSET);
+}
+
+void mem_init(void)
+{
+	struct atmel_sfr *sfr = (struct atmel_sfr *)ATMEL_BASE_SFR;
+	struct atmel_mpddrc_config ddr2;
+
+	ddr2_conf(&ddr2);
+
+	writel(ATMEL_SFR_DDRCFG_FDQIEN | ATMEL_SFR_DDRCFG_FDQSIEN,
+	       &sfr->ddrcfg);
+
+	/* enable MPDDR clock */
+	at91_periph_clk_enable(ATMEL_ID_MPDDRC);
+	at91_system_clk_enable(AT91_PMC_DDR);
+
+	/* DDRAM2 Controller initialize */
+	ddr2_init(ATMEL_BASE_MPDDRC, ATMEL_BASE_DDRCS, &ddr2);
+}
+
+void at91_pmc_init(void)
+{
+	u32 tmp;
+
+	tmp = AT91_PMC_PLLAR_29 |
+	      AT91_PMC_PLLXR_PLLCOUNT(0x3f) |
+	      AT91_PMC_PLLXR_MUL(43) | AT91_PMC_PLLXR_DIV(1);
+	at91_plla_init(tmp);
+
+	at91_pllicpr_init(AT91_PMC_IPLL_PLLA(0x3));
+
+	tmp = AT91_PMC_MCKR_MDIV_4 | AT91_PMC_MCKR_CSS_PLLA;
+	at91_mck_init(tmp);
+}
+#endif
diff --git a/board/st/stm32f429-discovery/stm32f429-discovery.c b/board/st/stm32f429-discovery/stm32f429-discovery.c
index d6763c3..1c34a8e 100644
--- a/board/st/stm32f429-discovery/stm32f429-discovery.c
+++ b/board/st/stm32f429-discovery/stm32f429-discovery.c
@@ -13,6 +13,7 @@
 
 #include <common.h>
 #include <dm.h>
+#include <stm32_rcc.h>
 #include <asm/io.h>
 #include <asm/armv7m.h>
 #include <asm/arch/stm32.h>
@@ -293,6 +294,8 @@
 {
 	int res;
 
+	configure_clocks();
+
 	res = uart_setup_gpio();
 	if (res)
 		return res;
diff --git a/cmd/blk_common.c b/cmd/blk_common.c
index 0c0c23e..bf2f626 100644
--- a/cmd/blk_common.c
+++ b/cmd/blk_common.c
@@ -95,8 +95,6 @@
 		} else {
 			return CMD_RET_USAGE;
 		}
-
-		return 0;
 	}
 }
 #endif
diff --git a/common/command.c b/common/command.c
index e5d9b9c..21a6d40 100644
--- a/common/command.c
+++ b/common/command.c
@@ -318,7 +318,7 @@
 	return len;
 }
 
-static char tmp_buf[CONFIG_SYS_CBSIZE];	/* copy of console I/O buffer	*/
+static char tmp_buf[CONFIG_SYS_CBSIZE + 1];	/* copy of console I/O buffer */
 
 int cmd_auto_complete(const char *const prompt, char *buf, int *np, int *colp)
 {
diff --git a/configs/adp-ae3xx_defconfig b/configs/adp-ae3xx_defconfig
index a3a40bf..6005669 100644
--- a/configs/adp-ae3xx_defconfig
+++ b/configs/adp-ae3xx_defconfig
@@ -27,12 +27,15 @@
 CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_DM_MMC=y
+CONFIG_MMC_NDS32=y
+CONFIG_FTSDC010=y
 CONFIG_DM_ETH=y
 CONFIG_FTMAC100=y
 CONFIG_BAUDRATE=38400
 CONFIG_DM_SERIAL=y
 CONFIG_SYS_NS16550=y
 CONFIG_DM_SPI=y
-CONFIG_NDS_AE3XX_SPI=y
+CONFIG_ATCSPI200_SPI=y
 CONFIG_TIMER=y
-CONFIG_AE3XX_TIMER=y
+CONFIG_ATCPIT100_TIMER=y
diff --git a/configs/adp-ag101p_defconfig b/configs/adp-ag101p_defconfig
index 5cf2d26..82cf7f2 100644
--- a/configs/adp-ag101p_defconfig
+++ b/configs/adp-ag101p_defconfig
@@ -18,6 +18,9 @@
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_DM=y
 CONFIG_MMC=y
+CONFIG_DM_MMC=y
+CONFIG_MMC_NDS32=y
+CONFIG_FTSDC010=y
 CONFIG_MTD_NOR_FLASH=y
 CONFIG_DM_ETH=y
 CONFIG_FTMAC100=y
diff --git a/configs/sama5d2_ptc_ek_mmc_defconfig b/configs/sama5d2_ptc_ek_mmc_defconfig
new file mode 100644
index 0000000..03dc69b
--- /dev/null
+++ b/configs/sama5d2_ptc_ek_mmc_defconfig
@@ -0,0 +1,60 @@
+CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
+CONFIG_TARGET_SAMA5D2_PTC_EK=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_DEFAULT_DEVICE_TREE="at91-sama5d2_ptc_ek"
+CONFIG_DEBUG_UART=y
+CONFIG_FIT=y
+CONFIG_SYS_EXTRA_OPTIONS="SAMA5D2,SYS_USE_MMC"
+CONFIG_SD_BOOT=y
+CONFIG_BOOTDELAY=3
+CONFIG_CONSOLE_MUX=y
+# CONFIG_DISPLAY_BOARDINFO is not set
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_BOOTZ=y
+# CONFIG_CMD_IMI is not set
+# CONFIG_CMD_FLASH is not set
+# CONFIG_CMD_FPGA is not set
+CONFIG_CMD_I2C=y
+# CONFIG_CMD_LOADS is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_NAND=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FAT=y
+CONFIG_OF_CONTROL=y
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_DM=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_CLK=y
+CONFIG_CLK_AT91=y
+CONFIG_AT91_UTMI=y
+CONFIG_AT91_H32MX=y
+CONFIG_AT91_GENERIC_CLK=y
+CONFIG_DM_GPIO=y
+CONFIG_ATMEL_PIO4=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_AT91=y
+CONFIG_I2C_EEPROM=y
+CONFIG_DM_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_ATMEL=y
+CONFIG_DM_ETH=y
+CONFIG_MACB=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_AT91PIO4=y
+CONFIG_DM_SERIAL=y
+CONFIG_DEBUG_UART_ATMEL=y
+CONFIG_DEBUG_UART_BASE=0xf801c000
+CONFIG_DEBUG_UART_CLOCK=82000000
+CONFIG_DEBUG_UART_BOARD_INIT=y
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_ATMEL_USART=y
+CONFIG_TIMER=y
+CONFIG_ATMEL_PIT_TIMER=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_STORAGE=y
diff --git a/configs/sama5d2_ptc_ek_nandflash_defconfig b/configs/sama5d2_ptc_ek_nandflash_defconfig
new file mode 100644
index 0000000..8340f81
--- /dev/null
+++ b/configs/sama5d2_ptc_ek_nandflash_defconfig
@@ -0,0 +1,60 @@
+CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
+CONFIG_TARGET_SAMA5D2_PTC_EK=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_DEFAULT_DEVICE_TREE="at91-sama5d2_ptc_ek"
+CONFIG_DEBUG_UART=y
+CONFIG_FIT=y
+CONFIG_SYS_EXTRA_OPTIONS="SAMA5D2,SYS_USE_NANDFLASH"
+CONFIG_NAND_BOOT=y
+CONFIG_BOOTDELAY=3
+CONFIG_CONSOLE_MUX=y
+# CONFIG_DISPLAY_BOARDINFO is not set
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_BOOTZ=y
+# CONFIG_CMD_IMI is not set
+# CONFIG_CMD_FLASH is not set
+# CONFIG_CMD_FPGA is not set
+CONFIG_CMD_I2C=y
+# CONFIG_CMD_LOADS is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_NAND=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FAT=y
+CONFIG_OF_CONTROL=y
+CONFIG_ENV_IS_IN_NAND=y
+CONFIG_DM=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_CLK=y
+CONFIG_CLK_AT91=y
+CONFIG_AT91_UTMI=y
+CONFIG_AT91_H32MX=y
+CONFIG_AT91_GENERIC_CLK=y
+CONFIG_DM_GPIO=y
+CONFIG_ATMEL_PIO4=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_AT91=y
+CONFIG_I2C_EEPROM=y
+CONFIG_DM_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_ATMEL=y
+CONFIG_DM_ETH=y
+CONFIG_MACB=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_AT91PIO4=y
+CONFIG_DM_SERIAL=y
+CONFIG_DEBUG_UART_ATMEL=y
+CONFIG_DEBUG_UART_BASE=0xf801c000
+CONFIG_DEBUG_UART_CLOCK=82000000
+CONFIG_DEBUG_UART_BOARD_INIT=y
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_ATMEL_USART=y
+CONFIG_TIMER=y
+CONFIG_ATMEL_PIT_TIMER=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_STORAGE=y
diff --git a/configs/sama5d2_ptc_nandflash_defconfig b/configs/sama5d2_ptc_nandflash_defconfig
deleted file mode 100644
index cfbdbb0..0000000
--- a/configs/sama5d2_ptc_nandflash_defconfig
+++ /dev/null
@@ -1,33 +0,0 @@
-CONFIG_ARM=y
-CONFIG_ARCH_AT91=y
-CONFIG_TARGET_SAMA5D2_PTC=y
-CONFIG_SPL_GPIO_SUPPORT=y
-CONFIG_SPL_LIBCOMMON_SUPPORT=y
-CONFIG_SPL_LIBGENERIC_SUPPORT=y
-CONFIG_SPL_SERIAL_SUPPORT=y
-CONFIG_SPL_NAND_SUPPORT=y
-CONFIG_NAND_BOOT=y
-CONFIG_BOOTDELAY=3
-CONFIG_USE_BOOTARGS=y
-CONFIG_BOOTARGS="console=ttyS0,57600 earlyprintk mtdparts=atmel_nand:6M(bootstrap)ro, 6M(kernel)ro,-(rootfs) rootfstype=ubifs ubi.mtd=2 root=ubi0:rootfs"
-# CONFIG_DISPLAY_BOARDINFO is not set
-CONFIG_SPL=y
-# CONFIG_CMD_IMI is not set
-# CONFIG_CMD_FLASH is not set
-# CONFIG_CMD_FPGA is not set
-# CONFIG_CMD_LOADS is not set
-CONFIG_CMD_NAND=y
-CONFIG_CMD_NAND_TRIMFFS=y
-CONFIG_CMD_SF=y
-CONFIG_CMD_USB=y
-CONFIG_CMD_FAT=y
-CONFIG_ENV_IS_IN_NAND=y
-# CONFIG_MMC is not set
-CONFIG_SPI_FLASH=y
-CONFIG_USB=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_MANUFACTURER="Atmel SAMA5D2_PTC"
-CONFIG_USB_GADGET_ATMEL_USBA=y
-CONFIG_USB_ETHER=y
diff --git a/configs/sama5d2_ptc_spiflash_defconfig b/configs/sama5d2_ptc_spiflash_defconfig
deleted file mode 100644
index 25ee077..0000000
--- a/configs/sama5d2_ptc_spiflash_defconfig
+++ /dev/null
@@ -1,34 +0,0 @@
-CONFIG_ARM=y
-CONFIG_ARCH_AT91=y
-CONFIG_TARGET_SAMA5D2_PTC=y
-CONFIG_SPL_GPIO_SUPPORT=y
-CONFIG_SPL_LIBCOMMON_SUPPORT=y
-CONFIG_SPL_LIBGENERIC_SUPPORT=y
-CONFIG_SPL_SERIAL_SUPPORT=y
-CONFIG_SPL_SPI_FLASH_SUPPORT=y
-CONFIG_SPL_SPI_SUPPORT=y
-CONFIG_SPI_BOOT=y
-CONFIG_BOOTDELAY=3
-CONFIG_USE_BOOTARGS=y
-CONFIG_BOOTARGS="console=ttyS0,57600 earlyprintk mtdparts=atmel_nand:6M(bootstrap)ro, 6M(kernel)ro,-(rootfs) rootfstype=ubifs ubi.mtd=2 root=ubi0:rootfs"
-# CONFIG_DISPLAY_BOARDINFO is not set
-CONFIG_SPL=y
-# CONFIG_CMD_IMI is not set
-# CONFIG_CMD_FLASH is not set
-# CONFIG_CMD_FPGA is not set
-# CONFIG_CMD_LOADS is not set
-CONFIG_CMD_NAND=y
-CONFIG_CMD_NAND_TRIMFFS=y
-CONFIG_CMD_SF=y
-CONFIG_CMD_USB=y
-CONFIG_CMD_FAT=y
-CONFIG_ENV_IS_IN_SPI_FLASH=y
-# CONFIG_MMC is not set
-CONFIG_SPI_FLASH=y
-CONFIG_USB=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_MANUFACTURER="Atmel SAMA5D2_PTC"
-CONFIG_USB_GADGET_ATMEL_USBA=y
-CONFIG_USB_ETHER=y
diff --git a/configs/stm32f746-disco_defconfig b/configs/stm32f746-disco_defconfig
index 378cf83..b661761 100644
--- a/configs/stm32f746-disco_defconfig
+++ b/configs/stm32f746-disco_defconfig
@@ -30,6 +30,8 @@
 CONFIG_NETCONSOLE=y
 CONFIG_CLK=y
 CONFIG_DM_GPIO=y
+CONFIG_MISC=y
+CONFIG_STM32_RCC=y
 # CONFIG_MMC is not set
 CONFIG_MTD=y
 CONFIG_MTD_NOR_FLASH=y
@@ -43,6 +45,8 @@
 CONFIG_PINCTRL_STM32=y
 CONFIG_RAM=y
 CONFIG_STM32_SDRAM=y
+CONFIG_DM_RESET=y
+CONFIG_STM32_RESET=y
 CONFIG_STM32X7_SERIAL=y
 CONFIG_DM_SPI=y
 CONFIG_STM32_QSPI=y
diff --git a/configs/wb45n_defconfig b/configs/wb45n_defconfig
new file mode 100644
index 0000000..6cf41df
--- /dev/null
+++ b/configs/wb45n_defconfig
@@ -0,0 +1,27 @@
+CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
+CONFIG_TARGET_WB45N=y
+CONFIG_SPL_GPIO_SUPPORT=y
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_SPL_SERIAL_SUPPORT=y
+CONFIG_SPL_NAND_SUPPORT=y
+CONFIG_FIT=y
+CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9X5,SYS_USE_NANDFLASH"
+CONFIG_BOOTDELAY=3
+CONFIG_BOARD_EARLY_INIT_F=y
+CONFIG_SPL=y
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_BOOTZ=y
+CONFIG_CMD_MEMTEST=y
+# CONFIG_CMD_FLASH is not set
+# CONFIG_CMD_FPGA is not set
+# CONFIG_CMD_LOADS is not set
+CONFIG_CMD_NAND=y
+CONFIG_CMD_NAND_TRIMFFS=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_ENV_IS_IN_NAND=y
+CONFIG_LZMA=y
+CONFIG_OF_LIBFDT=y
diff --git a/configs/wb50n_defconfig b/configs/wb50n_defconfig
new file mode 100644
index 0000000..1f3e41e
--- /dev/null
+++ b/configs/wb50n_defconfig
@@ -0,0 +1,30 @@
+CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
+CONFIG_TARGET_WB50N=y
+CONFIG_SPL_GPIO_SUPPORT=y
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_SPL_SERIAL_SUPPORT=y
+CONFIG_SPL_NAND_SUPPORT=y
+CONFIG_FIT=y
+CONFIG_SYS_EXTRA_OPTIONS="SAMA5D3,SYS_USE_NANDFLASH"
+CONFIG_BOOTDELAY=3
+CONFIG_SPL=y
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_BOOTZ=y
+CONFIG_CMD_MEMTEST=y
+# CONFIG_CMD_FLASH is not set
+# CONFIG_CMD_FPGA is not set
+# CONFIG_CMD_LOADS is not set
+CONFIG_CMD_NAND=y
+CONFIG_CMD_NAND_TRIMFFS=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_ENV_IS_IN_NAND=y
+CONFIG_PHYLIB=y
+CONFIG_PHY_MICREL=y
+CONFIG_PHY_MICREL_KSZ90X1=y
+CONFIG_NETDEVICES=y
+CONFIG_LZMA=y
+CONFIG_OF_LIBFDT=y
diff --git a/disk/part_efi.c b/disk/part_efi.c
index f6f5bee..bea8b20 100644
--- a/disk/part_efi.c
+++ b/disk/part_efi.c
@@ -350,7 +350,7 @@
 static int set_protective_mbr(struct blk_desc *dev_desc)
 {
 	/* Setup the Protective MBR */
-	ALLOC_CACHE_ALIGN_BUFFER(legacy_mbr, p_mbr, 1);
+	ALLOC_CACHE_ALIGN_BUFFER_PAD(legacy_mbr, p_mbr, 1, dev_desc->blksz);
 	memset(p_mbr, 0, sizeof(*p_mbr));
 
 	if (p_mbr == NULL) {
@@ -931,7 +931,7 @@
 		return 0;
 	}
 
-	ALLOC_CACHE_ALIGN_BUFFER(legacy_mbr, mbr, dev_desc->blksz);
+	ALLOC_CACHE_ALIGN_BUFFER_PAD(legacy_mbr, mbr, 1, dev_desc->blksz);
 
 	/* Read MBR Header from device */
 	if (blk_dread(dev_desc, 0, 1, (ulong *)mbr) != 1) {
diff --git a/doc/device-tree-bindings/spi/spi-atcspi200.txt b/doc/device-tree-bindings/spi/spi-atcspi200.txt
new file mode 100644
index 0000000..9c0630b
--- /dev/null
+++ b/doc/device-tree-bindings/spi/spi-atcspi200.txt
@@ -0,0 +1,37 @@
+Andestech ATCSPI200 SPI controller Device Tree Bindings
+-------------------------------------------------------
+ATCSPI200 is a Serial Peripheral Interface (SPI) controller
+which serves as a SPI master or a SPI slave.
+
+It is often be embedded in AE3XX and AE250 platforms.
+
+Required properties:
+- compatible: has to be "andestech,atcspi200".
+- reg: Base address and size of the controllers memory area.
+- #address-cells: <1>, as required by generic SPI binding.
+- #size-cells: <0>, also as required by generic SPI binding.
+- interrupts: Property with a value describing the interrupt number.
+- clocks: Clock phandles (see clock bindings for details).
+- spi-max-frequency: Maximum SPI clocking speed of device in Hz.
+
+Optional properties:
+- num-cs: Number of chip selects used.
+
+Example:
+
+	spi: spi@f0b00000 {
+		compatible = "andestech,atcspi200";
+		reg = <0xf0b00000 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		num-cs = <1>;
+		clocks = <&spiclk>;
+		interrupts = <3 4>;
+		flash@0 {
+			compatible = "spi-flash";
+			spi-max-frequency = <50000000>;
+			reg = <0>;
+			spi-cpol;
+			spi-cpha;
+		};
+	};
diff --git a/doc/device-tree-bindings/timer/atcpit100_timer.txt b/doc/device-tree-bindings/timer/atcpit100_timer.txt
new file mode 100644
index 0000000..620814e
--- /dev/null
+++ b/doc/device-tree-bindings/timer/atcpit100_timer.txt
@@ -0,0 +1,31 @@
+Andestech ATCPIT100 timer
+------------------------------------------------------------------
+ATCPIT100 is a generic IP block from Andes Technology, embedded in
+Andestech AE3XX, AE250 platforms and other designs.
+
+This timer is a set of compact multi-function timers, which can be
+used as pulse width modulators (PWM) as well as simple timers.
+
+It supports up to 4 PIT channels. Each PIT channel is a
+multi-function timer and provide the following usage scenarios:
+One 32-bit timer
+Two 16-bit timers
+Four 8-bit timers
+One 16-bit PWM
+One 16-bit timer and one 8-bit PWM
+Two 8-bit timer and one 8-bit PWM
+
+Required properties:
+- compatible	: Should be "andestech,atcpit100"
+- reg		: Address and length of the register set
+- interrupts	: Reference to the timer interrupt
+- clock-frequency : The rate in HZ in input of the Andestech ATCPIT100 timer
+
+Examples:
+
+timer0: timer@f0400000 {
+	compatible = "andestech,atcpit100";
+	reg = <0xf0400000 0x1000>;
+	interrupts = <2 4>;
+	clock-frequency = <30000000>;
+}:
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index baa60a5..f6644ee 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -46,6 +46,14 @@
 	help
 	  Enable this to support the clocks
 
+config CLK_STM32F
+	bool "Enable clock driver support for STM32F family"
+	depends on CLK && (STM32F7 || STM32F4)
+	default y
+	help
+	  This clock driver adds support for RCC clock management
+	  for STM32F4 and STM32F7 SoCs.
+
 config CLK_ZYNQ
 	bool "Enable clock driver support for Zynq"
 	depends on CLK && ARCH_ZYNQ
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 83fe88c..bcc8f82 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -21,5 +21,5 @@
 obj-$(CONFIG_CLK_BCM6345) += clk_bcm6345.o
 obj-$(CONFIG_CLK_BOSTON) += clk_boston.o
 obj-$(CONFIG_ARCH_ASPEED) += aspeed/
-obj-$(CONFIG_STM32F7) += clk_stm32f7.o
+obj-$(CONFIG_CLK_STM32F) += clk_stm32f.o
 obj-$(CONFIG_STM32H7) += clk_stm32h7.o
diff --git a/drivers/clk/at91/Kconfig b/drivers/clk/at91/Kconfig
index c6c5761..fd56f20 100644
--- a/drivers/clk/at91/Kconfig
+++ b/drivers/clk/at91/Kconfig
@@ -14,11 +14,11 @@
 
 config AT91_UTMI
 	bool "Support UTMI PLL Clock"
-	depends on CLK_AT91 && SPL_DM
+	depends on CLK_AT91
 	select REGMAP
-	select SPL_REGMAP
+	select SPL_REGMAP if SPL_DM
 	select SYSCON
-	select SPL_SYSCON
+	select SPL_SYSCON if SPL_DM
 	help
 	  This option is used to enable the AT91 UTMI PLL clock
 	  driver. It is the clock provider of USB, and UPLLCK is the
diff --git a/drivers/clk/at91/clk-generated.c b/drivers/clk/at91/clk-generated.c
index 8c9a3cb..2aacbae 100644
--- a/drivers/clk/at91/clk-generated.c
+++ b/drivers/clk/at91/clk-generated.c
@@ -53,16 +53,17 @@
 	struct clk parent;
 	ulong clk_rate;
 	u32 tmp, gckdiv;
-	u8 parent_id;
+	u8 clock_source, parent_index;
 	int ret;
 
 	writel(clk->id & AT91_PMC_PCR_PID_MASK, &pmc->pcr);
 	tmp = readl(&pmc->pcr);
-	parent_id = (tmp >> AT91_PMC_PCR_GCKCSS_OFFSET) &
+	clock_source = (tmp >> AT91_PMC_PCR_GCKCSS_OFFSET) &
 		    AT91_PMC_PCR_GCKCSS_MASK;
 	gckdiv = (tmp >> AT91_PMC_PCR_GCKDIV_OFFSET) & AT91_PMC_PCR_GCKDIV_MASK;
 
-	ret = clk_get_by_index(dev_get_parent(clk->dev), parent_id, &parent);
+	parent_index = clock_source - 1;
+	ret = clk_get_by_index(dev_get_parent(clk->dev), parent_index, &parent);
 	if (ret)
 		return 0;
 
@@ -82,7 +83,7 @@
 	ulong tmp_rate, best_rate = rate, parent_rate;
 	int tmp_diff, best_diff = -1;
 	u32 div, best_div = 0;
-	u8 best_parent_id = 0;
+	u8 best_parent_index, best_clock_source = 0;
 	u8 i;
 	u32 tmp;
 	int ret;
@@ -98,9 +99,7 @@
 
 		for (div = 1; div < GENERATED_MAX_DIV + 2; div++) {
 			tmp_rate = DIV_ROUND_CLOSEST(parent_rate, div);
-			if (rate < tmp_rate)
-				continue;
-			tmp_diff = rate - tmp_rate;
+			tmp_diff = abs(rate - tmp_rate);
 
 			if (best_diff < 0 || best_diff > tmp_diff) {
 				best_rate = tmp_rate;
@@ -108,7 +107,8 @@
 
 				best_div = div - 1;
 				best_parent = parent;
-				best_parent_id = i;
+				best_parent_index = i;
+				best_clock_source = best_parent_index + 1;
 			}
 
 			if (!best_diff || tmp_rate < rate)
@@ -129,7 +129,7 @@
 	writel(clk->id & AT91_PMC_PCR_PID_MASK, &pmc->pcr);
 	tmp = readl(&pmc->pcr);
 	tmp &= ~(AT91_PMC_PCR_GCKDIV | AT91_PMC_PCR_GCKCSS);
-	tmp |= AT91_PMC_PCR_GCKCSS_(best_parent_id) |
+	tmp |= AT91_PMC_PCR_GCKCSS_(best_clock_source) |
 	       AT91_PMC_PCR_CMD_WRITE |
 	       AT91_PMC_PCR_GCKDIV_(best_div) |
 	       AT91_PMC_PCR_GCKEN;
diff --git a/drivers/clk/clk_stm32f.c b/drivers/clk/clk_stm32f.c
new file mode 100644
index 0000000..634f071
--- /dev/null
+++ b/drivers/clk/clk_stm32f.c
@@ -0,0 +1,441 @@
+/*
+ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
+ * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <stm32_rcc.h>
+
+#include <asm/io.h>
+#include <asm/arch/stm32.h>
+#include <asm/arch/stm32_periph.h>
+#include <asm/arch/stm32_pwr.h>
+
+#include <dt-bindings/mfd/stm32f7-rcc.h>
+
+#define RCC_CR_HSION			BIT(0)
+#define RCC_CR_HSEON			BIT(16)
+#define RCC_CR_HSERDY			BIT(17)
+#define RCC_CR_HSEBYP			BIT(18)
+#define RCC_CR_CSSON			BIT(19)
+#define RCC_CR_PLLON			BIT(24)
+#define RCC_CR_PLLRDY			BIT(25)
+#define RCC_CR_PLLSAION			BIT(28)
+#define RCC_CR_PLLSAIRDY		BIT(29)
+
+#define RCC_PLLCFGR_PLLM_MASK		GENMASK(5, 0)
+#define RCC_PLLCFGR_PLLN_MASK		GENMASK(14, 6)
+#define RCC_PLLCFGR_PLLP_MASK		GENMASK(17, 16)
+#define RCC_PLLCFGR_PLLQ_MASK		GENMASK(27, 24)
+#define RCC_PLLCFGR_PLLSRC		BIT(22)
+#define RCC_PLLCFGR_PLLM_SHIFT		0
+#define RCC_PLLCFGR_PLLN_SHIFT		6
+#define RCC_PLLCFGR_PLLP_SHIFT		16
+#define RCC_PLLCFGR_PLLQ_SHIFT		24
+
+#define RCC_CFGR_AHB_PSC_MASK		GENMASK(7, 4)
+#define RCC_CFGR_APB1_PSC_MASK		GENMASK(12, 10)
+#define RCC_CFGR_APB2_PSC_MASK		GENMASK(15, 13)
+#define RCC_CFGR_SW0			BIT(0)
+#define RCC_CFGR_SW1			BIT(1)
+#define RCC_CFGR_SW_MASK		GENMASK(1, 0)
+#define RCC_CFGR_SW_HSI			0
+#define RCC_CFGR_SW_HSE			RCC_CFGR_SW0
+#define RCC_CFGR_SW_PLL			RCC_CFGR_SW1
+#define RCC_CFGR_SWS0			BIT(2)
+#define RCC_CFGR_SWS1			BIT(3)
+#define RCC_CFGR_SWS_MASK		GENMASK(3, 2)
+#define RCC_CFGR_SWS_HSI		0
+#define RCC_CFGR_SWS_HSE		RCC_CFGR_SWS0
+#define RCC_CFGR_SWS_PLL		RCC_CFGR_SWS1
+#define RCC_CFGR_HPRE_SHIFT		4
+#define RCC_CFGR_PPRE1_SHIFT		10
+#define RCC_CFGR_PPRE2_SHIFT		13
+
+#define RCC_PLLCFGR_PLLSAIN_MASK	GENMASK(14, 6)
+#define RCC_PLLCFGR_PLLSAIP_MASK	GENMASK(17, 16)
+#define RCC_PLLSAICFGR_PLLSAIN_SHIFT	6
+#define RCC_PLLSAICFGR_PLLSAIP_SHIFT	16
+#define RCC_PLLSAICFGR_PLLSAIP_4	BIT(17)
+#define RCC_PLLSAICFGR_PLLSAIQ_4	BIT(26)
+#define RCC_PLLSAICFGR_PLLSAIR_2	BIT(29)
+
+#define RCC_DCKCFGRX_CK48MSEL		BIT(27)
+#define RCC_DCKCFGRX_SDMMC1SEL		BIT(28)
+#define RCC_DCKCFGR2_SDMMC2SEL		BIT(29)
+
+#define RCC_APB2ENR_SAI1EN		BIT(22)
+
+/*
+ * RCC AHB1ENR specific definitions
+ */
+#define RCC_AHB1ENR_ETHMAC_EN		BIT(25)
+#define RCC_AHB1ENR_ETHMAC_TX_EN	BIT(26)
+#define RCC_AHB1ENR_ETHMAC_RX_EN	BIT(27)
+
+/*
+ * RCC APB1ENR specific definitions
+ */
+#define RCC_APB1ENR_TIM2EN		BIT(0)
+#define RCC_APB1ENR_PWREN		BIT(28)
+
+/*
+ * RCC APB2ENR specific definitions
+ */
+#define RCC_APB2ENR_SYSCFGEN		BIT(14)
+
+struct stm32_clk_info stm32f4_clk_info = {
+	/* 180 MHz */
+	.sys_pll_psc = {
+		.pll_m = 8,
+		.pll_n = 360,
+		.pll_p = 2,
+		.pll_q = 8,
+		.ahb_psc = AHB_PSC_1,
+		.apb1_psc = APB_PSC_4,
+		.apb2_psc = APB_PSC_2,
+	},
+	.has_overdrive = false,
+	.v2 = false,
+};
+
+struct stm32_clk_info stm32f7_clk_info = {
+	/* 200 MHz */
+	.sys_pll_psc = {
+		.pll_m = 25,
+		.pll_n = 400,
+		.pll_p = 2,
+		.pll_q = 8,
+		.ahb_psc = AHB_PSC_1,
+		.apb1_psc = APB_PSC_4,
+		.apb2_psc = APB_PSC_2,
+	},
+	.has_overdrive = true,
+	.v2 = true,
+};
+
+struct stm32_clk {
+	struct stm32_rcc_regs *base;
+	struct stm32_pwr_regs *pwr_regs;
+	struct stm32_clk_info *info;
+};
+
+static int configure_clocks(struct udevice *dev)
+{
+	struct stm32_clk *priv = dev_get_priv(dev);
+	struct stm32_rcc_regs *regs = priv->base;
+	struct stm32_pwr_regs *pwr = priv->pwr_regs;
+	struct pll_psc sys_pll_psc = priv->info->sys_pll_psc;
+	u32 pllsaicfgr = 0;
+
+	/* Reset RCC configuration */
+	setbits_le32(&regs->cr, RCC_CR_HSION);
+	writel(0, &regs->cfgr); /* Reset CFGR */
+	clrbits_le32(&regs->cr, (RCC_CR_HSEON | RCC_CR_CSSON
+		| RCC_CR_PLLON | RCC_CR_PLLSAION));
+	writel(0x24003010, &regs->pllcfgr); /* Reset value from RM */
+	clrbits_le32(&regs->cr, RCC_CR_HSEBYP);
+	writel(0, &regs->cir); /* Disable all interrupts */
+
+	/* Configure for HSE+PLL operation */
+	setbits_le32(&regs->cr, RCC_CR_HSEON);
+	while (!(readl(&regs->cr) & RCC_CR_HSERDY))
+		;
+
+	setbits_le32(&regs->cfgr, ((
+		sys_pll_psc.ahb_psc << RCC_CFGR_HPRE_SHIFT)
+		| (sys_pll_psc.apb1_psc << RCC_CFGR_PPRE1_SHIFT)
+		| (sys_pll_psc.apb2_psc << RCC_CFGR_PPRE2_SHIFT)));
+
+	/* Configure the main PLL */
+	setbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLSRC); /* pll source HSE */
+	clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLM_MASK,
+			sys_pll_psc.pll_m << RCC_PLLCFGR_PLLM_SHIFT);
+	clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLN_MASK,
+			sys_pll_psc.pll_n << RCC_PLLCFGR_PLLN_SHIFT);
+	clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLP_MASK,
+			((sys_pll_psc.pll_p >> 1) - 1) << RCC_PLLCFGR_PLLP_SHIFT);
+	clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLQ_MASK,
+			sys_pll_psc.pll_q << RCC_PLLCFGR_PLLQ_SHIFT);
+
+	/* Configure the SAI PLL to get a 48 MHz source */
+	pllsaicfgr = RCC_PLLSAICFGR_PLLSAIR_2 | RCC_PLLSAICFGR_PLLSAIQ_4 |
+		     RCC_PLLSAICFGR_PLLSAIP_4;
+	pllsaicfgr |= 192 << RCC_PLLSAICFGR_PLLSAIN_SHIFT;
+	writel(pllsaicfgr, &regs->pllsaicfgr);
+
+	/* Enable the main PLL */
+	setbits_le32(&regs->cr, RCC_CR_PLLON);
+	while (!(readl(&regs->cr) & RCC_CR_PLLRDY))
+		;
+
+	if (priv->info->v2) { /*stm32f7 case */
+		/* select PLLSAI as 48MHz clock source */
+		setbits_le32(&regs->dckcfgr2, RCC_DCKCFGRX_CK48MSEL);
+
+		/* select 48MHz as SDMMC1 clock source */
+		clrbits_le32(&regs->dckcfgr2, RCC_DCKCFGRX_SDMMC1SEL);
+
+		/* select 48MHz as SDMMC2 clock source */
+		clrbits_le32(&regs->dckcfgr2, RCC_DCKCFGR2_SDMMC2SEL);
+	} else  { /* stm32f4 case */
+		/* select PLLSAI as 48MHz clock source */
+		setbits_le32(&regs->dckcfgr, RCC_DCKCFGRX_CK48MSEL);
+
+		/* select 48MHz as SDMMC1 clock source */
+		clrbits_le32(&regs->dckcfgr, RCC_DCKCFGRX_SDMMC1SEL);
+	}
+
+	/* Enable the SAI PLL */
+	setbits_le32(&regs->cr, RCC_CR_PLLSAION);
+	while (!(readl(&regs->cr) & RCC_CR_PLLSAIRDY))
+		;
+
+	setbits_le32(&regs->apb1enr, RCC_APB1ENR_PWREN);
+
+	if (priv->info->has_overdrive) {
+		/*
+		 * Enable high performance mode
+		 * System frequency up to 200 MHz
+		 */
+		setbits_le32(&pwr->cr1, PWR_CR1_ODEN);
+		/* Infinite wait! */
+		while (!(readl(&pwr->csr1) & PWR_CSR1_ODRDY))
+			;
+		/* Enable the Over-drive switch */
+		setbits_le32(&pwr->cr1, PWR_CR1_ODSWEN);
+		/* Infinite wait! */
+		while (!(readl(&pwr->csr1) & PWR_CSR1_ODSWRDY))
+			;
+	}
+
+	stm32_flash_latency_cfg(5);
+	clrbits_le32(&regs->cfgr, (RCC_CFGR_SW0 | RCC_CFGR_SW1));
+	setbits_le32(&regs->cfgr, RCC_CFGR_SW_PLL);
+
+	while ((readl(&regs->cfgr) & RCC_CFGR_SWS_MASK) !=
+			RCC_CFGR_SWS_PLL)
+		;
+	/* gate the SAI clock, needed for MMC 1&2 clocks */
+	setbits_le32(&regs->apb2enr, RCC_APB2ENR_SAI1EN);
+
+	return 0;
+}
+
+static unsigned long stm32_clk_pll48clk_rate(struct stm32_clk *priv,
+					     u32 sysclk)
+{
+	struct stm32_rcc_regs *regs = priv->base;
+	u16 pllq, pllm, pllsain, pllsaip;
+	bool pllsai;
+
+	pllq = (readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLQ_MASK)
+	       >> RCC_PLLCFGR_PLLQ_SHIFT;
+
+	if (priv->info->v2) /*stm32f7 case */
+		pllsai = readl(&regs->dckcfgr2) & RCC_DCKCFGRX_CK48MSEL;
+	else
+		pllsai = readl(&regs->dckcfgr) & RCC_DCKCFGRX_CK48MSEL;
+
+	if (pllsai) {
+		/* PLL48CLK is selected from PLLSAI, get PLLSAI value */
+		pllm = (readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLM_MASK);
+		pllsain = ((readl(&regs->pllsaicfgr) & RCC_PLLCFGR_PLLSAIN_MASK)
+			>> RCC_PLLSAICFGR_PLLSAIN_SHIFT);
+		pllsaip = ((((readl(&regs->pllsaicfgr) & RCC_PLLCFGR_PLLSAIP_MASK)
+			>> RCC_PLLSAICFGR_PLLSAIP_SHIFT) + 1) << 1);
+		return ((CONFIG_STM32_HSE_HZ / pllm) * pllsain) / pllsaip;
+	}
+	/* PLL48CLK is selected from PLLQ */
+	return sysclk / pllq;
+}
+
+static unsigned long stm32_clk_get_rate(struct clk *clk)
+{
+	struct stm32_clk *priv = dev_get_priv(clk->dev);
+	struct stm32_rcc_regs *regs = priv->base;
+	u32 sysclk = 0;
+	u32 shift = 0;
+	u16 pllm, plln, pllp;
+	/* Prescaler table lookups for clock computation */
+	u8 ahb_psc_table[16] = {
+		0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9
+	};
+	u8 apb_psc_table[8] = {
+		0, 0, 0, 0, 1, 2, 3, 4
+	};
+
+	if ((readl(&regs->cfgr) & RCC_CFGR_SWS_MASK) ==
+			RCC_CFGR_SWS_PLL) {
+		pllm = (readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLM_MASK);
+		plln = ((readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLN_MASK)
+			>> RCC_PLLCFGR_PLLN_SHIFT);
+		pllp = ((((readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLP_MASK)
+			>> RCC_PLLCFGR_PLLP_SHIFT) + 1) << 1);
+		sysclk = ((CONFIG_STM32_HSE_HZ / pllm) * plln) / pllp;
+	} else {
+		return -EINVAL;
+	}
+
+	switch (clk->id) {
+	/*
+	 * AHB CLOCK: 3 x 32 bits consecutive registers are used :
+	 * AHB1, AHB2 and AHB3
+	 */
+	case STM32F7_AHB1_CLOCK(GPIOA) ... STM32F7_AHB3_CLOCK(QSPI):
+		shift = ahb_psc_table[(
+			(readl(&regs->cfgr) & RCC_CFGR_AHB_PSC_MASK)
+			>> RCC_CFGR_HPRE_SHIFT)];
+		return sysclk >>= shift;
+	/* APB1 CLOCK */
+	case STM32F7_APB1_CLOCK(TIM2) ... STM32F7_APB1_CLOCK(UART8):
+		shift = apb_psc_table[(
+			(readl(&regs->cfgr) & RCC_CFGR_APB1_PSC_MASK)
+			>> RCC_CFGR_PPRE1_SHIFT)];
+		return sysclk >>= shift;
+	/* APB2 CLOCK */
+	case STM32F7_APB2_CLOCK(TIM1) ... STM32F7_APB2_CLOCK(LTDC):
+		/*
+		 * particular case for SDMMC1 and SDMMC2 :
+		 * 48Mhz source clock can be from main PLL or from
+		 * SAI PLL
+		 */
+		switch (clk->id) {
+		case STM32F7_APB2_CLOCK(SDMMC1):
+			if (readl(&regs->dckcfgr2) & RCC_DCKCFGRX_SDMMC1SEL)
+				/* System clock is selected as SDMMC1 clock */
+				return sysclk;
+			else
+				return stm32_clk_pll48clk_rate(priv, sysclk);
+			break;
+		case STM32F7_APB2_CLOCK(SDMMC2):
+			if (readl(&regs->dckcfgr2) & RCC_DCKCFGR2_SDMMC2SEL)
+				/* System clock is selected as SDMMC2 clock */
+				return sysclk;
+			else
+				return stm32_clk_pll48clk_rate(priv, sysclk);
+			break;
+		}
+
+		shift = apb_psc_table[(
+			(readl(&regs->cfgr) & RCC_CFGR_APB2_PSC_MASK)
+			>> RCC_CFGR_PPRE2_SHIFT)];
+		return sysclk >>= shift;
+	default:
+		pr_err("clock index %ld out of range\n", clk->id);
+		return -EINVAL;
+	}
+}
+
+static int stm32_clk_enable(struct clk *clk)
+{
+	struct stm32_clk *priv = dev_get_priv(clk->dev);
+	struct stm32_rcc_regs *regs = priv->base;
+	u32 offset = clk->id / 32;
+	u32 bit_index = clk->id % 32;
+
+	debug("%s: clkid = %ld, offset from AHB1ENR is %d, bit_index = %d\n",
+	      __func__, clk->id, offset, bit_index);
+	setbits_le32(&regs->ahb1enr + offset, BIT(bit_index));
+
+	return 0;
+}
+
+void clock_setup(int peripheral)
+{
+	switch (peripheral) {
+	case SYSCFG_CLOCK_CFG:
+		setbits_le32(&STM32_RCC->apb2enr, RCC_APB2ENR_SYSCFGEN);
+		break;
+	case TIMER2_CLOCK_CFG:
+		setbits_le32(&STM32_RCC->apb1enr, RCC_APB1ENR_TIM2EN);
+		break;
+	case STMMAC_CLOCK_CFG:
+		setbits_le32(&STM32_RCC->ahb1enr, RCC_AHB1ENR_ETHMAC_EN);
+		setbits_le32(&STM32_RCC->ahb1enr, RCC_AHB1ENR_ETHMAC_RX_EN);
+		setbits_le32(&STM32_RCC->ahb1enr, RCC_AHB1ENR_ETHMAC_TX_EN);
+		break;
+	default:
+		break;
+	}
+}
+
+static int stm32_clk_probe(struct udevice *dev)
+{
+	struct ofnode_phandle_args args;
+	int err;
+
+	debug("%s\n", __func__);
+
+	struct stm32_clk *priv = dev_get_priv(dev);
+	fdt_addr_t addr;
+
+	addr = dev_read_addr(dev);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	priv->base = (struct stm32_rcc_regs *)addr;
+
+	switch (dev_get_driver_data(dev)) {
+	case STM32F4:
+		priv->info = &stm32f4_clk_info;
+		break;
+	case STM32F7:
+		priv->info = &stm32f7_clk_info;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (priv->info->has_overdrive) {
+		err = dev_read_phandle_with_args(dev, "st,syscfg", NULL, 0, 0,
+						 &args);
+		if (err) {
+			debug("%s: can't find syscon device (%d)\n", __func__,
+			      err);
+			return err;
+		}
+
+		priv->pwr_regs = (struct stm32_pwr_regs *)ofnode_get_addr(args.node);
+	}
+
+	configure_clocks(dev);
+
+	return 0;
+}
+
+static int stm32_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args)
+{
+	debug("%s(clk=%p)\n", __func__, clk);
+
+	if (args->args_count != 2) {
+		debug("Invaild args_count: %d\n", args->args_count);
+		return -EINVAL;
+	}
+
+	if (args->args_count)
+		clk->id = args->args[1];
+	else
+		clk->id = 0;
+
+	return 0;
+}
+
+static struct clk_ops stm32_clk_ops = {
+	.of_xlate	= stm32_clk_of_xlate,
+	.enable		= stm32_clk_enable,
+	.get_rate	= stm32_clk_get_rate,
+};
+
+U_BOOT_DRIVER(stm32fx_clk) = {
+	.name			= "stm32fx_rcc_clock",
+	.id			= UCLASS_CLK,
+	.ops			= &stm32_clk_ops,
+	.probe			= stm32_clk_probe,
+	.priv_auto_alloc_size	= sizeof(struct stm32_clk),
+	.flags			= DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/clk/clk_stm32f7.c b/drivers/clk/clk_stm32f7.c
deleted file mode 100644
index f1a9e9c..0000000
--- a/drivers/clk/clk_stm32f7.c
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
- * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics.
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <clk-uclass.h>
-#include <dm.h>
-#include <asm/io.h>
-#include <asm/arch/rcc.h>
-#include <asm/arch/stm32.h>
-#include <asm/arch/stm32_periph.h>
-
-#include <dt-bindings/mfd/stm32f7-rcc.h>
-
-#define RCC_CR_HSION			BIT(0)
-#define RCC_CR_HSEON			BIT(16)
-#define RCC_CR_HSERDY			BIT(17)
-#define RCC_CR_HSEBYP			BIT(18)
-#define RCC_CR_CSSON			BIT(19)
-#define RCC_CR_PLLON			BIT(24)
-#define RCC_CR_PLLRDY			BIT(25)
-
-#define RCC_PLLCFGR_PLLM_MASK		GENMASK(5, 0)
-#define RCC_PLLCFGR_PLLN_MASK		GENMASK(14, 6)
-#define RCC_PLLCFGR_PLLP_MASK		GENMASK(17, 16)
-#define RCC_PLLCFGR_PLLQ_MASK		GENMASK(27, 24)
-#define RCC_PLLCFGR_PLLSRC		BIT(22)
-#define RCC_PLLCFGR_PLLM_SHIFT		0
-#define RCC_PLLCFGR_PLLN_SHIFT		6
-#define RCC_PLLCFGR_PLLP_SHIFT		16
-#define RCC_PLLCFGR_PLLQ_SHIFT		24
-
-#define RCC_CFGR_AHB_PSC_MASK		GENMASK(7, 4)
-#define RCC_CFGR_APB1_PSC_MASK		GENMASK(12, 10)
-#define RCC_CFGR_APB2_PSC_MASK		GENMASK(15, 13)
-#define RCC_CFGR_SW0			BIT(0)
-#define RCC_CFGR_SW1			BIT(1)
-#define RCC_CFGR_SW_MASK		GENMASK(1, 0)
-#define RCC_CFGR_SW_HSI			0
-#define RCC_CFGR_SW_HSE			RCC_CFGR_SW0
-#define RCC_CFGR_SW_PLL			RCC_CFGR_SW1
-#define RCC_CFGR_SWS0			BIT(2)
-#define RCC_CFGR_SWS1			BIT(3)
-#define RCC_CFGR_SWS_MASK		GENMASK(3, 2)
-#define RCC_CFGR_SWS_HSI		0
-#define RCC_CFGR_SWS_HSE		RCC_CFGR_SWS0
-#define RCC_CFGR_SWS_PLL		RCC_CFGR_SWS1
-#define RCC_CFGR_HPRE_SHIFT		4
-#define RCC_CFGR_PPRE1_SHIFT		10
-#define RCC_CFGR_PPRE2_SHIFT		13
-
-/*
- * Offsets of some PWR registers
- */
-#define PWR_CR1_ODEN			BIT(16)
-#define PWR_CR1_ODSWEN			BIT(17)
-#define PWR_CSR1_ODRDY			BIT(16)
-#define PWR_CSR1_ODSWRDY		BIT(17)
-
-struct pll_psc {
-	u8	pll_m;
-	u16	pll_n;
-	u8	pll_p;
-	u8	pll_q;
-	u8	ahb_psc;
-	u8	apb1_psc;
-	u8	apb2_psc;
-};
-
-#define AHB_PSC_1			0
-#define AHB_PSC_2			0x8
-#define AHB_PSC_4			0x9
-#define AHB_PSC_8			0xA
-#define AHB_PSC_16			0xB
-#define AHB_PSC_64			0xC
-#define AHB_PSC_128			0xD
-#define AHB_PSC_256			0xE
-#define AHB_PSC_512			0xF
-
-#define APB_PSC_1			0
-#define APB_PSC_2			0x4
-#define APB_PSC_4			0x5
-#define APB_PSC_8			0x6
-#define APB_PSC_16			0x7
-
-struct stm32_clk {
-	struct stm32_rcc_regs *base;
-};
-
-#if !defined(CONFIG_STM32_HSE_HZ)
-#error "CONFIG_STM32_HSE_HZ not defined!"
-#else
-#if (CONFIG_STM32_HSE_HZ == 25000000)
-#if (CONFIG_SYS_CLK_FREQ == 200000000)
-/* 200 MHz */
-struct pll_psc sys_pll_psc = {
-	.pll_m = 25,
-	.pll_n = 400,
-	.pll_p = 2,
-	.pll_q = 8,
-	.ahb_psc = AHB_PSC_1,
-	.apb1_psc = APB_PSC_4,
-	.apb2_psc = APB_PSC_2
-};
-#endif
-#else
-#error "No PLL/Prescaler configuration for given CONFIG_STM32_HSE_HZ exists"
-#endif
-#endif
-
-static int configure_clocks(struct udevice *dev)
-{
-	struct stm32_clk *priv = dev_get_priv(dev);
-	struct stm32_rcc_regs *regs = priv->base;
-
-	/* Reset RCC configuration */
-	setbits_le32(&regs->cr, RCC_CR_HSION);
-	writel(0, &regs->cfgr); /* Reset CFGR */
-	clrbits_le32(&regs->cr, (RCC_CR_HSEON | RCC_CR_CSSON
-		| RCC_CR_PLLON));
-	writel(0x24003010, &regs->pllcfgr); /* Reset value from RM */
-	clrbits_le32(&regs->cr, RCC_CR_HSEBYP);
-	writel(0, &regs->cir); /* Disable all interrupts */
-
-	/* Configure for HSE+PLL operation */
-	setbits_le32(&regs->cr, RCC_CR_HSEON);
-	while (!(readl(&regs->cr) & RCC_CR_HSERDY))
-		;
-
-	setbits_le32(&regs->cfgr, ((
-		sys_pll_psc.ahb_psc << RCC_CFGR_HPRE_SHIFT)
-		| (sys_pll_psc.apb1_psc << RCC_CFGR_PPRE1_SHIFT)
-		| (sys_pll_psc.apb2_psc << RCC_CFGR_PPRE2_SHIFT)));
-
-	/* Configure the main PLL */
-	setbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLSRC); /* pll source HSE */
-	clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLM_MASK,
-			sys_pll_psc.pll_m << RCC_PLLCFGR_PLLM_SHIFT);
-	clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLN_MASK,
-			sys_pll_psc.pll_n << RCC_PLLCFGR_PLLN_SHIFT);
-	clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLP_MASK,
-			((sys_pll_psc.pll_p >> 1) - 1) << RCC_PLLCFGR_PLLP_SHIFT);
-	clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLQ_MASK,
-			sys_pll_psc.pll_q << RCC_PLLCFGR_PLLQ_SHIFT);
-
-	/* Enable the main PLL */
-	setbits_le32(&regs->cr, RCC_CR_PLLON);
-	while (!(readl(&regs->cr) & RCC_CR_PLLRDY))
-		;
-
-	/* Enable high performance mode, System frequency up to 200 MHz */
-	setbits_le32(&regs->apb1enr, RCC_APB1ENR_PWREN);
-	setbits_le32(&STM32_PWR->cr1, PWR_CR1_ODEN);
-	/* Infinite wait! */
-	while (!(readl(&STM32_PWR->csr1) & PWR_CSR1_ODRDY))
-		;
-	/* Enable the Over-drive switch */
-	setbits_le32(&STM32_PWR->cr1, PWR_CR1_ODSWEN);
-	/* Infinite wait! */
-	while (!(readl(&STM32_PWR->csr1) & PWR_CSR1_ODSWRDY))
-		;
-
-	stm32_flash_latency_cfg(5);
-	clrbits_le32(&regs->cfgr, (RCC_CFGR_SW0 | RCC_CFGR_SW1));
-	setbits_le32(&regs->cfgr, RCC_CFGR_SW_PLL);
-
-	while ((readl(&regs->cfgr) & RCC_CFGR_SWS_MASK) !=
-			RCC_CFGR_SWS_PLL)
-		;
-
-	return 0;
-}
-
-static unsigned long stm32_clk_get_rate(struct clk *clk)
-{
-	struct stm32_clk *priv = dev_get_priv(clk->dev);
-	struct stm32_rcc_regs *regs = priv->base;
-	u32 sysclk = 0;
-	u32 shift = 0;
-	/* Prescaler table lookups for clock computation */
-	u8 ahb_psc_table[16] = {
-		0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9
-	};
-	u8 apb_psc_table[8] = {
-		0, 0, 0, 0, 1, 2, 3, 4
-	};
-
-	if ((readl(&regs->cfgr) & RCC_CFGR_SWS_MASK) ==
-			RCC_CFGR_SWS_PLL) {
-		u16 pllm, plln, pllp;
-		pllm = (readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLM_MASK);
-		plln = ((readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLN_MASK)
-			>> RCC_PLLCFGR_PLLN_SHIFT);
-		pllp = ((((readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLP_MASK)
-			>> RCC_PLLCFGR_PLLP_SHIFT) + 1) << 1);
-		sysclk = ((CONFIG_STM32_HSE_HZ / pllm) * plln) / pllp;
-	} else {
-		return -EINVAL;
-	}
-
-	switch (clk->id) {
-	/*
-	 * AHB CLOCK: 3 x 32 bits consecutive registers are used :
-	 * AHB1, AHB2 and AHB3
-	 */
-	case STM32F7_AHB1_CLOCK(GPIOA) ... STM32F7_AHB3_CLOCK(QSPI):
-		shift = ahb_psc_table[(
-			(readl(&regs->cfgr) & RCC_CFGR_AHB_PSC_MASK)
-			>> RCC_CFGR_HPRE_SHIFT)];
-		return sysclk >>= shift;
-		break;
-	/* APB1 CLOCK */
-	case STM32F7_APB1_CLOCK(TIM2) ... STM32F7_APB1_CLOCK(UART8):
-		shift = apb_psc_table[(
-			(readl(&regs->cfgr) & RCC_CFGR_APB1_PSC_MASK)
-			>> RCC_CFGR_PPRE1_SHIFT)];
-		return sysclk >>= shift;
-		break;
-	/* APB2 CLOCK */
-	case STM32F7_APB2_CLOCK(TIM1) ... STM32F7_APB2_CLOCK(LTDC):
-		shift = apb_psc_table[(
-			(readl(&regs->cfgr) & RCC_CFGR_APB2_PSC_MASK)
-			>> RCC_CFGR_PPRE2_SHIFT)];
-		return sysclk >>= shift;
-		break;
-	default:
-		pr_err("clock index %ld out of range\n", clk->id);
-		return -EINVAL;
-		break;
-	}
-}
-
-static int stm32_clk_enable(struct clk *clk)
-{
-	struct stm32_clk *priv = dev_get_priv(clk->dev);
-	struct stm32_rcc_regs *regs = priv->base;
-	u32 offset = clk->id / 32;
-	u32 bit_index = clk->id % 32;
-
-	debug("%s: clkid = %ld, offset from AHB1ENR is %d, bit_index = %d\n",
-	      __func__, clk->id, offset, bit_index);
-	setbits_le32(&regs->ahb1enr + offset, BIT(bit_index));
-
-	return 0;
-}
-
-void clock_setup(int peripheral)
-{
-	switch (peripheral) {
-	case SYSCFG_CLOCK_CFG:
-		setbits_le32(&STM32_RCC->apb2enr, RCC_APB2ENR_SYSCFGEN);
-		break;
-	case TIMER2_CLOCK_CFG:
-		setbits_le32(&STM32_RCC->apb1enr, RCC_APB1ENR_TIM2EN);
-		break;
-	case STMMAC_CLOCK_CFG:
-		setbits_le32(&STM32_RCC->ahb1enr, RCC_AHB1ENR_ETHMAC_EN);
-		setbits_le32(&STM32_RCC->ahb1enr, RCC_AHB1ENR_ETHMAC_RX_EN);
-		setbits_le32(&STM32_RCC->ahb1enr, RCC_AHB1ENR_ETHMAC_TX_EN);
-		break;
-	default:
-		break;
-	}
-}
-
-static int stm32_clk_probe(struct udevice *dev)
-{
-	debug("%s: stm32_clk_probe\n", __func__);
-
-	struct stm32_clk *priv = dev_get_priv(dev);
-	fdt_addr_t addr;
-
-	addr = devfdt_get_addr(dev);
-	if (addr == FDT_ADDR_T_NONE)
-		return -EINVAL;
-
-	priv->base = (struct stm32_rcc_regs *)addr;
-
-	configure_clocks(dev);
-
-	return 0;
-}
-
-static int stm32_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args)
-{
-	debug("%s(clk=%p)\n", __func__, clk);
-
-	if (args->args_count != 2) {
-		debug("Invaild args_count: %d\n", args->args_count);
-		return -EINVAL;
-	}
-
-	if (args->args_count)
-		clk->id = args->args[1];
-	else
-		clk->id = 0;
-
-	return 0;
-}
-
-static struct clk_ops stm32_clk_ops = {
-	.of_xlate	= stm32_clk_of_xlate,
-	.enable		= stm32_clk_enable,
-	.get_rate	= stm32_clk_get_rate,
-};
-
-static const struct udevice_id stm32_clk_ids[] = {
-	{ .compatible = "st,stm32f42xx-rcc"},
-	{}
-};
-
-U_BOOT_DRIVER(stm32f7_clk) = {
-	.name			= "stm32f7_clk",
-	.id			= UCLASS_CLK,
-	.of_match		= stm32_clk_ids,
-	.ops			= &stm32_clk_ops,
-	.probe			= stm32_clk_probe,
-	.priv_auto_alloc_size	= sizeof(struct stm32_clk),
-	.flags			= DM_FLAG_PRE_RELOC,
-};
diff --git a/drivers/misc/stm32_rcc.c b/drivers/misc/stm32_rcc.c
index 32d3971..87d9928 100644
--- a/drivers/misc/stm32_rcc.c
+++ b/drivers/misc/stm32_rcc.c
@@ -8,31 +8,63 @@
 #include <common.h>
 #include <dm.h>
 #include <misc.h>
+#include <stm32_rcc.h>
+#include <dm/device-internal.h>
 #include <dm/lists.h>
 
+struct stm32_rcc_clk stm32_rcc_clk_f4 = {
+	.drv_name = "stm32fx_rcc_clock",
+	.soc = STM32F4,
+};
+
+struct stm32_rcc_clk stm32_rcc_clk_f7 = {
+	.drv_name = "stm32fx_rcc_clock",
+	.soc = STM32F7,
+};
+
+struct stm32_rcc_clk stm32_rcc_clk_h7 = {
+	.drv_name = "stm32h7_rcc_clock",
+};
+
 static int stm32_rcc_bind(struct udevice *dev)
 {
-	int ret;
 	struct udevice *child;
+	struct driver *drv;
+	struct stm32_rcc_clk *rcc_clk =
+		(struct stm32_rcc_clk *)dev_get_driver_data(dev);
+	int ret;
 
 	debug("%s(dev=%p)\n", __func__, dev);
 
-	ret = device_bind_driver_to_node(dev, "stm32h7_rcc_clock",
-					 "stm32h7_rcc_clock",
-					 dev_ofnode(dev), &child);
+	drv = lists_driver_lookup_name(rcc_clk->drv_name);
+	if (!drv) {
+		debug("Cannot find driver '%s'\n", rcc_clk->drv_name);
+		return -ENOENT;
+	}
+
+	ret = device_bind_with_driver_data(dev, drv, rcc_clk->drv_name,
+					   rcc_clk->soc,
+					   dev_ofnode(dev), &child);
+
 	if (ret)
 		return ret;
 
+#ifdef CONFIG_SPL_BUILD
+	return 0;
+#else
 	return device_bind_driver_to_node(dev, "stm32_rcc_reset",
 					  "stm32_rcc_reset",
 					  dev_ofnode(dev), &child);
+#endif
 }
 
 static const struct misc_ops stm32_rcc_ops = {
 };
 
 static const struct udevice_id stm32_rcc_ids[] = {
-	{.compatible = "st,stm32h743-rcc"},
+	{.compatible = "st,stm32f42xx-rcc", .data = (ulong)&stm32_rcc_clk_f4 },
+	{.compatible = "st,stm32f746-rcc", .data = (ulong)&stm32_rcc_clk_f7 },
+	{.compatible = "st,stm32h743-rcc", .data = (ulong)&stm32_rcc_clk_h7 },
 	{ }
 };
 
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 62ce0af..8fbeaa7 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -401,6 +401,18 @@
 	  If you have a board based on such a SoC and with a SD/MMC slot,
 	  say Y or M here.
 
+config MMC_NDS32
+	bool "Andestech SD/MMC controller support"
+	depends on DM_MMC && OF_CONTROL && BLK && FTSDC010
+	help
+	  This enables support for the Andestech SD/MMM controller, which is
+	  based on Faraday IP.
+
+config FTSDC010
+	bool "Ftsdc010 SD/MMC controller Support"
+	help
+	  This SD/MMC controller is present in Andestech SoCs which is based on Faraday IP.
+
 endif
 
 config TEGRA124_MMC_DISABLE_EXT_LOOPBACK
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index d505f37..9af375b 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -44,6 +44,7 @@
 obj-$(CONFIG_SH_MMCIF) += sh_mmcif.o
 obj-$(CONFIG_SH_SDHI) += sh_sdhi.o
 obj-$(CONFIG_STM32_SDMMC2) += stm32_sdmmc2.o
+obj-$(CONFIG_MMC_NDS32) += nds32_mmc.o
 
 # SDHCI
 obj-$(CONFIG_MMC_SDHCI)			+= sdhci.o
diff --git a/drivers/mmc/atmel_sdhci.c b/drivers/mmc/atmel_sdhci.c
index c19a1f3..9b37e32 100644
--- a/drivers/mmc/atmel_sdhci.c
+++ b/drivers/mmc/atmel_sdhci.c
@@ -13,6 +13,7 @@
 #include <asm/arch/clk.h>
 
 #define ATMEL_SDHC_MIN_FREQ	400000
+#define ATMEL_SDHC_GCK_RATE	240000000
 
 #ifndef CONFIG_DM_MMC
 int atmel_sdhci_init(void *regbase, u32 id)
@@ -57,9 +58,6 @@
 	struct atmel_sdhci_plat *plat = dev_get_platdata(dev);
 	struct sdhci_host *host = dev_get_priv(dev);
 	u32 max_clk;
-	u32 caps, caps_1;
-	u32 clk_base, clk_mul;
-	ulong gck_rate;
 	struct clk clk;
 	int ret;
 
@@ -78,17 +76,11 @@
 	host->bus_width	= fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
 					 "bus-width", 4);
 
-	caps = sdhci_readl(host, SDHCI_CAPABILITIES);
-	clk_base = (caps & SDHCI_CLOCK_V3_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
-	caps_1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
-	clk_mul = (caps_1 & SDHCI_CLOCK_MUL_MASK) >> SDHCI_CLOCK_MUL_SHIFT;
-	gck_rate = clk_base * 1000000 * (clk_mul + 1);
-
 	ret = clk_get_by_index(dev, 1, &clk);
 	if (ret)
 		return ret;
 
-	ret = clk_set_rate(&clk, gck_rate);
+	ret = clk_set_rate(&clk, ATMEL_SDHC_GCK_RATE);
 	if (ret)
 		return ret;
 
diff --git a/drivers/mmc/ftsdc010_mci.c b/drivers/mmc/ftsdc010_mci.c
index 652a718..6ac4f83 100644
--- a/drivers/mmc/ftsdc010_mci.c
+++ b/drivers/mmc/ftsdc010_mci.c
@@ -12,24 +12,15 @@
 #include <part.h>
 #include <mmc.h>
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/errno.h>
 #include <asm/byteorder.h>
 #include <faraday/ftsdc010.h>
+#include "ftsdc010_mci.h"
 
 #define CFG_CMD_TIMEOUT (CONFIG_SYS_HZ >> 4) /* 250 ms */
 #define CFG_RST_TIMEOUT CONFIG_SYS_HZ /* 1 sec reset timeout */
 
-struct ftsdc010_chip {
-	void __iomem *regs;
-	uint32_t wprot;   /* write protected (locked) */
-	uint32_t rate;    /* actual SD clock in Hz */
-	uint32_t sclk;    /* FTSDC010 source clock in Hz */
-	uint32_t fifo;    /* fifo depth in bytes */
-	uint32_t acmd;
-	struct mmc_config cfg;	/* mmc configuration */
-};
-
 static inline int ftsdc010_send_cmd(struct mmc *mmc, struct mmc_cmd *mmc_cmd)
 {
 	struct ftsdc010_chip *chip = mmc->priv;
@@ -127,9 +118,8 @@
 static int ftsdc010_wait(struct ftsdc010_mmc __iomem *regs, uint32_t mask)
 {
 	int ret = -ETIMEDOUT;
-	uint32_t st, ts;
-
-	for (ts = get_timer(0); get_timer(ts) < CFG_CMD_TIMEOUT; ) {
+	uint32_t st, timeout = 10000000;
+	while (timeout--) {
 		st = readl(&regs->status);
 		if (!(st & mask))
 			continue;
@@ -138,8 +128,9 @@
 		break;
 	}
 
-	if (ret)
+	if (ret){
 		debug("ftsdc010: wait st(0x%x) timeout\n", mask);
+	}
 
 	return ret;
 }
@@ -147,10 +138,16 @@
 /*
  * u-boot mmc api
  */
-
+#ifdef CONFIG_DM_MMC
+static int ftsdc010_request(struct udevice *dev, struct mmc_cmd *cmd,
+	struct mmc_data *data)
+{
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+#else
 static int ftsdc010_request(struct mmc *mmc, struct mmc_cmd *cmd,
 	struct mmc_data *data)
 {
+#endif
 	int ret = -EOPNOTSUPP;
 	uint32_t len = 0;
 	struct ftsdc010_chip *chip = mmc->priv;
@@ -245,14 +242,20 @@
 
 	if (!ret) {
 		ret = ftsdc010_wait(regs,
-			FTSDC010_STATUS_DATA_END | FTSDC010_STATUS_DATA_ERROR);
+			FTSDC010_STATUS_DATA_END | FTSDC010_STATUS_DATA_CRC_OK);
 	}
 
 	return ret;
 }
 
+#ifdef CONFIG_DM_MMC
+static int ftsdc010_set_ios(struct udevice *dev)
+{
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+#else
 static int ftsdc010_set_ios(struct mmc *mmc)
 {
+#endif
 	struct ftsdc010_chip *chip = mmc->priv;
 	struct ftsdc010_mmc __iomem *regs = chip->regs;
 
@@ -274,20 +277,43 @@
 	return 0;
 }
 
-static int ftsdc010_init(struct mmc *mmc)
+#ifdef CONFIG_DM_MMC
+static int ftsdc010_get_cd(struct udevice *dev)
 {
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+#else
+static int ftsdc010_get_cd(struct mmc *mmc)
+{
+#endif
 	struct ftsdc010_chip *chip = mmc->priv;
 	struct ftsdc010_mmc __iomem *regs = chip->regs;
-	uint32_t ts;
-
-	if (readl(&regs->status) & FTSDC010_STATUS_CARD_DETECT)
-		return -ENOMEDIUM;
+	return !(readl(&regs->status) & FTSDC010_STATUS_CARD_DETECT);
+}
 
+#ifdef CONFIG_DM_MMC
+static int ftsdc010_get_wp(struct udevice *dev)
+{
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+#else
+static int ftsdc010_get_wp(struct mmc *mmc)
+{
+#endif
+	struct ftsdc010_chip *chip = mmc->priv;
+	struct ftsdc010_mmc __iomem *regs = chip->regs;
 	if (readl(&regs->status) & FTSDC010_STATUS_WRITE_PROT) {
 		printf("ftsdc010: write protected\n");
 		chip->wprot = 1;
 	}
 
+	return 0;
+}
+
+static int ftsdc010_init(struct mmc *mmc)
+{
+	struct ftsdc010_chip *chip = mmc->priv;
+	struct ftsdc010_mmc __iomem *regs = chip->regs;
+	uint32_t ts;
+
 	chip->fifo = (readl(&regs->feature) & 0xff) << 2;
 
 	/* 1. chip reset */
@@ -311,11 +337,69 @@
 	return 0;
 }
 
+#ifdef CONFIG_DM_MMC
+int ftsdc010_probe(struct udevice *dev)
+{
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+	return ftsdc010_init(mmc);
+}
+
+const struct dm_mmc_ops dm_ftsdc010_ops = {
+	.send_cmd	= ftsdc010_request,
+	.set_ios	= ftsdc010_set_ios,
+	.get_cd		= ftsdc010_get_cd,
+	.get_wp		= ftsdc010_get_wp,
+};
+
+#else
 static const struct mmc_ops ftsdc010_ops = {
 	.send_cmd	= ftsdc010_request,
 	.set_ios	= ftsdc010_set_ios,
+	.getcd		= ftsdc010_get_cd,
+	.getwp		= ftsdc010_get_wp,
 	.init		= ftsdc010_init,
 };
+#endif
+
+void ftsdc_setup_cfg(struct mmc_config *cfg, const char *name, int buswidth,
+		     uint caps, u32 max_clk, u32 min_clk)
+{
+	cfg->name = name;
+	cfg->f_min = min_clk;
+	cfg->f_max = max_clk;
+	cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
+	cfg->host_caps = caps;
+	if (buswidth == 8) {
+		cfg->host_caps |= MMC_MODE_8BIT;
+		cfg->host_caps &= ~MMC_MODE_4BIT;
+	} else {
+		cfg->host_caps |= MMC_MODE_4BIT;
+		cfg->host_caps &= ~MMC_MODE_8BIT;
+	}
+	cfg->part_type = PART_TYPE_DOS;
+	cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+}
+
+void set_bus_width(struct ftsdc010_mmc __iomem *regs, struct mmc_config *cfg)
+{
+	switch (readl(&regs->bwr) & FTSDC010_BWR_CAPS_MASK) {
+	case FTSDC010_BWR_CAPS_4BIT:
+		cfg->host_caps |= MMC_MODE_4BIT;
+		break;
+	case FTSDC010_BWR_CAPS_8BIT:
+		cfg->host_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;
+		break;
+	default:
+		break;
+	}
+}
+
+#ifdef CONFIG_BLK
+int ftsdc010_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg)
+{
+	return mmc_bind(dev, mmc, cfg);
+}
+#else
 
 int ftsdc010_mmc_init(int devid)
 {
@@ -345,19 +429,11 @@
 #endif
 
 	chip->cfg.name = "ftsdc010";
+#ifndef CONFIG_DM_MMC
 	chip->cfg.ops = &ftsdc010_ops;
+#endif
 	chip->cfg.host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz;
-	switch (readl(&regs->bwr) & FTSDC010_BWR_CAPS_MASK) {
-	case FTSDC010_BWR_CAPS_4BIT:
-		chip->cfg.host_caps |= MMC_MODE_4BIT;
-		break;
-	case FTSDC010_BWR_CAPS_8BIT:
-		chip->cfg.host_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;
-		break;
-	default:
-		break;
-	}
-
+	set_bus_width(regs , &chip->cfg);
 	chip->cfg.voltages  = MMC_VDD_32_33 | MMC_VDD_33_34;
 	chip->cfg.f_max     = chip->sclk / 2;
 	chip->cfg.f_min     = chip->sclk / 0x100;
@@ -373,3 +449,4 @@
 
 	return 0;
 }
+#endif
diff --git a/drivers/mmc/ftsdc010_mci.h b/drivers/mmc/ftsdc010_mci.h
new file mode 100644
index 0000000..31a27fd
--- /dev/null
+++ b/drivers/mmc/ftsdc010_mci.h
@@ -0,0 +1,53 @@
+/*
+ * Faraday FTSDC010 Secure Digital Memory Card Host Controller
+ *
+ * Copyright (C) 2011 Andes Technology Corporation
+ * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#include <mmc.h>
+
+#ifndef __FTSDC010_MCI_H
+#define __FTSDC010_MCI_H
+
+struct ftsdc010_chip {
+	void __iomem *regs;
+	uint32_t wprot;   /* write protected (locked) */
+	uint32_t rate;    /* actual SD clock in Hz */
+	uint32_t sclk;    /* FTSDC010 source clock in Hz */
+	uint32_t fifo;    /* fifo depth in bytes */
+	uint32_t acmd;
+	struct mmc_config cfg;	/* mmc configuration */
+	const char *name;
+	void *ioaddr;
+	unsigned int caps;
+	unsigned int version;
+	unsigned int clock;
+	unsigned int bus_hz;
+	unsigned int div;
+	int dev_index;
+	int dev_id;
+	int buswidth;
+	u32 fifoth_val;
+	struct mmc *mmc;
+	void *priv;
+	bool fifo_mode;
+};
+
+
+#ifdef CONFIG_DM_MMC
+/* Export the operations to drivers */
+int ftsdc010_probe(struct udevice *dev);
+extern const struct dm_mmc_ops dm_ftsdc010_ops;
+#endif
+void ftsdc_setup_cfg(struct mmc_config *cfg, const char *name, int buswidth,
+		     uint caps, u32 max_clk, u32 min_clk);
+void set_bus_width(struct ftsdc010_mmc __iomem *regs, struct mmc_config *cfg);
+
+#ifdef CONFIG_BLK
+int ftsdc010_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg);
+#endif
+
+
+#endif /* __FTSDC010_MCI_H */
diff --git a/drivers/mmc/nds32_mmc.c b/drivers/mmc/nds32_mmc.c
new file mode 100644
index 0000000..6d3c857
--- /dev/null
+++ b/drivers/mmc/nds32_mmc.c
@@ -0,0 +1,136 @@
+/*
+ * Andestech ATFSDC010 SD/MMC driver
+ *
+ * (C) Copyright 2017
+ * Rick Chen, NDS32 Software Engineering, rick@andestech.com
+
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dt-structs.h>
+#include <errno.h>
+#include <mapmem.h>
+#include <mmc.h>
+#include <pwrseq.h>
+#include <syscon.h>
+#include <linux/err.h>
+#include <faraday/ftsdc010.h>
+#include "ftsdc010_mci.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+struct nds_mmc {
+	fdt32_t		bus_width;
+	bool		cap_mmc_highspeed;
+	bool		cap_sd_highspeed;
+	fdt32_t		clock_freq_min_max[2];
+	struct phandle_2_cell	clocks[4];
+	fdt32_t		fifo_depth;
+	fdt32_t		reg[2];
+};
+#endif
+
+struct nds_mmc_plat {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct nds_mmc dtplat;
+#endif
+	struct mmc_config cfg;
+	struct mmc mmc;
+};
+
+struct ftsdc_priv {
+	struct clk clk;
+	struct ftsdc010_chip chip;
+	int fifo_depth;
+	bool fifo_mode;
+	u32 minmax[2];
+};
+
+static int nds32_mmc_ofdata_to_platdata(struct udevice *dev)
+{
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct ftsdc_priv *priv = dev_get_priv(dev);
+	struct ftsdc010_chip *chip = &priv->chip;
+	chip->name = dev->name;
+	chip->ioaddr = (void *)devfdt_get_addr(dev);
+	chip->buswidth = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
+					"bus-width", 4);
+	chip->priv = dev;
+	priv->fifo_depth = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
+				    "fifo-depth", 0);
+	priv->fifo_mode = fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev),
+					  "fifo-mode");
+	if (fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev),
+			 "clock-freq-min-max", priv->minmax, 2)) {
+		int val = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
+				  "max-frequency", -EINVAL);
+		if (val < 0)
+			return val;
+
+		priv->minmax[0] = 400000;  /* 400 kHz */
+		priv->minmax[1] = val;
+	} else {
+		debug("%s: 'clock-freq-min-max' property was deprecated.\n",
+		__func__);
+	}
+#endif
+	chip->sclk = priv->minmax[1];
+	chip->regs = chip->ioaddr;
+	return 0;
+}
+
+static int nds32_mmc_probe(struct udevice *dev)
+{
+	struct nds_mmc_plat *plat = dev_get_platdata(dev);
+	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+	struct ftsdc_priv *priv = dev_get_priv(dev);
+	struct ftsdc010_chip *chip = &priv->chip;
+	struct udevice *pwr_dev __maybe_unused;
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	int ret;
+	struct nds_mmc *dtplat = &plat->dtplat;
+	chip->name = dev->name;
+	chip->ioaddr = map_sysmem(dtplat->reg[0], dtplat->reg[1]);
+	chip->buswidth = dtplat->bus_width;
+	chip->priv = dev;
+	chip->dev_index = 1;
+	memcpy(priv->minmax, dtplat->clock_freq_min_max, sizeof(priv->minmax));
+	ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &priv->clk);
+	if (ret < 0)
+		return ret;
+#endif
+	ftsdc_setup_cfg(&plat->cfg, dev->name, chip->buswidth, chip->caps,
+			priv->minmax[1] , priv->minmax[0]);
+	chip->mmc = &plat->mmc;
+	chip->mmc->priv = &priv->chip;
+	chip->mmc->dev = dev;
+	upriv->mmc = chip->mmc;
+	return ftsdc010_probe(dev);
+}
+
+static int nds32_mmc_bind(struct udevice *dev)
+{
+	struct nds_mmc_plat *plat = dev_get_platdata(dev);
+	return ftsdc010_bind(dev, &plat->mmc, &plat->cfg);
+}
+
+static const struct udevice_id nds32_mmc_ids[] = {
+	{ .compatible = "andestech,atsdc010" },
+	{ }
+};
+
+U_BOOT_DRIVER(nds32_mmc_drv) = {
+	.name		= "nds32_mmc",
+	.id		= UCLASS_MMC,
+	.of_match	= nds32_mmc_ids,
+	.ofdata_to_platdata = nds32_mmc_ofdata_to_platdata,
+	.ops		= &dm_ftsdc010_ops,
+	.bind		= nds32_mmc_bind,
+	.probe		= nds32_mmc_probe,
+	.priv_auto_alloc_size = sizeof(struct ftsdc_priv),
+	.platdata_auto_alloc_size = sizeof(struct nds_mmc_plat),
+};
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 88da9a4..494639f 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -210,12 +210,12 @@
 	  used to access the SPI NOR flash on platforms embedding this
 	  Freescale IP core.
 
-config NDS_AE3XX_SPI
-	bool "Andestech AE3XX SPI driver"
+config ATCSPI200_SPI
+	bool "Andestech ATCSPI200 SPI driver"
 	help
-	  Enable the Andestech AE3XX SPI driver. This driver can be
-	  used to access the SPI flash on platforms embedding this
-	  Andestech IP core.
+	  Enable the Andestech ATCSPI200 SPI driver. This driver can be
+	  used to access the SPI flash on AE3XX and AE250 platforms embedding
+	  this Andestech IP core.
 
 config TI_QSPI
 	bool "TI QSPI driver"
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index ad56203..e3184db 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -34,7 +34,7 @@
 obj-$(CONFIG_MVEBU_A3700_SPI) += mvebu_a3700_spi.o
 obj-$(CONFIG_MXC_SPI) += mxc_spi.o
 obj-$(CONFIG_MXS_SPI) += mxs_spi.o
-obj-$(CONFIG_NDS_AE3XX_SPI) += nds_ae3xx_spi.o
+obj-$(CONFIG_ATCSPI200_SPI) += atcspi200_spi.o
 obj-$(CONFIG_OMAP3_SPI) += omap3_spi.o
 obj-$(CONFIG_PIC32_SPI) += pic32_spi.o
 obj-$(CONFIG_ROCKCHIP_SPI) += rk_spi.o
diff --git a/drivers/spi/nds_ae3xx_spi.c b/drivers/spi/atcspi200_spi.c
similarity index 80%
rename from drivers/spi/nds_ae3xx_spi.c
rename to drivers/spi/atcspi200_spi.c
index f5bd99a..3e29df0 100644
--- a/drivers/spi/nds_ae3xx_spi.c
+++ b/drivers/spi/atcspi200_spi.c
@@ -1,5 +1,5 @@
 /*
- * NDS SPI controller driver.
+ * Andestech ATCSPI200 SPI controller driver.
  *
  * Copyright 2017 Andes Technology, Inc.
  * Author: Rick Chen (rick@andestech.com)
@@ -25,7 +25,7 @@
 #define SPI1_BASE		0xf0f00000
 #define NSPI_MAX_CS_NUM		1
 
-struct ae3xx_spi_regs {
+struct atcspi200_spi_regs {
 	u32	rev;
 	u32	reserve1[3];
 	u32	format;		/* 0x10 */
@@ -78,7 +78,7 @@
 #ifndef CONFIG_DM_SPI
 	struct spi_slave slave;
 #endif
-	volatile struct ae3xx_spi_regs *regs;
+	volatile struct atcspi200_spi_regs *regs;
 	int		to;
 	unsigned int	freq;
 	ulong		clock;
@@ -94,7 +94,7 @@
 	unsigned int    max_transfer_length;
 };
 
-static int __ae3xx_spi_set_speed(struct nds_spi_slave *ns)
+static int __atcspi200_spi_set_speed(struct nds_spi_slave *ns)
 {
 	u32 tm;
 	u8 div;
@@ -117,7 +117,7 @@
 
 }
 
-static int __ae3xx_spi_claim_bus(struct nds_spi_slave *ns)
+static int __atcspi200_spi_claim_bus(struct nds_spi_slave *ns)
 {
 		unsigned int format=0;
 		ns->regs->ctrl |= (TXFRST|RXFRST|SPIRST);
@@ -128,18 +128,18 @@
 		ns->cmd_len = 0;
 		format = ns->mode|DATA_LENGTH(8);
 		ns->regs->format = format;
-		__ae3xx_spi_set_speed(ns);
+		__atcspi200_spi_set_speed(ns);
 
 		return 0;
 }
 
-static int __ae3xx_spi_release_bus(struct nds_spi_slave *ns)
+static int __atcspi200_spi_release_bus(struct nds_spi_slave *ns)
 {
 	/* do nothing */
 	return 0;
 }
 
-static int __ae3xx_spi_start(struct nds_spi_slave *ns)
+static int __atcspi200_spi_start(struct nds_spi_slave *ns)
 {
 	int i,olen=0;
 	int tc = ns->regs->tctrl;
@@ -168,7 +168,7 @@
 	return 0;
 }
 
-static int __ae3xx_spi_stop(struct nds_spi_slave *ns)
+static int __atcspi200_spi_stop(struct nds_spi_slave *ns)
 {
 	ns->regs->timing = ns->mtiming;
 	while ((ns->regs->status & SPIBSY)&&(ns->to--))
@@ -190,7 +190,7 @@
 }
 
 
-static int __ae3xx_spi_xfer(struct nds_spi_slave *ns,
+static int __atcspi200_spi_xfer(struct nds_spi_slave *ns,
 		unsigned int bitlen,  const void *data_out, void *data_in,
 		unsigned long flags)
 {
@@ -230,7 +230,7 @@
 			memcpy(cmd_buf, data_out, cmd_len);
 			data_out = 0;
 			data_len = 0;
-			__ae3xx_spi_start(ns);
+			__atcspi200_spi_start(ns);
 			break;
 		}
 		debug("spi_xfer: data_out %08X(%p) data_in %08X(%p) data_len %u\n",
@@ -245,7 +245,7 @@
 			num_bytes = (tran_len) % CHUNK_SIZE;
 			if(num_bytes == 0)
 				num_bytes = CHUNK_SIZE;
-			__ae3xx_spi_start(ns);
+			__atcspi200_spi_start(ns);
 
 			while (num_blks) {
 				event = in_le32(&ns->regs->status);
@@ -279,9 +279,9 @@
 				ns->cmd_buf[3] += ((tran_len)&0xff);
 				ns->data_len = data_len;
 			}
-			ret = __ae3xx_spi_stop(ns);
+			ret = __atcspi200_spi_stop(ns);
 		}
-		ret = __ae3xx_spi_stop(ns);
+		ret = __atcspi200_spi_stop(ns);
 
 		return ret;
 }
@@ -300,11 +300,11 @@
 
 	switch (bus) {
 	case SPI0_BUS:
-			ns->regs = (struct ae3xx_spi_regs *)SPI0_BASE;
+			ns->regs = (struct atcspi200_spi_regs *)SPI0_BASE;
 			break;
 
 		case SPI1_BUS:
-			ns->regs = (struct ae3xx_spi_regs *)SPI1_BASE;
+			ns->regs = (struct atcspi200_spi_regs *)SPI1_BASE;
 			break;
 
 		default:
@@ -336,20 +336,20 @@
 int spi_claim_bus(struct spi_slave *slave)
 {
 	struct nds_spi_slave *ns = to_nds_spi_slave(slave);
-	return __ae3xx_spi_claim_bus(ns);
+	return __atcspi200_spi_claim_bus(ns);
 }
 
 void spi_release_bus(struct spi_slave *slave)
 {
 	struct nds_spi_slave *ns = to_nds_spi_slave(slave);
-	__ae3xx_spi_release_bus(ns);
+	__atcspi200_spi_release_bus(ns);
 }
 
 int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *data_out,
 		void *data_in, unsigned long flags)
 {
 	struct nds_spi_slave *ns = to_nds_spi_slave(slave);
-	return __ae3xx_spi_xfer(ns, bitlen, data_out, data_in, flags);
+	return __atcspi200_spi_xfer(ns, bitlen, data_out, data_in, flags);
 }
 
 int spi_cs_is_valid(unsigned int bus, unsigned int cs)
@@ -360,28 +360,28 @@
 void spi_cs_activate(struct spi_slave *slave)
 {
 	struct nds_spi_slave *ns = to_nds_spi_slave(slave);
-	__ae3xx_spi_start(ns);
+	__atcspi200_spi_start(ns);
 }
 
 void spi_cs_deactivate(struct spi_slave *slave)
 {
 	struct nds_spi_slave *ns = to_nds_spi_slave(slave);
-	__ae3xx_spi_stop(ns);
+	__atcspi200_spi_stop(ns);
 }
 #else
-static int ae3xx_spi_set_speed(struct udevice *bus, uint max_hz)
+static int atcspi200_spi_set_speed(struct udevice *bus, uint max_hz)
 {
 	struct nds_spi_slave *ns = dev_get_priv(bus);
 
 	debug("%s speed %u\n", __func__, max_hz);
 
 	ns->freq = max_hz;
-	__ae3xx_spi_set_speed(ns);
+	__atcspi200_spi_set_speed(ns);
 
 	return 0;
 }
 
-static int ae3xx_spi_set_mode(struct udevice *bus, uint mode)
+static int atcspi200_spi_set_mode(struct udevice *bus, uint mode)
 {
 	struct nds_spi_slave *ns = dev_get_priv(bus);
 
@@ -391,7 +391,7 @@
 	return 0;
 }
 
-static int ae3xx_spi_claim_bus(struct udevice *dev)
+static int atcspi200_spi_claim_bus(struct udevice *dev)
 {
 	struct dm_spi_slave_platdata *slave_plat =
 		dev_get_parent_platdata(dev);
@@ -403,27 +403,27 @@
 		return -EINVAL;
 	}
 
-	return __ae3xx_spi_claim_bus(ns);
+	return __atcspi200_spi_claim_bus(ns);
 }
 
-static int ae3xx_spi_release_bus(struct udevice *dev)
+static int atcspi200_spi_release_bus(struct udevice *dev)
 {
 	struct nds_spi_slave *ns = dev_get_priv(dev->parent);
 
-	return __ae3xx_spi_release_bus(ns);
+	return __atcspi200_spi_release_bus(ns);
 }
 
-static int ae3xx_spi_xfer(struct udevice *dev, unsigned int bitlen,
+static int atcspi200_spi_xfer(struct udevice *dev, unsigned int bitlen,
 			    const void *dout, void *din,
 			    unsigned long flags)
 {
 	struct udevice *bus = dev->parent;
 	struct nds_spi_slave *ns = dev_get_priv(bus);
 
-	return __ae3xx_spi_xfer(ns, bitlen, dout, din, flags);
+	return __atcspi200_spi_xfer(ns, bitlen, dout, din, flags);
 }
 
-static int ae3xx_spi_get_clk(struct udevice *bus)
+static int atcspi200_spi_get_clk(struct udevice *bus)
 {
 	struct nds_spi_slave *ns = dev_get_priv(bus);
 	struct clk clk;
@@ -444,26 +444,26 @@
 	return 0;
 }
 
-static int ae3xx_spi_probe(struct udevice *bus)
+static int atcspi200_spi_probe(struct udevice *bus)
 {
 	struct nds_spi_slave *ns = dev_get_priv(bus);
 
 	ns->to = SPI_TIMEOUT;
 	ns->max_transfer_length = MAX_TRANSFER_LEN;
 	ns->mtiming = ns->regs->timing;
-	ae3xx_spi_get_clk(bus);
+	atcspi200_spi_get_clk(bus);
 
 	return 0;
 }
 
-static int ae3xx_ofdata_to_platadata(struct udevice *bus)
+static int atcspi200_ofdata_to_platadata(struct udevice *bus)
 {
 	struct nds_spi_slave *ns = dev_get_priv(bus);
 	const void *blob = gd->fdt_blob;
 	int node = dev_of_offset(bus);
 
 	ns->regs = map_physmem(devfdt_get_addr(bus),
-				 sizeof(struct ae3xx_spi_regs),
+				 sizeof(struct atcspi200_spi_regs),
 				 MAP_NOCACHE);
 	if (!ns->regs) {
 		printf("%s: could not map device address\n", __func__);
@@ -474,26 +474,26 @@
 	return 0;
 }
 
-static const struct dm_spi_ops ae3xx_spi_ops = {
-	.claim_bus	= ae3xx_spi_claim_bus,
-	.release_bus	= ae3xx_spi_release_bus,
-	.xfer		= ae3xx_spi_xfer,
-	.set_speed	= ae3xx_spi_set_speed,
-	.set_mode	= ae3xx_spi_set_mode,
+static const struct dm_spi_ops atcspi200_spi_ops = {
+	.claim_bus	= atcspi200_spi_claim_bus,
+	.release_bus	= atcspi200_spi_release_bus,
+	.xfer		= atcspi200_spi_xfer,
+	.set_speed	= atcspi200_spi_set_speed,
+	.set_mode	= atcspi200_spi_set_mode,
 };
 
-static const struct udevice_id ae3xx_spi_ids[] = {
+static const struct udevice_id atcspi200_spi_ids[] = {
 	{ .compatible = "andestech,atcspi200" },
 	{ }
 };
 
-U_BOOT_DRIVER(ae3xx_spi) = {
-	.name = "ae3xx_spi",
+U_BOOT_DRIVER(atcspi200_spi) = {
+	.name = "atcspi200_spi",
 	.id = UCLASS_SPI,
-	.of_match = ae3xx_spi_ids,
-	.ops = &ae3xx_spi_ops,
-	.ofdata_to_platdata = ae3xx_ofdata_to_platadata,
+	.of_match = atcspi200_spi_ids,
+	.ops = &atcspi200_spi_ops,
+	.ofdata_to_platdata = atcspi200_ofdata_to_platadata,
 	.priv_auto_alloc_size = sizeof(struct nds_spi_slave),
-	.probe = ae3xx_spi_probe,
+	.probe = atcspi200_spi_probe,
 };
 #endif
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
index 6305bbf..3a1f831 100644
--- a/drivers/timer/Kconfig
+++ b/drivers/timer/Kconfig
@@ -105,11 +105,12 @@
 	help
 	  Select this to enable a timer for AG01P devices.
 
-config AE3XX_TIMER
-	bool "AE3XX timer support"
-	depends on TIMER && NDS32
+config ATCPIT100_TIMER
+	bool "ATCPIT100 timer support"
+	depends on TIMER
 	help
-	  Select this to enable a timer for AE3XX devices.
+	  Select this to enable a ATCPIT100 timer which will be embeded
+		in AE3XX, AE250 boards.
 
 config ROCKCHIP_TIMER
         bool "Rockchip timer support"
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
index 69e8961..15e5154 100644
--- a/drivers/timer/Makefile
+++ b/drivers/timer/Makefile
@@ -13,6 +13,6 @@
 obj-$(CONFIG_STI_TIMER)		+= sti-timer.o
 obj-$(CONFIG_ARC_TIMER)	+= arc_timer.o
 obj-$(CONFIG_AG101P_TIMER) += ag101p_timer.o
-obj-$(CONFIG_AE3XX_TIMER) += ae3xx_timer.o
+obj-$(CONFIG_ATCPIT100_TIMER) += atcpit100_timer.o
 obj-$(CONFIG_ROCKCHIP_TIMER) += rockchip_timer.o
 obj-$(CONFIG_ATMEL_PIT_TIMER) += atmel_pit_timer.o
diff --git a/drivers/timer/ae3xx_timer.c b/drivers/timer/atcpit100_timer.c
similarity index 67%
rename from drivers/timer/ae3xx_timer.c
rename to drivers/timer/atcpit100_timer.c
index bcc07a0..963f978 100644
--- a/drivers/timer/ae3xx_timer.c
+++ b/drivers/timer/atcpit100_timer.c
@@ -14,7 +14,7 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#define REG32_TMR(x)	(*(unsigned long *)	((plat->regs) + (x>>2)))
+#define REG32_TMR(x)	(*(u32 *)	((plat->regs) + (x>>2)))
 
 /*
  * Definition of register offsets
@@ -67,51 +67,51 @@
 	u32	int_mask;	/* 0x38 */
 };
 
-struct atftmr_timer_platdata {
-	unsigned long *regs;
+struct atcpit_timer_platdata {
+	u32 *regs;
 };
 
-static int atftmr_timer_get_count(struct udevice *dev, u64 *count)
+static int atcpit_timer_get_count(struct udevice *dev, u64 *count)
 {
-	struct atftmr_timer_platdata *plat = dev->platdata;
+	struct atcpit_timer_platdata *plat = dev_get_platdata(dev);
 	u32 val;
 	val = ~(REG32_TMR(CH_CNT(1))+0xffffffff);
 	*count = timer_conv_64(val);
 	return 0;
 }
 
-static int atctmr_timer_probe(struct udevice *dev)
+static int atcpit_timer_probe(struct udevice *dev)
 {
-	struct atftmr_timer_platdata *plat = dev->platdata;
+	struct atcpit_timer_platdata *plat = dev_get_platdata(dev);
 	REG32_TMR(CH_REL(1)) = 0xffffffff;
 	REG32_TMR(CH_CTL(1)) = APB_CLK|TMR_32;
 	REG32_TMR(CH_EN) |= CH_TMR_EN(1 , 0);
 	return 0;
 }
 
-static int atctme_timer_ofdata_to_platdata(struct udevice *dev)
+static int atcpit_timer_ofdata_to_platdata(struct udevice *dev)
 {
-	struct atftmr_timer_platdata *plat = dev_get_platdata(dev);
+	struct atcpit_timer_platdata *plat = dev_get_platdata(dev);
 	plat->regs = map_physmem(devfdt_get_addr(dev) , 0x100 , MAP_NOCACHE);
 	return 0;
 }
 
-static const struct timer_ops ag101p_timer_ops = {
-	.get_count = atftmr_timer_get_count,
+static const struct timer_ops atcpit_timer_ops = {
+	.get_count = atcpit_timer_get_count,
 };
 
-static const struct udevice_id ag101p_timer_ids[] = {
+static const struct udevice_id atcpit_timer_ids[] = {
 	{ .compatible = "andestech,atcpit100" },
 	{}
 };
 
-U_BOOT_DRIVER(altera_timer) = {
-	.name	= "ae3xx_timer",
+U_BOOT_DRIVER(atcpit100_timer) = {
+	.name	= "atcpit100_timer",
 	.id	= UCLASS_TIMER,
-	.of_match = ag101p_timer_ids,
-	.ofdata_to_platdata = atctme_timer_ofdata_to_platdata,
-	.platdata_auto_alloc_size = sizeof(struct atftmr_timer_platdata),
-	.probe = atctmr_timer_probe,
-	.ops	= &ag101p_timer_ops,
+	.of_match = atcpit_timer_ids,
+	.ofdata_to_platdata = atcpit_timer_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct atcpit_timer_platdata),
+	.probe = atcpit_timer_probe,
+	.ops	= &atcpit_timer_ops,
 	.flags = DM_FLAG_PRE_RELOC,
 };
diff --git a/dts/Makefile b/dts/Makefile
index 3a93daf..c9b2a89 100644
--- a/dts/Makefile
+++ b/dts/Makefile
@@ -22,10 +22,29 @@
 dtb_depends += $(DTB:.dtb=.dts)
 endif
 
+# Pass the original device tree file through fdtgrep twice. The first pass
+# removes any unwanted nodes (i.e. those which don't have the
+# 'u-boot,dm-pre-reloc' property and thus are not needed by SPL. The second
+# pass removes various unused properties from the remaining nodes.
+# The output is typically a much smaller device tree file.
+ifeq ($(CONFIG_TPL_BUILD),y)
+fdtgrep_props := -b u-boot,dm-pre-reloc -b u-boot,dm-tpl
+else
+fdtgrep_props := -b u-boot,dm-pre-reloc -b u-boot,dm-spl
+endif
+quiet_cmd_fdtgrep = FDTGREP $@
+      cmd_fdtgrep = $(objtree)/tools/fdtgrep $(fdtgrep_props) -RT $< \
+		-n /chosen -n /config -O dtb | \
+	$(objtree)/tools/fdtgrep -r -O dtb - -o $@ \
+		$(addprefix -P ,$(subst $\",,$(CONFIG_OF_SPL_REMOVE_PROPS)))
+
+$(obj)/dt-spl.dtb: $(DTB) $(objtree)/tools/fdtgrep FORCE
+	$(call if_changed,fdtgrep)
+
 $(obj)/dt.dtb: $(DTB) FORCE
 	$(call if_changed,shipped)
 
-targets += dt.dtb
+targets += dt.dtb dt-spl.dtb
 
 $(DTB): $(dtb_depends)
 ifeq ($(EXT_DTB),)
@@ -42,14 +61,22 @@
 arch-dtbs:
 	$(Q)$(MAKE) $(build)=$(ARCH_PATH) dtbs
 
-.SECONDARY: $(obj)/dt.dtb.S
+.SECONDARY: $(obj)/dt.dtb.S $(obj)/dt-spl.dtb.S
 
+
+ifeq ($(CONFIG_SPL_BUILD),y)
+obj-$(CONFIG_OF_EMBED) := dt-spl.dtb.o
+# support "out-of-tree" build for dtb-spl
+$(obj)/dt-spl.dtb.o: $(obj)/dt-spl.dtb.S FORCE
+	$(call if_changed_dep,as_o_S)
+else
 obj-$(CONFIG_OF_EMBED) := dt.dtb.o
+endif
 
-dtbs: $(obj)/dt.dtb
+dtbs: $(obj)/dt.dtb $(obj)/dt-spl.dtb
 	@:
 
-clean-files := dt.dtb.S
+clean-files := dt.dtb.S dt-spl.dtb.S
 
 # Let clean descend into dts directories
 subdir- += ../arch/arm/dts ../arch/microblaze/dts ../arch/mips/dts ../arch/sandbox/dts ../arch/x86/dts
diff --git a/env/mmc.c b/env/mmc.c
index 3343f9e..ed7bcf1 100644
--- a/env/mmc.c
+++ b/env/mmc.c
@@ -73,7 +73,7 @@
 		.partition = "u-boot,mmc-env-partition",
 		.offset = "u-boot,mmc-env-offset",
 	};
-	s64 val, defvalue;
+	s64 val = 0, defvalue;
 	const char *propname;
 	const char *str;
 	int err;
diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index 7fe7843..d16883f 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -1149,11 +1149,13 @@
 
 int fat_opendir(const char *filename, struct fs_dir_stream **dirsp)
 {
-	fat_dir *dir = calloc(1, sizeof(*dir));
+	fat_dir *dir;
 	int ret;
 
+	dir = malloc_cache_aligned(sizeof(*dir));
 	if (!dir)
 		return -ENOMEM;
+	memset(dir, 0, sizeof(*dir));
 
 	ret = fat_itr_root(&dir->itr, &dir->fsdata);
 	if (ret)
diff --git a/fs/fs_internal.c b/fs/fs_internal.c
index 58b4410..5cdd272 100644
--- a/fs/fs_internal.c
+++ b/fs/fs_internal.c
@@ -15,12 +15,13 @@
 	       lbaint_t sector, int byte_offset, int byte_len, char *buf)
 {
 	unsigned block_len;
-	int log2blksz = blk->log2blksz;
+	int log2blksz;
 	ALLOC_CACHE_ALIGN_BUFFER(char, sec_buf, (blk ? blk->blksz : 0));
 	if (blk == NULL) {
 		printf("** Invalid Block Device Descriptor (NULL)\n");
 		return 0;
 	}
+	log2blksz = blk->log2blksz;
 
 	/* Check partition boundaries */
 	if ((sector + ((byte_offset + byte_len - 1) >> log2blksz))
diff --git a/include/common.h b/include/common.h
index e14e1da..6e24545 100644
--- a/include/common.h
+++ b/include/common.h
@@ -201,6 +201,7 @@
 extern ulong monitor_flash_len;
 int mac_read_from_eeprom(void);
 extern u8 __dtb_dt_begin[];	/* embedded device tree blob */
+extern u8 __dtb_dt_spl_begin[];	/* embedded device tree blob for SPL/TPL */
 int set_cpu_clk_info(void);
 int mdm_init(void);
 int print_cpuinfo(void);
diff --git a/include/configs/adp-ae3xx.h b/include/configs/adp-ae3xx.h
index 6946029..5644a61 100644
--- a/include/configs/adp-ae3xx.h
+++ b/include/configs/adp-ae3xx.h
@@ -91,7 +91,6 @@
 /*
  * SD (MMC) controller
  */
-#define CONFIG_FTSDC010
 #define CONFIG_FTSDC010_NUMBER		1
 #define CONFIG_FTSDC010_SDIO
 
diff --git a/include/configs/adp-ag101p.h b/include/configs/adp-ag101p.h
index fad4d30..f2de384 100644
--- a/include/configs/adp-ag101p.h
+++ b/include/configs/adp-ag101p.h
@@ -97,7 +97,6 @@
 /*
  * SD (MMC) controller
  */
-#define CONFIG_FTSDC010
 #define CONFIG_FTSDC010_NUMBER		1
 #define CONFIG_FTSDC010_SDIO
 
diff --git a/include/configs/sama5d2_ptc.h b/include/configs/sama5d2_ptc.h
deleted file mode 100644
index c52dcd4..0000000
--- a/include/configs/sama5d2_ptc.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Configuration settings for the SAMA5D2 PTC Engineering board.
- *
- * Copyright (C) 2016 Atmel
- *		      Wenyou Yang <wenyou.yang@atmel.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#ifndef __CONFIG_H
-#define __CONFIG_H
-
-#include "at91-sama5_common.h"
-
-/* serial console */
-#define CONFIG_ATMEL_USART
-#define CONFIG_USART_BASE		0xf801c000
-#define CONFIG_USART_ID			24
-
-#define CONFIG_SYS_SDRAM_BASE		0x20000000
-#define CONFIG_SYS_SDRAM_SIZE		0x20000000
-
-#define CONFIG_SYS_TIMER_COUNTER	0xf804803c
-
-#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 */
-
-#undef CONFIG_AT91_GPIO
-#define CONFIG_ATMEL_PIO4
-
-/* SDRAM */
-#define CONFIG_NR_DRAM_BANKS		1
-
-/* SerialFlash */
-#ifdef CONFIG_CMD_SF
-#define CONFIG_ATMEL_SPI
-#define CONFIG_SPI_FLASH_ATMEL
-#define CONFIG_SF_DEFAULT_BUS		0
-#define CONFIG_SF_DEFAULT_CS		0
-#define CONFIG_SF_DEFAULT_SPEED		30000000
-#endif
-
-/* NAND flash */
-#ifdef CONFIG_CMD_NAND
-#define CONFIG_NAND_ATMEL
-#define CONFIG_SYS_MAX_NAND_DEVICE	1
-#define CONFIG_SYS_NAND_BASE		0x80000000
-/* our ALE is AD21 */
-#define CONFIG_SYS_NAND_MASK_ALE	(1 << 21)
-/* our CLE is AD22 */
-#define CONFIG_SYS_NAND_MASK_CLE	(1 << 22)
-#define CONFIG_SYS_NAND_ONFI_DETECTION
-/* PMECC & PMERRLOC */
-#define CONFIG_ATMEL_NAND_HWECC
-#define CONFIG_ATMEL_NAND_HW_PMECC
-#endif
-
-/* USB device */
-
-/* Ethernet Hardware */
-#define CONFIG_MACB
-#define CONFIG_RMII
-#define CONFIG_NET_RETRY_COUNT		20
-#define CONFIG_MACB_SEARCH_PHY
-
-#ifdef CONFIG_NAND_BOOT
-#undef CONFIG_ENV_OFFSET
-#undef CONFIG_ENV_OFFSET_REDUND
-#undef CONFIG_BOOTCOMMAND
-/* u-boot env in nand flash */
-#define CONFIG_ENV_OFFSET		0x200000
-#define CONFIG_ENV_OFFSET_REDUND	0x400000
-#define CONFIG_BOOTCOMMAND		"nand read 0x21000000 0xb80000 0x80000;"	\
-					"nand read 0x22000000 0x600000 0x600000;"	\
-					"bootz 0x22000000 - 0x21000000"
-#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_SYS_MONITOR_LEN		(512 << 10)
-
-#ifdef CONFIG_SPI_BOOT
-#define CONFIG_SPL_SPI_LOAD
-#define CONFIG_SYS_SPI_U_BOOT_OFFS	0x8000
-
-#elif CONFIG_NAND_BOOT
-#define CONFIG_SPL_NAND_DRIVERS
-#define CONFIG_SPL_NAND_BASE
-#endif
-#define CONFIG_PMECC_CAP		8
-#define CONFIG_PMECC_SECTOR_SIZE	512
-#define CONFIG_SYS_NAND_U_BOOT_OFFS	0x40000
-#define CONFIG_SYS_NAND_5_ADDR_CYCLE
-#define CONFIG_SYS_NAND_PAGE_SIZE	0x1000
-#define CONFIG_SYS_NAND_PAGE_COUNT	64
-#define CONFIG_SYS_NAND_OOBSIZE		224
-#define CONFIG_SYS_NAND_BLOCK_SIZE	0x40000
-#define CONFIG_SYS_NAND_BAD_BLOCK_POS	0x0
-#define CONFIG_SPL_GENERATE_ATMEL_PMECC_HEADER
-
-#endif
diff --git a/include/configs/sama5d2_ptc_ek.h b/include/configs/sama5d2_ptc_ek.h
new file mode 100644
index 0000000..d99eaee
--- /dev/null
+++ b/include/configs/sama5d2_ptc_ek.h
@@ -0,0 +1,46 @@
+/*
+ * Configuration file for the SAMA5D2 PTC EK Board.
+ *
+ * Copyright (C) 2017 Microchip Technology Inc.
+ *		      Wenyou Yang <wenyou.yang@microchip.com>
+ *		      Ludovic Desroches <ludovic.desroches@microchip.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include "at91-sama5_common.h"
+
+#undef CONFIG_SYS_AT91_MAIN_CLOCK
+#define CONFIG_SYS_AT91_MAIN_CLOCK      24000000 /* from 24 MHz crystal */
+
+#define CONFIG_MISC_INIT_R
+
+/* SDRAM */
+#define CONFIG_NR_DRAM_BANKS		1
+#define CONFIG_SYS_SDRAM_BASE		0x20000000
+#define CONFIG_SYS_SDRAM_SIZE		0x20000000
+
+#define CONFIG_SYS_INIT_SP_ADDR \
+	(CONFIG_SYS_SDRAM_BASE + 16 * 1024 - GENERATED_GBL_DATA_SIZE)
+
+#define CONFIG_SYS_LOAD_ADDR		0x22000000 /* load address */
+
+/* NAND Flash */
+#ifdef CONFIG_CMD_NAND
+#define CONFIG_NAND_ATMEL
+#define CONFIG_SYS_MAX_NAND_DEVICE	1
+#define CONFIG_SYS_NAND_BASE		ATMEL_BASE_CS3
+/* our ALE is AD21 */
+#define CONFIG_SYS_NAND_MASK_ALE	BIT(21)
+/* our CLE is AD22 */
+#define CONFIG_SYS_NAND_MASK_CLE	BIT(22)
+#define CONFIG_SYS_NAND_ONFI_DETECTION
+/* PMECC & PMERRLOC */
+#define CONFIG_ATMEL_NAND_HWECC
+#define CONFIG_ATMEL_NAND_HW_PMECC
+#endif
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/wb45n.h b/include/configs/wb45n.h
new file mode 100644
index 0000000..8989d55
--- /dev/null
+++ b/include/configs/wb45n.h
@@ -0,0 +1,161 @@
+/*
+ * Configuation settings for the WB45N CPU Module.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __CONFIG_H__
+#define __CONFIG_H__
+
+#include <asm/hardware.h>
+
+#define CONFIG_SYS_TEXT_BASE        0x23f00000
+
+/* ARM asynchronous clock */
+#define CONFIG_SYS_AT91_SLOW_CLOCK  32768
+#define CONFIG_SYS_AT91_MAIN_CLOCK  12000000	/* 12 MHz crystal */
+
+#define CONFIG_CMDLINE_TAG	/* enable passing of ATAGs */
+#define CONFIG_SETUP_MEMORY_TAGS
+#define CONFIG_INITRD_TAG
+#define CONFIG_SKIP_LOWLEVEL_INIT
+
+/* general purpose I/O */
+#define CONFIG_ATMEL_LEGACY	/* required until (g)pio is fixed */
+#define CONFIG_AT91_GPIO
+
+/* serial console */
+#define CONFIG_ATMEL_USART
+#define CONFIG_USART_BASE   ATMEL_BASE_DBGU
+#define CONFIG_USART_ID     ATMEL_ID_SYS
+
+/*
+ * BOOTP options
+ */
+#define CONFIG_BOOTP_BOOTFILESIZE
+#define CONFIG_BOOTP_BOOTPATH
+#define CONFIG_BOOTP_GATEWAY
+#define CONFIG_BOOTP_HOSTNAME
+
+/* SDRAM */
+#define CONFIG_NR_DRAM_BANKS        1
+#define CONFIG_SYS_SDRAM_BASE       0x20000000
+#define CONFIG_SYS_SDRAM_SIZE       0x04000000	/* 64 MB */
+
+#define CONFIG_SYS_INIT_SP_ADDR \
+    (CONFIG_SYS_SDRAM_BASE + 4 * 1024 - GENERATED_GBL_DATA_SIZE)
+
+/* NAND flash */
+#define CONFIG_NAND_ATMEL
+#define CONFIG_SYS_MAX_NAND_DEVICE  1
+#define CONFIG_SYS_NAND_BASE        0x40000000
+/* our ALE is AD21 */
+#define CONFIG_SYS_NAND_MASK_ALE    (1 << 21)
+/* our CLE is AD22 */
+#define CONFIG_SYS_NAND_MASK_CLE    (1 << 22)
+#define CONFIG_SYS_NAND_ENABLE_PIN  AT91_PIN_PD4
+#define CONFIG_SYS_NAND_READY_PIN   AT91_PIN_PD5
+
+/* PMECC & PMERRLOC */
+#define CONFIG_ATMEL_NAND_HWECC     1
+#define CONFIG_ATMEL_NAND_HW_PMECC  1
+#define CONFIG_PMECC_CAP            4
+#define CONFIG_PMECC_SECTOR_SIZE    512
+
+#define CONFIG_MTD_DEVICE
+#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_PARTITIONS
+#define CONFIG_RBTREE
+#define CONFIG_LZO
+
+/* Ethernet */
+#define CONFIG_MACB
+#define CONFIG_RMII
+#define CONFIG_NET_RETRY_COUNT      20
+#define CONFIG_MACB_SEARCH_PHY
+#define CONFIG_ETHADDR              C0:EE:40:00:00:00
+#define CONFIG_ENV_OVERWRITE        1
+
+/* System */
+#define CONFIG_SYS_LOAD_ADDR        0x22000000	/* load address */
+#define CONFIG_SYS_MEMTEST_START    CONFIG_SYS_SDRAM_BASE
+#define CONFIG_SYS_MEMTEST_END      0x23e00000
+
+#ifdef CONFIG_SYS_USE_NANDFLASH
+/* bootstrap + u-boot + env + linux in nandflash */
+#define CONFIG_ENV_OFFSET           0xa0000
+#define CONFIG_ENV_OFFSET_REDUND    0xc0000
+#define CONFIG_ENV_SIZE             0x20000	/* 1 block = 128 kB */
+
+#define CONFIG_BOOTCOMMAND  "nand read 0x22000000 0xe0000 0x280000; " \
+    "run _mtd; bootm"
+
+#define MTDIDS_DEFAULT      "nand0=atmel_nand"
+#define MTDPARTS_DEFAULT    "mtdparts=atmel_nand:" \
+                            "128K(at91bs)," \
+                            "512K(u-boot)," \
+                            "128K(u-boot-env)," \
+                            "128K(redund-env)," \
+                            "2560K(kernel-a)," \
+                            "2560K(kernel-b)," \
+                            "38912K(rootfs-a)," \
+                            "38912K(rootfs-b)," \
+                            "46208K(user)," \
+                            "512K(logs)"
+
+#else
+#error No boot method selected, please select 'CONFIG_SYS_USE_NANDFLASH'
+#endif
+
+#define CONFIG_BOOTARGS     "console=ttyS0,115200 earlyprintk " \
+                            "rw noinitrd mem=64M "              \
+                            "rootfstype=ubifs root=ubi0:rootfs ubi.mtd=6"
+
+#define CONFIG_EXTRA_ENV_SETTINGS       \
+    "_mtd=mtdparts default; setenv bootargs ${bootargs} ${mtdparts}\0" \
+    "autoload=no\0" \
+    "autostart=no\0" \
+    "ethaddr=" __stringify(CONFIG_ETHADDR) "\0" \
+    "\0"
+
+#define CONFIG_SYS_CBSIZE   256
+#define CONFIG_SYS_MAXARGS  16
+#define CONFIG_SYS_LONGHELP
+#define CONFIG_CMDLINE_EDITING
+#define CONFIG_AUTO_COMPLETE
+
+/*
+ * Size of malloc() pool
+ */
+#define CONFIG_SYS_MALLOC_LEN       (512 * 1024 + 0x1000)
+
+/* SPL */
+#define CONFIG_SPL_FRAMEWORK
+#define CONFIG_SPL_TEXT_BASE        0x300000
+#define CONFIG_SPL_MAX_SIZE         0x6000
+#define CONFIG_SPL_STACK            0x308000
+
+#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_SYS_MONITOR_LEN      (512 << 10)
+
+#define CONFIG_SYS_MASTER_CLOCK     132096000
+#define CONFIG_SYS_AT91_PLLA        0x20c73f03
+#define CONFIG_SYS_MCKR             0x1301
+#define CONFIG_SYS_MCKR_CSS         0x1302
+
+#define CONFIG_SPL_NAND_DRIVERS
+#define CONFIG_SPL_NAND_BASE
+#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x20000
+#define CONFIG_SYS_NAND_5_ADDR_CYCLE
+#define CONFIG_SYS_NAND_PAGE_SIZE   0x800
+#define CONFIG_SYS_NAND_PAGE_COUNT  64
+#define CONFIG_SYS_NAND_OOBSIZE     64
+#define CONFIG_SYS_NAND_BLOCK_SIZE  0x20000
+#define CONFIG_SYS_NAND_BAD_BLOCK_POS   0x0
+#define CONFIG_SPL_GENERATE_ATMEL_PMECC_HEADER
+
+#endif				/* __CONFIG_H__ */
diff --git a/include/configs/wb50n.h b/include/configs/wb50n.h
new file mode 100644
index 0000000..4ab81c8
--- /dev/null
+++ b/include/configs/wb50n.h
@@ -0,0 +1,139 @@
+/*
+ * Configuation settings for the WB50N CPU Module.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include <asm/hardware.h>
+
+#define CONFIG_SYS_TEXT_BASE            0x23f00000
+
+/* ARM asynchronous clock */
+#define CONFIG_SYS_AT91_SLOW_CLOCK      32768
+#define CONFIG_SYS_AT91_MAIN_CLOCK      12000000	/* from 12 MHz crystal */
+
+#define CONFIG_ARCH_CPU_INIT
+
+#define CONFIG_CMDLINE_TAG	/* enable passing of ATAGs */
+#define CONFIG_SETUP_MEMORY_TAGS
+#define CONFIG_INITRD_TAG
+
+#ifndef CONFIG_SPL_BUILD
+#define CONFIG_SKIP_LOWLEVEL_INIT
+#endif
+
+#define CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
+#define CONFIG_IMAGE_FORMAT_LEGACY
+
+/* general purpose I/O */
+#define CONFIG_AT91_GPIO
+
+/* serial console */
+#define CONFIG_ATMEL_USART
+#define CONFIG_USART_BASE       ATMEL_BASE_DBGU
+#define CONFIG_USART_ID         ATMEL_ID_DBGU
+
+/*
+ * BOOTP options
+ */
+#define CONFIG_BOOTP_BOOTFILESIZE
+#define CONFIG_BOOTP_BOOTPATH
+#define CONFIG_BOOTP_GATEWAY
+#define CONFIG_BOOTP_HOSTNAME
+
+/* SDRAM */
+#define CONFIG_NR_DRAM_BANKS        1
+#define CONFIG_SYS_SDRAM_BASE       ATMEL_BASE_DDRCS
+#define CONFIG_SYS_SDRAM_SIZE       0x04000000
+
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SYS_INIT_SP_ADDR     0x310000
+#else
+#define CONFIG_SYS_INIT_SP_ADDR \
+    (CONFIG_SYS_SDRAM_BASE + 4 * 1024 - GENERATED_GBL_DATA_SIZE)
+#endif
+
+#define CONFIG_SYS_MEMTEST_START    0x21000000
+#define CONFIG_SYS_MEMTEST_END      0x22000000
+#define CONFIG_SYS_ALT_MEMTEST
+
+/* NAND flash */
+#define CONFIG_NAND_ATMEL
+#define CONFIG_SYS_MAX_NAND_DEVICE  1
+#define CONFIG_SYS_NAND_BASE        ATMEL_BASE_CS3
+/* our ALE is AD21 */
+#define CONFIG_SYS_NAND_MASK_ALE    (1 << 21)
+/* our CLE is AD22 */
+#define CONFIG_SYS_NAND_MASK_CLE    (1 << 22)
+#define CONFIG_SYS_NAND_ONFI_DETECTION
+/* PMECC & PMERRLOC */
+#define CONFIG_ATMEL_NAND_HWECC
+#define CONFIG_ATMEL_NAND_HW_PMECC
+#define CONFIG_PMECC_CAP            8
+#define CONFIG_PMECC_SECTOR_SIZE    512
+
+/* Ethernet Hardware */
+#define CONFIG_MACB
+#define CONFIG_RMII
+#define CONFIG_NET_RETRY_COUNT      20
+#define CONFIG_MACB_SEARCH_PHY
+#define CONFIG_RGMII
+#define CONFIG_ETHADDR              C0:EE:40:00:00:00
+#define CONFIG_ENV_OVERWRITE        1
+
+#define CONFIG_SYS_LOAD_ADDR        0x22000000	/* load address */
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+    "autoload=no\0" \
+    "autostart=no\0"
+
+/* bootstrap + u-boot + env in nandflash */
+#define CONFIG_ENV_OFFSET           0xA0000
+#define CONFIG_ENV_OFFSET_REDUND    0xC0000
+#define CONFIG_ENV_SIZE             0x20000
+#define CONFIG_BOOTCOMMAND \
+    "nand read 0x22000000 0x000e0000 0x500000; " \
+    "bootm"
+
+#define CONFIG_BOOTARGS \
+    "rw rootfstype=ubifs ubi.mtd=6 root=ubi0:rootfs"
+
+#define CONFIG_BAUDRATE             115200
+
+#define CONFIG_SYS_CBSIZE           1024
+#define CONFIG_SYS_MAXARGS          16
+#define CONFIG_SYS_PBSIZE \
+    (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+#define CONFIG_SYS_LONGHELP
+#define CONFIG_CMDLINE_EDITING
+#define CONFIG_AUTO_COMPLETE
+
+/* Size of malloc() pool */
+#define CONFIG_SYS_MALLOC_LEN       (2 * 1024 * 1024)
+
+/* SPL */
+#define CONFIG_SPL_FRAMEWORK
+#define CONFIG_SPL_TEXT_BASE        0x300000
+#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_SYS_MONITOR_LEN      (512 << 10)
+
+#define CONFIG_SPL_NAND_DRIVERS
+#define CONFIG_SPL_NAND_BASE
+#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x20000
+#define CONFIG_SYS_NAND_5_ADDR_CYCLE
+#define CONFIG_SYS_NAND_PAGE_SIZE   0x800
+#define CONFIG_SYS_NAND_PAGE_COUNT  64
+#define CONFIG_SYS_NAND_OOBSIZE     64
+#define CONFIG_SYS_NAND_BLOCK_SIZE  0x20000
+#define CONFIG_SYS_NAND_BAD_BLOCK_POS   0x0
+#define CONFIG_SPL_GENERATE_ATMEL_PMECC_HEADER
+
+#endif
diff --git a/include/dt-bindings/mfd/stm32f7-rcc.h b/include/dt-bindings/mfd/stm32f7-rcc.h
index e36cc69..44c0914 100644
--- a/include/dt-bindings/mfd/stm32f7-rcc.h
+++ b/include/dt-bindings/mfd/stm32f7-rcc.h
@@ -90,6 +90,7 @@
 #define STM32F7_RCC_APB2_TIM8		1
 #define STM32F7_RCC_APB2_USART1		4
 #define STM32F7_RCC_APB2_USART6		5
+#define STM32F7_RCC_APB2_SDMMC2		7
 #define STM32F7_RCC_APB2_ADC1		8
 #define STM32F7_RCC_APB2_ADC2		9
 #define STM32F7_RCC_APB2_ADC3		10
diff --git a/include/stm32_rcc.h b/include/stm32_rcc.h
new file mode 100644
index 0000000..063177b
--- /dev/null
+++ b/include/stm32_rcc.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2017
+ * Author(s): Patrice CHOTARD, <patrice.chotard@st.com> for STMicroelectronics.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __STM32_RCC_H_
+#define __STM32_RCC_H_
+
+#define AHB_PSC_1			0
+#define AHB_PSC_2			0x8
+#define AHB_PSC_4			0x9
+#define AHB_PSC_8			0xA
+#define AHB_PSC_16			0xB
+#define AHB_PSC_64			0xC
+#define AHB_PSC_128			0xD
+#define AHB_PSC_256			0xE
+#define AHB_PSC_512			0xF
+
+#define APB_PSC_1			0
+#define APB_PSC_2			0x4
+#define APB_PSC_4			0x5
+#define APB_PSC_8			0x6
+#define APB_PSC_16			0x7
+
+struct pll_psc {
+	u8	pll_m;
+	u16	pll_n;
+	u8	pll_p;
+	u8	pll_q;
+	u8	ahb_psc;
+	u8	apb1_psc;
+	u8	apb2_psc;
+};
+
+struct stm32_clk_info {
+	struct pll_psc sys_pll_psc;
+	bool has_overdrive;
+	bool v2;
+};
+
+enum soc_family {
+	STM32F4,
+	STM32F7,
+};
+
+struct stm32_rcc_clk {
+	char *drv_name;
+	enum soc_family soc;
+};
+
+struct stm32_rcc_regs {
+	u32 cr;		/* RCC clock control */
+	u32 pllcfgr;	/* RCC PLL configuration */
+	u32 cfgr;	/* RCC clock configuration */
+	u32 cir;	/* RCC clock interrupt */
+	u32 ahb1rstr;	/* RCC AHB1 peripheral reset */
+	u32 ahb2rstr;	/* RCC AHB2 peripheral reset */
+	u32 ahb3rstr;	/* RCC AHB3 peripheral reset */
+	u32 rsv0;
+	u32 apb1rstr;	/* RCC APB1 peripheral reset */
+	u32 apb2rstr;	/* RCC APB2 peripheral reset */
+	u32 rsv1[2];
+	u32 ahb1enr;	/* RCC AHB1 peripheral clock enable */
+	u32 ahb2enr;	/* RCC AHB2 peripheral clock enable */
+	u32 ahb3enr;	/* RCC AHB3 peripheral clock enable */
+	u32 rsv2;
+	u32 apb1enr;	/* RCC APB1 peripheral clock enable */
+	u32 apb2enr;	/* RCC APB2 peripheral clock enable */
+	u32 rsv3[2];
+	u32 ahb1lpenr;	/* RCC AHB1 periph clk enable in low pwr mode */
+	u32 ahb2lpenr;	/* RCC AHB2 periph clk enable in low pwr mode */
+	u32 ahb3lpenr;	/* RCC AHB3 periph clk enable in low pwr mode */
+	u32 rsv4;
+	u32 apb1lpenr;	/* RCC APB1 periph clk enable in low pwr mode */
+	u32 apb2lpenr;	/* RCC APB2 periph clk enable in low pwr mode */
+	u32 rsv5[2];
+	u32 bdcr;	/* RCC Backup domain control */
+	u32 csr;	/* RCC clock control & status */
+	u32 rsv6[2];
+	u32 sscgr;	/* RCC spread spectrum clock generation */
+	u32 plli2scfgr;	/* RCC PLLI2S configuration */
+	/* below registers are only available on STM32F46x and STM32F7 SoCs*/
+	u32 pllsaicfgr;	/* PLLSAI configuration */
+	u32 dckcfgr;	/* dedicated clocks configuration register */
+	/* Below registers are only available on STM32F7 SoCs */
+	u32 dckcfgr2;	/* dedicated clocks configuration register */
+};
+
+#endif /* __STM32_RCC_H_ */
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index c4582ea..873bcfa 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -1268,7 +1268,11 @@
 # endif
 # ifdef CONFIG_OF_EMBED
 	/* Get a pointer to the FDT */
+#  ifdef CONFIG_SPL_BUILD
+	gd->fdt_blob = __dtb_dt_spl_begin;
+#  else
 	gd->fdt_blob = __dtb_dt_begin;
+#  endif
 # elif defined CONFIG_OF_SEPARATE
 #  ifdef CONFIG_SPL_BUILD
 	/* FDT is at end of BSS unless it is in a different memory region */
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
index b5e7019..64390e5 100644
--- a/scripts/Makefile.spl
+++ b/scripts/Makefile.spl
@@ -239,24 +239,8 @@
 	@bss_size_str=$(shell $(NM) $< | awk 'BEGIN {size = 0} /__bss_size/ {size = $$1} END {print "ibase=16; " toupper(size)}' | bc); \
 	dd if=/dev/zero of=$@ bs=1 count=$${bss_size_str} 2>/dev/null;
 
-# Pass the original device tree file through fdtgrep twice. The first pass
-# removes any unwanted nodes (i.e. those which don't have the
-# 'u-boot,dm-pre-reloc' property and thus are not needed by SPL. The second
-# pass removes various unused properties from the remaining nodes.
-# The output is typically a much smaller device tree file.
-ifeq ($(CONFIG_TPL_BUILD),y)
-fdtgrep_props := -b u-boot,dm-pre-reloc -b u-boot,dm-tpl
-else
-fdtgrep_props := -b u-boot,dm-pre-reloc -b u-boot,dm-spl
-endif
-quiet_cmd_fdtgrep = FDTGREP $@
-      cmd_fdtgrep = $(objtree)/tools/fdtgrep $(fdtgrep_props) -RT $< \
-		-n /chosen -n /config -O dtb | \
-	$(objtree)/tools/fdtgrep -r -O dtb - -o $@ \
-		$(addprefix -P ,$(subst $\",,$(CONFIG_OF_SPL_REMOVE_PROPS)))
-
-$(obj)/$(SPL_BIN).dtb: dts/dt.dtb $(objtree)/tools/fdtgrep FORCE
-	$(call if_changed,fdtgrep)
+$(obj)/$(SPL_BIN).dtb: dts/dt-spl.dtb FORCE
+	$(call if_changed,copy)
 
 pythonpath = PYTHONPATH=scripts/dtc/pylibfdt
 
diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c
index 963a615..18c2324 100644
--- a/tools/env/fw_env.c
+++ b/tools/env/fw_env.c
@@ -25,6 +25,7 @@
 #include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <dirent.h>
 
 #ifdef MTD_OLD
 # include <stdint.h>
@@ -34,6 +35,8 @@
 # include <mtd/mtd-user.h>
 #endif
 
+#include <mtd/ubi-user.h>
+
 #include "fw_env_private.h"
 #include "fw_env.h"
 
@@ -58,6 +61,7 @@
 	ulong erase_size;		/* device erase size */
 	ulong env_sectors;		/* number of environment sectors */
 	uint8_t mtd_type;		/* type of the MTD device */
+	int is_ubi;			/* set if we use UBI volume */
 };
 
 static struct envdev_s envdevices[2] =
@@ -76,6 +80,7 @@
 #define DEVESIZE(i)   envdevices[(i)].erase_size
 #define ENVSECTORS(i) envdevices[(i)].env_sectors
 #define DEVTYPE(i)    envdevices[(i)].mtd_type
+#define IS_UBI(i)     envdevices[(i)].is_ubi
 
 #define CUR_ENVSIZE ENVSIZE(dev_current)
 
@@ -120,6 +125,228 @@
 #define DEFAULT_ENV_INSTANCE_STATIC
 #include <env_default.h>
 
+#define UBI_DEV_START "/dev/ubi"
+#define UBI_SYSFS "/sys/class/ubi"
+#define UBI_VOL_NAME_PATT "ubi%d_%d"
+
+static int is_ubi_devname(const char *devname)
+{
+	return !strncmp(devname, UBI_DEV_START, sizeof(UBI_DEV_START) - 1);
+}
+
+static int ubi_check_volume_sysfs_name(const char *volume_sysfs_name,
+				       const char *volname)
+{
+	char path[256];
+	FILE *file;
+	char *name;
+	int ret;
+
+	strcpy(path, UBI_SYSFS "/");
+	strcat(path, volume_sysfs_name);
+	strcat(path, "/name");
+
+	file = fopen(path, "r");
+	if (!file)
+		return -1;
+
+	ret = fscanf(file, "%ms", &name);
+	fclose(file);
+	if (ret <= 0 || !name) {
+		fprintf(stderr,
+			"Failed to read from file %s, ret = %d, name = %s\n",
+			path, ret, name);
+		return -1;
+	}
+
+	if (!strcmp(name, volname)) {
+		free(name);
+		return 0;
+	}
+	free(name);
+
+	return -1;
+}
+
+static int ubi_get_volnum_by_name(int devnum, const char *volname)
+{
+	DIR *sysfs_ubi;
+	struct dirent *dirent;
+	int ret;
+	int tmp_devnum;
+	int volnum;
+
+	sysfs_ubi = opendir(UBI_SYSFS);
+	if (!sysfs_ubi)
+		return -1;
+
+#ifdef DEBUG
+	fprintf(stderr, "Looking for volume name \"%s\"\n", volname);
+#endif
+
+	while (1) {
+		dirent = readdir(sysfs_ubi);
+		if (!dirent)
+			return -1;
+
+		ret = sscanf(dirent->d_name, UBI_VOL_NAME_PATT,
+			     &tmp_devnum, &volnum);
+		if (ret == 2 && devnum == tmp_devnum) {
+			if (ubi_check_volume_sysfs_name(dirent->d_name,
+							volname) == 0)
+				return volnum;
+		}
+	}
+
+	return -1;
+}
+
+static int ubi_get_devnum_by_devname(const char *devname)
+{
+	int devnum;
+	int ret;
+
+	ret = sscanf(devname + sizeof(UBI_DEV_START) - 1, "%d", &devnum);
+	if (ret != 1)
+		return -1;
+
+	return devnum;
+}
+
+static const char *ubi_get_volume_devname(const char *devname,
+					  const char *volname)
+{
+	char *volume_devname;
+	int volnum;
+	int devnum;
+	int ret;
+
+	devnum = ubi_get_devnum_by_devname(devname);
+	if (devnum < 0)
+		return NULL;
+
+	volnum = ubi_get_volnum_by_name(devnum, volname);
+	if (volnum < 0)
+		return NULL;
+
+	ret = asprintf(&volume_devname, "%s_%d", devname, volnum);
+	if (ret < 0)
+		return NULL;
+
+#ifdef DEBUG
+	fprintf(stderr, "Found ubi volume \"%s:%s\" -> %s\n",
+		devname, volname, volume_devname);
+#endif
+
+	return volume_devname;
+}
+
+static void ubi_check_dev(unsigned int dev_id)
+{
+	char *devname = (char *)DEVNAME(dev_id);
+	char *pname;
+	const char *volname = NULL;
+	const char *volume_devname;
+
+	if (!is_ubi_devname(DEVNAME(dev_id)))
+		return;
+
+	IS_UBI(dev_id) = 1;
+
+	for (pname = devname; *pname != '\0'; pname++) {
+		if (*pname == ':') {
+			*pname = '\0';
+			volname = pname + 1;
+			break;
+		}
+	}
+
+	if (volname) {
+		/* Let's find real volume device name */
+		volume_devname = ubi_get_volume_devname(devname, volname);
+		if (!volume_devname) {
+			fprintf(stderr, "Didn't found ubi volume \"%s\"\n",
+				volname);
+			return;
+		}
+
+		free(devname);
+		DEVNAME(dev_id) = volume_devname;
+	}
+}
+
+static int ubi_update_start(int fd, int64_t bytes)
+{
+	if (ioctl(fd, UBI_IOCVOLUP, &bytes))
+		return -1;
+	return 0;
+}
+
+static int ubi_read(int fd, void *buf, size_t count)
+{
+	ssize_t ret;
+
+	while (count > 0) {
+		ret = read(fd, buf, count);
+		if (ret > 0) {
+			count -= ret;
+			buf += ret;
+
+			continue;
+		}
+
+		if (ret == 0) {
+			/*
+			 * Happens in case of too short volume data size. If we
+			 * return error status we will fail it will be treated
+			 * as UBI device error.
+			 *
+			 * Leave catching this error to CRC check.
+			 */
+			fprintf(stderr, "Warning: end of data on ubi volume\n");
+			return 0;
+		} else if (errno == EBADF) {
+			/*
+			 * Happens in case of corrupted volume. The same as
+			 * above, we cannot return error now, as we will still
+			 * be able to successfully write environment later.
+			 */
+			fprintf(stderr, "Warning: corrupted volume?\n");
+			return 0;
+		} else if (errno == EINTR) {
+			continue;
+		}
+
+		fprintf(stderr, "Cannot read %u bytes from ubi volume, %s\n",
+			(unsigned int)count, strerror(errno));
+		return -1;
+	}
+
+	return 0;
+}
+
+static int ubi_write(int fd, const void *buf, size_t count)
+{
+	ssize_t ret;
+
+	while (count > 0) {
+		ret = write(fd, buf, count);
+		if (ret <= 0) {
+			if (ret < 0 && errno == EINTR)
+				continue;
+
+			fprintf(stderr, "Cannot write %u bytes to ubi volume\n",
+				(unsigned int)count);
+			return -1;
+		}
+
+		count -= ret;
+		buf += ret;
+	}
+
+	return 0;
+}
+
 static int flash_io (int mode);
 static int parse_config(struct env_opts *opts);
 
@@ -960,6 +1187,12 @@
 		DEVOFFSET (dev_target), DEVNAME (dev_target));
 #endif
 
+	if (IS_UBI(dev_target)) {
+		if (ubi_update_start(fd_target, CUR_ENVSIZE) < 0)
+			return 0;
+		return ubi_write(fd_target, environment.image, CUR_ENVSIZE);
+	}
+
 	rc = flash_write_buf(dev_target, fd_target, environment.image,
 			     CUR_ENVSIZE);
 	if (rc < 0)
@@ -984,6 +1217,12 @@
 {
 	int rc;
 
+	if (IS_UBI(dev_current)) {
+		DEVTYPE(dev_current) = MTD_ABSENT;
+
+		return ubi_read(fd, environment.image, CUR_ENVSIZE);
+	}
+
 	rc = flash_read_buf(dev_current, fd, environment.image, CUR_ENVSIZE,
 			    DEVOFFSET(dev_current));
 	if (rc != CUR_ENVSIZE)
@@ -1165,7 +1404,8 @@
 			   DEVTYPE(!dev_current) == MTD_UBIVOLUME) {
 			environment.flag_scheme = FLAG_INCREMENTAL;
 		} else if (DEVTYPE(dev_current) == MTD_ABSENT &&
-			   DEVTYPE(!dev_current) == MTD_ABSENT) {
+			   DEVTYPE(!dev_current) == MTD_ABSENT &&
+			   IS_UBI(dev_current) == IS_UBI(!dev_current)) {
 			environment.flag_scheme = FLAG_INCREMENTAL;
 		} else {
 			fprintf (stderr, "Incompatible flash types!\n");
@@ -1271,8 +1511,12 @@
 static int check_device_config(int dev)
 {
 	struct stat st;
+	int32_t lnum = 0;
 	int fd, rc = 0;
 
+	/* Fills in IS_UBI(), converts DEVNAME() with ubi volume name */
+	ubi_check_dev(dev);
+
 	fd = open(DEVNAME(dev), O_RDONLY);
 	if (fd < 0) {
 		fprintf(stderr,
@@ -1288,7 +1532,14 @@
 		goto err;
 	}
 
-	if (S_ISCHR(st.st_mode)) {
+	if (IS_UBI(dev)) {
+		rc = ioctl(fd, UBI_IOCEBISMAP, &lnum);
+		if (rc < 0) {
+			fprintf(stderr, "Cannot get UBI information for %s\n",
+				DEVNAME(dev));
+			goto err;
+		}
+	} else if (S_ISCHR(st.st_mode)) {
 		struct mtd_info_user mtdinfo;
 		rc = ioctl(fd, MEMGETINFO, &mtdinfo);
 		if (rc < 0) {
diff --git a/tools/env/fw_env.config b/tools/env/fw_env.config
index 7916ebd..053895a 100644
--- a/tools/env/fw_env.config
+++ b/tools/env/fw_env.config
@@ -28,3 +28,11 @@
 
 # VFAT example
 #/boot/uboot.env	0x0000          0x4000
+
+# UBI volume
+#/dev/ubi0_0		0x0		0x1f000		0x1f000
+#/dev/ubi0_1		0x0		0x1f000		0x1f000
+
+# UBI volume by name
+#/dev/ubi0:env		0x0		0x1f000		0x1f000
+#/dev/ubi0:env-redund	0x0		0x1f000		0x1f000