Merge tag 'efi-2019-07-rc3-3' of git://git.denx.de/u-boot-efi

Pull request for UEFI sub-system for v2019.07-rc3 (3)

Several bug fixes for the UEFI sub-system are provided.
The SetTime() boottime service is implemented.
diff --git a/Kconfig b/Kconfig
index 5f5c5cc..fcde0c3 100644
--- a/Kconfig
+++ b/Kconfig
@@ -147,7 +147,7 @@
 
 config SYS_MALLOC_LEN
 	hex "Define memory for Dynamic allocation"
-	depends on ARCH_ZYNQ || ARCH_VERSAL
+	depends on ARCH_ZYNQ || ARCH_VERSAL || ARCH_STM32MP
 	help
 	  This defines memory to be allocated for Dynamic allocation
 	  TODO: Use for other architectures
diff --git a/arch/Kconfig b/arch/Kconfig
index 239289b..e574b0d 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -28,6 +28,7 @@
 	select HAVE_PRIVATE_LIBGCC
 	select SYS_BOOT_GET_CMDLINE
 	select SYS_BOOT_GET_KBD
+	select SUPPORT_OF_CONTROL
 
 config MICROBLAZE
 	bool "MicroBlaze architecture"
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index efb9aab..01ff57c 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1488,6 +1488,7 @@
 	imply CMD_DM
 	imply CMD_POWEROFF
 	imply ENV_VARS_UBOOT_RUNTIME_CONFIG
+	imply USE_PREBOOT
 	help
 	  Support for STM32MP SoC family developed by STMicroelectronics,
 	  MPUs based on ARM cortex A core
diff --git a/arch/arm/cpu/armv7/arch_timer.c b/arch/arm/cpu/armv7/arch_timer.c
index 3db31c0..5de6305 100644
--- a/arch/arm/cpu/armv7/arch_timer.c
+++ b/arch/arm/cpu/armv7/arch_timer.c
@@ -49,6 +49,9 @@
 
 ulong timer_get_boot_us(void)
 {
+	if (!gd->arch.timer_rate_hz)
+		timer_init();
+
 	return lldiv(get_ticks(), gd->arch.timer_rate_hz / 1000000);
 }
 
diff --git a/arch/arm/dts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi b/arch/arm/dts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi
index 7d9b95c..dc30360 100644
--- a/arch/arm/dts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi
+++ b/arch/arm/dts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi
@@ -16,8 +16,8 @@
  * address mapping : RBC
  * Tc > + 85C : N
  */
-#define DDR_MEM_NAME "DDR3-1066/888 bin G 1x4Gb 533MHz v1.43"
-#define DDR_MEM_SPEED 533
+#define DDR_MEM_NAME "DDR3-1066/888 bin G 1x4Gb 533MHz v1.44"
+#define DDR_MEM_SPEED 533000
 #define DDR_MEM_SIZE 0x20000000
 
 #define DDR_MSTR 0x00041401
@@ -108,11 +108,11 @@
 #define DDR_DX1DLLCR 0x40000000
 #define DDR_DX1DQTR 0xFFFFFFFF
 #define DDR_DX1DQSTR 0x3DB02000
-#define DDR_DX2GCR 0x0000CE81
+#define DDR_DX2GCR 0x0000CE80
 #define DDR_DX2DLLCR 0x40000000
 #define DDR_DX2DQTR 0xFFFFFFFF
 #define DDR_DX2DQSTR 0x3DB02000
-#define DDR_DX3GCR 0x0000CE81
+#define DDR_DX3GCR 0x0000CE80
 #define DDR_DX3DLLCR 0x40000000
 #define DDR_DX3DQTR 0xFFFFFFFF
 #define DDR_DX3DQSTR 0x3DB02000
diff --git a/arch/arm/dts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi b/arch/arm/dts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi
index 8a5a821..8158a56 100644
--- a/arch/arm/dts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi
+++ b/arch/arm/dts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi
@@ -1,9 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
 /*
  * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
- */
-
-/* STM32MP157C ED1 and ED2 BOARD configuration
+ *
+ * STM32MP157C ED1 BOARD configuration
  * 2x DDR3L 4Gb each, 16-bit, 533MHz, Single Die Package in flyby topology.
  * Reference used NT5CC256M16DP-DI from NANYA
  *
@@ -15,10 +14,11 @@
  * timing mode	optimized
  * Scheduling/QoS options : type = 2
  * address mapping : RBC
+ * Tc > + 85C : N
  */
 
-#define DDR_MEM_NAME "DDR3-1066 bin G 2x4Gb 533MHz v1.36"
-#define DDR_MEM_SPEED 533
+#define DDR_MEM_NAME "DDR3-1066/888 bin G 2x4Gb 533MHz v1.44"
+#define DDR_MEM_SPEED 533000
 #define DDR_MEM_SIZE 0x40000000
 
 #define DDR_MSTR 0x00040401
@@ -62,7 +62,7 @@
 #define DDR_ADDRMAP11 0x00000000
 #define DDR_ODTCFG 0x06000600
 #define DDR_ODTMAP 0x00000001
-#define DDR_SCHED 0x00001201
+#define DDR_SCHED 0x00000C01
 #define DDR_SCHED1 0x00000000
 #define DDR_PERFHPR1 0x01000001
 #define DDR_PERFLPR1 0x08000200
@@ -74,15 +74,15 @@
 #define DDR_PCCFG 0x00000010
 #define DDR_PCFGR_0 0x00010000
 #define DDR_PCFGW_0 0x00000000
-#define DDR_PCFGQOS0_0 0x02100B03
+#define DDR_PCFGQOS0_0 0x02100C03
 #define DDR_PCFGQOS1_0 0x00800100
-#define DDR_PCFGWQOS0_0 0x01100B03
+#define DDR_PCFGWQOS0_0 0x01100C03
 #define DDR_PCFGWQOS1_0 0x01000200
 #define DDR_PCFGR_1 0x00010000
 #define DDR_PCFGW_1 0x00000000
-#define DDR_PCFGQOS0_1 0x02100B03
-#define DDR_PCFGQOS1_1 0x00800100
-#define DDR_PCFGWQOS0_1 0x01100B03
+#define DDR_PCFGQOS0_1 0x02100C03
+#define DDR_PCFGQOS1_1 0x00800040
+#define DDR_PCFGWQOS0_1 0x01100C03
 #define DDR_PCFGWQOS1_1 0x01000200
 #define DDR_PGCR 0x01442E02
 #define DDR_PTR0 0x0022AA5B
@@ -100,7 +100,7 @@
 #define DDR_MR2 0x00000208
 #define DDR_MR3 0x00000000
 #define DDR_ODTCR 0x00010000
-#define DDR_ZQ0CR1 0x0000005B
+#define DDR_ZQ0CR1 0x00000038
 #define DDR_DX0GCR 0x0000CE81
 #define DDR_DX0DLLCR 0x40000000
 #define DDR_DX0DQTR 0xFFFFFFFF
diff --git a/arch/arm/mach-stm32mp/Kconfig b/arch/arm/mach-stm32mp/Kconfig
index 73aa382..77f66c6 100644
--- a/arch/arm/mach-stm32mp/Kconfig
+++ b/arch/arm/mach-stm32mp/Kconfig
@@ -17,12 +17,20 @@
 	select SPL_DM_RESET
 	select SPL_SERIAL_SUPPORT
 	select SPL_SYSCON
+	imply BOOTSTAGE_STASH if SPL_BOOTSTAGE
+	imply SPL_BOOTSTAGE if BOOTSTAGE
 	imply SPL_DISPLAY_PRINT
 	imply SPL_LIBDISK_SUPPORT
 
 config SYS_SOC
 	default "stm32mp"
 
+config SYS_MALLOC_LEN
+	default 0x2000000
+
+config ENV_SIZE
+	default 0x1000
+
 config TARGET_STM32MP1
 	bool "Support stm32mp1xx"
 	select ARCH_SUPPORT_PSCI if !STM32MP1_TRUSTED
@@ -33,6 +41,10 @@
 	select STM32_RCC
 	select STM32_RESET
 	select SYS_ARCH_TIMER
+	imply BOOTCOUNT_LIMIT
+	imply BOOTSTAGE
+	imply CMD_BOOTCOUNT
+	imply CMD_BOOTSTAGE
 	imply SYSRESET_PSCI if STM32MP1_TRUSTED
 	imply SYSRESET_SYSCON if !STM32MP1_TRUSTED
 	help
@@ -70,6 +82,18 @@
 	  Partition on the second MMC to load U-Boot from when the MMC is being
 	  used in raw mode
 
+config BOOTSTAGE_STASH_ADDR
+	default 0xC3000000
+
+if BOOTCOUNT_LIMIT
+config SYS_BOOTCOUNT_SINGLEWORD
+	default y
+
+# TAMP_BOOTCOUNT = TAMP_BACKUP_REGISTER(21)
+config SYS_BOOTCOUNT_ADDR
+	default 0x5C00A154
+endif
+
 if DEBUG_UART
 
 config DEBUG_UART_BOARD_INIT
diff --git a/arch/arm/mach-stm32mp/bsec.c b/arch/arm/mach-stm32mp/bsec.c
index 9ed8d8c..0166649 100644
--- a/arch/arm/mach-stm32mp/bsec.c
+++ b/arch/arm/mach-stm32mp/bsec.c
@@ -7,9 +7,9 @@
 #include <dm.h>
 #include <misc.h>
 #include <asm/io.h>
-#include <linux/iopoll.h>
 #include <asm/arch/stm32mp1_smc.h>
 #include <linux/arm-smccc.h>
+#include <linux/iopoll.h>
 
 #define BSEC_OTP_MAX_VALUE		95
 
diff --git a/arch/arm/mach-stm32mp/include/mach/ddr.h b/arch/arm/mach-stm32mp/include/mach/ddr.h
index 1857584..b8a17cf 100644
--- a/arch/arm/mach-stm32mp/include/mach/ddr.h
+++ b/arch/arm/mach-stm32mp/include/mach/ddr.h
@@ -6,6 +6,13 @@
 #ifndef __MACH_STM32MP_DDR_H_
 #define __MACH_STM32MP_DDR_H_
 
-int board_ddr_power_init(void);
+/* DDR power initializations */
+enum ddr_type {
+	STM32MP_DDR3,
+	STM32MP_LPDDR2,
+	STM32MP_LPDDR3,
+};
+
+int board_ddr_power_init(enum ddr_type ddr_type);
 
 #endif
diff --git a/arch/arm/mach-stm32mp/include/mach/stm32.h b/arch/arm/mach-stm32mp/include/mach/stm32.h
index c526c88..6795352 100644
--- a/arch/arm/mach-stm32mp/include/mach/stm32.h
+++ b/arch/arm/mach-stm32mp/include/mach/stm32.h
@@ -88,6 +88,7 @@
 #define TAMP_BACKUP_MAGIC_NUMBER	TAMP_BACKUP_REGISTER(4)
 #define TAMP_BACKUP_BRANCH_ADDRESS	TAMP_BACKUP_REGISTER(5)
 #define TAMP_BOOT_CONTEXT		TAMP_BACKUP_REGISTER(20)
+#define TAMP_BOOTCOUNT			TAMP_BACKUP_REGISTER(21)
 
 #define TAMP_BOOT_MODE_MASK		GENMASK(15, 8)
 #define TAMP_BOOT_MODE_SHIFT		8
diff --git a/arch/arm/mach-stm32mp/psci.c b/arch/arm/mach-stm32mp/psci.c
index c2dff38..139bb09 100644
--- a/arch/arm/mach-stm32mp/psci.c
+++ b/arch/arm/mach-stm32mp/psci.c
@@ -47,14 +47,14 @@
 	return (periphbase & CBAR_MASK) + GIC_DIST_OFFSET;
 }
 
-static void __secure stm32mp_smp_kick_all_cpus(void)
+static void __secure stm32mp_raise_sgi0(int cpu)
 {
 	u32 gic_dist_addr;
 
 	gic_dist_addr = stm32mp_get_gicd_base_address();
 
-	/* kick all CPUs (except this one) by writing to GICD_SGIR */
-	writel(1U << 24, gic_dist_addr + GICD_SGIR);
+	/* ask cpu with SGI0 */
+	writel((BIT(cpu) << 16), gic_dist_addr + GICD_SGIR);
 }
 
 void __secure psci_arch_cpu_entry(void)
@@ -62,6 +62,9 @@
 	u32 cpu = psci_get_cpu_id();
 
 	psci_set_state(cpu, PSCI_AFFINITY_LEVEL_ON);
+
+	/* reset magic in TAMP register */
+	writel(0xFFFFFFFF, TAMP_BACKUP_MAGIC_NUMBER);
 }
 
 int __secure psci_features(u32 function_id, u32 psci_fid)
@@ -127,6 +130,16 @@
 	if (psci_state[cpu] == PSCI_AFFINITY_LEVEL_ON)
 		return ARM_PSCI_RET_ALREADY_ON;
 
+	/* reset magic in TAMP register */
+	if (readl(TAMP_BACKUP_MAGIC_NUMBER))
+		writel(0xFFFFFFFF, TAMP_BACKUP_MAGIC_NUMBER);
+	/*
+	 * ROM code need a first SGI0 after core reset
+	 * core is ready when magic is set to 0 in ROM code
+	 */
+	while (readl(TAMP_BACKUP_MAGIC_NUMBER))
+		stm32mp_raise_sgi0(cpu);
+
 	/* store target PC and context id*/
 	psci_save(cpu, pc, context_id);
 
@@ -142,7 +155,8 @@
 		writel(BOOT_API_A7_CORE0_MAGIC_NUMBER,
 		       TAMP_BACKUP_MAGIC_NUMBER);
 
-	stm32mp_smp_kick_all_cpus();
+	/* Generate an IT to start the core */
+	stm32mp_raise_sgi0(cpu);
 
 	return ARM_PSCI_RET_SUCCESS;
 }
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 1f6df5c..fef1081 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -6,36 +6,69 @@
 
 # processor family
 config MCF520x
+	select OF_CONTROL
+	select DM
+        select DM_SERIAL
 	bool
 
 config MCF52x2
+	select OF_CONTROL
+	select DM
+        select DM_SERIAL
 	bool
 
 config MCF523x
+	select OF_CONTROL
+	select DM
+        select DM_SERIAL
 	bool
 
 config MCF530x
+	select OF_CONTROL
+	select DM
+        select DM_SERIAL
 	bool
 
 config MCF5301x
+	select OF_CONTROL
+	select DM
+        select DM_SERIAL
 	bool
 
 config MCF532x
+	select OF_CONTROL
+	select DM
+        select DM_SERIAL
 	bool
 
 config MCF537x
+	select OF_CONTROL
+	select DM
+        select DM_SERIAL
 	bool
 
 config MCF5441x
+	select OF_CONTROL
+	select DM
+        select DM_SERIAL
 	bool
 
 config MCF5445x
+	select OF_CONTROL
+	select DM
+        select DM_SERIAL
 	bool
 
 config MCF5227x
+	select OF_CONTROL
+	select DM
+        select DM_SERIAL
 	bool
 
 config MCF547x_8x
+	select OF_CONTROL
+        select DM
+        select DM_SERIAL
 	bool
 
 # processor type
diff --git a/arch/m68k/cpu/mcf5227x/Makefile b/arch/m68k/cpu/mcf5227x/Makefile
index ef43893..6a38c48 100644
--- a/arch/m68k/cpu/mcf5227x/Makefile
+++ b/arch/m68k/cpu/mcf5227x/Makefile
@@ -6,4 +6,4 @@
 # ccflags-y += -DET_DEBUG
 
 extra-y	= start.o
-obj-y	= cpu.o speed.o cpu_init.o interrupts.o
+obj-y	= cpu.o speed.o cpu_init.o interrupts.o dspi.o
diff --git a/arch/m68k/cpu/mcf5227x/cpu_init.c b/arch/m68k/cpu/mcf5227x/cpu_init.c
index 0d6a484..3bbc42f 100644
--- a/arch/m68k/cpu/mcf5227x/cpu_init.c
+++ b/arch/m68k/cpu/mcf5227x/cpu_init.c
@@ -16,6 +16,15 @@
 #include <asm/rtc.h>
 #include <linux/compiler.h>
 
+void cfspi_port_conf(void)
+{
+	gpio_t *gpio = (gpio_t *)MMAP_GPIO;
+
+	out_8(&gpio->par_dspi,
+	      GPIO_PAR_DSPI_SIN_SIN | GPIO_PAR_DSPI_SOUT_SOUT |
+	      GPIO_PAR_DSPI_SCK_SCK);
+}
+
 /*
  * Breath some life into the CPU...
  *
@@ -93,6 +102,8 @@
 #endif
 
 	icache_enable();
+
+	cfspi_port_conf();
 }
 
 /*
@@ -137,57 +148,3 @@
 		break;
 	}
 }
-
-#ifdef CONFIG_CF_DSPI
-void cfspi_port_conf(void)
-{
-	gpio_t *gpio = (gpio_t *) MMAP_GPIO;
-
-	out_8(&gpio->par_dspi,
-		GPIO_PAR_DSPI_SIN_SIN | GPIO_PAR_DSPI_SOUT_SOUT |
-		GPIO_PAR_DSPI_SCK_SCK);
-}
-
-int cfspi_claim_bus(uint bus, uint cs)
-{
-	dspi_t *dspi = (dspi_t *) MMAP_DSPI;
-	gpio_t *gpio = (gpio_t *) MMAP_GPIO;
-
-	if ((in_be32(&dspi->sr) & DSPI_SR_TXRXS) != DSPI_SR_TXRXS)
-		return -1;
-
-	/* Clear FIFO and resume transfer */
-	clrbits_be32(&dspi->mcr, DSPI_MCR_CTXF | DSPI_MCR_CRXF);
-
-	switch (cs) {
-	case 0:
-		clrbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS0_UNMASK);
-		setbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS0_PCS0);
-		break;
-	case 2:
-		clrbits_8(&gpio->par_timer, ~GPIO_PAR_TIMER_T2IN_UNMASK);
-		setbits_8(&gpio->par_timer, GPIO_PAR_TIMER_T2IN_DSPIPCS2);
-		break;
-	}
-
-	return 0;
-}
-
-void cfspi_release_bus(uint bus, uint cs)
-{
-	dspi_t *dspi = (dspi_t *) MMAP_DSPI;
-	gpio_t *gpio = (gpio_t *) MMAP_GPIO;
-
-	/* Clear FIFO */
-	clrbits_be32(&dspi->mcr, DSPI_MCR_CTXF | DSPI_MCR_CRXF);
-
-	switch (cs) {
-	case 0:
-		clrbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS0_PCS0);
-		break;
-	case 2:
-		clrbits_8(&gpio->par_timer, ~GPIO_PAR_TIMER_T2IN_UNMASK);
-		break;
-	}
-}
-#endif
diff --git a/arch/m68k/cpu/mcf5227x/dspi.c b/arch/m68k/cpu/mcf5227x/dspi.c
new file mode 100644
index 0000000..8fc4da2
--- /dev/null
+++ b/arch/m68k/cpu/mcf5227x/dspi.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019
+ * Angelo Dureghello <angleo@sysam.it>
+ *
+ * CPU specific dspi routines
+ */
+
+#include <common.h>
+#include <asm/immap.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_CF_DSPI
+void dspi_chip_select(int cs)
+{
+	struct gpio *gpio = (struct gpio *)MMAP_GPIO;
+
+	switch (cs) {
+	case 0:
+		clrbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS0_UNMASK);
+		setbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS0_PCS0);
+		break;
+	case 2:
+		clrbits_8(&gpio->par_timer, ~GPIO_PAR_TIMER_T2IN_UNMASK);
+		setbits_8(&gpio->par_timer, GPIO_PAR_TIMER_T2IN_DSPIPCS2);
+		break;
+	}
+}
+
+void dspi_chip_unselect(int cs)
+{
+	struct gpio *gpio = (struct gpio *)MMAP_GPIO;
+
+	switch (cs) {
+	case 0:
+		clrbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS0_PCS0);
+		break;
+	case 2:
+		clrbits_8(&gpio->par_timer, ~GPIO_PAR_TIMER_T2IN_UNMASK);
+		break;
+	}
+}
+#endif /* CONFIG_CF_DSPI */
diff --git a/arch/m68k/cpu/mcf5227x/start.S b/arch/m68k/cpu/mcf5227x/start.S
index e1b6c35..61f9c68 100644
--- a/arch/m68k/cpu/mcf5227x/start.S
+++ b/arch/m68k/cpu/mcf5227x/start.S
@@ -378,7 +378,8 @@
 	clr.l	%sp@-
 
 	/* run low-level board init code (from flash) */
-	bsr	board_init_f
+	move.l	#board_init_f, %a1
+	jsr	(%a1)
 
 	/* board_init_f() does not return */
 
diff --git a/arch/m68k/cpu/mcf5445x/Makefile b/arch/m68k/cpu/mcf5445x/Makefile
index be2cb2a..ba90fc3 100644
--- a/arch/m68k/cpu/mcf5445x/Makefile
+++ b/arch/m68k/cpu/mcf5445x/Makefile
@@ -6,4 +6,4 @@
 # ccflags-y += -DET_DEBUG
 
 extra-y	= start.o
-obj-y	= cpu.o speed.o cpu_init.o interrupts.o pci.o
+obj-y	= cpu.o speed.o cpu_init.o interrupts.o pci.o dspi.o
diff --git a/arch/m68k/cpu/mcf5445x/cpu_init.c b/arch/m68k/cpu/mcf5445x/cpu_init.c
index 7632d92..8f4991c 100644
--- a/arch/m68k/cpu/mcf5445x/cpu_init.c
+++ b/arch/m68k/cpu/mcf5445x/cpu_init.c
@@ -66,6 +66,32 @@
 #endif
 }
 
+#ifdef CONFIG_CF_DSPI
+void cfspi_port_conf(void)
+{
+	gpio_t *gpio = (gpio_t *)MMAP_GPIO;
+
+#ifdef CONFIG_MCF5445x
+	out_8(&gpio->par_dspi,
+	      GPIO_PAR_DSPI_SIN_SIN |
+	      GPIO_PAR_DSPI_SOUT_SOUT |
+	      GPIO_PAR_DSPI_SCK_SCK);
+#endif
+
+#ifdef CONFIG_MCF5441x
+	pm_t *pm = (pm_t *)MMAP_PM;
+
+	out_8(&gpio->par_dspi0,
+	      GPIO_PAR_DSPI0_SIN_DSPI0SIN | GPIO_PAR_DSPI0_SOUT_DSPI0SOUT |
+	      GPIO_PAR_DSPI0_SCK_DSPI0SCK);
+	out_8(&gpio->srcr_dspiow, 3);
+
+	/* DSPI0 */
+	out_8(&pm->pmcr0, 23);
+#endif
+}
+#endif
+
 /*
  * Breath some life into the CPU...
  *
@@ -204,6 +230,10 @@
 		GPIO_PAR_FBCTL_OE | GPIO_PAR_FBCTL_TA_TA |
 		GPIO_PAR_FBCTL_RW_RW | GPIO_PAR_FBCTL_TS_TS);
 
+#ifdef CONFIG_CF_SPI
+	cfspi_port_conf();
+#endif
+
 #ifdef CONFIG_SYS_FSL_I2C
 	out_be16(&gpio->par_feci2c,
 		GPIO_PAR_FECI2C_SCL_SCL | GPIO_PAR_FECI2C_SDA_SDA);
@@ -429,119 +459,7 @@
 	} else
 		clrbits_8(&gpio->par_fec, ~GPIO_PAR_FEC_FEC_MASK);
 #endif
-	return 0;
-}
-#endif
-
-#ifdef CONFIG_CF_DSPI
-void cfspi_port_conf(void)
-{
-	gpio_t *gpio = (gpio_t *) MMAP_GPIO;
-
-#ifdef CONFIG_MCF5445x
-	out_8(&gpio->par_dspi,
-		GPIO_PAR_DSPI_SIN_SIN |
-		GPIO_PAR_DSPI_SOUT_SOUT |
-		GPIO_PAR_DSPI_SCK_SCK);
-#endif
-
-#ifdef CONFIG_MCF5441x
-	pm_t *pm = (pm_t *) MMAP_PM;
-
-	out_8(&gpio->par_dspi0,
-		GPIO_PAR_DSPI0_SIN_DSPI0SIN | GPIO_PAR_DSPI0_SOUT_DSPI0SOUT |
-		GPIO_PAR_DSPI0_SCK_DSPI0SCK);
-	out_8(&gpio->srcr_dspiow, 3);
-
-	/* DSPI0 */
-	out_8(&pm->pmcr0, 23);
-#endif
-}
-
-int cfspi_claim_bus(uint bus, uint cs)
-{
-	dspi_t *dspi = (dspi_t *) MMAP_DSPI;
-	gpio_t *gpio = (gpio_t *) MMAP_GPIO;
-
-	if ((in_be32(&dspi->sr) & DSPI_SR_TXRXS) != DSPI_SR_TXRXS)
-		return -1;
-
-	/* Clear FIFO and resume transfer */
-	clrbits_be32(&dspi->mcr, DSPI_MCR_CTXF | DSPI_MCR_CRXF);
-
-#ifdef CONFIG_MCF5445x
-	switch (cs) {
-	case 0:
-		clrbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS0_PCS0);
-		setbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS0_PCS0);
-		break;
-	case 1:
-		clrbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS1_PCS1);
-		setbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS1_PCS1);
-		break;
-	case 2:
-		clrbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS2_PCS2);
-		setbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS2_PCS2);
-		break;
-	case 3:
-		clrbits_8(&gpio->par_dma, ~GPIO_PAR_DMA_DACK0_UNMASK);
-		setbits_8(&gpio->par_dma, GPIO_PAR_DMA_DACK0_PCS3);
-		break;
-	case 5:
-		clrbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS5_PCS5);
-		setbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS5_PCS5);
-		break;
-	}
-#endif
-
-#ifdef CONFIG_MCF5441x
-	switch (cs) {
-	case 0:
-		clrbits_8(&gpio->par_dspi0, ~GPIO_PAR_DSPI0_PCS0_MASK);
-		setbits_8(&gpio->par_dspi0, GPIO_PAR_DSPI0_PCS0_DSPI0PCS0);
-		break;
-	case 1:
-		clrbits_8(&gpio->par_dspiow, GPIO_PAR_DSPIOW_DSPI0PSC1);
-		setbits_8(&gpio->par_dspiow, GPIO_PAR_DSPIOW_DSPI0PSC1);
-		break;
-	}
-#endif
-
 	return 0;
 }
-
-void cfspi_release_bus(uint bus, uint cs)
-{
-	dspi_t *dspi = (dspi_t *) MMAP_DSPI;
-	gpio_t *gpio = (gpio_t *) MMAP_GPIO;
-
-	/* Clear FIFO */
-	clrbits_be32(&dspi->mcr, DSPI_MCR_CTXF | DSPI_MCR_CRXF);
-
-#ifdef CONFIG_MCF5445x
-	switch (cs) {
-	case 0:
-		clrbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS0_PCS0);
-		break;
-	case 1:
-		clrbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS1_PCS1);
-		break;
-	case 2:
-		clrbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS2_PCS2);
-		break;
-	case 3:
-		clrbits_8(&gpio->par_dma, ~GPIO_PAR_DMA_DACK0_UNMASK);
-		break;
-	case 5:
-		clrbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS5_PCS5);
-		break;
-	}
 #endif
 
-#ifdef CONFIG_MCF5441x
-	if (cs == 1)
-		clrbits_8(&gpio->par_dspiow, GPIO_PAR_DSPIOW_DSPI0PSC1);
-#endif
-}
-
-#endif
diff --git a/arch/m68k/cpu/mcf5445x/dspi.c b/arch/m68k/cpu/mcf5445x/dspi.c
new file mode 100644
index 0000000..b0e2f2c
--- /dev/null
+++ b/arch/m68k/cpu/mcf5445x/dspi.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019
+ * Angelo Dureghello <angleo@sysam.it>
+ *
+ * CPU specific dspi routines
+ */
+
+#include <common.h>
+#include <asm/immap.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_CF_DSPI
+void dspi_chip_select(int cs)
+{
+	struct gpio *gpio = (struct gpio *)MMAP_GPIO;
+
+#ifdef CONFIG_MCF5445x
+	switch (cs) {
+	case 0:
+		clrbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS0_PCS0);
+		setbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS0_PCS0);
+		break;
+	case 1:
+		clrbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS1_PCS1);
+		setbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS1_PCS1);
+		break;
+	case 2:
+		clrbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS2_PCS2);
+		setbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS2_PCS2);
+		break;
+	case 3:
+		clrbits_8(&gpio->par_dma, ~GPIO_PAR_DMA_DACK0_UNMASK);
+		setbits_8(&gpio->par_dma, GPIO_PAR_DMA_DACK0_PCS3);
+		break;
+	case 5:
+		clrbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS5_PCS5);
+		setbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS5_PCS5);
+		break;
+	}
+#endif
+#ifdef CONFIG_MCF5441x
+	switch (cs) {
+	case 0:
+		clrbits_8(&gpio->par_dspi0,
+			  ~GPIO_PAR_DSPI0_PCS0_MASK);
+		setbits_8(&gpio->par_dspi0,
+			  GPIO_PAR_DSPI0_PCS0_DSPI0PCS0);
+		break;
+	case 1:
+		clrbits_8(&gpio->par_dspiow,
+			  GPIO_PAR_DSPIOW_DSPI0PSC1);
+		setbits_8(&gpio->par_dspiow,
+			  GPIO_PAR_DSPIOW_DSPI0PSC1);
+		break;
+	}
+#endif
+}
+
+void dspi_chip_unselect(int cs)
+{
+	struct gpio *gpio = (struct gpio *)MMAP_GPIO;
+
+#ifdef CONFIG_MCF5445x
+	switch (cs) {
+	case 0:
+		clrbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS0_PCS0);
+		break;
+	case 1:
+		clrbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS1_PCS1);
+		break;
+	case 2:
+		clrbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS2_PCS2);
+		break;
+	case 3:
+		clrbits_8(&gpio->par_dma, ~GPIO_PAR_DMA_DACK0_UNMASK);
+		break;
+	case 5:
+		clrbits_8(&gpio->par_dspi, GPIO_PAR_DSPI_PCS5_PCS5);
+		break;
+	}
+#endif
+#ifdef CONFIG_MCF5441x
+	if (cs == 1)
+		clrbits_8(&gpio->par_dspiow, GPIO_PAR_DSPIOW_DSPI0PSC1);
+#endif
+}
+#endif /* CONFIG_CF_DSPI */
diff --git a/arch/m68k/cpu/mcf547x_8x/start.S b/arch/m68k/cpu/mcf547x_8x/start.S
index 7cb5db7..4dd57bf 100644
--- a/arch/m68k/cpu/mcf547x_8x/start.S
+++ b/arch/m68k/cpu/mcf547x_8x/start.S
@@ -131,7 +131,8 @@
 	 * then (and always) gd struct space will be reserved
 	 */
 	move.l	%sp, -(%sp)
-	bsr	board_init_f_alloc_reserve
+	move.l	#board_init_f_alloc_reserve, %a1
+	jsr	(%a1)
 
 	/* update stack and frame-pointers */
 	move.l  %d0, %sp
@@ -139,7 +140,8 @@
 
 	/* initialize reserved area */
 	move.l	%d0, -(%sp)
-	bsr	board_init_f_init_reserve
+	move.l	#board_init_f_init_reserve, %a1
+	jsr	(%a1)
 
 	/* run low-level CPU init code (from flash) */
 	jbsr	cpu_init_f
diff --git a/arch/m68k/cpu/u-boot.lds b/arch/m68k/cpu/u-boot.lds
index 9645120..64cf2ff 100644
--- a/arch/m68k/cpu/u-boot.lds
+++ b/arch/m68k/cpu/u-boot.lds
@@ -68,13 +68,15 @@
 	__ex_table : { *(__ex_table) }
 	__stop___ex_table = .;
 
-	. = ALIGN(256);
+	. = ALIGN(4);
 	__init_begin = .;
 	.text.init : { *(.text.init) }
 	.data.init : { *(.data.init) }
-	. = ALIGN(256);
+	. = ALIGN(4);
 	__init_end = .;
 
+	_end = .;
+
 	__bss_start = .;
 	.bss (NOLOAD)       :
 	{
diff --git a/arch/m68k/dts/M5208EVBE.dts b/arch/m68k/dts/M5208EVBE.dts
new file mode 100644
index 0000000..e78513f
--- /dev/null
+++ b/arch/m68k/dts/M5208EVBE.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5208.dtsi"
+
+/ {
+	model = "Freescale M5208EVBE";
+	compatible = "fsl,M5208EVBE";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
diff --git a/arch/m68k/dts/M52277EVB.dts b/arch/m68k/dts/M52277EVB.dts
new file mode 100644
index 0000000..a2210c8
--- /dev/null
+++ b/arch/m68k/dts/M52277EVB.dts
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5227x.dtsi"
+
+/ {
+	model = "Freescale M52277EVB";
+	compatible = "fsl,M52277EVB";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&dspi0 {
+	status = "okay";
+};
diff --git a/arch/m68k/dts/M52277EVB_stmicro.dts b/arch/m68k/dts/M52277EVB_stmicro.dts
new file mode 100644
index 0000000..5fd3ca5
--- /dev/null
+++ b/arch/m68k/dts/M52277EVB_stmicro.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5227x.dtsi"
+
+/ {
+	model = "Freescale M52277_stmicro";
+	compatible = "fsl,M52277_stmicro";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
diff --git a/arch/m68k/dts/M5235EVB.dts b/arch/m68k/dts/M5235EVB.dts
new file mode 100644
index 0000000..1a32539
--- /dev/null
+++ b/arch/m68k/dts/M5235EVB.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf523x.dtsi"
+
+/ {
+	model = "Freescale M5235EVB";
+	compatible = "fsl,M5235EVB";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
diff --git a/arch/m68k/dts/M5235EVB_Flash32.dts b/arch/m68k/dts/M5235EVB_Flash32.dts
new file mode 100644
index 0000000..fcbffb2
--- /dev/null
+++ b/arch/m68k/dts/M5235EVB_Flash32.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf523x.dtsi"
+
+/ {
+	model = "Freescale M5235EVB_Flash32";
+	compatible = "fsl,M5235EVB_Flash32";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
diff --git a/arch/m68k/dts/M5249EVB.dts b/arch/m68k/dts/M5249EVB.dts
new file mode 100644
index 0000000..b2a1be9
--- /dev/null
+++ b/arch/m68k/dts/M5249EVB.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5249.dtsi"
+
+/ {
+	model = "Freescale M5249EVB";
+	compatible = "fsl,M5249EVB";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
diff --git a/arch/m68k/dts/M5253DEMO.dts b/arch/m68k/dts/M5253DEMO.dts
new file mode 100644
index 0000000..7ebaa9a
--- /dev/null
+++ b/arch/m68k/dts/M5253DEMO.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5253.dtsi"
+
+/ {
+	model = "Freescale M5253DEMO";
+	compatible = "fsl,M5253DEMO";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
diff --git a/arch/m68k/dts/M5272C3.dts b/arch/m68k/dts/M5272C3.dts
new file mode 100644
index 0000000..6efb8a4
--- /dev/null
+++ b/arch/m68k/dts/M5272C3.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5272.dtsi"
+
+/ {
+	model = "Freescale M5272C3";
+	compatible = "fsl,M5272C3";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
diff --git a/arch/m68k/dts/M5275EVB.dts b/arch/m68k/dts/M5275EVB.dts
new file mode 100644
index 0000000..cd9eb7d
--- /dev/null
+++ b/arch/m68k/dts/M5275EVB.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5275.dtsi"
+
+/ {
+	model = "Freescale M5275EVB";
+	compatible = "fsl,M5275EVB";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
diff --git a/arch/m68k/dts/M5282EVB.dts b/arch/m68k/dts/M5282EVB.dts
new file mode 100644
index 0000000..9527caa
--- /dev/null
+++ b/arch/m68k/dts/M5282EVB.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5282.dtsi"
+
+/ {
+	model = "Freescale M5282EVB";
+	compatible = "fsl,M5282EVB";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
diff --git a/arch/m68k/dts/M53017EVB.dts b/arch/m68k/dts/M53017EVB.dts
new file mode 100644
index 0000000..b267488
--- /dev/null
+++ b/arch/m68k/dts/M53017EVB.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5301x.dtsi"
+
+/ {
+	model = "Freescale M53017EVB";
+	compatible = "fsl,M53017EVB";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
diff --git a/arch/m68k/dts/M5329AFEE.dts b/arch/m68k/dts/M5329AFEE.dts
new file mode 100644
index 0000000..7d121d6
--- /dev/null
+++ b/arch/m68k/dts/M5329AFEE.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5329.dtsi"
+
+/ {
+	model = "Freescale M5329AFEE";
+	compatible = "fsl,M5329AFEE";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
diff --git a/arch/m68k/dts/M5329BFEE.dts b/arch/m68k/dts/M5329BFEE.dts
new file mode 100644
index 0000000..cd087b6
--- /dev/null
+++ b/arch/m68k/dts/M5329BFEE.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5329.dtsi"
+
+/ {
+	model = "Freescale M5329BFEE";
+	compatible = "fsl,M5329BFEE";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
diff --git a/arch/m68k/dts/M5373EVB.dts b/arch/m68k/dts/M5373EVB.dts
new file mode 100644
index 0000000..930f911
--- /dev/null
+++ b/arch/m68k/dts/M5373EVB.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf537x.dtsi"
+
+/ {
+	model = "Freescale M5373EVB";
+	compatible = "fsl,M5373EVB";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
diff --git a/arch/m68k/dts/M54418TWR.dts b/arch/m68k/dts/M54418TWR.dts
new file mode 100644
index 0000000..7765c7a
--- /dev/null
+++ b/arch/m68k/dts/M54418TWR.dts
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5441x.dtsi"
+
+/ {
+	model = "Freescale M54418TWR";
+	compatible = "fsl,M54418TWR";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&dspi0 {
+	status = "okay";
+};
diff --git a/arch/m68k/dts/M54418TWR_nand_mii.dts b/arch/m68k/dts/M54418TWR_nand_mii.dts
new file mode 100644
index 0000000..9b1cb85
--- /dev/null
+++ b/arch/m68k/dts/M54418TWR_nand_mii.dts
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5441x.dtsi"
+
+/ {
+	model = "Freescale M54418TWR_nand_mii";
+	compatible = "fsl,M54418TWR_nand_mii";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&dspi0 {
+	status = "okay";
+};
diff --git a/arch/m68k/dts/M54418TWR_nand_rmii.dts b/arch/m68k/dts/M54418TWR_nand_rmii.dts
new file mode 100644
index 0000000..824a66a
--- /dev/null
+++ b/arch/m68k/dts/M54418TWR_nand_rmii.dts
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5441x.dtsi"
+
+/ {
+	model = "Freescale M54418TWR_nand_rmii";
+	compatible = "fsl,M54418TWR_nand_rmii";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&dspi0 {
+	status = "okay";
+};
diff --git a/arch/m68k/dts/M54418TWR_nand_rmii_lowfreq.dts b/arch/m68k/dts/M54418TWR_nand_rmii_lowfreq.dts
new file mode 100644
index 0000000..74fa197
--- /dev/null
+++ b/arch/m68k/dts/M54418TWR_nand_rmii_lowfreq.dts
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5441x.dtsi"
+
+/ {
+	model = "Freescale M54418TWR_nand_rmii_lowfreq";
+	compatible = "fsl,M54418TWR_nand_rmii_lowfreq";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&dspi0 {
+	status = "okay";
+};
diff --git a/arch/m68k/dts/M54418TWR_serial_mii.dts b/arch/m68k/dts/M54418TWR_serial_mii.dts
new file mode 100644
index 0000000..22f27b5
--- /dev/null
+++ b/arch/m68k/dts/M54418TWR_serial_mii.dts
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5441x.dtsi"
+
+/ {
+	model = "Freescale M54418TWR_serial_mii";
+	compatible = "fsl,M54418TWR_serial_mii";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&dspi0 {
+	status = "okay";
+};
diff --git a/arch/m68k/dts/M54418TWR_serial_rmii.dts b/arch/m68k/dts/M54418TWR_serial_rmii.dts
new file mode 100644
index 0000000..0ddefd9
--- /dev/null
+++ b/arch/m68k/dts/M54418TWR_serial_rmii.dts
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5441x.dtsi"
+
+/ {
+	model = "Freescale M54418TWR_serial_rmii";
+	compatible = "fsl,M54418TWR_serial_rmii";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&dspi0 {
+	status = "okay";
+};
diff --git a/arch/m68k/dts/M54451EVB.dts b/arch/m68k/dts/M54451EVB.dts
new file mode 100644
index 0000000..b57bfea
--- /dev/null
+++ b/arch/m68k/dts/M54451EVB.dts
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5445x.dtsi"
+
+/ {
+	model = "Freescale M54451EVB";
+	compatible = "fsl,M54451EVB";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&dspi0 {
+	status = "okay";
+};
diff --git a/arch/m68k/dts/M54451EVB_stmicro.dts b/arch/m68k/dts/M54451EVB_stmicro.dts
new file mode 100644
index 0000000..9a088e1
--- /dev/null
+++ b/arch/m68k/dts/M54451EVB_stmicro.dts
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5445x.dtsi"
+
+/ {
+	model = "Freescale M54451EVB_stmicro";
+	compatible = "fsl,M54451EVB";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&dspi0 {
+	status = "okay";
+};
diff --git a/arch/m68k/dts/M54455EVB.dts b/arch/m68k/dts/M54455EVB.dts
new file mode 100644
index 0000000..dd11181
--- /dev/null
+++ b/arch/m68k/dts/M54455EVB.dts
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5445x.dtsi"
+
+/ {
+	model = "Freescale M54455EVB";
+	compatible = "fsl,M54455EVB";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&dspi0 {
+	status = "okay";
+};
diff --git a/arch/m68k/dts/M54455EVB_a66.dts b/arch/m68k/dts/M54455EVB_a66.dts
new file mode 100644
index 0000000..70d544b
--- /dev/null
+++ b/arch/m68k/dts/M54455EVB_a66.dts
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5445x.dtsi"
+
+/ {
+	model = "Freescale M54455EVB_a66";
+	compatible = "fsl,M54455EVB_a66";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&dspi0 {
+	status = "okay";
+};
diff --git a/arch/m68k/dts/M54455EVB_i66.dts b/arch/m68k/dts/M54455EVB_i66.dts
new file mode 100644
index 0000000..b37a872
--- /dev/null
+++ b/arch/m68k/dts/M54455EVB_i66.dts
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5445x.dtsi"
+
+/ {
+	model = "Freescale M54455EVB_i66";
+	compatible = "fsl,M54455EVB_i66";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&dspi0 {
+	status = "okay";
+};
diff --git a/arch/m68k/dts/M54455EVB_intel.dts b/arch/m68k/dts/M54455EVB_intel.dts
new file mode 100644
index 0000000..c92228f
--- /dev/null
+++ b/arch/m68k/dts/M54455EVB_intel.dts
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5445x.dtsi"
+
+/ {
+	model = "Freescale M54455EVB_intel";
+	compatible = "fsl,M5275EVB_intel";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&dspi0 {
+	status = "okay";
+};
+
diff --git a/arch/m68k/dts/M54455EVB_stm33.dts b/arch/m68k/dts/M54455EVB_stm33.dts
new file mode 100644
index 0000000..9e467f9
--- /dev/null
+++ b/arch/m68k/dts/M54455EVB_stm33.dts
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5445x.dtsi"
+
+/ {
+	model = "Freescale M54455EVB_stm33";
+	compatible = "fsl,M5275EVB_stm33";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&dspi0 {
+	status = "okay";
+};
diff --git a/arch/m68k/dts/M5475AFE.dts b/arch/m68k/dts/M5475AFE.dts
new file mode 100644
index 0000000..0c0a79b
--- /dev/null
+++ b/arch/m68k/dts/M5475AFE.dts
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf54xx.dtsi"
+
+/ {
+	model = "Freescale M5475AFE";
+	compatible = "fsl,M5475AFE";
+};
+
diff --git a/arch/m68k/dts/M5475BFE.dts b/arch/m68k/dts/M5475BFE.dts
new file mode 100644
index 0000000..c4d1409
--- /dev/null
+++ b/arch/m68k/dts/M5475BFE.dts
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf54xx.dtsi"
+
+/ {
+	model = "Freescale M5475BFE";
+	compatible = "fsl,M5475BFE";
+};
+
diff --git a/arch/m68k/dts/M5475CFE.dts b/arch/m68k/dts/M5475CFE.dts
new file mode 100644
index 0000000..4c92c33
--- /dev/null
+++ b/arch/m68k/dts/M5475CFE.dts
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf54xx.dtsi"
+
+/ {
+	model = "Freescale M5475CFE";
+	compatible = "fsl,M5475CFE";
+};
+
diff --git a/arch/m68k/dts/M5475DFE.dts b/arch/m68k/dts/M5475DFE.dts
new file mode 100644
index 0000000..c41c1b3
--- /dev/null
+++ b/arch/m68k/dts/M5475DFE.dts
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf54xx.dtsi"
+
+/ {
+	model = "Freescale M5475DFE";
+	compatible = "fsl,M5475DFE";
+};
+
diff --git a/arch/m68k/dts/M5475EFE.dts b/arch/m68k/dts/M5475EFE.dts
new file mode 100644
index 0000000..5a920b2
--- /dev/null
+++ b/arch/m68k/dts/M5475EFE.dts
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf54xx.dtsi"
+
+/ {
+	model = "Freescale M5475EFE";
+	compatible = "fsl,M5475EFE";
+};
+
diff --git a/arch/m68k/dts/M5475FFE.dts b/arch/m68k/dts/M5475FFE.dts
new file mode 100644
index 0000000..d312a6a
--- /dev/null
+++ b/arch/m68k/dts/M5475FFE.dts
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf54xx.dtsi"
+
+/ {
+	model = "Freescale M5475FFE";
+	compatible = "fsl,M5475FFE";
+};
+
diff --git a/arch/m68k/dts/M5475GFE.dts b/arch/m68k/dts/M5475GFE.dts
new file mode 100644
index 0000000..9e794da
--- /dev/null
+++ b/arch/m68k/dts/M5475GFE.dts
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf54xx.dtsi"
+
+/ {
+	model = "Freescale M5475GFE";
+	compatible = "fsl,M5475GFE";
+};
+
diff --git a/arch/m68k/dts/M5485AFE.dts b/arch/m68k/dts/M5485AFE.dts
new file mode 100644
index 0000000..3466751
--- /dev/null
+++ b/arch/m68k/dts/M5485AFE.dts
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf54xx.dtsi"
+
+/ {
+	model = "Freescale M5485AFE";
+	compatible = "fsl,M5485AFE";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
diff --git a/arch/m68k/dts/M5485BFE.dts b/arch/m68k/dts/M5485BFE.dts
new file mode 100644
index 0000000..6d48795
--- /dev/null
+++ b/arch/m68k/dts/M5485BFE.dts
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf54xx.dtsi"
+
+/ {
+	model = "Freescale M5485BFE";
+	compatible = "fsl,M5485BFE";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
diff --git a/arch/m68k/dts/M5485CFE.dts b/arch/m68k/dts/M5485CFE.dts
new file mode 100644
index 0000000..d1a7d9d
--- /dev/null
+++ b/arch/m68k/dts/M5485CFE.dts
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf54xx.dtsi"
+
+/ {
+	model = "Freescale M5485CFE";
+	compatible = "fsl,M5485CFE";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
diff --git a/arch/m68k/dts/M5485DFE.dts b/arch/m68k/dts/M5485DFE.dts
new file mode 100644
index 0000000..7c362e2
--- /dev/null
+++ b/arch/m68k/dts/M5485DFE.dts
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf54xx.dtsi"
+
+/ {
+	model = "Freescale M5485DFE";
+	compatible = "fsl,M5485DFE";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
diff --git a/arch/m68k/dts/M5485EFE.dts b/arch/m68k/dts/M5485EFE.dts
new file mode 100644
index 0000000..4c688dc
--- /dev/null
+++ b/arch/m68k/dts/M5485EFE.dts
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf54xx.dtsi"
+
+/ {
+	model = "Freescale M5485EFE";
+	compatible = "fsl,M5485EFE";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
diff --git a/arch/m68k/dts/M5485FFE.dts b/arch/m68k/dts/M5485FFE.dts
new file mode 100644
index 0000000..87ec2c5
--- /dev/null
+++ b/arch/m68k/dts/M5485FFE.dts
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf54xx.dtsi"
+
+/ {
+	model = "Freescale M5485FFE";
+	compatible = "fsl,M5485FFE";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
diff --git a/arch/m68k/dts/M5485GFE.dts b/arch/m68k/dts/M5485GFE.dts
new file mode 100644
index 0000000..9f67e55
--- /dev/null
+++ b/arch/m68k/dts/M5485GFE.dts
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf54xx.dtsi"
+
+/ {
+	model = "Freescale M5485GFE";
+	compatible = "fsl,M5485GFE";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
diff --git a/arch/m68k/dts/M5485HFE.dts b/arch/m68k/dts/M5485HFE.dts
new file mode 100644
index 0000000..2eb2213
--- /dev/null
+++ b/arch/m68k/dts/M5485HFE.dts
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf54xx.dtsi"
+
+/ {
+	model = "Freescale M5485HFE";
+	compatible = "fsl,M5485HFE";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
diff --git a/arch/m68k/dts/Makefile b/arch/m68k/dts/Makefile
new file mode 100644
index 0000000..e059f23
--- /dev/null
+++ b/arch/m68k/dts/Makefile
@@ -0,0 +1,59 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+dtb-$(CONFIG_TARGET_M52277EVB) += M52277EVB.dtb \
+	M52277EVB_stmicro.dtb
+dtb-$(CONFIG_TARGET_M5235EVB) += M5235EVB.dtb \
+	M5235EVB_Flash32.dtb
+dtb-$(CONFIG_TARGET_COBRA5272) += cobra5272.dtb
+dtb-$(CONFIG_TARGET_EB_CPU5282) += eb_cpu5282.dtb \
+	eb_cpu5282_internal.dtb
+dtb-$(CONFIG_TARGET_M5208EVBE) += M5208EVBE.dtb
+dtb-$(CONFIG_TARGET_M5249EVB) += M5249EVB.dtb
+dtb-$(CONFIG_TARGET_M5253DEMO) += M5253DEMO.dtb
+dtb-$(CONFIG_TARGET_M5272C3) += M5272C3.dtb
+dtb-$(CONFIG_TARGET_M5275EVB) += M5275EVB.dtb
+dtb-$(CONFIG_TARGET_M5282EVB) += M5282EVB.dtb
+dtb-$(CONFIG_TARGET_ASTRO_MCF5373L) += astro_mcf5373l.dtb
+dtb-$(CONFIG_TARGET_M53017EVB) += M53017EVB.dtb
+dtb-$(CONFIG_TARGET_M5329EVB) += M5329AFEE.dtb M5329BFEE.dtb
+dtb-$(CONFIG_TARGET_M5373EVB) += M5373EVB.dtb
+dtb-$(CONFIG_TARGET_M54418TWR) += M54418TWR.dtb \
+	M54418TWR_nand_mii.dtb \
+	M54418TWR_nand_rmii.dtb \
+	M54418TWR_serial_mii.dtb \
+	M54418TWR_serial_rmii.dtb \
+	M54418TWR_nand_rmii_lowfreq.dtb
+dtb-$(CONFIG_TARGET_M54451EVB) += M54451EVB.dtb \
+	M54451EVB_stmicro.dtb
+dtb-$(CONFIG_TARGET_M54455EVB) += M54455EVB.dtb \
+	M54455EVB_intel.dtb \
+	M54455EVB_stm33.dtb \
+	M54455EVB_a66.dtb \
+	M54455EVB_i66.dtb
+dtb-$(CONFIG_TARGET_AMCORE) += amcore.dtb
+dtb-$(CONFIG_TARGET_STMARK2) += stmark2.dtb
+dtb-$(CONFIG_TARGET_M5475EVB) += M5475AFE.dtb \
+	M5475BFE.dtb \
+	M5475CFE.dtb \
+	M5475DFE.dtb \
+	M5475EFE.dtb \
+	M5475FFE.dtb \
+	M5475GFE.dtb
+dtb-$(CONFIG_TARGET_M5485EVB) += M5485AFE.dtb \
+	M5485BFE.dtb \
+	M5485CFE.dtb \
+	M5485DFE.dtb \
+	M5485EFE.dtb \
+	M5485FFE.dtb \
+	M5485GFE.dtb \
+	M5485HFE.dtb
+
+targets += $(dtb-y)
+
+DTC_FLAGS += -R 4 -p 0x1000
+
+PHONY += dtbs
+dtbs: $(addprefix $(obj)/, $(dtb-y))
+	@:
+
+clean-files := *.dtb
diff --git a/arch/m68k/dts/amcore.dts b/arch/m68k/dts/amcore.dts
new file mode 100644
index 0000000..c21fb8f
--- /dev/null
+++ b/arch/m68k/dts/amcore.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5307.dtsi"
+
+/ {
+	model = "Sysam AMCORE";
+	compatible = "sysam,AMCORE";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
diff --git a/arch/m68k/dts/astro_mcf5373l.dts b/arch/m68k/dts/astro_mcf5373l.dts
new file mode 100644
index 0000000..1b1a46a
--- /dev/null
+++ b/arch/m68k/dts/astro_mcf5373l.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf537x.dtsi"
+
+/ {
+	model = "Astro mcf5373l";
+	compatible = "astro,mcf5373l";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
diff --git a/arch/m68k/dts/cobra5272.dts b/arch/m68k/dts/cobra5272.dts
new file mode 100644
index 0000000..f3b7497
--- /dev/null
+++ b/arch/m68k/dts/cobra5272.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5272.dtsi"
+
+/ {
+	model = "Cobra 5272";
+	compatible = "cobra,M5272";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
diff --git a/arch/m68k/dts/eb_cpu5282.dts b/arch/m68k/dts/eb_cpu5282.dts
new file mode 100644
index 0000000..4641e9c
--- /dev/null
+++ b/arch/m68k/dts/eb_cpu5282.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5282.dtsi"
+
+/ {
+	model = "BuS eb_cpuM5282";
+	compatible = "bus,eb_cpuM5282";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
diff --git a/arch/m68k/dts/eb_cpu5282_internal.dts b/arch/m68k/dts/eb_cpu5282_internal.dts
new file mode 100644
index 0000000..0acb793
--- /dev/null
+++ b/arch/m68k/dts/eb_cpu5282_internal.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5282.dtsi"
+
+/ {
+	model = "BuS eb_cpu5282_internals";
+	compatible = "bus,eb_cpu5282_internals";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
diff --git a/arch/m68k/dts/mcf5208.dtsi b/arch/m68k/dts/mcf5208.dtsi
new file mode 100644
index 0000000..558d8bf
--- /dev/null
+++ b/arch/m68k/dts/mcf5208.dtsi
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/ {
+	compatible = "fsl,mcf5208";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		uart0: uart@fc060000 {
+			compatible = "fsl,mcf-uart";
+			reg = <0xfc060000 0x40>;
+			status = "disabled";
+		};
+
+		uart1: uart@fc064000 {
+			compatible = "fsl,mcf-uart";
+			reg = <0xfc064000 0x40>;
+			status = "disabled";
+		};
+
+		uart2: uart@fc068000 {
+			compatible = "fsl,mcf-uart";
+			reg = <0xfc068000 0x40>;
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/m68k/dts/mcf5227x.dtsi b/arch/m68k/dts/mcf5227x.dtsi
new file mode 100644
index 0000000..8c95edd
--- /dev/null
+++ b/arch/m68k/dts/mcf5227x.dtsi
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/ {
+	compatible = "fsl,mcf5227x";
+
+	aliases {
+		serial0 = &uart0;
+		spi0 = &dspi0;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		uart0: uart@fc060000 {
+			compatible = "fsl,mcf-uart";
+			reg = <0xfc060000 0x40>;
+			status = "disabled";
+		};
+
+		uart1: uart@fc064000 {
+			compatible = "fsl,mcf-uart";
+			reg = <0xfc064000 0x40>;
+			status = "disabled";
+		};
+
+		uart2: uart@fc068000 {
+			compatible = "fsl,mcf-uart";
+			reg = <0xfc068000 0x40>;
+			status = "disabled";
+		};
+
+		dspi0: dspi@fc05c000 {
+			compatible = "fsl,mcf-dspi";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xfc05c000 0x100>;
+			spi-max-frequency = <50000000>;
+			num-cs = <4>;
+			spi-mode = <0>;
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/m68k/dts/mcf523x.dtsi b/arch/m68k/dts/mcf523x.dtsi
new file mode 100644
index 0000000..9e79d47
--- /dev/null
+++ b/arch/m68k/dts/mcf523x.dtsi
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/ {
+	compatible = "fsl,mcf523x";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		ipsbar: ipsbar@4000000 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x00000000 0x40000000 0x40000000>;
+			reg = <0x40000000 0x40000000>;
+
+			uart0: uart@200 {
+				compatible = "fsl,mcf-uart";
+				reg = <0x200 0x40>;
+				status = "disabled";
+			};
+
+			uart1: uart@240 {
+				compatible = "fsl,mcf-uart";
+				reg = <0x240 0x40>;
+				status = "disabled";
+			};
+
+			uart2: uart@280 {
+				compatible = "fsl,mcf-uart";
+				reg = <0x280 0x40>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/m68k/dts/mcf5249.dtsi b/arch/m68k/dts/mcf5249.dtsi
new file mode 100644
index 0000000..248b3dc
--- /dev/null
+++ b/arch/m68k/dts/mcf5249.dtsi
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/ {
+	compatible = "fsl,mcf5249";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		mbar: mbar@10000000 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x00000000 0x10000000 0x10000>;
+			reg = <0x10000000 0x10000>;
+
+			uart0: uart@1c0 {
+				compatible = "fsl,mcf-uart";
+				reg = <0x1c0 0x40>;
+				status = "disabled";
+			};
+
+			uart1: uart@200 {
+				compatible = "fsl,mcf-uart";
+				reg = <0x200 0x40>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/m68k/dts/mcf5253.dtsi b/arch/m68k/dts/mcf5253.dtsi
new file mode 100644
index 0000000..3bde2d6
--- /dev/null
+++ b/arch/m68k/dts/mcf5253.dtsi
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/ {
+	compatible = "fsl,mcf5253";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		mbar: mbar@10000000 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x00000000 0x10000000 0x10000>;
+			reg = <0x10000000 0x10000>;
+
+			uart0: uart@1c0 {
+				compatible = "fsl,mcf-uart";
+				reg = <0x1c0 0x40>;
+				status = "disabled";
+			};
+
+			uart1: uart@200 {
+				compatible = "fsl,mcf-uart";
+				reg = <0x200 0x40>;
+				status = "disabled";
+			};
+
+			uart3: uart@c00 {
+				compatible = "fsl,mcf-uart";
+				reg = <0xc00 0x40>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/m68k/dts/mcf5271.dtsi b/arch/m68k/dts/mcf5271.dtsi
new file mode 100644
index 0000000..2935552
--- /dev/null
+++ b/arch/m68k/dts/mcf5271.dtsi
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/ {
+	compatible = "fsl,mcf5271";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		ipsbar: ipsbar@4000000 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x00000000 0x40000000 0x40000000>;
+			reg = <0x40000000 0x40000000>;
+
+			uart0: uart@200 {
+				compatible = "fsl,mcf-uart";
+				reg = <0x200 0x40>;
+				status = "disabled";
+			};
+
+			uart1: uart@240 {
+				compatible = "fsl,mcf-uart";
+				reg = <0x240 0x40>;
+				status = "disabled";
+			};
+
+			uart2: uart@280 {
+				compatible = "fsl,mcf-uart";
+				reg = <0x280 0x40>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/m68k/dts/mcf5272.dtsi b/arch/m68k/dts/mcf5272.dtsi
new file mode 100644
index 0000000..a561177
--- /dev/null
+++ b/arch/m68k/dts/mcf5272.dtsi
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/ {
+	compatible = "fsl,mcf5272";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		mbar: mbar@10000000 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x00000000 0x10000000 0x10000>;
+			reg = <0x10000000 0x10000>;
+
+			uart0: uart@100 {
+				compatible = "fsl,mcf-uart";
+				reg = <0x100 0x40>;
+				status = "disabled";
+			};
+
+			uart1: uart@140 {
+				compatible = "fsl,mcf-uart";
+				reg = <0x140 0x40>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/m68k/dts/mcf5275.dtsi b/arch/m68k/dts/mcf5275.dtsi
new file mode 100644
index 0000000..b375609
--- /dev/null
+++ b/arch/m68k/dts/mcf5275.dtsi
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/ {
+	compatible = "fsl,mcf5275";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		ipsbar: ipsbar@4000000 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x00000000 0x40000000 0x40000000>;
+			reg = <0x40000000 0x40000000>;
+
+			uart0: uart@200 {
+				compatible = "fsl,mcf-uart";
+				reg = <0x200 0x40>;
+				status = "disabled";
+			};
+
+			uart1: uart@240 {
+				compatible = "fsl,mcf-uart";
+				reg = <0x240 0x40>;
+				status = "disabled";
+			};
+
+			uart2: uart@280 {
+				compatible = "fsl,mcf-uart";
+				reg = <0x280 0x40>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/m68k/dts/mcf5282.dtsi b/arch/m68k/dts/mcf5282.dtsi
new file mode 100644
index 0000000..3ad1be7
--- /dev/null
+++ b/arch/m68k/dts/mcf5282.dtsi
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/ {
+	compatible = "fsl,mcf5282";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		ipsbar: ipsbar@4000000 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x00000000 0x40000000 0x40000000>;
+			reg = <0x40000000 0x40000000>;
+
+			uart0: uart@200 {
+				compatible = "fsl,mcf-uart";
+				reg = <0x200 0x40>;
+				status = "disabled";
+			};
+
+			uart1: uart@240 {
+				compatible = "fsl,mcf-uart";
+				reg = <0x240 0x40>;
+				status = "disabled";
+			};
+
+			uart2: uart@280 {
+				compatible = "fsl,mcf-uart";
+				reg = <0x280 0x40>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/m68k/dts/mcf5301x.dtsi b/arch/m68k/dts/mcf5301x.dtsi
new file mode 100644
index 0000000..0891e4d
--- /dev/null
+++ b/arch/m68k/dts/mcf5301x.dtsi
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/ {
+	compatible = "fsl,mcf5301x";
+
+	aliases {
+		serial0 = &uart0;
+		spi0 = &dspi0;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		uart0: uart@fc060000 {
+			compatible = "fsl,mcf-uart";
+			reg = <0xfc060000 0x40>;
+			status = "disabled";
+		};
+
+		uart1: uart@fc064000 {
+			compatible = "fsl,mcf-uart";
+			reg = <0xfc064000 0x40>;
+			status = "disabled";
+		};
+
+		uart2: uart@fc068000 {
+			compatible = "fsl,mcf-uart";
+			reg = <0xfc068000 0x40>;
+			status = "disabled";
+		};
+
+		dspi0: dspi@fc05c000 {
+			compatible = "fsl,mcf-dspi";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xfc05c000 0x100>;
+			spi-max-frequency = <50000000>;
+			num-cs = <4>;
+			spi-mode = <0>;
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/m68k/dts/mcf5307.dtsi b/arch/m68k/dts/mcf5307.dtsi
new file mode 100644
index 0000000..e199cf9
--- /dev/null
+++ b/arch/m68k/dts/mcf5307.dtsi
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/ {
+	compatible = "fsl,mcf5307";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		/* MBAR */
+		mbar: mbar@10000000 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x00000000 0x10000000 0x10000>;
+			reg = <0x10000000 0x10000>;
+
+			uart0: uart@1c0 {
+				compatible = "fsl,mcf-uart";
+				reg = <0x1c0 0x40>;
+				status = "disabled";
+			};
+
+			uart1: uart@200 {
+				compatible = "fsl,mcf-uart";
+				reg = <0x200 0x40>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/m68k/dts/mcf5329.dtsi b/arch/m68k/dts/mcf5329.dtsi
new file mode 100644
index 0000000..aeaa643
--- /dev/null
+++ b/arch/m68k/dts/mcf5329.dtsi
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/ {
+	compatible = "fsl,mcf5329";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		uart0: uart@fc060000 {
+			compatible = "fsl,mcf-uart";
+			reg = <0xfc060000 0x40>;
+			status = "disabled";
+		};
+
+		uart1: uart@fc064000 {
+			compatible = "fsl,mcf-uart";
+			reg = <0xfc064000 0x40>;
+			status = "disabled";
+		};
+
+		uart2: uart@fc068000 {
+			compatible = "fsl,mcf-uart";
+			reg = <0xfc068000 0x40>;
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/m68k/dts/mcf537x.dtsi b/arch/m68k/dts/mcf537x.dtsi
new file mode 100644
index 0000000..aeaa643
--- /dev/null
+++ b/arch/m68k/dts/mcf537x.dtsi
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/ {
+	compatible = "fsl,mcf5329";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		uart0: uart@fc060000 {
+			compatible = "fsl,mcf-uart";
+			reg = <0xfc060000 0x40>;
+			status = "disabled";
+		};
+
+		uart1: uart@fc064000 {
+			compatible = "fsl,mcf-uart";
+			reg = <0xfc064000 0x40>;
+			status = "disabled";
+		};
+
+		uart2: uart@fc068000 {
+			compatible = "fsl,mcf-uart";
+			reg = <0xfc068000 0x40>;
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/m68k/dts/mcf5441x.dtsi b/arch/m68k/dts/mcf5441x.dtsi
new file mode 100644
index 0000000..71b392a
--- /dev/null
+++ b/arch/m68k/dts/mcf5441x.dtsi
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/ {
+	compatible = "fsl,mcf5441x";
+
+	aliases {
+		serial0 = &uart0;
+		spi0 = &dspi0;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		uart0: uart@fc060000 {
+			compatible = "fsl,mcf-uart";
+			reg = <0xfc060000 0x40>;
+			status = "disabled";
+		};
+
+		uart1: uart@fc064000 {
+			compatible = "fsl,mcf-uart";
+			reg = <0xfc064000 0x40>;
+			status = "disabled";
+		};
+
+		uart2: uart@fc068000 {
+			compatible = "fsl,mcf-uart";
+			reg = <0xfc068000 0x40>;
+			status = "disabled";
+		};
+
+		uart3: uart@fc06c000 {
+			compatible = "fsl,mcf-uart";
+			reg = <0xfc06c000 0x40>;
+			status = "disabled";
+		};
+
+		dspi0: dspi@fc05c000 {
+			compatible = "fsl,mcf-dspi";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xfc05c000 0x100>;
+			spi-max-frequency = <50000000>;
+			num-cs = <4>;
+			spi-mode = <0>;
+			status = "disabled";
+		};
+
+		dspi1: dspi@fc03c000 {
+			compatible = "fsl,mcf-dspi";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xfc03c000 0x100>;
+			spi-max-frequency = <50000000>;
+			num-cs = <4>;
+			spi-mode = <0>;
+			status = "disabled";
+		};
+
+		dspi2: dspi@ec038000 {
+			compatible = "fsl,mcf-dspi";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xec038000 0x100>;
+			spi-max-frequency = <50000000>;
+			num-cs = <4>;
+			spi-mode = <0>;
+			status = "disabled";
+		};
+
+		dspi3: dspi@ec03c000 {
+			compatible = "fsl,mcf-dspi";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xec03c00 0x100>;
+			spi-max-frequency = <50000000>;
+			num-cs = <4>;
+			spi-mode = <0>;
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/m68k/dts/mcf5445x.dtsi b/arch/m68k/dts/mcf5445x.dtsi
new file mode 100644
index 0000000..ccbee29
--- /dev/null
+++ b/arch/m68k/dts/mcf5445x.dtsi
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/ {
+	compatible = "fsl,mcf5445x";
+
+	aliases {
+		serial0 = &uart0;
+		spi0 = &dspi0;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		uart0: uart@fc060000 {
+			compatible = "fsl,mcf-uart";
+			reg = <0xfc060000 0x40>;
+			status = "disabled";
+		};
+
+		uart1: uart@fc064000 {
+			compatible = "fsl,mcf-uart";
+			reg = <0xfc064000 0x40>;
+			status = "disabled";
+		};
+
+		uart2: uart@fc068000 {
+			compatible = "fsl,mcf-uart";
+			reg = <0xfc068000 0x40>;
+			status = "disabled";
+		};
+
+		dspi0: dspi@fc05c000 {
+			compatible = "fsl,mcf-dspi";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xfc05c000 0x100>;
+			spi-max-frequency = <50000000>;
+			num-cs = <4>;
+			spi-mode = <0>;
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/m68k/dts/mcf54xx.dtsi b/arch/m68k/dts/mcf54xx.dtsi
new file mode 100644
index 0000000..537bb42
--- /dev/null
+++ b/arch/m68k/dts/mcf54xx.dtsi
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/ {
+	compatible = "fsl,mcf54x5";
+
+	aliases {
+		/* TO DO, clarify on serial, this SoC seems to have SPC and
+		 * no UARTS.
+		 */
+		spi0 = &dspi0;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		mbar: mbar@80000000 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x00000000 0x80000000 0x10000>;
+			reg = <0x80000000 0x10000>;
+
+			dspi0: dspi@8a00 {
+				compatible = "fsl,mcf-dspi";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x8a00 0x100>;
+				spi-max-frequency = <50000000>;
+				num-cs = <4>;
+				spi-mode = <0>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/m68k/dts/stmark2.dts b/arch/m68k/dts/stmark2.dts
new file mode 100644
index 0000000..fd8ce4f
--- /dev/null
+++ b/arch/m68k/dts/stmark2.dts
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/dts-v1/;
+/include/ "mcf5441x.dtsi"
+
+/ {
+	model = "Sysam stmark2";
+	compatible = "sysam,stmark2";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&dspi0 {
+	spi-mode = <3>;
+	status = "okay";
+
+	flash: is25lp128@1 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spi-flash";
+		spi-max-frequency = <60000000>;
+		reg = <1>;
+	};
+};
diff --git a/arch/m68k/include/asm/coldfire/dspi.h b/arch/m68k/include/asm/coldfire/dspi.h
index afd5c79..ddd8f33 100644
--- a/arch/m68k/include/asm/coldfire/dspi.h
+++ b/arch/m68k/include/asm/coldfire/dspi.h
@@ -138,4 +138,8 @@
 /* Bit definitions and macros for DRFDR group */
 #define DSPI_RFDR_RXDATA(x)		(((x)&0x0000FFFF))
 
+/* Architecture-related operations */
+void dspi_chip_select(int cs);
+void dspi_chip_unselect(int cs);
+
 #endif				/* __DSPI_H__ */
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 9cf8e98..5cb9bdf 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -84,13 +84,13 @@
 	select DM_SERIAL
 	imply DM_SPI
 	imply DM_SPI_FLASH
-	select ARCH_MISC_INIT
 	select MIPS_TUNE_24KC
 	select OF_CONTROL
 	select ROM_EXCEPTION_VECTORS
 	select SUPPORTS_CPU_MIPS32_R1
 	select SUPPORTS_CPU_MIPS32_R2
 	select SUPPORTS_LITTLE_ENDIAN
+	select SYS_MALLOC_CLEAR_ON_INIT
 	select SYSRESET
 
 config ARCH_JZ47XX
diff --git a/arch/mips/mach-mtmips/cpu.c b/arch/mips/mach-mtmips/cpu.c
index fcd0484..b0a6397 100644
--- a/arch/mips/mach-mtmips/cpu.c
+++ b/arch/mips/mach-mtmips/cpu.c
@@ -68,18 +68,3 @@
 
 	return 0;
 }
-
-int arch_misc_init(void)
-{
-	/*
-	 * It has been noticed, that sometimes the d-cache is not in a
-	 * "clean-state" when U-Boot is running on MT7688. This was
-	 * detected when using the ethernet driver (which uses d-cache)
-	 * and a TFTP command does not complete. Flushing the complete
-	 * d-cache (again?) here seems to fix this issue.
-	 */
-	flush_dcache_range(gd->bd->bi_memstart,
-			   gd->bd->bi_memstart + gd->ram_size - 1);
-
-	return 0;
-}
diff --git a/arch/powerpc/cpu/mpc85xx/Kconfig b/arch/powerpc/cpu/mpc85xx/Kconfig
index 0057f19..aebf168 100644
--- a/arch/powerpc/cpu/mpc85xx/Kconfig
+++ b/arch/powerpc/cpu/mpc85xx/Kconfig
@@ -352,7 +352,6 @@
 	select PHYS_64BIT
 	select FSL_DDR_FIRST_SLOT_QUAD_CAPABLE
 	select FSL_DDR_INTERACTIVE
-	imply CMD_SATA
 
 config TARGET_T2080RDB
 	bool "Support T2080RDB"
@@ -361,6 +360,7 @@
 	select SUPPORT_SPL
 	select PHYS_64BIT
 	imply CMD_SATA
+	imply FSL_SATA
 	imply PANIC_HANG
 
 config TARGET_T2081QDS
@@ -1081,10 +1081,8 @@
 	select SYS_FSL_SEC_COMPAT_4
 	select SYS_PPC64
 	select FSL_IFC
-	imply CMD_SATA
 	imply CMD_NAND
 	imply CMD_REGINFO
-	imply FSL_SATA
 
 config ARCH_T2081
 	bool
diff --git a/arch/powerpc/dts/t2080.dtsi b/arch/powerpc/dts/t2080.dtsi
index db65ea5..d2bebb0 100644
--- a/arch/powerpc/dts/t2080.dtsi
+++ b/arch/powerpc/dts/t2080.dtsi
@@ -58,5 +58,50 @@
 			device_type = "open-pic";
 			clock-frequency = <0x0>;
 		};
+
+		esdhc: esdhc@114000 {
+			compatible = "fsl,esdhc";
+			reg = <0x114000 0x1000>;
+			interrupts = <48 2 0 0>;
+			clock-frequency = <0>;
+			sdhci,auto-cmd12;
+			bus-width = <4>;
+			voltage-ranges = <1800 1800 3300 3300>;
+		};
+
+		usb0: usb@210000 {
+			compatible = "fsl-usb2-mph";
+			reg = <0x210000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <44 0x2 0 0>;
+			phy_type = "utmi";
+		};
+
+		usb1: usb@211000 {
+			compatible = "fsl-usb2-dr";
+			reg = <0x211000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <45 0x2 0 0>;
+			dr_mode = "host";
+			phy_type = "utmi";
+		};
+
+		sata0: sata@220000 {
+			compatible = "fsl,pq-sata-v2";
+			reg = <0x220000 0x1000>;
+			interrupts = <68 0x2 0 0>;
+			sata-number = <0x0>;
+			sata-fpdma = <0x0>;
+		};
+
+		sata1: sata@221000 {
+			compatible = "fsl,pq-sata-v2";
+			reg = <0x221000 0x1000>;
+			interrupts = <69 0x2 0 0>;
+			sata-number = <0x0>;
+			sata-fpdma = <0x0>;
+		};
 	};
 };
diff --git a/board/st/stm32mp1/board.c b/board/st/stm32mp1/board.c
index 5c1acca..c3d832f 100644
--- a/board/st/stm32mp1/board.c
+++ b/board/st/stm32mp1/board.c
@@ -38,9 +38,10 @@
 #endif
 
 #ifdef CONFIG_PMIC_STPMIC1
-int board_ddr_power_init(void)
+int board_ddr_power_init(enum ddr_type ddr_type)
 {
 	struct udevice *dev;
+	bool buck3_at_1800000v = false;
 	int ret;
 
 	ret = uclass_get_device_by_driver(UCLASS_PMIC,
@@ -49,53 +50,127 @@
 		/* No PMIC on board */
 		return 0;
 
-	/* VTT = Set LDO3 to sync mode */
-	ret = pmic_reg_read(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3));
-	if (ret < 0)
-		return ret;
+	switch (ddr_type) {
+	case STM32MP_DDR3:
+		/* VTT = Set LDO3 to sync mode */
+		ret = pmic_reg_read(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3));
+		if (ret < 0)
+			return ret;
 
-	ret &= ~STPMIC1_LDO3_MODE;
-	ret &= ~STPMIC1_LDO12356_VOUT_MASK;
-	ret |= STPMIC1_LDO_VOUT(STPMIC1_LDO3_DDR_SEL);
+		ret &= ~STPMIC1_LDO3_MODE;
+		ret &= ~STPMIC1_LDO12356_VOUT_MASK;
+		ret |= STPMIC1_LDO_VOUT(STPMIC1_LDO3_DDR_SEL);
 
-	ret = pmic_reg_write(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3),
-			     ret);
-	if (ret < 0)
-		return ret;
+		ret = pmic_reg_write(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3),
+				     ret);
+		if (ret < 0)
+			return ret;
 
-	/* VDD_DDR = Set BUCK2 to 1.35V */
-	ret = pmic_clrsetbits(dev,
-			      STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK2),
-			      STPMIC1_BUCK_VOUT_MASK,
-			      STPMIC1_BUCK2_1350000V);
-	if (ret < 0)
-		return ret;
+		/* VDD_DDR = Set BUCK2 to 1.35V */
+		ret = pmic_clrsetbits(dev,
+				      STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK2),
+				      STPMIC1_BUCK_VOUT_MASK,
+				      STPMIC1_BUCK2_1350000V);
+		if (ret < 0)
+			return ret;
 
-	/* Enable VDD_DDR = BUCK2 */
-	ret = pmic_clrsetbits(dev,
-			      STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK2),
-			      STPMIC1_BUCK_ENA, STPMIC1_BUCK_ENA);
-	if (ret < 0)
-		return ret;
+		/* Enable VDD_DDR = BUCK2 */
+		ret = pmic_clrsetbits(dev,
+				      STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK2),
+				      STPMIC1_BUCK_ENA, STPMIC1_BUCK_ENA);
+		if (ret < 0)
+			return ret;
 
-	mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
+		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
 
-	/* Enable VREF */
-	ret = pmic_clrsetbits(dev, STPMIC1_REFDDR_MAIN_CR,
-			      STPMIC1_VREF_ENA, STPMIC1_VREF_ENA);
-	if (ret < 0)
-		return ret;
+		/* Enable VREF */
+		ret = pmic_clrsetbits(dev, STPMIC1_REFDDR_MAIN_CR,
+				      STPMIC1_VREF_ENA, STPMIC1_VREF_ENA);
+		if (ret < 0)
+			return ret;
 
-	mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
+		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
 
-	/* Enable LDO3 */
-	ret = pmic_clrsetbits(dev,
-			      STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3),
-			      STPMIC1_LDO_ENA, STPMIC1_LDO_ENA);
-	if (ret < 0)
-		return ret;
+		/* Enable VTT = LDO3 */
+		ret = pmic_clrsetbits(dev,
+				      STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3),
+				      STPMIC1_LDO_ENA, STPMIC1_LDO_ENA);
+		if (ret < 0)
+			return ret;
+
+		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
+
+		break;
+
+	case STM32MP_LPDDR2:
+	case STM32MP_LPDDR3:
+		/*
+		 * configure VDD_DDR1 = LDO3
+		 * Set LDO3 to 1.8V
+		 * + bypass mode if BUCK3 = 1.8V
+		 * + normal mode if BUCK3 != 1.8V
+		 */
+		ret = pmic_reg_read(dev,
+				    STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK3));
+		if (ret < 0)
+			return ret;
+
+		if ((ret & STPMIC1_BUCK3_1800000V) == STPMIC1_BUCK3_1800000V)
+			buck3_at_1800000v = true;
+
+		ret = pmic_reg_read(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3));
+		if (ret < 0)
+			return ret;
+
+		ret &= ~STPMIC1_LDO3_MODE;
+		ret &= ~STPMIC1_LDO12356_VOUT_MASK;
+		ret |= STPMIC1_LDO3_1800000;
+		if (buck3_at_1800000v)
+			ret |= STPMIC1_LDO3_MODE;
+
+		ret = pmic_reg_write(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3),
+				     ret);
+		if (ret < 0)
+			return ret;
+
+		/* VDD_DDR2 : Set BUCK2 to 1.2V */
+		ret = pmic_clrsetbits(dev,
+				      STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK2),
+				      STPMIC1_BUCK_VOUT_MASK,
+				      STPMIC1_BUCK2_1200000V);
+		if (ret < 0)
+			return ret;
+
+		/* Enable VDD_DDR1 = LDO3 */
+		ret = pmic_clrsetbits(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3),
+				      STPMIC1_LDO_ENA, STPMIC1_LDO_ENA);
+		if (ret < 0)
+			return ret;
+
+		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
+
+		/* Enable VDD_DDR2 =BUCK2 */
+		ret = pmic_clrsetbits(dev,
+				      STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK2),
+				      STPMIC1_BUCK_ENA, STPMIC1_BUCK_ENA);
+		if (ret < 0)
+			return ret;
+
+		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
+
+		/* Enable VREF */
+		ret = pmic_clrsetbits(dev, STPMIC1_REFDDR_MAIN_CR,
+				      STPMIC1_VREF_ENA, STPMIC1_VREF_ENA);
+		if (ret < 0)
+			return ret;
+
+		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
+
+		break;
 
-	mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
+	default:
+		break;
+	};
 
 	return 0;
 }
diff --git a/common/Kconfig b/common/Kconfig
index 1a1951f..c759952 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -247,6 +247,7 @@
 config PREBOOT
 	string "preboot default value"
 	depends on USE_PREBOOT
+	default ""
 	help
 	  This is the default of "preboot" environment variable.
 
diff --git a/common/Makefile b/common/Makefile
index 8c92feb..c7e41ef 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -124,6 +124,7 @@
 
 obj-y += cli.o
 obj-$(CONFIG_FSL_DDR_INTERACTIVE) += cli_simple.o cli_readline.o
+obj-$(CONFIG_STM32MP1_DDR_INTERACTIVE) += cli_simple.o cli_readline.o
 obj-$(CONFIG_DFU_OVER_USB) += dfu.o
 obj-y += command.o
 obj-$(CONFIG_$(SPL_TPL_)LOG) += log.o
diff --git a/configs/M5208EVBE_defconfig b/configs/M5208EVBE_defconfig
index 934cda4..01b2c97 100644
--- a/configs/M5208EVBE_defconfig
+++ b/configs/M5208EVBE_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0x0
 CONFIG_TARGET_M5208EVBE=y
+CONFIG_DEFAULT_DEVICE_TREE="M5208EVBE"
 CONFIG_BOOTDELAY=1
 # CONFIG_DISPLAY_BOARDINFO is not set
 # CONFIG_CMDLINE_EDITING is not set
diff --git a/configs/M52277EVB_defconfig b/configs/M52277EVB_defconfig
index efa5e71..bc7b051 100644
--- a/configs/M52277EVB_defconfig
+++ b/configs/M52277EVB_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0x0
 CONFIG_TARGET_M52277EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M52277EVB"
 CONFIG_SYS_EXTRA_OPTIONS="SYS_SPANSION_BOOT"
 CONFIG_BOOTDELAY=3
 # CONFIG_DISPLAY_BOARDINFO is not set
@@ -25,4 +26,5 @@
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_SPI=y
+CONFIG_DM_SPI=y
 CONFIG_CF_SPI=y
diff --git a/configs/M52277EVB_stmicro_defconfig b/configs/M52277EVB_stmicro_defconfig
index cafc861..d417be6 100644
--- a/configs/M52277EVB_stmicro_defconfig
+++ b/configs/M52277EVB_stmicro_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0x43E00000
 CONFIG_TARGET_M52277EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M52277EVB_stmicro"
 CONFIG_SYS_EXTRA_OPTIONS="CF_SBF,SYS_STMICRO_BOOT"
 CONFIG_BOOTDELAY=3
 # CONFIG_DISPLAY_BOARDINFO is not set
@@ -26,4 +27,5 @@
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_SPI=y
+CONFIG_DM_SPI=y
 CONFIG_CF_SPI=y
diff --git a/configs/M5235EVB_Flash32_defconfig b/configs/M5235EVB_Flash32_defconfig
index fff5743..aef8281 100644
--- a/configs/M5235EVB_Flash32_defconfig
+++ b/configs/M5235EVB_Flash32_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0xFFC00000
 CONFIG_TARGET_M5235EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M5235EVB_Flash32"
 CONFIG_SYS_EXTRA_OPTIONS="NORFLASH_PS32BIT"
 CONFIG_BOOTDELAY=1
 # CONFIG_DISPLAY_BOARDINFO is not set
diff --git a/configs/M5235EVB_defconfig b/configs/M5235EVB_defconfig
index 07e0f4f..efc0317 100644
--- a/configs/M5235EVB_defconfig
+++ b/configs/M5235EVB_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0xFFE00000
 CONFIG_TARGET_M5235EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M5235EVB"
 CONFIG_BOOTDELAY=1
 # CONFIG_DISPLAY_BOARDINFO is not set
 # CONFIG_CMDLINE_EDITING is not set
diff --git a/configs/M5249EVB_defconfig b/configs/M5249EVB_defconfig
index 908f6a1..3f76665 100644
--- a/configs/M5249EVB_defconfig
+++ b/configs/M5249EVB_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0xFFE00000
 CONFIG_TARGET_M5249EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M5249EVB"
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 # CONFIG_DISPLAY_BOARDINFO is not set
 # CONFIG_CMDLINE_EDITING is not set
diff --git a/configs/M5253DEMO_defconfig b/configs/M5253DEMO_defconfig
index 4685c4e..2dbbd22 100644
--- a/configs/M5253DEMO_defconfig
+++ b/configs/M5253DEMO_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0xFF800000
 CONFIG_TARGET_M5253DEMO=y
+CONFIG_DEFAULT_DEVICE_TREE="M5253DEMO"
 CONFIG_BOOTDELAY=5
 # CONFIG_DISPLAY_BOARDINFO is not set
 # CONFIG_CMDLINE_EDITING is not set
diff --git a/configs/M5272C3_defconfig b/configs/M5272C3_defconfig
index 85283d4..dc4d045 100644
--- a/configs/M5272C3_defconfig
+++ b/configs/M5272C3_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0xFFE00000
 CONFIG_TARGET_M5272C3=y
+CONFIG_DEFAULT_DEVICE_TREE="M5272C3"
 CONFIG_BOOTDELAY=5
 # CONFIG_DISPLAY_BOARDINFO is not set
 # CONFIG_CMDLINE_EDITING is not set
diff --git a/configs/M5275EVB_defconfig b/configs/M5275EVB_defconfig
index 5ff2624..2e1f60c 100644
--- a/configs/M5275EVB_defconfig
+++ b/configs/M5275EVB_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0xFFE00000
 CONFIG_TARGET_M5275EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M5275EVB"
 CONFIG_BOOTDELAY=5
 # CONFIG_DISPLAY_BOARDINFO is not set
 # CONFIG_CMDLINE_EDITING is not set
diff --git a/configs/M5282EVB_defconfig b/configs/M5282EVB_defconfig
index 289922b..f904d90 100644
--- a/configs/M5282EVB_defconfig
+++ b/configs/M5282EVB_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0xFFE00000
 CONFIG_TARGET_M5282EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M5282EVB"
 CONFIG_BOOTDELAY=5
 # CONFIG_DISPLAY_BOARDINFO is not set
 # CONFIG_CMDLINE_EDITING is not set
diff --git a/configs/M53017EVB_defconfig b/configs/M53017EVB_defconfig
index 0b1073a..9eef96d 100644
--- a/configs/M53017EVB_defconfig
+++ b/configs/M53017EVB_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0x0
 CONFIG_TARGET_M53017EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M53017EVB"
 CONFIG_BOOTDELAY=1
 CONFIG_USE_BOOTARGS=y
 CONFIG_BOOTARGS="root=/dev/mtdblock3 rw rootfstype=jffs2"
diff --git a/configs/M5329AFEE_defconfig b/configs/M5329AFEE_defconfig
index c6dff0e..6899ac1 100644
--- a/configs/M5329AFEE_defconfig
+++ b/configs/M5329AFEE_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0x0
 CONFIG_TARGET_M5329EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M5329AFEE"
 CONFIG_SYS_EXTRA_OPTIONS="NANDFLASH_SIZE=0"
 CONFIG_BOOTDELAY=1
 # CONFIG_DISPLAY_BOARDINFO is not set
diff --git a/configs/M5329BFEE_defconfig b/configs/M5329BFEE_defconfig
index 56dba26..16777c1 100644
--- a/configs/M5329BFEE_defconfig
+++ b/configs/M5329BFEE_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0x0
 CONFIG_TARGET_M5329EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M5329BFEE"
 CONFIG_SYS_EXTRA_OPTIONS="NANDFLASH_SIZE=16"
 CONFIG_BOOTDELAY=1
 # CONFIG_DISPLAY_BOARDINFO is not set
diff --git a/configs/M5373EVB_defconfig b/configs/M5373EVB_defconfig
index 3982320..95cf43a 100644
--- a/configs/M5373EVB_defconfig
+++ b/configs/M5373EVB_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0x0
 CONFIG_TARGET_M5373EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M5373EVB"
 CONFIG_SYS_EXTRA_OPTIONS="NANDFLASH_SIZE=16"
 CONFIG_BOOTDELAY=1
 # CONFIG_DISPLAY_BOARDINFO is not set
diff --git a/configs/M54418TWR_defconfig b/configs/M54418TWR_defconfig
index a239f4a..da5feb5 100644
--- a/configs/M54418TWR_defconfig
+++ b/configs/M54418TWR_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0x47E00000
 CONFIG_TARGET_M54418TWR=y
+CONFIG_DEFAULT_DEVICE_TREE="M54418TWR"
 CONFIG_SYS_EXTRA_OPTIONS="CF_SBF,SYS_SERIAL_BOOT,SYS_INPUT_CLKSRC=50000000"
 CONFIG_USE_BOOTARGS=y
 CONFIG_BOOTARGS="root=/dev/nfs rw nfsroot=192.168.1.1:/tftpboot/192.168.1.2  ip=192.168.1.2:192.168.1.1:192.168.1.1: 255.255.255.0::eth0:off:rw console=ttyS0,115200"
@@ -27,3 +28,4 @@
 CONFIG_MII=y
 CONFIG_SPI=y
 CONFIG_CF_SPI=y
+CONFIG_DM_SPI=y
diff --git a/configs/M54418TWR_nand_mii_defconfig b/configs/M54418TWR_nand_mii_defconfig
index 04ca3a8..1c2d337 100644
--- a/configs/M54418TWR_nand_mii_defconfig
+++ b/configs/M54418TWR_nand_mii_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0x47E00000
 CONFIG_TARGET_M54418TWR=y
+CONFIG_DEFAULT_DEVICE_TREE="M54418TWR_nand_mii"
 CONFIG_SYS_EXTRA_OPTIONS="SYS_NAND_BOOT,SYS_INPUT_CLKSRC=25000000"
 CONFIG_USE_BOOTARGS=y
 CONFIG_BOOTARGS="root=/dev/mtdblock2 rw rootfstype=jffs2 mtdparts=NAND:1M(u-boot)ro,7M(kernel)ro,-(jffs2) console=ttyS0,115200"
@@ -23,4 +24,5 @@
 CONFIG_SPI_FLASH_ATMEL=y
 CONFIG_MII=y
 CONFIG_SPI=y
+CONFIG_DM_SPI=y
 CONFIG_CF_SPI=y
diff --git a/configs/M54418TWR_nand_rmii_defconfig b/configs/M54418TWR_nand_rmii_defconfig
index f6acf60..29d891b 100644
--- a/configs/M54418TWR_nand_rmii_defconfig
+++ b/configs/M54418TWR_nand_rmii_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0x47E00000
 CONFIG_TARGET_M54418TWR=y
+CONFIG_DEFAULT_DEVICE_TREE="M54418TWR_nand_rmii"
 CONFIG_SYS_EXTRA_OPTIONS="SYS_NAND_BOOT,SYS_INPUT_CLKSRC=50000000"
 CONFIG_USE_BOOTARGS=y
 CONFIG_BOOTARGS="root=/dev/mtdblock2 rw rootfstype=jffs2 mtdparts=NAND:1M(u-boot)ro,7M(kernel)ro,-(jffs2) console=ttyS0,115200"
@@ -23,4 +24,5 @@
 CONFIG_SPI_FLASH_ATMEL=y
 CONFIG_MII=y
 CONFIG_SPI=y
+CONFIG_DM_SPI=y
 CONFIG_CF_SPI=y
diff --git a/configs/M54418TWR_nand_rmii_lowfreq_defconfig b/configs/M54418TWR_nand_rmii_lowfreq_defconfig
index 6b631d6..4881076 100644
--- a/configs/M54418TWR_nand_rmii_lowfreq_defconfig
+++ b/configs/M54418TWR_nand_rmii_lowfreq_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0x47E00000
 CONFIG_TARGET_M54418TWR=y
+CONFIG_DEFAULT_DEVICE_TREE="M54418TWR_nand_rmii_lowfreq"
 CONFIG_SYS_EXTRA_OPTIONS="SYS_NAND_BOOT,LOW_MCFCLK,SYS_INPUT_CLKSRC=50000000"
 CONFIG_USE_BOOTARGS=y
 CONFIG_BOOTARGS="root=/dev/mtdblock2 rw rootfstype=jffs2 mtdparts=NAND:1M(u-boot)ro,7M(kernel)ro,-(jffs2) console=ttyS0,115200"
@@ -23,4 +24,5 @@
 CONFIG_SPI_FLASH_ATMEL=y
 CONFIG_MII=y
 CONFIG_SPI=y
+CONFIG_DM_SPI=y
 CONFIG_CF_SPI=y
diff --git a/configs/M54418TWR_serial_mii_defconfig b/configs/M54418TWR_serial_mii_defconfig
index 8b72bd3..476e9ee 100644
--- a/configs/M54418TWR_serial_mii_defconfig
+++ b/configs/M54418TWR_serial_mii_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0x47E00000
 CONFIG_TARGET_M54418TWR=y
+CONFIG_DEFAULT_DEVICE_TREE="M54418TWR_serial_mii"
 CONFIG_SYS_EXTRA_OPTIONS="CF_SBF,SYS_SERIAL_BOOT,SYS_INPUT_CLKSRC=25000000"
 CONFIG_USE_BOOTARGS=y
 CONFIG_BOOTARGS="root=/dev/nfs rw nfsroot=192.168.1.1:/tftpboot/192.168.1.2  ip=192.168.1.2:192.168.1.1:192.168.1.1: 255.255.255.0::eth0:off:rw console=ttyS0,115200"
@@ -26,4 +27,5 @@
 CONFIG_SPI_FLASH_ATMEL=y
 CONFIG_MII=y
 CONFIG_SPI=y
+CONFIG_DM_SPI=y
 CONFIG_CF_SPI=y
diff --git a/configs/M54418TWR_serial_rmii_defconfig b/configs/M54418TWR_serial_rmii_defconfig
index a239f4a..5209157 100644
--- a/configs/M54418TWR_serial_rmii_defconfig
+++ b/configs/M54418TWR_serial_rmii_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0x47E00000
 CONFIG_TARGET_M54418TWR=y
+CONFIG_DEFAULT_DEVICE_TREE="M54418TWR_serial_rmii"
 CONFIG_SYS_EXTRA_OPTIONS="CF_SBF,SYS_SERIAL_BOOT,SYS_INPUT_CLKSRC=50000000"
 CONFIG_USE_BOOTARGS=y
 CONFIG_BOOTARGS="root=/dev/nfs rw nfsroot=192.168.1.1:/tftpboot/192.168.1.2  ip=192.168.1.2:192.168.1.1:192.168.1.1: 255.255.255.0::eth0:off:rw console=ttyS0,115200"
@@ -26,4 +27,5 @@
 CONFIG_SPI_FLASH_ATMEL=y
 CONFIG_MII=y
 CONFIG_SPI=y
+CONFIG_DM_SPI=y
 CONFIG_CF_SPI=y
diff --git a/configs/M54451EVB_defconfig b/configs/M54451EVB_defconfig
index 8448b6c..c85b476 100644
--- a/configs/M54451EVB_defconfig
+++ b/configs/M54451EVB_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0x0
 CONFIG_TARGET_M54451EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M54451EVB"
 CONFIG_SYS_EXTRA_OPTIONS="SYS_INPUT_CLKSRC=24000000"
 CONFIG_BOOTDELAY=1
 CONFIG_USE_BOOTARGS=y
@@ -30,4 +31,5 @@
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_MII=y
 CONFIG_SPI=y
+CONFIG_DM_SPI=y
 CONFIG_CF_SPI=y
diff --git a/configs/M54451EVB_stmicro_defconfig b/configs/M54451EVB_stmicro_defconfig
index b614ca7..a26e2d0 100644
--- a/configs/M54451EVB_stmicro_defconfig
+++ b/configs/M54451EVB_stmicro_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0x47E00000
 CONFIG_TARGET_M54451EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M54451EVB_stmicro"
 CONFIG_SYS_EXTRA_OPTIONS="CF_SBF,SYS_STMICRO_BOOT,SYS_INPUT_CLKSRC=24000000"
 CONFIG_BOOTDELAY=1
 CONFIG_USE_BOOTARGS=y
@@ -31,4 +32,5 @@
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_MII=y
 CONFIG_SPI=y
+CONFIG_DM_SPI=y
 CONFIG_CF_SPI=y
diff --git a/configs/M54455EVB_a66_defconfig b/configs/M54455EVB_a66_defconfig
index f9be1c3..9cfd1f8 100644
--- a/configs/M54455EVB_a66_defconfig
+++ b/configs/M54455EVB_a66_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0x4000000
 CONFIG_TARGET_M54455EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M54455EVB_a66"
 CONFIG_SYS_EXTRA_OPTIONS="SYS_ATMEL_BOOT,SYS_INPUT_CLKSRC=66666666"
 CONFIG_BOOTDELAY=1
 CONFIG_USE_BOOTARGS=y
@@ -34,4 +35,5 @@
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_MII=y
 CONFIG_SPI=y
+CONFIG_DM_SPI=y
 CONFIG_CF_SPI=y
diff --git a/configs/M54455EVB_defconfig b/configs/M54455EVB_defconfig
index abb69a9..8d0f9bf 100644
--- a/configs/M54455EVB_defconfig
+++ b/configs/M54455EVB_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0x4000000
 CONFIG_TARGET_M54455EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M54455EVB"
 CONFIG_SYS_EXTRA_OPTIONS="SYS_ATMEL_BOOT,SYS_INPUT_CLKSRC=33333333"
 CONFIG_BOOTDELAY=1
 CONFIG_USE_BOOTARGS=y
@@ -35,4 +36,5 @@
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_MII=y
 CONFIG_SPI=y
+CONFIG_DM_SPI=y
 CONFIG_CF_SPI=y
diff --git a/configs/M54455EVB_i66_defconfig b/configs/M54455EVB_i66_defconfig
index 6050df5..d47a20a 100644
--- a/configs/M54455EVB_i66_defconfig
+++ b/configs/M54455EVB_i66_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0x0
 CONFIG_TARGET_M54455EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M54455EVB_i66"
 CONFIG_SYS_EXTRA_OPTIONS="SYS_INTEL_BOOT,SYS_INPUT_CLKSRC=66666666"
 CONFIG_BOOTDELAY=1
 CONFIG_USE_BOOTARGS=y
@@ -34,4 +35,5 @@
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_MII=y
 CONFIG_SPI=y
+CONFIG_DM_SPI=y
 CONFIG_CF_SPI=y
diff --git a/configs/M54455EVB_intel_defconfig b/configs/M54455EVB_intel_defconfig
index 686c00e..b90dad7 100644
--- a/configs/M54455EVB_intel_defconfig
+++ b/configs/M54455EVB_intel_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0x0
 CONFIG_TARGET_M54455EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M54455EVB_intel"
 CONFIG_SYS_EXTRA_OPTIONS="SYS_INTEL_BOOT,SYS_INPUT_CLKSRC=33333333"
 CONFIG_BOOTDELAY=1
 CONFIG_USE_BOOTARGS=y
@@ -34,4 +35,5 @@
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_MII=y
 CONFIG_SPI=y
+CONFIG_DM_SPI=y
 CONFIG_CF_SPI=y
diff --git a/configs/M54455EVB_stm33_defconfig b/configs/M54455EVB_stm33_defconfig
index 467bfae..a39fda6 100644
--- a/configs/M54455EVB_stm33_defconfig
+++ b/configs/M54455EVB_stm33_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0x4FE00000
 CONFIG_TARGET_M54455EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M54455EVB_stm33"
 CONFIG_SYS_EXTRA_OPTIONS="SYS_STMICRO_BOOT,CF_SBF,SYS_INPUT_CLKSRC=33333333"
 CONFIG_BOOTDELAY=1
 CONFIG_USE_BOOTARGS=y
@@ -36,4 +37,5 @@
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_MII=y
 CONFIG_SPI=y
+CONFIG_DM_SPI=y
 CONFIG_CF_SPI=y
diff --git a/configs/M5475AFE_defconfig b/configs/M5475AFE_defconfig
index b0296ac..71e78fd 100644
--- a/configs/M5475AFE_defconfig
+++ b/configs/M5475AFE_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0xFF800000
 CONFIG_TARGET_M5475EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M5475AFE"
 CONFIG_SYS_EXTRA_OPTIONS="SYS_BUSCLK=133333333,SYS_BOOTSZ=2,SYS_DRAMSZ=64"
 CONFIG_BOOTDELAY=1
 # CONFIG_CMDLINE_EDITING is not set
diff --git a/configs/M5475BFE_defconfig b/configs/M5475BFE_defconfig
index 7fc61bd..9db3d28 100644
--- a/configs/M5475BFE_defconfig
+++ b/configs/M5475BFE_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0xFF800000
 CONFIG_TARGET_M5475EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M5475BFE"
 CONFIG_SYS_EXTRA_OPTIONS="SYS_BUSCLK=133333333,SYS_BOOTSZ=2,SYS_DRAMSZ=64,SYS_NOR1SZ=16"
 CONFIG_BOOTDELAY=1
 # CONFIG_CMDLINE_EDITING is not set
diff --git a/configs/M5475CFE_defconfig b/configs/M5475CFE_defconfig
index 22d1074..4069d59 100644
--- a/configs/M5475CFE_defconfig
+++ b/configs/M5475CFE_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0xFF800000
 CONFIG_TARGET_M5475EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M5475CFE"
 CONFIG_SYS_EXTRA_OPTIONS="SYS_BUSCLK=133333333,SYS_BOOTSZ=2,SYS_DRAMSZ=64,SYS_NOR1SZ=16,SYS_VIDEO,SYS_USBCTRL"
 CONFIG_BOOTDELAY=1
 # CONFIG_CMDLINE_EDITING is not set
diff --git a/configs/M5475DFE_defconfig b/configs/M5475DFE_defconfig
index ee8c2ab..fb5ecbb 100644
--- a/configs/M5475DFE_defconfig
+++ b/configs/M5475DFE_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0xFF800000
 CONFIG_TARGET_M5475EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M5475DFE"
 CONFIG_SYS_EXTRA_OPTIONS="SYS_BUSCLK=133333333,SYS_BOOTSZ=2,SYS_DRAMSZ=64,SYS_USBCTRL"
 CONFIG_BOOTDELAY=1
 # CONFIG_CMDLINE_EDITING is not set
diff --git a/configs/M5475EFE_defconfig b/configs/M5475EFE_defconfig
index 939e56b..45d6f23 100644
--- a/configs/M5475EFE_defconfig
+++ b/configs/M5475EFE_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0xFF800000
 CONFIG_TARGET_M5475EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M5475EFE"
 CONFIG_SYS_EXTRA_OPTIONS="SYS_BUSCLK=133333333,SYS_BOOTSZ=2,SYS_DRAMSZ=64,SYS_VIDEO,SYS_USBCTRL"
 CONFIG_BOOTDELAY=1
 # CONFIG_CMDLINE_EDITING is not set
diff --git a/configs/M5475FFE_defconfig b/configs/M5475FFE_defconfig
index 1fef8ff..43d5c96 100644
--- a/configs/M5475FFE_defconfig
+++ b/configs/M5475FFE_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0xFF800000
 CONFIG_TARGET_M5475EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M5475FFE"
 CONFIG_SYS_EXTRA_OPTIONS="SYS_BUSCLK=133333333,SYS_BOOTSZ=2,SYS_DRAMSZ=64,SYS_NOR1SZ=32,SYS_VIDEO,SYS_USBCTRL,SYS_DRAMSZ1=64"
 CONFIG_BOOTDELAY=1
 # CONFIG_CMDLINE_EDITING is not set
diff --git a/configs/M5475GFE_defconfig b/configs/M5475GFE_defconfig
index d78caff..11ea9cd 100644
--- a/configs/M5475GFE_defconfig
+++ b/configs/M5475GFE_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0xFF800000
 CONFIG_TARGET_M5475EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M5475GFE"
 CONFIG_SYS_EXTRA_OPTIONS="SYS_BUSCLK=133333333,SYS_BOOTSZ=4,SYS_DRAMSZ=64"
 CONFIG_BOOTDELAY=1
 # CONFIG_CMDLINE_EDITING is not set
diff --git a/configs/M5485AFE_defconfig b/configs/M5485AFE_defconfig
index 5cda25a..8f9aaa9 100644
--- a/configs/M5485AFE_defconfig
+++ b/configs/M5485AFE_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0xFF800000
 CONFIG_TARGET_M5485EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M5485AFE"
 CONFIG_SYS_EXTRA_OPTIONS="SYS_BUSCLK=100000000,SYS_BOOTSZ=2,SYS_DRAMSZ=64"
 CONFIG_BOOTDELAY=1
 # CONFIG_CMDLINE_EDITING is not set
diff --git a/configs/M5485BFE_defconfig b/configs/M5485BFE_defconfig
index 7cd4a53..ce26bed 100644
--- a/configs/M5485BFE_defconfig
+++ b/configs/M5485BFE_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0xFF800000
 CONFIG_TARGET_M5485EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M5485BFE"
 CONFIG_SYS_EXTRA_OPTIONS="SYS_BUSCLK=100000000,SYS_BOOTSZ=2,SYS_DRAMSZ=64,SYS_NOR1SZ=16"
 CONFIG_BOOTDELAY=1
 # CONFIG_CMDLINE_EDITING is not set
diff --git a/configs/M5485CFE_defconfig b/configs/M5485CFE_defconfig
index ff5e8ef..47b2732 100644
--- a/configs/M5485CFE_defconfig
+++ b/configs/M5485CFE_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0xFF800000
 CONFIG_TARGET_M5485EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M5485CFE"
 CONFIG_SYS_EXTRA_OPTIONS="SYS_BUSCLK=100000000,SYS_BOOTSZ=2,SYS_DRAMSZ=64,SYS_NOR1SZ=16,SYS_VIDEO,SYS_USBCTRL"
 CONFIG_BOOTDELAY=1
 # CONFIG_CMDLINE_EDITING is not set
diff --git a/configs/M5485DFE_defconfig b/configs/M5485DFE_defconfig
index c4dd6c3..eb0d19b 100644
--- a/configs/M5485DFE_defconfig
+++ b/configs/M5485DFE_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0xFF800000
 CONFIG_TARGET_M5485EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M5485DFE"
 CONFIG_SYS_EXTRA_OPTIONS="SYS_BUSCLK=100000000,SYS_BOOTSZ=2,SYS_DRAMSZ=64,SYS_USBCTRL"
 CONFIG_BOOTDELAY=1
 # CONFIG_CMDLINE_EDITING is not set
diff --git a/configs/M5485EFE_defconfig b/configs/M5485EFE_defconfig
index 4e84828..9504b26 100644
--- a/configs/M5485EFE_defconfig
+++ b/configs/M5485EFE_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0xFF800000
 CONFIG_TARGET_M5485EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M5485EFE"
 CONFIG_SYS_EXTRA_OPTIONS="SYS_BUSCLK=100000000,SYS_BOOTSZ=2,SYS_DRAMSZ=64,SYS_VIDEO,SYS_USBCTRL"
 CONFIG_BOOTDELAY=1
 # CONFIG_CMDLINE_EDITING is not set
diff --git a/configs/M5485FFE_defconfig b/configs/M5485FFE_defconfig
index f6264e8..f2bc3a0 100644
--- a/configs/M5485FFE_defconfig
+++ b/configs/M5485FFE_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0xFF800000
 CONFIG_TARGET_M5485EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M5485FFE"
 CONFIG_SYS_EXTRA_OPTIONS="SYS_BUSCLK=100000000,SYS_BOOTSZ=2,SYS_DRAMSZ=64,SYS_NOR1SZ=32,SYS_VIDEO,SYS_USBCTRL,SYS_DRAMSZ1=64"
 CONFIG_BOOTDELAY=1
 # CONFIG_CMDLINE_EDITING is not set
diff --git a/configs/M5485GFE_defconfig b/configs/M5485GFE_defconfig
index 9a589e0..43ddd41 100644
--- a/configs/M5485GFE_defconfig
+++ b/configs/M5485GFE_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0xFF800000
 CONFIG_TARGET_M5485EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M5485GFE"
 CONFIG_SYS_EXTRA_OPTIONS="SYS_BUSCLK=100000000,SYS_BOOTSZ=4,SYS_DRAMSZ=64"
 CONFIG_BOOTDELAY=1
 # CONFIG_CMDLINE_EDITING is not set
diff --git a/configs/M5485HFE_defconfig b/configs/M5485HFE_defconfig
index edc50c8..820d5aa 100644
--- a/configs/M5485HFE_defconfig
+++ b/configs/M5485HFE_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0xFF800000
 CONFIG_TARGET_M5485EVB=y
+CONFIG_DEFAULT_DEVICE_TREE="M5485HFE"
 CONFIG_SYS_EXTRA_OPTIONS="SYS_BUSCLK=100000000,SYS_BOOTSZ=2,SYS_DRAMSZ=64,SYS_NOR1SZ=16,SYS_VIDEO"
 CONFIG_BOOTDELAY=1
 # CONFIG_CMDLINE_EDITING is not set
diff --git a/configs/T2080QDS_NAND_defconfig b/configs/T2080QDS_NAND_defconfig
index 4c39f66..4a8ec11 100644
--- a/configs/T2080QDS_NAND_defconfig
+++ b/configs/T2080QDS_NAND_defconfig
@@ -7,6 +7,7 @@
 CONFIG_SPL=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_T2080QDS=y
+CONFIG_AHCI=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
@@ -39,7 +40,10 @@
 CONFIG_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="t2080qds"
 CONFIG_ENV_IS_IN_NAND=y
+CONFIG_DM=y
+CONFIG_FSL_AHCI=y
 CONFIG_FSL_CAAM=y
+CONFIG_DM_MMC=y
 CONFIG_FSL_ESDHC=y
 CONFIG_MTD_NOR_FLASH=y
 CONFIG_FLASH_CFI_DRIVER=y
@@ -57,8 +61,11 @@
 CONFIG_PHY_AQUANTIA=y
 CONFIG_E1000=y
 CONFIG_MII=y
+CONFIG_SCSI=y
+CONFIG_DM_SCSI=y
 CONFIG_SYS_NS16550=y
 CONFIG_SPI=y
 CONFIG_FSL_ESPI=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_STORAGE=y
diff --git a/configs/T2080QDS_SDCARD_defconfig b/configs/T2080QDS_SDCARD_defconfig
index 5fe12da..d830b17 100644
--- a/configs/T2080QDS_SDCARD_defconfig
+++ b/configs/T2080QDS_SDCARD_defconfig
@@ -8,6 +8,7 @@
 CONFIG_SPL=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_T2080QDS=y
+CONFIG_AHCI=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
@@ -39,7 +40,10 @@
 CONFIG_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="t2080qds"
 CONFIG_ENV_IS_IN_MMC=y
+CONFIG_DM=y
+CONFIG_FSL_AHCI=y
 CONFIG_FSL_CAAM=y
+CONFIG_DM_MMC=y
 CONFIG_FSL_ESDHC=y
 CONFIG_MTD_NOR_FLASH=y
 CONFIG_FLASH_CFI_DRIVER=y
@@ -56,8 +60,11 @@
 CONFIG_PHY_AQUANTIA=y
 CONFIG_E1000=y
 CONFIG_MII=y
+CONFIG_SCSI=y
+CONFIG_DM_SCSI=y
 CONFIG_SYS_NS16550=y
 CONFIG_SPI=y
 CONFIG_FSL_ESPI=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_STORAGE=y
diff --git a/configs/T2080QDS_SECURE_BOOT_defconfig b/configs/T2080QDS_SECURE_BOOT_defconfig
index dd71811..f6284fe 100644
--- a/configs/T2080QDS_SECURE_BOOT_defconfig
+++ b/configs/T2080QDS_SECURE_BOOT_defconfig
@@ -3,6 +3,8 @@
 CONFIG_SECURE_BOOT=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_T2080QDS=y
+CONFIG_MPC85XX_HAVE_RESET_VECTOR=y
+CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_F is not set
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
@@ -26,7 +28,11 @@
 CONFIG_CMD_MTDPARTS=y
 CONFIG_MTDIDS_DEFAULT="nor0=fe8000000.nor,nand0=fff800000.flash,spi0=spife110000.0"
 CONFIG_MTDPARTS_DEFAULT="mtdparts=fe8000000.nor:1m(uboot),5m(kernel),128k(dtb),96m(fs),-(user);fff800000.flash:1m(uboot),5m(kernel),128k(dtb),96m(fs),-(user);spife110000.0:1m(uboot),5m(kernel),128k(dtb),-(user)"
+CONFIG_OF_CONTROL=y
+CONFIG_DEFAULT_DEVICE_TREE="t2080qds"
 CONFIG_DM=y
+CONFIG_FSL_AHCI=y
+CONFIG_DM_MMC=y
 CONFIG_FSL_ESDHC=y
 CONFIG_MTD_NOR_FLASH=y
 CONFIG_FLASH_CFI_DRIVER=y
@@ -43,12 +49,14 @@
 CONFIG_PHY_AQUANTIA=y
 CONFIG_E1000=y
 CONFIG_MII=y
+CONFIG_SCSI=y
+CONFIG_DM_SCSI=y
 CONFIG_SYS_NS16550=y
 CONFIG_SPI=y
 CONFIG_FSL_ESPI=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_STORAGE=y
 CONFIG_RSA=y
 CONFIG_SPL_RSA=y
 CONFIG_RSA_SOFTWARE_EXP=y
-CONFIG_OF_LIBFDT=y
diff --git a/configs/T2080QDS_SPIFLASH_defconfig b/configs/T2080QDS_SPIFLASH_defconfig
index 899f61c..812a1b1 100644
--- a/configs/T2080QDS_SPIFLASH_defconfig
+++ b/configs/T2080QDS_SPIFLASH_defconfig
@@ -9,6 +9,7 @@
 CONFIG_SPL_SPI_SUPPORT=y
 CONFIG_MPC85xx=y
 CONFIG_TARGET_T2080QDS=y
+CONFIG_AHCI=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
@@ -40,7 +41,10 @@
 CONFIG_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="t2080qds"
 CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_DM=y
+CONFIG_FSL_AHCI=y
 CONFIG_FSL_CAAM=y
+CONFIG_DM_MMC=y
 CONFIG_FSL_ESDHC=y
 CONFIG_MTD_NOR_FLASH=y
 CONFIG_FLASH_CFI_DRIVER=y
@@ -57,8 +61,11 @@
 CONFIG_PHY_AQUANTIA=y
 CONFIG_E1000=y
 CONFIG_MII=y
+CONFIG_SCSI=y
+CONFIG_DM_SCSI=y
 CONFIG_SYS_NS16550=y
 CONFIG_SPI=y
 CONFIG_FSL_ESPI=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_STORAGE=y
diff --git a/configs/T2080QDS_SRIO_PCIE_BOOT_defconfig b/configs/T2080QDS_SRIO_PCIE_BOOT_defconfig
index 133dc7d..f18759f 100644
--- a/configs/T2080QDS_SRIO_PCIE_BOOT_defconfig
+++ b/configs/T2080QDS_SRIO_PCIE_BOOT_defconfig
@@ -2,6 +2,8 @@
 CONFIG_SYS_TEXT_BASE=0xFFF40000
 CONFIG_MPC85xx=y
 CONFIG_TARGET_T2080QDS=y
+CONFIG_MPC85XX_HAVE_RESET_VECTOR=y
+CONFIG_AHCI=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
@@ -22,8 +24,13 @@
 CONFIG_MP=y
 CONFIG_CMD_EXT2=y
 CONFIG_CMD_FAT=y
+CONFIG_OF_CONTROL=y
+CONFIG_DEFAULT_DEVICE_TREE="t2080qds"
 CONFIG_ENV_IS_IN_REMOTE=y
+CONFIG_DM=y
+CONFIG_FSL_AHCI=y
 CONFIG_FSL_CAAM=y
+CONFIG_DM_MMC=y
 CONFIG_FSL_ESDHC=y
 CONFIG_SPI_FLASH=y
 CONFIG_SF_DEFAULT_MODE=0
@@ -35,9 +42,11 @@
 CONFIG_PHY_AQUANTIA=y
 CONFIG_E1000=y
 CONFIG_MII=y
+CONFIG_SCSI=y
+CONFIG_DM_SCSI=y
 CONFIG_SYS_NS16550=y
 CONFIG_SPI=y
 CONFIG_FSL_ESPI=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_STORAGE=y
-CONFIG_OF_LIBFDT=y
diff --git a/configs/T2080QDS_defconfig b/configs/T2080QDS_defconfig
index 7f5a26f..8166c13 100644
--- a/configs/T2080QDS_defconfig
+++ b/configs/T2080QDS_defconfig
@@ -3,6 +3,7 @@
 CONFIG_MPC85xx=y
 CONFIG_TARGET_T2080QDS=y
 CONFIG_MPC85XX_HAVE_RESET_VECTOR=y
+CONFIG_AHCI=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
@@ -28,7 +29,10 @@
 CONFIG_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="t2080qds"
 CONFIG_ENV_IS_IN_FLASH=y
+CONFIG_DM=y
+CONFIG_FSL_AHCI=y
 CONFIG_FSL_CAAM=y
+CONFIG_DM_MMC=y
 CONFIG_FSL_ESDHC=y
 CONFIG_MTD_NOR_FLASH=y
 CONFIG_FLASH_CFI_DRIVER=y
@@ -45,8 +49,11 @@
 CONFIG_PHY_AQUANTIA=y
 CONFIG_E1000=y
 CONFIG_MII=y
+CONFIG_SCSI=y
+CONFIG_DM_SCSI=y
 CONFIG_SYS_NS16550=y
 CONFIG_SPI=y
 CONFIG_FSL_ESPI=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_STORAGE=y
diff --git a/configs/amcore_defconfig b/configs/amcore_defconfig
index 43e71cd..de56175 100644
--- a/configs/amcore_defconfig
+++ b/configs/amcore_defconfig
@@ -2,6 +2,7 @@
 CONFIG_SYS_TEXT_BASE=0xFFC00000
 CONFIG_SYS_MALLOC_F_LEN=0x800
 CONFIG_TARGET_AMCORE=y
+CONFIG_DEFAULT_DEVICE_TREE="amcore"
 CONFIG_BOOTDELAY=1
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 # CONFIG_DISPLAY_BOARDINFO is not set
diff --git a/configs/astro_mcf5373l_defconfig b/configs/astro_mcf5373l_defconfig
index 230c4cb..6d72bec 100644
--- a/configs/astro_mcf5373l_defconfig
+++ b/configs/astro_mcf5373l_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0x00000000
 CONFIG_TARGET_ASTRO_MCF5373L=y
+CONFIG_DEFAULT_DEVICE_TREE="astro_mcf5373l"
 CONFIG_BOOTDELAY=1
 CONFIG_USE_BOOTARGS=y
 CONFIG_BOOTARGS=" console=ttyS2,115200 rootfstype=romfs loaderversion=$loaderversion"
diff --git a/configs/cobra5272_defconfig b/configs/cobra5272_defconfig
index fc295af..7b9c6c6 100644
--- a/configs/cobra5272_defconfig
+++ b/configs/cobra5272_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0xFFE00000
 CONFIG_TARGET_COBRA5272=y
+CONFIG_DEFAULT_DEVICE_TREE="cobra5272"
 CONFIG_BOOTDELAY=5
 # CONFIG_DISPLAY_BOARDINFO is not set
 # CONFIG_CMDLINE_EDITING is not set
diff --git a/configs/eb_cpu5282_defconfig b/configs/eb_cpu5282_defconfig
index 3632706..8d3106e 100644
--- a/configs/eb_cpu5282_defconfig
+++ b/configs/eb_cpu5282_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0xFF000000
 CONFIG_TARGET_EB_CPU5282=y
+CONFIG_DEFAULT_DEVICE_TREE="eb_cpu5282"
 CONFIG_SYS_EXTRA_OPTIONS="SYS_MONITOR_BASE=0xFF000400"
 CONFIG_BOOTDELAY=5
 # CONFIG_CONSOLE_MUX is not set
diff --git a/configs/eb_cpu5282_internal_defconfig b/configs/eb_cpu5282_internal_defconfig
index 73c6744..e3240c1 100644
--- a/configs/eb_cpu5282_internal_defconfig
+++ b/configs/eb_cpu5282_internal_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0xF0000000
 CONFIG_TARGET_EB_CPU5282=y
+CONFIG_DEFAULT_DEVICE_TREE="eb_cpu5282_internal"
 CONFIG_SYS_EXTRA_OPTIONS="SYS_MONITOR_BASE=0xF0000418"
 CONFIG_BOOTDELAY=5
 # CONFIG_CONSOLE_MUX is not set
diff --git a/configs/gardena-smart-gateway-mt7688-ram_defconfig b/configs/gardena-smart-gateway-mt7688-ram_defconfig
index e099506..cb0d33e 100644
--- a/configs/gardena-smart-gateway-mt7688-ram_defconfig
+++ b/configs/gardena-smart-gateway-mt7688-ram_defconfig
@@ -12,6 +12,7 @@
 CONFIG_OF_STDOUT_VIA_ALIAS=y
 CONFIG_USE_BOOTCOMMAND=y
 CONFIG_BOOTCOMMAND="cp.b 83000000 84000000 10000 && dhcp uEnv.txt && env import -t ${fileaddr} ${filesize} && run do_u_boot_init; reset"
+CONFIG_USE_PREBOOT=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_BOARD_EARLY_INIT_F=y
@@ -26,6 +27,7 @@
 CONFIG_CMD_MTD=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
+CONFIG_CMD_WDT=y
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
diff --git a/configs/gardena-smart-gateway-mt7688_defconfig b/configs/gardena-smart-gateway-mt7688_defconfig
index ad0db2e..ad2fbd0 100644
--- a/configs/gardena-smart-gateway-mt7688_defconfig
+++ b/configs/gardena-smart-gateway-mt7688_defconfig
@@ -15,6 +15,7 @@
 CONFIG_OF_STDOUT_VIA_ALIAS=y
 CONFIG_USE_BOOTCOMMAND=y
 CONFIG_BOOTCOMMAND="cp.b 83000000 84000000 10000 && dhcp uEnv.txt && env import -t ${fileaddr} ${filesize} && run do_u_boot_init; reset"
+CONFIG_USE_PREBOOT=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_BOARD_EARLY_INIT_F=y
@@ -29,6 +30,7 @@
 CONFIG_CMD_MTD=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
+CONFIG_CMD_WDT=y
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
diff --git a/configs/stmark2_defconfig b/configs/stmark2_defconfig
index 630b01c..40769a8 100644
--- a/configs/stmark2_defconfig
+++ b/configs/stmark2_defconfig
@@ -1,6 +1,7 @@
 CONFIG_M68K=y
 CONFIG_SYS_TEXT_BASE=0x47E00000
 CONFIG_TARGET_STMARK2=y
+CONFIG_DEFAULT_DEVICE_TREE="stmark2"
 CONFIG_SYS_EXTRA_OPTIONS="CF_SBF,SYS_SERIAL_BOOT,SYS_INPUT_CLKSRC=30000000"
 # CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_HUSH_PARSER=y
@@ -29,5 +30,7 @@
 CONFIG_SPI_FLASH_ISSI=y
 CONFIG_SPI_FLASH_MTD=y
 CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_CF_SPI=y
 CONFIG_REGEX=y
diff --git a/doc/device-tree-bindings/clock/st,stm32mp1.txt b/doc/device-tree-bindings/clock/st,stm32mp1.txt
index ffcf8cd..02e1460 100644
--- a/doc/device-tree-bindings/clock/st,stm32mp1.txt
+++ b/doc/device-tree-bindings/clock/st,stm32mp1.txt
@@ -1,185 +1,186 @@
 STMicroelectronics STM32MP1 clock tree initialization
 =====================================================
 
-The STM32MP clock tree initialization is based on device tree information
-for RCC IP and on fixed clocks.
+The STM32MP1 clock tree initialization is based on device tree information
+for RCC IP node (st,stm32mp1-rcc) and on fixed-clock nodes.
 
--------------------------------
-RCC CLOCK = st,stm32mp1-rcc-clk
--------------------------------
+RCC IP = st,stm32mp1-rcc
+========================
 
 The RCC IP is both a reset and a clock controller but this documentation only
 describes the fields added for clock tree initialization which are not present
-in Linux binding.
+in Linux binding for compatible "st,stm32mp1-rcc" defined in st,stm32mp1-rcc.txt
+file.
 
-Please refer to ../mfd/st,stm32-rcc.txt for all the other properties common
-with Linux.
+The added properties for clock tree initialization are:
 
 Required properties:
+- st,clksrc : The clock sources configuration array in a platform specific
+              order.
 
-- compatible: Should be "st,stm32mp1-rcc-clk"
+  For the STM32MP15x family there are 9 clock sources selector which are
+  configured in the following order:
+	MPU AXI MCU PLL12 PLL3 PLL4 RTC MCO1 MCO2
 
-- st,clksrc : The clock source in this order
+  Clock source configuration values are defined by macros CLK_<NAME>_<SOURCE>
+  from dt-bindings/clock/stm32mp1-clksrc.h.
 
-	for STM32MP15x: 9 clock sources are requested
-		MPU AXI MCU PLL12 PLL3 PLL4 RTC MCO1 MCO2
+  Example:
+	st,clksrc = <
+		CLK_MPU_PLL1P
+		CLK_AXI_PLL2P
+		CLK_MCU_PLL3P
+		CLK_PLL12_HSE
+		CLK_PLL3_HSE
+		CLK_PLL4_HSE
+		CLK_RTC_LSE
+		CLK_MCO1_DISABLED
+		CLK_MCO2_DISABLED
+	>;
 
-	with value equals to RCC clock specifier as defined in
-	dt-bindings/clock/stm32mp1-clksrc.h: CLK_<NAME>_<SOURCE>
+- st,clkdiv : The clock main dividers value specified in an array
+              in a platform specific order.
 
-- st,clkdiv : The div parameters in this order
-	for STM32MP15x: 11 dividers value are requested
-		MPU AXI MCU APB1 APB2 APB3 APB4 APB5 RTC MCO1 MCO2
+  When used, it shall describe the whole clock dividers tree.
 
-	with DIV coding defined in RCC associated register RCC_xxxDIVR
+  For the STM32MP15x family there are 11 dividers values expected.
+  They shall be configured in the following order:
+		MPU AXI MCU APB1 APB2 APB3 APB4 APB5 RTC MCO1 MCO2
 
-	most the case, it is:
+  The each divider value uses the DIV coding defined in RCC associated
+  register RCC_xxxDIVR. In most the case, it is:
 		0x0: not divided
 		0x1: division by 2
 		0x2: division by 4
 		0x3: division by 8
 		...
 
-	but for RTC MCO1 MCO2, the coding is different:
+  Note that for RTC MCO1 MCO2, the coding is different:
 		0x0: not divided
 		0x1: division by 2
 		0x2: division by 3
 		0x3: division by 4
 		...
 
-Optional Properties:
-- st,pll
-    PLL children node for PLL1 to PLL4 : (see ref manual for details)
-    with associated index 0 to 3 (st,pll@0 to st,pll@4)
-    PLLx is off when the associated node is absent
-
-    - Sub-nodes:
+  Example:
+	st,clkdiv = <
+		1 /*MPU*/
+		0 /*AXI*/
+		0 /*MCU*/
+		1 /*APB1*/
+		1 /*APB2*/
+		1 /*APB3*/
+		1 /*APB4*/
+		2 /*APB5*/
+		23 /*RTC*/
+		0 /*MCO1*/
+		0 /*MCO2*/
+	>;
 
-	- cfg:	The parameters for PLL configuration in this order:
-		DIVM DIVN DIVP DIVQ DIVR Output
+Optional Properties:
+- st,pll : A specific PLL configuration, including frequency.
 
-		with DIV value as defined in RCC spec:
-			0x0: bypass (division by 1)
-			0x1: division by 2
-			0x2: division by 3
-			0x3: division by 4
-			...
+  PLL children nodes for PLL1 to PLL4 (see ref manual for details)
+  are listed with associated index 0 to 3 (st,pll@0 to st,pll@3).
+  PLLx is off when the associated node is absent.
 
-		and Output = bitfield for each output value = 1:ON/0:OFF
-			BIT(0) => output P : DIVPEN
-			BIT(1) => output Q : DIVQEN
-			BIT(2) => output R : DIVREN
-		  NB : macro PQR(p,q,r) can be used to build this value
-		       with p,p,r = 0 or 1
+  Here are the available properties for each PLL node:
 
-	- frac : Fractional part of the multiplication factor
-		(optional, PLL is in integer mode when absent)
+    - cfg: The parameters for PLL configuration in the following order:
+           DIVM DIVN DIVP DIVQ DIVR Output.
 
-	- csg : Clock Spreading Generator (optional)
-	        with parameters in this order:
-		MOD_PER INC_STEP SSCG_MODE
+	DIVx values are defined as in RCC spec:
+		0x0: bypass (division by 1)
+		0x1: division by 2
+		0x2: division by 3
+		0x3: division by 4
+		...
 
-		* MOD_PER: Modulation Period Adjustment
-		* INC_STEP: Modulation Depth Adjustment
-		* SSCG_MODE: Spread spectrum clock generator mode
-		  you can use associated defines from stm32mp1-clksrc.h
-		  * SSCG_MODE_CENTER_SPREAD = 0
-		  * SSCG_MODE_DOWN_SPREAD = 1
+	Output contains a bitfield for each output value (1:ON/0:OFF)
+		BIT(0) => output P : DIVPEN
+		BIT(1) => output Q : DIVQEN
+		BIT(2) => output R : DIVREN
+	  NB: macro PQR(p,q,r) can be used to build this value
+	      with p,q,r = 0 or 1.
 
+    - frac : Fractional part of the multiplication factor
+             (optional, PLL is in integer mode when absent).
 
-- st,pkcs : used to configure the peripherals kernel clock selection
-  containing a list of peripheral kernel clock source identifier as defined
-  in the file dt-bindings/clock/stm32mp1-clksrc.h
+    - csg : Clock Spreading Generator (optional) with parameters in the
+	    following order: MOD_PER INC_STEP SSCG_MODE.
 
-  Example:
+	MOD_PER: Modulation Period Adjustment
+	INC_STEP: Modulation Depth Adjustment
+	SSCG_MODE: Spread spectrum clock generator mode, with associated
+		   defined from stm32mp1-clksrc.h:
+			- SSCG_MODE_CENTER_SPREAD = 0
+			- SSCG_MODE_DOWN_SPREAD = 1
 
-	rcc: rcc@50000000 {
-		compatible = "syscon", "simple-mfd";
+    Example:
+	st,pll@0 {
+		cfg = < 1 53 0 0 0 1 >;
+		frac = < 0x810 >;
+	};
+	st,pll@1 {
+		cfg = < 1 43 1 0 0 PQR(0,1,1) >;
+		csg = < 10 20 1 >;
+	};
+	st,pll@2 {
+		cfg = < 2 85 3 13 3 0 >;
+		csg = < 10 20 SSCG_MODE_CENTER_SPREAD >;
+		};
+	st,pll@3 {
+		cfg = < 2 78 4 7 9 3 >;
+	};
 
-		reg = <0x50000000 0x1000>;
+- st,pkcs : used to configure the peripherals kernel clock selection.
 
-		rcc_clk: rcc-clk@50000000 {
-			#clock-cells = <1>;
-			compatible = "st,stm32mp1-rcc-clk";
+  The property is a list of peripheral kernel clock source identifiers defined
+  by macros CLK_<KERNEL-CLOCK>_<PARENT-CLOCK> as defined by header file
+  dt-bindings/clock/stm32mp1-clksrc.h.
 
-			st,clksrc = <	CLK_MPU_PLL1P
-					CLK_AXI_PLL2P
-					CLK_MCU_HSI
-					CLK_PLL12_HSE
-					CLK_PLL3_HSE
-					CLK_PLL4_HSE
-					CLK_RTC_HSE
-					CLK_MCO1_DISABLED
-					CLK_MCO2_DISABLED
-			>;
+  st,pkcs may not list all the kernel clocks and has no ordering requirements.
 
-			st,clkdiv = <
-				1 /*MPU*/
-				0 /*AXI*/
-				0 /*MCU*/
-				1 /*APB1*/
-				1 /*APB2*/
-				1 /*APB3*/
-				1 /*APB4*/
-				5 /*APB5*/
-				23 /*RTC*/
-				0 /*MCO1*/
-				0 /*MCO2*/
-			>;
-
-			st,pll@0 {
-				cfg = < 1 53 0 0 0 1 >;
-				frac = < 0x810 >;
-			};
-			st,pll@1 {
-				cfg = < 1 43 1 0 0 PQR(0,1,1) >;
-				csg = < 10 20 1 >;
-			};
-			st,pll@2 {
-				cfg = < 2 85 3 13 3 0 >;
-				csg = < 10 20 SSCG_MODE_CENTER_SPREAD >;
-			};
-			st,pll@3 {
-				cfg = < 2 78 4 7 9 3 >;
-			};
-			st,pkcs = <
-					CLK_STGEN_HSE
-					CLK_CKPER_HSI
-					CLK_USBPHY_PLL2P
-					CLK_DSI_PLL2Q
-				  >;
-		};
-	};
+  Example:
+	st,pkcs = <
+		CLK_STGEN_HSE
+		CLK_CKPER_HSI
+		CLK_USBPHY_PLL2P
+		CLK_DSI_PLL2Q
+		CLK_I2C46_HSI
+		CLK_UART1_HSI
+		CLK_UART24_HSI
+	>;
 
---------------------------
 other clocks = fixed-clock
---------------------------
+==========================
+
 The clock tree is also based on 5 fixed-clock in clocks node
 used to define the state of associated ST32MP1 oscillators:
-- clk-lsi
-- clk-lse
-- clk-hsi
-- clk-hse
-- clk-csi
+  - clk-lsi
+  - clk-lse
+  - clk-hsi
+  - clk-hse
+  - clk-csi
 
 At boot the clock tree initialization will
-- enable the oscillator present in device tree
-- disable HSI oscillator if the node is absent (always activated by bootrom)
+  - enable oscillators present in device tree
+  - disable HSI oscillator if the node is absent (always activated by bootrom)
 
 Optional properties :
 
 a) for external oscillator: "clk-lse", "clk-hse"
 
-	4 optional fields are managed
-	- "st,bypass" Configure the oscillator bypass mode (HSEBYP, LSEBYP)
-	- "st,digbypass" Configure the bypass mode as full-swing digital signal
-	  (DIGBYP)
-	- "st,css" Activate the clock security system (HSECSSON, LSECSSON)
-	- "st,drive" (only for LSE) value of the drive for the oscillator
-	   (see LSEDRV_ define in the file dt-bindings/clock/stm32mp1-clksrc.h)
+  4 optional fields are managed
+  - "st,bypass" configures the oscillator bypass mode (HSEBYP, LSEBYP)
+  - "st,digbypass" configures the bypass mode as full-swing digital
+    signal (DIGBYP)
+  - "st,css" activates the clock security system (HSECSSON, LSECSSON)
+  - "st,drive" (only for LSE) contains the value of the drive for the
+     oscillator (see LSEDRV_ defined in the file
+     dt-bindings/clock/stm32mp1-clksrc.h)
 
-	Example board file:
-
+  Example board file:
 	/ {
 		clocks {
 			clk_hse: clk-hse {
@@ -200,13 +201,12 @@
 
 b) for internal oscillator: "clk-hsi"
 
-	internally HSI clock is fixed to 64MHz for STM32MP157 soc
-	in device tree clk-hsi is the clock after HSIDIV (ck_hsi in RCC doc)
-	So this clock frequency is used to compute the expected HSI_DIV
-	for the clock tree initialisation
+  Internally HSI clock is fixed to 64MHz for STM32MP157 SoC.
+  In device tree, clk-hsi is the clock after HSIDIV (clk_hsi in RCC
+  doc). So this clock frequency is used to compute the expected HSI_DIV
+  for the clock tree initialization.
 
-	ex: for HSIDIV = /1
-
+  Example with HSIDIV = /1:
 	/ {
 		clocks {
 			clk_hsi: clk-hsi {
@@ -216,8 +216,7 @@
 			};
 	};
 
-	ex: for HSIDIV = /2
-
+  Example with HSIDIV = /2
 	/ {
 		clocks {
 			clk_hsi: clk-hsi {
@@ -226,3 +225,151 @@
 				clock-frequency = <32000000>;
 			};
 	};
+
+Example of clock tree initialization
+====================================
+
+/ {
+	clocks {
+		u-boot,dm-pre-reloc;
+		clk_hse: clk-hse {
+			u-boot,dm-pre-reloc;
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <24000000>;
+			st,digbypass;
+		};
+
+		clk_hsi: clk-hsi {
+			u-boot,dm-pre-reloc;
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <64000000>;
+		};
+
+		clk_lse: clk-lse {
+			u-boot,dm-pre-reloc;
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <32768>;
+		};
+
+		clk_lsi: clk-lsi {
+			u-boot,dm-pre-reloc;
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <32000>;
+		};
+
+		clk_csi: clk-csi {
+			u-boot,dm-pre-reloc;
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <4000000>;
+		};
+	};
+
+	soc {
+
+		rcc: rcc@50000000 {
+			u-boot,dm-pre-reloc;
+			compatible = "st,stm32mp1-rcc", "syscon";
+			reg = <0x50000000 0x1000>;
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+			interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+
+			st,clksrc = <
+				CLK_MPU_PLL1P
+				CLK_AXI_PLL2P
+				CLK_MCU_PLL3P
+				CLK_PLL12_HSE
+				CLK_PLL3_HSE
+				CLK_PLL4_HSE
+				CLK_RTC_LSE
+				CLK_MCO1_DISABLED
+				CLK_MCO2_DISABLED
+			>;
+
+			st,clkdiv = <
+				1 /*MPU*/
+				0 /*AXI*/
+				0 /*MCU*/
+				1 /*APB1*/
+				1 /*APB2*/
+				1 /*APB3*/
+				1 /*APB4*/
+				2 /*APB5*/
+				23 /*RTC*/
+				0 /*MCO1*/
+				0 /*MCO2*/
+			>;
+
+			st,pkcs = <
+				CLK_CKPER_HSE
+				CLK_FMC_ACLK
+				CLK_QSPI_ACLK
+				CLK_ETH_DISABLED
+				CLK_SDMMC12_PLL4P
+				CLK_DSI_DSIPLL
+				CLK_STGEN_HSE
+				CLK_USBPHY_HSE
+				CLK_SPI2S1_PLL3Q
+				CLK_SPI2S23_PLL3Q
+				CLK_SPI45_HSI
+				CLK_SPI6_HSI
+				CLK_I2C46_HSI
+				CLK_SDMMC3_PLL4P
+				CLK_USBO_USBPHY
+				CLK_ADC_CKPER
+				CLK_CEC_LSE
+				CLK_I2C12_HSI
+				CLK_I2C35_HSI
+				CLK_UART1_HSI
+				CLK_UART24_HSI
+				CLK_UART35_HSI
+				CLK_UART6_HSI
+				CLK_UART78_HSI
+				CLK_SPDIF_PLL4P
+				CLK_FDCAN_PLL4Q
+				CLK_SAI1_PLL3Q
+				CLK_SAI2_PLL3Q
+				CLK_SAI3_PLL3Q
+				CLK_SAI4_PLL3Q
+				CLK_RNG1_LSI
+				CLK_RNG2_LSI
+				CLK_LPTIM1_PCLK1
+				CLK_LPTIM23_PCLK3
+				CLK_LPTIM45_LSE
+			>;
+
+			/* VCO = 1300.0 MHz => P = 650 (CPU) */
+			pll1: st,pll@0 {
+				cfg = < 2 80 0 0 0 PQR(1,0,0) >;
+				frac = < 0x800 >;
+				u-boot,dm-pre-reloc;
+			};
+
+			/* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU),
+			                       R = 533 (DDR) */
+			pll2: st,pll@1 {
+				cfg = < 2 65 1 0 0 PQR(1,1,1) >;
+				frac = < 0x1400 >;
+				u-boot,dm-pre-reloc;
+			};
+
+			/* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */
+			pll3: st,pll@2 {
+				cfg = < 1 33 1 16 36 PQR(1,1,1) >;
+				frac = < 0x1a04 >;
+				u-boot,dm-pre-reloc;
+			};
+
+			/* VCO = 594.0 MHz => P = 99, Q = 74, R = 74 */
+			pll4: st,pll@3 {
+				cfg = < 3 98 5 7 7 PQR(1,1,1) >;
+				u-boot,dm-pre-reloc;
+			};
+		};
+	};
+};
diff --git a/doc/device-tree-bindings/memory-controllers/st,stm32mp1-ddr.txt b/doc/device-tree-bindings/memory-controllers/st,stm32mp1-ddr.txt
index 3028636..ee708ce 100644
--- a/doc/device-tree-bindings/memory-controllers/st,stm32mp1-ddr.txt
+++ b/doc/device-tree-bindings/memory-controllers/st,stm32mp1-ddr.txt
@@ -16,7 +16,7 @@
 info attributes:
 ----------------
 - st,mem-name	: name for DDR configuration, simple string for information
-- st,mem-speed	: DDR expected speed for the setting in MHz
+- st,mem-speed	: DDR expected speed for the setting in kHz
 - st,mem-size	: DDR mem size in byte
 
 
@@ -102,7 +102,7 @@
 phyc attributes:
 ----------------
 - st,phy-reg	: phy values depending of the DDR type (DDR3/LPDDR2/LPDDR3)
-	for STM32MP15x: 10 values are requested in this order
+	for STM32MP15x: 11 values are requested in this order
 		PGCR
 		ACIOCR
 		DXCCR
@@ -173,7 +173,7 @@
 				      "ddrphycapb";
 
 			st,mem-name = "DDR3 2x4Gb 533MHz";
-			st,mem-speed = <533>;
+			st,mem-speed = <533000>;
 			st,mem-size = <0x40000000>;
 
 			st,ctl-reg = <
diff --git a/doc/device-tree-bindings/serial/mcf-uart.txt b/doc/device-tree-bindings/serial/mcf-uart.txt
new file mode 100644
index 0000000..d73f764
--- /dev/null
+++ b/doc/device-tree-bindings/serial/mcf-uart.txt
@@ -0,0 +1,19 @@
+Freescale ColdFire UART
+
+Required properties:
+- compatible : should be "fsl,mcf-uart"
+- reg: start address and size of the registers
+
+Example:
+
+soc {
+	compatible = "simple-bus";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	uart0: uart@fc060000 {
+		compatible = "fsl,mcf-uart";
+		reg = <0xfc060000 0x40>;
+		status = "disabled";
+	};
+};
diff --git a/doc/device-tree-bindings/spi/spi-mcf-dspi.txt b/doc/device-tree-bindings/spi/spi-mcf-dspi.txt
new file mode 100644
index 0000000..860eb8a
--- /dev/null
+++ b/doc/device-tree-bindings/spi/spi-mcf-dspi.txt
@@ -0,0 +1,30 @@
+Freescale ColdFire DSPI controller
+
+Required properties:
+- compatible : "fsl,mcf-dspi"
+- #address-cells: <1>, as required by generic SPI binding
+- #size-cells: <0>, also as required by generic SPI binding
+- reg : offset and length of the register set for the device
+
+Optional properties:
+- spi-max-frequency : max supported spi frequency
+- num-cs : the number of the chipselect signals
+- spi-mode: spi motorola mode, 0 to 3
+- ctar-params: CTAR0 to 7 register configuration, as an array
+  of 8 integer fields for each register, where each register
+  is defined as: <fmsz, pcssck, pasc, pdt, cssck, asc, dt, br>.
+
+Example:
+
+dspi0: dspi@fc05c000 {
+	compatible = "fsl,mcf-dspi";
+	#address-cells = <1>;
+	#size-cells = <0>;
+	reg = <0xfc05c000 0x100>;
+	spi-max-frequency = <50000000>;
+	num-cs = <4>;
+	spi-mode = <0>;
+	ctar-fields = <7, 0, 0, 0, 0, 0, 1, 6>,
+		      <7, 0, 0, 0, 0, 0, 1, 6>,
+		      <7, 0, 0, 0, 0, 0, 1, 6>;
+};
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 4e95a68..87636ae 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -59,6 +59,16 @@
 	  Enable this driver to support Sata devices through
 	  Synopsys DWC AHCI module.
 
+config FSL_AHCI
+	bool "Enable Freescale AHCI driver support"
+	select SCSI_AHCI
+	depends on AHCI
+	depends on DM_SCSI
+	help
+	  Enable this driver to support Sata devices found in
+	  some Freescale PowerPC SoCs.
+
+
 config DWC_AHSATA
 	bool "Enable DWC AHSATA driver support"
 	select LIBATA
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index a69edb1..6e03384 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -4,6 +4,7 @@
 # Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 
 obj-$(CONFIG_DWC_AHCI) += dwc_ahci.o
+obj-$(CONFIG_FSL_AHCI) += fsl_ahci.o
 obj-$(CONFIG_AHCI) += ahci-uclass.o
 obj-$(CONFIG_AHCI_PCI) += ahci-pci.o
 obj-$(CONFIG_SCSI_AHCI) += ahci.o
diff --git a/drivers/ata/fsl_ahci.c b/drivers/ata/fsl_ahci.c
new file mode 100644
index 0000000..d04cff3
--- /dev/null
+++ b/drivers/ata/fsl_ahci.c
@@ -0,0 +1,1030 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * NXP PPC SATA platform driver
+ *
+ * (C) Copyright 2019 NXP, Inc.
+ *
+ */
+#include <common.h>
+#include <asm/fsl_serdes.h>
+#include <dm/lists.h>
+#include <dm.h>
+#include <ahci.h>
+#include <scsi.h>
+#include <libata.h>
+#include <sata.h>
+#include <malloc.h>
+#include <memalign.h>
+#include <fis.h>
+
+#include "fsl_sata.h"
+
+struct fsl_ahci_priv {
+	u32 base;
+	u32 flag;
+	u32 number;
+	fsl_sata_t *fsl_sata;
+};
+
+static int fsl_ahci_bind(struct udevice *dev)
+{
+	return device_bind_driver(dev, "fsl_ahci_scsi", "fsl_ahci_scsi", NULL);
+}
+
+static int fsl_ahci_ofdata_to_platdata(struct udevice *dev)
+{
+	struct fsl_ahci_priv *priv = dev_get_priv(dev);
+
+	priv->number = dev_read_u32_default(dev, "sata-number", -1);
+	priv->flag = dev_read_u32_default(dev, "sata-fpdma", -1);
+
+	priv->base = dev_read_addr(dev);
+	if (priv->base == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int ata_wait_register(unsigned __iomem *addr, u32 mask,
+			     u32 val, u32 timeout_msec)
+{
+	int i;
+
+	for (i = 0; ((in_le32(addr) & mask) != val) && i < timeout_msec; i++)
+		mdelay(1);
+
+	return (i < timeout_msec) ? 0 : -1;
+}
+
+static void fsl_sata_dump_sfis(struct sata_fis_d2h *s)
+{
+	printf("Status FIS dump:\n\r");
+	printf("fis_type:		%02x\n\r", s->fis_type);
+	printf("pm_port_i:		%02x\n\r", s->pm_port_i);
+	printf("status:			%02x\n\r", s->status);
+	printf("error:			%02x\n\r", s->error);
+	printf("lba_low:		%02x\n\r", s->lba_low);
+	printf("lba_mid:		%02x\n\r", s->lba_mid);
+	printf("lba_high:		%02x\n\r", s->lba_high);
+	printf("device:			%02x\n\r", s->device);
+	printf("lba_low_exp:		%02x\n\r", s->lba_low_exp);
+	printf("lba_mid_exp:		%02x\n\r", s->lba_mid_exp);
+	printf("lba_high_exp:		%02x\n\r", s->lba_high_exp);
+	printf("res1:			%02x\n\r", s->res1);
+	printf("sector_count:		%02x\n\r", s->sector_count);
+	printf("sector_count_exp:	%02x\n\r", s->sector_count_exp);
+}
+
+static void fsl_sata_dump_regs(fsl_sata_reg_t __iomem *reg)
+{
+	printf("\n\rSATA:           %08x\n\r", (u32)reg);
+	printf("CQR:            %08x\n\r", in_le32(&reg->cqr));
+	printf("CAR:            %08x\n\r", in_le32(&reg->car));
+	printf("CCR:            %08x\n\r", in_le32(&reg->ccr));
+	printf("CER:            %08x\n\r", in_le32(&reg->cer));
+	printf("CQR:            %08x\n\r", in_le32(&reg->cqr));
+	printf("DER:            %08x\n\r", in_le32(&reg->der));
+	printf("CHBA:           %08x\n\r", in_le32(&reg->chba));
+	printf("HStatus:        %08x\n\r", in_le32(&reg->hstatus));
+	printf("HControl:       %08x\n\r", in_le32(&reg->hcontrol));
+	printf("CQPMP:          %08x\n\r", in_le32(&reg->cqpmp));
+	printf("SIG:            %08x\n\r", in_le32(&reg->sig));
+	printf("ICC:            %08x\n\r", in_le32(&reg->icc));
+	printf("SStatus:        %08x\n\r", in_le32(&reg->sstatus));
+	printf("SError:         %08x\n\r", in_le32(&reg->serror));
+	printf("SControl:       %08x\n\r", in_le32(&reg->scontrol));
+	printf("SNotification:  %08x\n\r", in_le32(&reg->snotification));
+	printf("TransCfg:       %08x\n\r", in_le32(&reg->transcfg));
+	printf("TransStatus:    %08x\n\r", in_le32(&reg->transstatus));
+	printf("LinkCfg:        %08x\n\r", in_le32(&reg->linkcfg));
+	printf("LinkCfg1:       %08x\n\r", in_le32(&reg->linkcfg1));
+	printf("LinkCfg2:       %08x\n\r", in_le32(&reg->linkcfg2));
+	printf("LinkStatus:     %08x\n\r", in_le32(&reg->linkstatus));
+	printf("LinkStatus1:    %08x\n\r", in_le32(&reg->linkstatus1));
+	printf("PhyCtrlCfg:     %08x\n\r", in_le32(&reg->phyctrlcfg));
+	printf("SYSPR:          %08x\n\r", in_be32(&reg->syspr));
+}
+
+static int init_sata(struct fsl_ahci_priv *priv)
+{
+	int i;
+	u32 cda;
+	u32 val32;
+	u32 sig;
+	fsl_sata_t *sata;
+	u32 length, align;
+	cmd_hdr_tbl_t *cmd_hdr;
+	fsl_sata_reg_t __iomem *reg;
+
+	int dev = priv->number;
+
+	if (dev < 0 || dev > (CONFIG_SYS_SATA_MAX_DEVICE - 1)) {
+		printf("the sata index %d is out of ranges\n\r", dev);
+		return -EINVAL;
+	}
+
+#ifdef CONFIG_MPC85xx
+	if (dev == 0 && (!is_serdes_configured(SATA1))) {
+		printf("SATA%d [dev = %d] is not enabled\n", dev + 1, dev);
+		return -EINVAL;
+	}
+	if (dev == 1 && (!is_serdes_configured(SATA2))) {
+		printf("SATA%d [dev = %d] is not enabled\n", dev + 1, dev);
+		return -EINVAL;
+	}
+#endif
+
+	/* Allocate SATA device driver struct */
+	sata = (fsl_sata_t *)malloc(sizeof(fsl_sata_t));
+	if (!sata) {
+		printf("alloc the sata device struct failed\n\r");
+		return -ENOMEM;
+	}
+	/* Zero all of the device driver struct */
+	memset((void *)sata, 0, sizeof(fsl_sata_t));
+
+	sata->dma_flag = priv->flag;
+	snprintf(sata->name, 12, "SATA%d", dev);
+
+	/* Set the controller register base address to device struct */
+	reg = (fsl_sata_reg_t *)priv->base;
+	sata->reg_base = reg;
+
+	/* Allocate the command header table, 4 bytes aligned */
+	length = sizeof(struct cmd_hdr_tbl);
+	align = SATA_HC_CMD_HDR_TBL_ALIGN;
+	sata->cmd_hdr_tbl_offset = (void *)malloc(length + align);
+	if (!sata->cmd_hdr_tbl_offset) {
+		printf("alloc the command header failed\n\r");
+		return -ENOMEM;
+	}
+
+	cmd_hdr = (cmd_hdr_tbl_t *)(((u32)sata->cmd_hdr_tbl_offset + align)
+						& ~(align - 1));
+	sata->cmd_hdr = cmd_hdr;
+
+	/* Zero all of the command header table */
+	memset((void *)sata->cmd_hdr_tbl_offset, 0, length + align);
+
+	/* Allocate command descriptor for all command */
+	length = sizeof(struct cmd_desc) * SATA_HC_MAX_CMD;
+	align = SATA_HC_CMD_DESC_ALIGN;
+	sata->cmd_desc_offset = (void *)malloc(length + align);
+	if (!sata->cmd_desc_offset) {
+		printf("alloc the command descriptor failed\n\r");
+		return -ENOMEM;
+	}
+	sata->cmd_desc = (cmd_desc_t *)(((u32)sata->cmd_desc_offset + align)
+						& ~(align - 1));
+	/* Zero all of command descriptor */
+	memset((void *)sata->cmd_desc_offset, 0, length + align);
+
+	/* Link the command descriptor to command header */
+	for (i = 0; i < SATA_HC_MAX_CMD; i++) {
+		cda = ((u32)sata->cmd_desc + SATA_HC_CMD_DESC_SIZE * i)
+					 & ~(CMD_HDR_CDA_ALIGN - 1);
+		cmd_hdr->cmd_slot[i].cda = cpu_to_le32(cda);
+	}
+
+	/* To have safe state, force the controller offline */
+	val32 = in_le32(&reg->hcontrol);
+	val32 &= ~HCONTROL_ONOFF;
+	val32 |= HCONTROL_FORCE_OFFLINE;
+	out_le32(&reg->hcontrol, val32);
+
+	/* Wait the controller offline */
+	ata_wait_register(&reg->hstatus, HSTATUS_ONOFF, 0, 1000);
+
+	/* Set the command header base address to CHBA register to tell DMA */
+	out_le32(&reg->chba, (u32)cmd_hdr & ~0x3);
+
+	/* Snoop for the command header */
+	val32 = in_le32(&reg->hcontrol);
+	val32 |= HCONTROL_HDR_SNOOP;
+	out_le32(&reg->hcontrol, val32);
+
+	/* Disable all of interrupts */
+	val32 = in_le32(&reg->hcontrol);
+	val32 &= ~HCONTROL_INT_EN_ALL;
+	out_le32(&reg->hcontrol, val32);
+
+	/* Clear all of interrupts */
+	val32 = in_le32(&reg->hstatus);
+	out_le32(&reg->hstatus, val32);
+
+	/* Set the ICC, no interrupt coalescing */
+	out_le32(&reg->icc, 0x01000000);
+
+	/* No PM attatched, the SATA device direct connect */
+	out_le32(&reg->cqpmp, 0);
+
+	/* Clear SError register */
+	val32 = in_le32(&reg->serror);
+	out_le32(&reg->serror, val32);
+
+	/* Clear CER register */
+	val32 = in_le32(&reg->cer);
+	out_le32(&reg->cer, val32);
+
+	/* Clear DER register */
+	val32 = in_le32(&reg->der);
+	out_le32(&reg->der, val32);
+
+	/* No device detection or initialization action requested */
+	out_le32(&reg->scontrol, 0x00000300);
+
+	/* Configure the transport layer, default value */
+	out_le32(&reg->transcfg, 0x08000016);
+
+	/* Configure the link layer, default value */
+	out_le32(&reg->linkcfg, 0x0000ff34);
+
+	/* Bring the controller online */
+	val32 = in_le32(&reg->hcontrol);
+	val32 |= HCONTROL_ONOFF;
+	out_le32(&reg->hcontrol, val32);
+
+	mdelay(100);
+
+	/* print sata device name */
+	printf("%s ", sata->name);
+
+	/* Wait PHY RDY signal changed for 500ms */
+	ata_wait_register(&reg->hstatus, HSTATUS_PHY_RDY,
+			  HSTATUS_PHY_RDY, 500);
+
+	/* Check PHYRDY */
+	val32 = in_le32(&reg->hstatus);
+	if (val32 & HSTATUS_PHY_RDY) {
+		sata->link = 1;
+	} else {
+		sata->link = 0;
+		printf("(No RDY)\n\r");
+		return -EINVAL;
+	}
+
+	/* Wait for signature updated, which is 1st D2H */
+	ata_wait_register(&reg->hstatus, HSTATUS_SIGNATURE,
+			  HSTATUS_SIGNATURE, 10000);
+
+	if (val32 & HSTATUS_SIGNATURE) {
+		sig = in_le32(&reg->sig);
+		debug("Signature updated, the sig =%08x\n\r", sig);
+		sata->ata_device_type = ata_dev_classify(sig);
+	}
+
+	/* Check the speed */
+	val32 = in_le32(&reg->sstatus);
+	if ((val32 & SSTATUS_SPD_MASK) == SSTATUS_SPD_GEN1)
+		printf("(1.5 Gbps)\n\r");
+	else if ((val32 & SSTATUS_SPD_MASK) == SSTATUS_SPD_GEN2)
+		printf("(3 Gbps)\n\r");
+
+	priv->fsl_sata = sata;
+
+	return 0;
+}
+
+static int fsl_ata_exec_ata_cmd(struct fsl_sata *sata,
+				struct sata_fis_h2d *cfis,
+				int is_ncq, int tag,
+				u8 *buffer, u32 len)
+{
+	cmd_hdr_entry_t *cmd_hdr;
+	cmd_desc_t *cmd_desc;
+	sata_fis_h2d_t *h2d;
+	prd_entry_t *prde;
+	u32 ext_c_ddc;
+	u32 prde_count;
+	u32 val32;
+	u32 ttl;
+	u32 der;
+	int i;
+
+	fsl_sata_reg_t *reg = sata->reg_base;
+
+	/* Check xfer length */
+	if (len > SATA_HC_MAX_XFER_LEN) {
+		printf("max transfer length is 64MB\n\r");
+		return 0;
+	}
+
+	/* Setup the command descriptor */
+	cmd_desc = sata->cmd_desc + tag;
+
+	/* Get the pointer cfis of command descriptor */
+	h2d = (sata_fis_h2d_t *)cmd_desc->cfis;
+
+	/* Zero the cfis of command descriptor */
+	memset((void *)h2d, 0, SATA_HC_CMD_DESC_CFIS_SIZE);
+
+	/* Copy the cfis from user to command descriptor */
+	h2d->fis_type = cfis->fis_type;
+	h2d->pm_port_c = cfis->pm_port_c;
+	h2d->command = cfis->command;
+
+	h2d->features = cfis->features;
+	h2d->features_exp = cfis->features_exp;
+
+	h2d->lba_low = cfis->lba_low;
+	h2d->lba_mid = cfis->lba_mid;
+	h2d->lba_high = cfis->lba_high;
+	h2d->lba_low_exp = cfis->lba_low_exp;
+	h2d->lba_mid_exp = cfis->lba_mid_exp;
+	h2d->lba_high_exp = cfis->lba_high_exp;
+
+	if (!is_ncq) {
+		h2d->sector_count = cfis->sector_count;
+		h2d->sector_count_exp = cfis->sector_count_exp;
+	} else { /* NCQ */
+		h2d->sector_count = (u8)(tag << 3);
+	}
+
+	h2d->device = cfis->device;
+	h2d->control = cfis->control;
+
+	/* Setup the PRD table */
+	prde = (prd_entry_t *)cmd_desc->prdt;
+	memset((void *)prde, 0, sizeof(struct prdt));
+
+	prde_count = 0;
+	ttl = len;
+	for (i = 0; i < SATA_HC_MAX_PRD_DIRECT; i++) {
+		if (!len)
+			break;
+		prde->dba = cpu_to_le32((u32)buffer & ~0x3);
+		debug("dba = %08x\n\r", (u32)buffer);
+
+		if (len < PRD_ENTRY_MAX_XFER_SZ) {
+			ext_c_ddc = PRD_ENTRY_DATA_SNOOP | len;
+			debug("ext_c_ddc1 = %08x, len = %08x\n\r",
+			      ext_c_ddc, len);
+			prde->ext_c_ddc = cpu_to_le32(ext_c_ddc);
+			prde_count++;
+			prde++;
+		} else {
+			ext_c_ddc = PRD_ENTRY_DATA_SNOOP; /* 4M bytes */
+			debug("ext_c_ddc2 = %08x, len = %08x\n\r",
+			      ext_c_ddc, len);
+			prde->ext_c_ddc = cpu_to_le32(ext_c_ddc);
+			buffer += PRD_ENTRY_MAX_XFER_SZ;
+			len -= PRD_ENTRY_MAX_XFER_SZ;
+			prde_count++;
+			prde++;
+		}
+	}
+
+	/* Setup the command slot of cmd hdr */
+	cmd_hdr = (cmd_hdr_entry_t *)&sata->cmd_hdr->cmd_slot[tag];
+
+	cmd_hdr->cda = cpu_to_le32((u32)cmd_desc & ~0x3);
+
+	val32 = prde_count << CMD_HDR_PRD_ENTRY_SHIFT;
+	val32 |= sizeof(sata_fis_h2d_t);
+	cmd_hdr->prde_fis_len = cpu_to_le32(val32);
+
+	cmd_hdr->ttl = cpu_to_le32(ttl);
+
+	if (!is_ncq)
+		val32 = CMD_HDR_ATTR_RES | CMD_HDR_ATTR_SNOOP;
+	else
+		val32 = CMD_HDR_ATTR_RES | CMD_HDR_ATTR_SNOOP |
+			CMD_HDR_ATTR_FPDMA;
+
+	tag &= CMD_HDR_ATTR_TAG;
+	val32 |= tag;
+
+	debug("attribute = %08x\n\r", val32);
+	cmd_hdr->attribute = cpu_to_le32(val32);
+
+	/* Make sure cmd desc and cmd slot valid before command issue */
+	sync();
+
+	/* PMP*/
+	val32 = (u32)(h2d->pm_port_c & 0x0f);
+	out_le32(&reg->cqpmp, val32);
+
+	/* Wait no active */
+	if (ata_wait_register(&reg->car, (1 << tag), 0, 10000))
+		printf("Wait no active time out\n\r");
+
+	/* Issue command */
+	if (!(in_le32(&reg->cqr) & (1 << tag))) {
+		val32 = 1 << tag;
+		out_le32(&reg->cqr, val32);
+	}
+
+	/* Wait command completed for 10s */
+	if (ata_wait_register(&reg->ccr, (1 << tag), (1 << tag), 10000)) {
+		if (!is_ncq)
+			printf("Non-NCQ command time out\n\r");
+		else
+			printf("NCQ command time out\n\r");
+	}
+
+	val32 = in_le32(&reg->cer);
+
+	if (val32) {
+		fsl_sata_dump_sfis((struct sata_fis_d2h *)cmd_desc->sfis);
+		printf("CE at device\n\r");
+		fsl_sata_dump_regs(reg);
+		der = in_le32(&reg->der);
+		out_le32(&reg->cer, val32);
+		out_le32(&reg->der, der);
+	}
+
+	/* Clear complete flags */
+	val32 = in_le32(&reg->ccr);
+	out_le32(&reg->ccr, val32);
+
+	return len;
+}
+
+static int fsl_sata_exec_cmd(struct fsl_sata *sata, struct sata_fis_h2d *cfis,
+			     enum cmd_type command_type, int tag, u8 *buffer,
+			     u32 len)
+{
+	int rc;
+
+	if (tag > SATA_HC_MAX_CMD || tag < 0) {
+		printf("tag is out of range, tag=%d\n\r", tag);
+		return -1;
+	}
+
+	switch (command_type) {
+	case CMD_ATA:
+		rc = fsl_ata_exec_ata_cmd(sata, cfis, 0, tag, buffer, len);
+		return rc;
+	case CMD_NCQ:
+		rc = fsl_ata_exec_ata_cmd(sata, cfis, 1, tag, buffer, len);
+		return rc;
+	case CMD_ATAPI:
+	case CMD_VENDOR_BIST:
+	case CMD_BIST:
+		printf("not support now\n\r");
+		return -1;
+	default:
+		break;
+	}
+
+	return -1;
+}
+
+static void fsl_sata_identify(fsl_sata_t *sata, u16 *id)
+{
+	struct sata_fis_h2d h2d, *cfis = &h2d;
+
+	memset(cfis, 0, sizeof(struct sata_fis_h2d));
+
+	cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
+	cfis->pm_port_c = 0x80; /* is command */
+	cfis->command = ATA_CMD_ID_ATA;
+
+	fsl_sata_exec_cmd(sata, cfis, CMD_ATA, 0, (u8 *)id, ATA_ID_WORDS * 2);
+	ata_swap_buf_le16(id, ATA_ID_WORDS);
+}
+
+static void fsl_sata_xfer_mode(fsl_sata_t *sata, u16 *id)
+{
+	sata->pio = id[ATA_ID_PIO_MODES];
+	sata->mwdma = id[ATA_ID_MWDMA_MODES];
+	sata->udma = id[ATA_ID_UDMA_MODES];
+	debug("pio %04x, mwdma %04x, udma %04x\n\r", sata->pio,
+	      sata->mwdma, sata->udma);
+}
+
+static void fsl_sata_init_wcache(fsl_sata_t *sata, u16 *id)
+{
+	if (ata_id_has_wcache(id) && ata_id_wcache_enabled(id))
+		sata->wcache = 1;
+	if (ata_id_has_flush(id))
+		sata->flush = 1;
+	if (ata_id_has_flush_ext(id))
+		sata->flush_ext = 1;
+}
+
+static void fsl_sata_set_features(fsl_sata_t *sata)
+{
+	struct sata_fis_h2d h2d, *cfis = &h2d;
+	u8 udma_cap;
+
+	memset(cfis, 0, sizeof(struct sata_fis_h2d));
+
+	cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
+	cfis->pm_port_c = 0x80; /* is command */
+	cfis->command = ATA_CMD_SET_FEATURES;
+	cfis->features = SETFEATURES_XFER;
+
+	/* First check the device capablity */
+	udma_cap = (u8)(sata->udma & 0xff);
+	debug("udma_cap %02x\n\r", udma_cap);
+
+	if (udma_cap == ATA_UDMA6)
+		cfis->sector_count = XFER_UDMA_6;
+	if (udma_cap == ATA_UDMA5)
+		cfis->sector_count = XFER_UDMA_5;
+	if (udma_cap == ATA_UDMA4)
+		cfis->sector_count = XFER_UDMA_4;
+	if (udma_cap == ATA_UDMA3)
+		cfis->sector_count = XFER_UDMA_3;
+
+	fsl_sata_exec_cmd(sata, cfis, CMD_ATA, 0, NULL, 0);
+}
+
+static u32 fsl_sata_rw_cmd(fsl_sata_t *sata, u32 start, u32 blkcnt,
+			   u8 *buffer, int is_write)
+{
+	struct sata_fis_h2d h2d, *cfis = &h2d;
+	u32 block;
+
+	block = start;
+
+	memset(cfis, 0, sizeof(struct sata_fis_h2d));
+
+	cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
+	cfis->pm_port_c = 0x80; /* is command */
+	cfis->command = (is_write) ? ATA_CMD_WRITE : ATA_CMD_READ;
+	cfis->device = ATA_LBA;
+
+	cfis->device |= (block >> 24) & 0xf;
+	cfis->lba_high = (block >> 16) & 0xff;
+	cfis->lba_mid = (block >> 8) & 0xff;
+	cfis->lba_low = block & 0xff;
+	cfis->sector_count = (u8)(blkcnt & 0xff);
+
+	fsl_sata_exec_cmd(sata, cfis, CMD_ATA, 0, buffer,
+			  ATA_SECT_SIZE * blkcnt);
+	return blkcnt;
+}
+
+static void fsl_sata_flush_cache(fsl_sata_t *sata)
+{
+	struct sata_fis_h2d h2d, *cfis = &h2d;
+
+	memset(cfis, 0, sizeof(struct sata_fis_h2d));
+
+	cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
+	cfis->pm_port_c = 0x80; /* is command */
+	cfis->command = ATA_CMD_FLUSH;
+
+	fsl_sata_exec_cmd(sata, cfis, CMD_ATA, 0, NULL, 0);
+}
+
+static u32 fsl_sata_rw_cmd_ext(fsl_sata_t *sata, u32 start,
+			       u32 blkcnt, u8 *buffer, int is_write)
+{
+	struct sata_fis_h2d h2d, *cfis = &h2d;
+	u64 block;
+
+	block = (u64)start;
+
+	memset(cfis, 0, sizeof(struct sata_fis_h2d));
+
+	cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
+	cfis->pm_port_c = 0x80; /* is command */
+
+	cfis->command = (is_write) ? ATA_CMD_WRITE_EXT
+				 : ATA_CMD_READ_EXT;
+
+	cfis->lba_high_exp = (block >> 40) & 0xff;
+	cfis->lba_mid_exp = (block >> 32) & 0xff;
+	cfis->lba_low_exp = (block >> 24) & 0xff;
+	cfis->lba_high = (block >> 16) & 0xff;
+	cfis->lba_mid = (block >> 8) & 0xff;
+	cfis->lba_low = block & 0xff;
+	cfis->device = ATA_LBA;
+	cfis->sector_count_exp = (blkcnt >> 8) & 0xff;
+	cfis->sector_count = blkcnt & 0xff;
+
+	fsl_sata_exec_cmd(sata, cfis, CMD_ATA, 0, buffer,
+			  ATA_SECT_SIZE * blkcnt);
+	return blkcnt;
+}
+
+static u32 fsl_sata_rw_ncq_cmd(fsl_sata_t *sata, u32 start, u32 blkcnt,
+			       u8 *buffer,
+			       int is_write)
+{
+	struct sata_fis_h2d h2d, *cfis = &h2d;
+	int ncq_channel;
+	u64 block;
+
+	if (sata->lba48 != 1) {
+		printf("execute FPDMA command on non-LBA48 hard disk\n\r");
+		return -1;
+	}
+
+	block = (u64)start;
+
+	memset(cfis, 0, sizeof(struct sata_fis_h2d));
+
+	cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
+	cfis->pm_port_c = 0x80; /* is command */
+
+	cfis->command = (is_write) ? ATA_CMD_FPDMA_WRITE
+				 : ATA_CMD_FPDMA_READ;
+
+	cfis->lba_high_exp = (block >> 40) & 0xff;
+	cfis->lba_mid_exp = (block >> 32) & 0xff;
+	cfis->lba_low_exp = (block >> 24) & 0xff;
+	cfis->lba_high = (block >> 16) & 0xff;
+	cfis->lba_mid = (block >> 8) & 0xff;
+	cfis->lba_low = block & 0xff;
+
+	cfis->device = ATA_LBA;
+	cfis->features_exp = (blkcnt >> 8) & 0xff;
+	cfis->features = blkcnt & 0xff;
+
+	if (sata->queue_depth >= SATA_HC_MAX_CMD)
+		ncq_channel = SATA_HC_MAX_CMD - 1;
+	else
+		ncq_channel = sata->queue_depth - 1;
+
+	/* Use the latest queue */
+	fsl_sata_exec_cmd(sata, cfis, CMD_NCQ, ncq_channel, buffer,
+			  ATA_SECT_SIZE * blkcnt);
+	return blkcnt;
+}
+
+static void fsl_sata_flush_cache_ext(fsl_sata_t *sata)
+{
+	struct sata_fis_h2d h2d, *cfis = &h2d;
+
+	memset(cfis, 0, sizeof(struct sata_fis_h2d));
+
+	cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
+	cfis->pm_port_c = 0x80; /* is command */
+	cfis->command = ATA_CMD_FLUSH_EXT;
+
+	fsl_sata_exec_cmd(sata, cfis, CMD_ATA, 0, NULL, 0);
+}
+
+static u32 ata_low_level_rw_lba48(fsl_sata_t *sata, u32 blknr, lbaint_t blkcnt,
+				  const void *buffer, int is_write)
+{
+	u32 start, blks;
+	u8 *addr;
+	int max_blks;
+
+	start = blknr;
+	blks = blkcnt;
+	addr = (u8 *)buffer;
+
+	max_blks = ATA_MAX_SECTORS_LBA48;
+	do {
+		if (blks > max_blks) {
+			if (sata->dma_flag != FLAGS_FPDMA)
+				fsl_sata_rw_cmd_ext(sata, start, max_blks,
+						    addr, is_write);
+			else
+				fsl_sata_rw_ncq_cmd(sata, start, max_blks,
+						    addr, is_write);
+			start += max_blks;
+			blks -= max_blks;
+			addr += ATA_SECT_SIZE * max_blks;
+		} else {
+			if (sata->dma_flag != FLAGS_FPDMA)
+				fsl_sata_rw_cmd_ext(sata, start, blks,
+						    addr, is_write);
+			else
+				fsl_sata_rw_ncq_cmd(sata, start, blks,
+						    addr, is_write);
+			start += blks;
+			blks = 0;
+			addr += ATA_SECT_SIZE * blks;
+		}
+	} while (blks != 0);
+
+	return blks;
+}
+
+static u32 ata_low_level_rw_lba28(fsl_sata_t *sata, u32 blknr, u32 blkcnt,
+				  const void *buffer, int is_write)
+{
+	u32 start, blks;
+	u8 *addr;
+	int max_blks;
+
+	start = blknr;
+	blks = blkcnt;
+	addr = (u8 *)buffer;
+
+	max_blks = ATA_MAX_SECTORS;
+	do {
+		if (blks > max_blks) {
+			fsl_sata_rw_cmd(sata, start, max_blks, addr, is_write);
+			start += max_blks;
+			blks -= max_blks;
+			addr += ATA_SECT_SIZE * max_blks;
+		} else {
+			fsl_sata_rw_cmd(sata, start, blks, addr, is_write);
+			start += blks;
+			blks = 0;
+			addr += ATA_SECT_SIZE * blks;
+		}
+	} while (blks != 0);
+
+	return blks;
+}
+
+/*
+ * SATA interface between low level driver and command layer
+ */
+static int sata_read(fsl_sata_t *sata, ulong blknr, lbaint_t blkcnt,
+		     void *buffer)
+{
+	u32 rc;
+
+	if (sata->lba48)
+		rc = ata_low_level_rw_lba48(sata, blknr, blkcnt, buffer,
+					    READ_CMD);
+	else
+		rc = ata_low_level_rw_lba28(sata, blknr, blkcnt, buffer,
+					    READ_CMD);
+	return rc;
+}
+
+static int sata_write(fsl_sata_t *sata, ulong blknr, lbaint_t blkcnt,
+		      const void *buffer)
+{
+	u32 rc;
+
+	if (sata->lba48) {
+		rc = ata_low_level_rw_lba48(sata, blknr, blkcnt, buffer,
+					    WRITE_CMD);
+		if (sata->wcache && sata->flush_ext)
+			fsl_sata_flush_cache_ext(sata);
+	} else {
+		rc = ata_low_level_rw_lba28(sata, blknr, blkcnt, buffer,
+					    WRITE_CMD);
+		if (sata->wcache && sata->flush)
+			fsl_sata_flush_cache(sata);
+	}
+
+	return rc;
+}
+
+int sata_getinfo(fsl_sata_t *sata, u16 *id)
+{
+	/* if no detected link */
+	if (!sata->link)
+		return -EINVAL;
+
+#ifdef CONFIG_LBA48
+	/* Check if support LBA48 */
+	if (ata_id_has_lba48(id)) {
+		sata->lba48 = 1;
+		debug("Device support LBA48\n\r");
+	} else {
+		debug("Device supports LBA28\n\r");
+	}
+#endif
+
+	/* Get the NCQ queue depth from device */
+	sata->queue_depth = ata_id_queue_depth(id);
+
+	/* Get the xfer mode from device */
+	fsl_sata_xfer_mode(sata, id);
+
+	/* Get the write cache status from device */
+	fsl_sata_init_wcache(sata, id);
+
+	/* Set the xfer mode to highest speed */
+	fsl_sata_set_features(sata);
+
+	return 0;
+}
+
+static int fsl_scsi_exec(fsl_sata_t *sata, struct scsi_cmd *pccb,
+			 bool is_write)
+{
+	int ret;
+	u32 temp;
+	u16 blocks = 0;
+	lbaint_t start = 0;
+	u8 *buffer = pccb->pdata;
+
+	/* Retrieve the base LBA number from the ccb structure. */
+	if (pccb->cmd[0] == SCSI_READ16) {
+		memcpy(&start, pccb->cmd + 2, 8);
+		start = be64_to_cpu(start);
+	} else {
+		memcpy(&temp, pccb->cmd + 2, 4);
+		start = be32_to_cpu(temp);
+	}
+
+	if (pccb->cmd[0] == SCSI_READ16)
+		blocks = (((u16)pccb->cmd[13]) << 8) | ((u16)pccb->cmd[14]);
+	else
+		blocks = (((u16)pccb->cmd[7]) << 8) | ((u16)pccb->cmd[8]);
+
+	debug("scsi_ahci: %s %u blocks starting from lba 0x" LBAFU "\n",
+	      is_write ?  "write" : "read", blocks, start);
+
+	if (is_write)
+		ret = sata_write(sata, start, blocks, buffer);
+	else
+		ret = sata_read(sata, start, blocks, buffer);
+
+	return ret;
+}
+
+static char *fsl_ata_id_strcpy(u16 *target, u16 *src, int len)
+{
+	int i;
+
+	for (i = 0; i < len / 2; i++)
+		target[i] = src[i];
+
+	return (char *)target;
+}
+
+static int fsl_ata_scsiop_inquiry(struct ahci_uc_priv *uc_priv,
+				  struct scsi_cmd *pccb,
+				  fsl_sata_t *sata)
+{
+	u8 port;
+	u16 *idbuf;
+
+	ALLOC_CACHE_ALIGN_BUFFER(u16, tmpid, ATA_ID_WORDS);
+
+	/* Clean ccb data buffer */
+	memset(pccb->pdata, 0, pccb->datalen);
+
+	if (pccb->datalen <= 35)
+		return 0;
+
+	/* Read id from sata */
+	port = pccb->target;
+
+	fsl_sata_identify(sata, (u16 *)tmpid);
+
+	if (!uc_priv->ataid[port]) {
+		uc_priv->ataid[port] = malloc(ATA_ID_WORDS * 2);
+		if (!uc_priv->ataid[port]) {
+			printf("%s: No memory for ataid[port]\n", __func__);
+			return -ENOMEM;
+		}
+	}
+
+	idbuf = uc_priv->ataid[port];
+
+	memcpy(idbuf, tmpid, ATA_ID_WORDS * 2);
+
+	memcpy(&pccb->pdata[8], "ATA     ", 8);
+	fsl_ata_id_strcpy((u16 *)&pccb->pdata[16], &idbuf[ATA_ID_PROD], 16);
+	fsl_ata_id_strcpy((u16 *)&pccb->pdata[32], &idbuf[ATA_ID_FW_REV], 4);
+
+	sata_getinfo(sata, (u16 *)idbuf);
+#ifdef DEBUG
+	ata_dump_id(idbuf);
+#endif
+	return 0;
+}
+
+/*
+ * SCSI READ CAPACITY10 command operation.
+ */
+static int fsl_ata_scsiop_read_capacity10(struct ahci_uc_priv *uc_priv,
+					  struct scsi_cmd *pccb)
+{
+	u32 cap;
+	u64 cap64;
+	u32 block_size;
+
+	if (!uc_priv->ataid[pccb->target]) {
+		printf("scsi_ahci: SCSI READ CAPACITY10 command failure.");
+		printf("\tNo ATA info!\n");
+		printf("\tPlease run SCSI command INQUIRY first!\n");
+		return -EPERM;
+	}
+
+	cap64 = ata_id_n_sectors(uc_priv->ataid[pccb->target]);
+	if (cap64 > 0x100000000ULL)
+		cap64 = 0xffffffff;
+
+	cap = cpu_to_be32(cap64);
+	memcpy(pccb->pdata, &cap, sizeof(cap));
+
+	block_size = cpu_to_be32((u32)512);
+	memcpy(&pccb->pdata[4], &block_size, 4);
+
+	return 0;
+}
+
+/*
+ * SCSI READ CAPACITY16 command operation.
+ */
+static int fsl_ata_scsiop_read_capacity16(struct ahci_uc_priv *uc_priv,
+					  struct scsi_cmd *pccb)
+{
+	u64 cap;
+	u64 block_size;
+
+	if (!uc_priv->ataid[pccb->target]) {
+		printf("scsi_ahci: SCSI READ CAPACITY16 command failure.");
+		printf("\tNo ATA info!\n");
+		printf("\tPlease run SCSI command INQUIRY first!\n");
+		return -EPERM;
+	}
+
+	cap = ata_id_n_sectors(uc_priv->ataid[pccb->target]);
+	cap = cpu_to_be64(cap);
+	memcpy(pccb->pdata, &cap, sizeof(cap));
+
+	block_size = cpu_to_be64((u64)512);
+	memcpy(&pccb->pdata[8], &block_size, 8);
+
+	return 0;
+}
+
+/*
+ * SCSI TEST UNIT READY command operation.
+ */
+static int fsl_ata_scsiop_test_unit_ready(struct ahci_uc_priv *uc_priv,
+					  struct scsi_cmd *pccb)
+{
+	return (uc_priv->ataid[pccb->target]) ? 0 : -EPERM;
+}
+
+static int fsl_ahci_scsi_exec(struct udevice *dev, struct scsi_cmd *pccb)
+{
+	struct ahci_uc_priv *uc_priv = dev_get_uclass_priv(dev->parent);
+	struct fsl_ahci_priv *priv = dev_get_priv(dev->parent);
+	fsl_sata_t *sata = priv->fsl_sata;
+	int ret;
+
+	switch (pccb->cmd[0]) {
+	case SCSI_READ16:
+	case SCSI_READ10:
+		ret = fsl_scsi_exec(sata, pccb, 0);
+		break;
+	case SCSI_WRITE10:
+		ret = fsl_scsi_exec(sata, pccb, 1);
+		break;
+	case SCSI_RD_CAPAC10:
+		ret = fsl_ata_scsiop_read_capacity10(uc_priv, pccb);
+		break;
+	case SCSI_RD_CAPAC16:
+		ret = fsl_ata_scsiop_read_capacity16(uc_priv, pccb);
+		break;
+	case SCSI_TST_U_RDY:
+		ret = fsl_ata_scsiop_test_unit_ready(uc_priv, pccb);
+		break;
+	case SCSI_INQUIRY:
+		ret = fsl_ata_scsiop_inquiry(uc_priv, pccb, sata);
+		break;
+	default:
+		printf("Unsupport SCSI command 0x%02x\n", pccb->cmd[0]);
+		return -ENOTSUPP;
+	}
+
+	if (ret) {
+		debug("SCSI command 0x%02x ret errno %d\n", pccb->cmd[0], ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int fsl_ahci_probe(struct udevice *dev)
+{
+	struct fsl_ahci_priv *priv = dev_get_priv(dev);
+	struct udevice *child_dev;
+	struct scsi_platdata *uc_plat;
+
+	device_find_first_child(dev, &child_dev);
+	if (!child_dev)
+		return -ENODEV;
+	uc_plat = dev_get_uclass_platdata(child_dev);
+	uc_plat->base = priv->base;
+	uc_plat->max_lun = 1;
+	uc_plat->max_id = 1;
+
+	return init_sata(priv);
+}
+
+struct scsi_ops fsl_scsi_ops = {
+	.exec		= fsl_ahci_scsi_exec,
+};
+
+static const struct udevice_id fsl_ahci_ids[] = {
+	{ .compatible = "fsl,pq-sata-v2" },
+	{ }
+};
+
+U_BOOT_DRIVER(fsl_ahci_scsi) = {
+	.name		= "fsl_ahci_scsi",
+	.id		= UCLASS_SCSI,
+	.ops		= &fsl_scsi_ops,
+};
+
+U_BOOT_DRIVER(fsl_ahci) = {
+	.name	= "fsl_ahci",
+	.id	= UCLASS_AHCI,
+	.of_match = fsl_ahci_ids,
+	.bind	= fsl_ahci_bind,
+	.ofdata_to_platdata = fsl_ahci_ofdata_to_platdata,
+	.probe	= fsl_ahci_probe,
+	.priv_auto_alloc_size = sizeof(struct fsl_ahci_priv),
+};
diff --git a/drivers/ata/fsl_sata.h b/drivers/ata/fsl_sata.h
index 1e2da10..a4ee83d 100644
--- a/drivers/ata/fsl_sata.h
+++ b/drivers/ata/fsl_sata.h
@@ -312,6 +312,7 @@
 	int		wcache;
 	int		flush;
 	int		flush_ext;
+	u32		dma_flag;
 } fsl_sata_t;
 
 #define READ_CMD	0
diff --git a/drivers/clk/clk_stm32mp1.c b/drivers/clk/clk_stm32mp1.c
index 24859fd..6272b00 100644
--- a/drivers/clk/clk_stm32mp1.c
+++ b/drivers/clk/clk_stm32mp1.c
@@ -1448,6 +1448,71 @@
 	setbits_le32(priv->base + pll[pll_id].pllxcr, RCC_PLLNCR_SSCG_CTRL);
 }
 
+static  __maybe_unused int pll_set_rate(struct udevice *dev,
+					int pll_id,
+					int div_id,
+					unsigned long clk_rate)
+{
+	struct stm32mp1_clk_priv *priv = dev_get_priv(dev);
+	unsigned int pllcfg[PLLCFG_NB];
+	ofnode plloff;
+	char name[12];
+	const struct stm32mp1_clk_pll *pll = priv->data->pll;
+	enum stm32mp1_plltype type = pll[pll_id].plltype;
+	int divm, divn, divy;
+	int ret;
+	ulong fck_ref;
+	u32 fracv;
+	u64 value;
+
+	if (div_id > _DIV_NB)
+		return -EINVAL;
+
+	sprintf(name, "st,pll@%d", pll_id);
+	plloff = dev_read_subnode(dev, name);
+	if (!ofnode_valid(plloff))
+		return -FDT_ERR_NOTFOUND;
+
+	ret = ofnode_read_u32_array(plloff, "cfg",
+				    pllcfg, PLLCFG_NB);
+	if (ret < 0)
+		return -FDT_ERR_NOTFOUND;
+
+	fck_ref = pll_get_fref_ck(priv, pll_id);
+
+	divm = pllcfg[PLLCFG_M];
+	/* select output divider = 0: for _DIV_P, 1:_DIV_Q 2:_DIV_R */
+	divy = pllcfg[PLLCFG_P + div_id];
+
+	/* For: PLL1 & PLL2 => VCO is * 2 but ck_pll_y is also / 2
+	 * So same final result than PLL2 et 4
+	 * with FRACV
+	 * Fck_pll_y = Fck_ref * ((DIVN + 1) + FRACV / 2^13)
+	 *             / (DIVy + 1) * (DIVM + 1)
+	 * value = (DIVN + 1) * 2^13 + FRACV / 2^13
+	 *       = Fck_pll_y (DIVy + 1) * (DIVM + 1) * 2^13 / Fck_ref
+	 */
+	value = ((u64)clk_rate * (divy + 1) * (divm + 1)) << 13;
+	value = lldiv(value, fck_ref);
+
+	divn = (value >> 13) - 1;
+	if (divn < DIVN_MIN ||
+	    divn > stm32mp1_pll[type].divn_max) {
+		pr_err("divn invalid = %d", divn);
+		return -EINVAL;
+	}
+	fracv = value - ((divn + 1) << 13);
+	pllcfg[PLLCFG_N] = divn;
+
+	/* reconfigure PLL */
+	pll_stop(priv, pll_id);
+	pll_config(priv, pll_id, pllcfg, fracv);
+	pll_start(priv, pll_id);
+	pll_output(priv, pll_id, pllcfg[PLLCFG_O]);
+
+	return 0;
+}
+
 static int set_clksrc(struct stm32mp1_clk_priv *priv, unsigned int clksrc)
 {
 	u32 address = priv->base + (clksrc >> 4);
@@ -1820,6 +1885,11 @@
 	int p;
 
 	switch (clk->id) {
+#if defined(STM32MP1_CLOCK_TREE_INIT) && \
+	defined(CONFIG_STM32MP1_DDR_INTERACTIVE)
+	case DDRPHYC:
+		break;
+#endif
 	case LTDC_PX:
 	case DSI_PX:
 		break;
@@ -1833,6 +1903,19 @@
 		return -EINVAL;
 
 	switch (p) {
+#if defined(STM32MP1_CLOCK_TREE_INIT) && \
+	defined(CONFIG_STM32MP1_DDR_INTERACTIVE)
+	case _PLL2_R: /* DDRPHYC */
+	{
+		/* only for change DDR clock in interactive mode */
+		ulong result;
+
+		set_clksrc(priv, CLK_AXI_HSI);
+		result = pll_set_rate(clk->dev,  _PLL2, _DIV_R, clk_rate);
+		set_clksrc(priv, CLK_AXI_PLL2P);
+		return result;
+	}
+#endif
 	case _PLL4_Q:
 		/* for LTDC_PX and DSI_PX case */
 		return pll_set_output_rate(clk->dev, _PLL4, _DIV_Q, clk_rate);
diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c
index 3872364..50c4fd0 100644
--- a/drivers/i2c/stm32f7_i2c.c
+++ b/drivers/i2c/stm32f7_i2c.c
@@ -500,7 +500,7 @@
 	af_delay_max = setup->analog_filter ?
 		       STM32_I2C_ANALOG_FILTER_DELAY_MAX : 0;
 
-	sdadel_min = setup->fall_time - i2c_specs[setup->speed].hddat_min -
+	sdadel_min = i2c_specs[setup->speed].hddat_min + setup->fall_time -
 		     af_delay_min - (setup->dnf + 3) * i2cclk;
 
 	sdadel_max = i2c_specs[setup->speed].vddat_max - setup->rise_time -
@@ -540,8 +540,12 @@
 					p_prev = p;
 
 					list_add_tail(&v->node, solutions);
+					break;
 				}
 			}
+
+			if (p_prev == p)
+				break;
 		}
 	}
 
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index 377b267..672691f 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -1435,7 +1435,9 @@
 #endif
 
 #if CONFIG_IS_ENABLED(DM_MMC)
+#ifndef CONFIG_PPC
 #include <asm/arch/clock.h>
+#endif
 __weak void init_clk_usdhc(u32 index)
 {
 }
@@ -1460,8 +1462,11 @@
 	addr = dev_read_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
-
+#ifdef CONFIG_PPC
+	priv->esdhc_regs = (struct fsl_esdhc *)lower_32_bits(addr);
+#else
 	priv->esdhc_regs = (struct fsl_esdhc *)addr;
+#endif
 	priv->dev = dev;
 	priv->mode = -1;
 	if (data) {
@@ -1568,7 +1573,11 @@
 
 		priv->sdhc_clk = clk_get_rate(&priv->per_clk);
 	} else {
+#ifndef CONFIG_PPC
 		priv->sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK + dev->seq);
+#else
+		priv->sdhc_clk = gd->arch.sdhc_clk;
+#endif
 		if (priv->sdhc_clk <= 0) {
 			dev_err(dev, "Unable to get clk for %s\n", dev->name);
 			return -EINVAL;
diff --git a/drivers/ram/stm32mp1/Kconfig b/drivers/ram/stm32mp1/Kconfig
index b9c8166..2fd8c7b 100644
--- a/drivers/ram/stm32mp1/Kconfig
+++ b/drivers/ram/stm32mp1/Kconfig
@@ -10,3 +10,40 @@
 		family:	support for LPDDR2, LPDDR3 and DDR3
 		the SDRAM parameters for controleur and phy need to be provided
 		in device tree (computed by DDR tuning tools)
+
+config STM32MP1_DDR_INTERACTIVE
+	bool "STM32MP1 DDR driver : interactive support"
+	depends on STM32MP1_DDR
+	help
+		activate interactive support in STM32MP1 DDR controller driver
+		used for DDR tuning tools
+		to enter in intercative mode type 'd' during SPL DDR driver
+		initialisation
+
+config STM32MP1_DDR_INTERACTIVE_FORCE
+	bool "STM32MP1 DDR driver : force interactive mode"
+	depends on STM32MP1_DDR_INTERACTIVE
+	default n
+	help
+		force interactive mode in STM32MP1 DDR controller driver
+		skip the polling of character 'd' in console
+		useful when SPL is loaded in sysram
+		directly by programmer
+
+config STM32MP1_DDR_TESTS
+	bool "STM32MP1 DDR driver : tests support"
+	depends on STM32MP1_DDR_INTERACTIVE
+	default y
+	help
+		activate test support for interactive support in
+		STM32MP1 DDR controller driver: command test
+
+config STM32MP1_DDR_TUNING
+	bool "STM32MP1 DDR driver : support of tuning"
+	depends on STM32MP1_DDR_INTERACTIVE
+	default y
+	help
+		activate tuning command in STM32MP1 DDR interactive mode
+		used for DDR tuning tools
+		- DQ Deskew algorithm
+		- DQS Trimming
diff --git a/drivers/ram/stm32mp1/Makefile b/drivers/ram/stm32mp1/Makefile
index 79eb028..e1e9135 100644
--- a/drivers/ram/stm32mp1/Makefile
+++ b/drivers/ram/stm32mp1/Makefile
@@ -5,3 +5,11 @@
 
 obj-y += stm32mp1_ram.o
 obj-y += stm32mp1_ddr.o
+
+obj-$(CONFIG_STM32MP1_DDR_INTERACTIVE) += stm32mp1_interactive.o
+obj-$(CONFIG_STM32MP1_DDR_TESTS) += stm32mp1_tests.o
+obj-$(CONFIG_STM32MP1_DDR_TUNING) += stm32mp1_tuning.o
+
+ifneq ($(DDR_INTERACTIVE),)
+CFLAGS_stm32mp1_interactive.o += -DCONFIG_STM32MP1_DDR_INTERACTIVE_FORCE=y
+endif
diff --git a/drivers/ram/stm32mp1/stm32mp1_ddr.c b/drivers/ram/stm32mp1/stm32mp1_ddr.c
index c7c3ba7..d765a46 100644
--- a/drivers/ram/stm32mp1/stm32mp1_ddr.c
+++ b/drivers/ram/stm32mp1/stm32mp1_ddr.c
@@ -41,8 +41,32 @@
 	 offsetof(struct stm32mp1_ddrphy, x),\
 	 offsetof(struct y, x)}
 
+#define DDR_REG_DYN(x) \
+	{#x,\
+	 offsetof(struct stm32mp1_ddrctl, x),\
+	 INVALID_OFFSET}
+
+#define DDRPHY_REG_DYN(x) \
+	{#x,\
+	 offsetof(struct stm32mp1_ddrphy, x),\
+	 INVALID_OFFSET}
+
+/***********************************************************
+ * PARAMETERS: value get from device tree :
+ *             size / order need to be aligned with binding
+ *             modification NOT ALLOWED !!!
+ ***********************************************************/
+#define DDRCTL_REG_REG_SIZE	25	/* st,ctl-reg */
+#define DDRCTL_REG_TIMING_SIZE	12	/* st,ctl-timing */
+#define DDRCTL_REG_MAP_SIZE	9	/* st,ctl-map */
+#define DDRCTL_REG_PERF_SIZE	17	/* st,ctl-perf */
+
+#define DDRPHY_REG_REG_SIZE	11	/* st,phy-reg */
+#define	DDRPHY_REG_TIMING_SIZE	10	/* st,phy-timing */
+#define	DDRPHY_REG_CAL_SIZE	12	/* st,phy-cal */
+
 #define DDRCTL_REG_REG(x)	DDRCTL_REG(x, stm32mp1_ddrctrl_reg)
-static const struct reg_desc ddr_reg[] = {
+static const struct reg_desc ddr_reg[DDRCTL_REG_REG_SIZE] = {
 	DDRCTL_REG_REG(mstr),
 	DDRCTL_REG_REG(mrctrl0),
 	DDRCTL_REG_REG(mrctrl1),
@@ -71,7 +95,7 @@
 };
 
 #define DDRCTL_REG_TIMING(x)	DDRCTL_REG(x, stm32mp1_ddrctrl_timing)
-static const struct reg_desc ddr_timing[] = {
+static const struct reg_desc ddr_timing[DDRCTL_REG_TIMING_SIZE] = {
 	DDRCTL_REG_TIMING(rfshtmg),
 	DDRCTL_REG_TIMING(dramtmg0),
 	DDRCTL_REG_TIMING(dramtmg1),
@@ -87,7 +111,7 @@
 };
 
 #define DDRCTL_REG_MAP(x)	DDRCTL_REG(x, stm32mp1_ddrctrl_map)
-static const struct reg_desc ddr_map[] = {
+static const struct reg_desc ddr_map[DDRCTL_REG_MAP_SIZE] = {
 	DDRCTL_REG_MAP(addrmap1),
 	DDRCTL_REG_MAP(addrmap2),
 	DDRCTL_REG_MAP(addrmap3),
@@ -100,7 +124,7 @@
 };
 
 #define DDRCTL_REG_PERF(x)	DDRCTL_REG(x, stm32mp1_ddrctrl_perf)
-static const struct reg_desc ddr_perf[] = {
+static const struct reg_desc ddr_perf[DDRCTL_REG_PERF_SIZE] = {
 	DDRCTL_REG_PERF(sched),
 	DDRCTL_REG_PERF(sched1),
 	DDRCTL_REG_PERF(perfhpr1),
@@ -121,7 +145,7 @@
 };
 
 #define DDRPHY_REG_REG(x)	DDRPHY_REG(x, stm32mp1_ddrphy_reg)
-static const struct reg_desc ddrphy_reg[] = {
+static const struct reg_desc ddrphy_reg[DDRPHY_REG_REG_SIZE] = {
 	DDRPHY_REG_REG(pgcr),
 	DDRPHY_REG_REG(aciocr),
 	DDRPHY_REG_REG(dxccr),
@@ -136,7 +160,7 @@
 };
 
 #define DDRPHY_REG_TIMING(x)	DDRPHY_REG(x, stm32mp1_ddrphy_timing)
-static const struct reg_desc ddrphy_timing[] = {
+static const struct reg_desc ddrphy_timing[DDRPHY_REG_TIMING_SIZE] = {
 	DDRPHY_REG_TIMING(ptr0),
 	DDRPHY_REG_TIMING(ptr1),
 	DDRPHY_REG_TIMING(ptr2),
@@ -150,7 +174,7 @@
 };
 
 #define DDRPHY_REG_CAL(x)	DDRPHY_REG(x, stm32mp1_ddrphy_cal)
-static const struct reg_desc ddrphy_cal[] = {
+static const struct reg_desc ddrphy_cal[DDRPHY_REG_CAL_SIZE] = {
 	DDRPHY_REG_CAL(dx0dllcr),
 	DDRPHY_REG_CAL(dx0dqtr),
 	DDRPHY_REG_CAL(dx0dqstr),
@@ -165,6 +189,45 @@
 	DDRPHY_REG_CAL(dx3dqstr),
 };
 
+/**************************************************************
+ * DYNAMIC REGISTERS: only used for debug purpose (read/modify)
+ **************************************************************/
+#ifdef CONFIG_STM32MP1_DDR_INTERACTIVE
+static const struct reg_desc ddr_dyn[] = {
+	DDR_REG_DYN(stat),
+	DDR_REG_DYN(init0),
+	DDR_REG_DYN(dfimisc),
+	DDR_REG_DYN(dfistat),
+	DDR_REG_DYN(swctl),
+	DDR_REG_DYN(swstat),
+	DDR_REG_DYN(pctrl_0),
+	DDR_REG_DYN(pctrl_1),
+};
+
+#define DDR_REG_DYN_SIZE	ARRAY_SIZE(ddr_dyn)
+
+static const struct reg_desc ddrphy_dyn[] = {
+	DDRPHY_REG_DYN(pir),
+	DDRPHY_REG_DYN(pgsr),
+	DDRPHY_REG_DYN(zq0sr0),
+	DDRPHY_REG_DYN(zq0sr1),
+	DDRPHY_REG_DYN(dx0gsr0),
+	DDRPHY_REG_DYN(dx0gsr1),
+	DDRPHY_REG_DYN(dx1gsr0),
+	DDRPHY_REG_DYN(dx1gsr1),
+	DDRPHY_REG_DYN(dx2gsr0),
+	DDRPHY_REG_DYN(dx2gsr1),
+	DDRPHY_REG_DYN(dx3gsr0),
+	DDRPHY_REG_DYN(dx3gsr1),
+};
+
+#define DDRPHY_REG_DYN_SIZE	ARRAY_SIZE(ddrphy_dyn)
+
+#endif
+
+/*****************************************************************
+ * REGISTERS ARRAY: used to parse device tree and interactive mode
+ *****************************************************************/
 enum reg_type {
 	REG_REG,
 	REG_TIMING,
@@ -173,6 +236,13 @@
 	REGPHY_REG,
 	REGPHY_TIMING,
 	REGPHY_CAL,
+#ifdef CONFIG_STM32MP1_DDR_INTERACTIVE
+/* dynamic registers => managed in driver or not changed,
+ * can be dumped in interactive mode
+ */
+	REG_DYN,
+	REGPHY_DYN,
+#endif
 	REG_TYPE_NB
 };
 
@@ -193,19 +263,26 @@
 
 const struct ddr_reg_info ddr_registers[REG_TYPE_NB] = {
 [REG_REG] = {
-	"static", ddr_reg, ARRAY_SIZE(ddr_reg), DDR_BASE},
+	"static", ddr_reg, DDRCTL_REG_REG_SIZE, DDR_BASE},
 [REG_TIMING] = {
-	"timing", ddr_timing, ARRAY_SIZE(ddr_timing), DDR_BASE},
+	"timing", ddr_timing, DDRCTL_REG_TIMING_SIZE, DDR_BASE},
 [REG_PERF] = {
-	"perf", ddr_perf, ARRAY_SIZE(ddr_perf), DDR_BASE},
+	"perf", ddr_perf, DDRCTL_REG_PERF_SIZE, DDR_BASE},
 [REG_MAP] = {
-	"map", ddr_map, ARRAY_SIZE(ddr_map), DDR_BASE},
+	"map", ddr_map, DDRCTL_REG_MAP_SIZE, DDR_BASE},
 [REGPHY_REG] = {
-	"static", ddrphy_reg, ARRAY_SIZE(ddrphy_reg), DDRPHY_BASE},
+	"static", ddrphy_reg, DDRPHY_REG_REG_SIZE, DDRPHY_BASE},
 [REGPHY_TIMING] = {
-	"timing", ddrphy_timing, ARRAY_SIZE(ddrphy_timing), DDRPHY_BASE},
+	"timing", ddrphy_timing, DDRPHY_REG_TIMING_SIZE, DDRPHY_BASE},
 [REGPHY_CAL] = {
-	"cal", ddrphy_cal, ARRAY_SIZE(ddrphy_cal), DDRPHY_BASE},
+	"cal", ddrphy_cal, DDRPHY_REG_CAL_SIZE, DDRPHY_BASE},
+#ifdef CONFIG_STM32MP1_DDR_INTERACTIVE
+[REG_DYN] = {
+	"dyn", ddr_dyn, DDR_REG_DYN_SIZE, DDR_BASE},
+[REGPHY_DYN] = {
+	"dyn", ddrphy_dyn, DDRPHY_REG_DYN_SIZE, DDRPHY_BASE},
+#endif
+
 };
 
 const char *base_name[] = {
@@ -244,8 +321,233 @@
 			      (u32)ptr, desc[i].name, value);
 		}
 	}
+}
+
+#ifdef CONFIG_STM32MP1_DDR_INTERACTIVE
+static void stm32mp1_dump_reg_desc(u32 base_addr, const struct reg_desc *desc)
+{
+	unsigned int *ptr;
+
+	ptr = (unsigned int *)(base_addr + desc->offset);
+	printf("%s= 0x%08x\n", desc->name, readl(ptr));
+}
+
+static void stm32mp1_dump_param_desc(u32 par_addr, const struct reg_desc *desc)
+{
+	unsigned int *ptr;
+
+	ptr = (unsigned int *)(par_addr + desc->par_offset);
+	printf("%s= 0x%08x\n", desc->name, readl(ptr));
+}
+
+static const struct reg_desc *found_reg(const char *name, enum reg_type *type)
+{
+	unsigned int i, j;
+	const struct reg_desc *desc;
+
+	for (i = 0; i < ARRAY_SIZE(ddr_registers); i++) {
+		desc = ddr_registers[i].desc;
+		for (j = 0; j < ddr_registers[i].size; j++) {
+			if (strcmp(name, desc[j].name) == 0) {
+				*type = i;
+				return &desc[j];
+			}
+		}
+	}
+	*type = REG_TYPE_NB;
+	return NULL;
 }
 
+int stm32mp1_dump_reg(const struct ddr_info *priv,
+		      const char *name)
+{
+	unsigned int i, j;
+	const struct reg_desc *desc;
+	u32 base_addr;
+	enum base_type p_base;
+	enum reg_type type;
+	const char *p_name;
+	enum base_type filter = NONE_BASE;
+	int result = -1;
+
+	if (name) {
+		if (strcmp(name, base_name[DDR_BASE]) == 0)
+			filter = DDR_BASE;
+		else if (strcmp(name, base_name[DDRPHY_BASE]) == 0)
+			filter = DDRPHY_BASE;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(ddr_registers); i++) {
+		p_base = ddr_registers[i].base;
+		p_name = ddr_registers[i].name;
+		if (!name || (filter == p_base || !strcmp(name, p_name))) {
+			result = 0;
+			desc = ddr_registers[i].desc;
+			base_addr = get_base_addr(priv, p_base);
+			printf("==%s.%s==\n", base_name[p_base], p_name);
+			for (j = 0; j < ddr_registers[i].size; j++)
+				stm32mp1_dump_reg_desc(base_addr, &desc[j]);
+		}
+	}
+	if (result) {
+		desc = found_reg(name, &type);
+		if (desc) {
+			p_base = ddr_registers[type].base;
+			base_addr = get_base_addr(priv, p_base);
+			stm32mp1_dump_reg_desc(base_addr, desc);
+			result = 0;
+		}
+	}
+	return result;
+}
+
+void stm32mp1_edit_reg(const struct ddr_info *priv,
+		       char *name, char *string)
+{
+	unsigned long *ptr, value;
+	enum reg_type type;
+	enum base_type base;
+	const struct reg_desc *desc;
+	u32 base_addr;
+
+	desc = found_reg(name, &type);
+
+	if (!desc) {
+		printf("%s not found\n", name);
+		return;
+	}
+	if (strict_strtoul(string, 16, &value) < 0) {
+		printf("invalid value %s\n", string);
+		return;
+	}
+	base = ddr_registers[type].base;
+	base_addr = get_base_addr(priv, base);
+	ptr = (unsigned long *)(base_addr + desc->offset);
+	writel(value, ptr);
+	printf("%s= 0x%08x\n", desc->name, readl(ptr));
+}
+
+static u32 get_par_addr(const struct stm32mp1_ddr_config *config,
+			enum reg_type type)
+{
+	u32 par_addr = 0x0;
+
+	switch (type) {
+	case REG_REG:
+		par_addr = (u32)&config->c_reg;
+		break;
+	case REG_TIMING:
+		par_addr = (u32)&config->c_timing;
+		break;
+	case REG_PERF:
+		par_addr = (u32)&config->c_perf;
+		break;
+	case REG_MAP:
+		par_addr = (u32)&config->c_map;
+		break;
+	case REGPHY_REG:
+		par_addr = (u32)&config->p_reg;
+		break;
+	case REGPHY_TIMING:
+		par_addr = (u32)&config->p_timing;
+		break;
+	case REGPHY_CAL:
+		par_addr = (u32)&config->p_cal;
+		break;
+	case REG_DYN:
+	case REGPHY_DYN:
+	case REG_TYPE_NB:
+		par_addr = (u32)NULL;
+		break;
+	}
+
+	return par_addr;
+}
+
+int stm32mp1_dump_param(const struct stm32mp1_ddr_config *config,
+			const char *name)
+{
+	unsigned int i, j;
+	const struct reg_desc *desc;
+	u32 par_addr;
+	enum base_type p_base;
+	enum reg_type type;
+	const char *p_name;
+	enum base_type filter = NONE_BASE;
+	int result = -EINVAL;
+
+	if (name) {
+		if (strcmp(name, base_name[DDR_BASE]) == 0)
+			filter = DDR_BASE;
+		else if (strcmp(name, base_name[DDRPHY_BASE]) == 0)
+			filter = DDRPHY_BASE;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(ddr_registers); i++) {
+		par_addr = get_par_addr(config, i);
+		if (!par_addr)
+			continue;
+		p_base = ddr_registers[i].base;
+		p_name = ddr_registers[i].name;
+		if (!name || (filter == p_base || !strcmp(name, p_name))) {
+			result = 0;
+			desc = ddr_registers[i].desc;
+			printf("==%s.%s==\n", base_name[p_base], p_name);
+			for (j = 0; j < ddr_registers[i].size; j++)
+				stm32mp1_dump_param_desc(par_addr, &desc[j]);
+		}
+	}
+	if (result) {
+		desc = found_reg(name, &type);
+		if (desc) {
+			par_addr = get_par_addr(config, type);
+			if (par_addr) {
+				stm32mp1_dump_param_desc(par_addr, desc);
+				result = 0;
+			}
+		}
+	}
+	return result;
+}
+
+void stm32mp1_edit_param(const struct stm32mp1_ddr_config *config,
+			 char *name, char *string)
+{
+	unsigned long *ptr, value;
+	enum reg_type type;
+	const struct reg_desc *desc;
+	u32 par_addr;
+
+	desc = found_reg(name, &type);
+	if (!desc) {
+		printf("%s not found\n", name);
+		return;
+	}
+	if (strict_strtoul(string, 16, &value) < 0) {
+		printf("invalid value %s\n", string);
+		return;
+	}
+	par_addr = get_par_addr(config, type);
+	if (!par_addr) {
+		printf("no parameter %s\n", name);
+		return;
+	}
+	ptr = (unsigned long *)(par_addr + desc->par_offset);
+	writel(value, ptr);
+	printf("%s= 0x%08x\n", desc->name, readl(ptr));
+}
+#endif
+
+__weak bool stm32mp1_ddr_interactive(void *priv,
+				     enum stm32mp1_ddr_interact_step step,
+				     const struct stm32mp1_ddr_config *config)
+{
+	return false;
+}
+
+#define INTERACTIVE(step)\
+	stm32mp1_ddr_interactive(priv, step, config)
+
 static void ddrphy_idone_wait(struct stm32mp1_ddrphy *phy)
 {
 	u32 pgsr;
@@ -312,7 +614,7 @@
 	/* self-refresh due to software => check also STAT.selfref_type */
 	if (mode == DDRCTRL_STAT_OPERATING_MODE_SR) {
 		mask |= DDRCTRL_STAT_SELFREF_TYPE_MASK;
-		stat |= DDRCTRL_STAT_SELFREF_TYPE_SR;
+		val |= DDRCTRL_STAT_SELFREF_TYPE_SR;
 	} else if (mode == DDRCTRL_STAT_OPERATING_MODE_NORMAL) {
 		/* normal mode: handle also automatic self refresh */
 		mask2 = DDRCTRL_STAT_OPERATING_MODE_MASK |
@@ -355,7 +657,7 @@
 }
 
 /* board-specific DDR power initializations. */
-__weak int board_ddr_power_init(void)
+__weak int board_ddr_power_init(enum ddr_type ddr_type)
 {
 	return 0;
 }
@@ -365,15 +667,21 @@
 		       const struct stm32mp1_ddr_config *config)
 {
 	u32 pir;
-	int ret;
+	int ret = -EINVAL;
 
-	ret = board_ddr_power_init();
+	if (config->c_reg.mstr & DDRCTRL_MSTR_DDR3)
+		ret = board_ddr_power_init(STM32MP_DDR3);
+	else if (config->c_reg.mstr & DDRCTRL_MSTR_LPDDR2)
+		ret = board_ddr_power_init(STM32MP_LPDDR2);
+	else if (config->c_reg.mstr & DDRCTRL_MSTR_LPDDR3)
+		ret = board_ddr_power_init(STM32MP_LPDDR3);
 
 	if (ret)
 		panic("ddr power init failed\n");
 
+start:
 	debug("name = %s\n", config->info.name);
-	debug("speed = %d MHz\n", config->info.speed);
+	debug("speed = %d kHz\n", config->info.speed);
 	debug("size  = 0x%x\n", config->info.size);
 /*
  * 1. Program the DWC_ddr_umctl2 registers
@@ -389,7 +697,7 @@
 
 /* 1.2. start CLOCK */
 	if (stm32mp1_ddr_clk_enable(priv, config->info.speed))
-		panic("invalid DRAM clock : %d MHz\n",
+		panic("invalid DRAM clock : %d kHz\n",
 		      config->info.speed);
 
 /* 1.3. deassert reset */
@@ -401,11 +709,12 @@
 	 */
 	clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAPBRST);
 
-/* 1.4. wait 4 cycles for synchronization */
-	asm(" nop");
-	asm(" nop");
-	asm(" nop");
-	asm(" nop");
+/* 1.4. wait 128 cycles to permit initialization of end logic */
+	udelay(2);
+	/* for PCLK = 133MHz => 1 us is enough, 2 to allow lower frequency */
+
+	if (INTERACTIVE(STEP_DDR_RESET))
+		goto start;
 
 /* 1.5. initialize registers ddr_umctl2 */
 	/* Stop uMCTL2 before PHY is ready */
@@ -424,6 +733,9 @@
 
 	set_reg(priv, REG_PERF, &config->c_perf);
 
+	if (INTERACTIVE(STEP_CTL_INIT))
+		goto start;
+
 /*  2. deassert reset signal core_ddrc_rstn, aresetn and presetn */
 	clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCORERST);
 	clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAXIRST);
@@ -436,6 +748,9 @@
 	set_reg(priv, REGPHY_TIMING, &config->p_timing);
 	set_reg(priv, REGPHY_CAL, &config->p_cal);
 
+	if (INTERACTIVE(STEP_PHY_INIT))
+		goto start;
+
 /*  4. Monitor PHY init status by polling PUBL register PGSR.IDONE
  *     Perform DDR PHY DRAM initialization and Gate Training Evaluation
  */
@@ -492,4 +807,7 @@
 	/* enable uMCTL2 AXI port 0 and 1 */
 	setbits_le32(&priv->ctl->pctrl_0, DDRCTRL_PCTRL_N_PORT_EN);
 	setbits_le32(&priv->ctl->pctrl_1, DDRCTRL_PCTRL_N_PORT_EN);
+
+	if (INTERACTIVE(STEP_DDR_READY))
+		goto start;
 }
diff --git a/drivers/ram/stm32mp1/stm32mp1_ddr.h b/drivers/ram/stm32mp1/stm32mp1_ddr.h
index 3cd0161..a8eed89 100644
--- a/drivers/ram/stm32mp1/stm32mp1_ddr.h
+++ b/drivers/ram/stm32mp1/stm32mp1_ddr.h
@@ -157,7 +157,7 @@
 
 struct stm32mp1_ddr_info {
 	const char *name;
-	u16 speed; /* in MHZ */
+	u32 speed; /* in kHZ */
 	u32 size;  /* memory size in byte = col * row * width */
 };
 
@@ -172,7 +172,7 @@
 	struct stm32mp1_ddrphy_cal p_cal;
 };
 
-int stm32mp1_ddr_clk_enable(struct ddr_info *priv, u16 mem_speed);
+int stm32mp1_ddr_clk_enable(struct ddr_info *priv, u32 mem_speed);
 void stm32mp1_ddrphy_init(struct stm32mp1_ddrphy *phy, u32 pir);
 void stm32mp1_refresh_disable(struct stm32mp1_ddrctl *ctl);
 void stm32mp1_refresh_restore(struct stm32mp1_ddrctl *ctl,
diff --git a/drivers/ram/stm32mp1/stm32mp1_ddr_regs.h b/drivers/ram/stm32mp1/stm32mp1_ddr_regs.h
index a606b2b..9d33186 100644
--- a/drivers/ram/stm32mp1/stm32mp1_ddr_regs.h
+++ b/drivers/ram/stm32mp1/stm32mp1_ddr_regs.h
@@ -234,6 +234,8 @@
 
 /* DDRCTRL REGISTERS */
 #define DDRCTRL_MSTR_DDR3			BIT(0)
+#define DDRCTRL_MSTR_LPDDR2			BIT(2)
+#define DDRCTRL_MSTR_LPDDR3			BIT(3)
 #define DDRCTRL_MSTR_DATA_BUS_WIDTH_MASK	GENMASK(13, 12)
 #define DDRCTRL_MSTR_DATA_BUS_WIDTH_FULL	(0 << 12)
 #define DDRCTRL_MSTR_DATA_BUS_WIDTH_HALF	(1 << 12)
@@ -330,6 +332,7 @@
 
 #define DDRPHYC_DXNGCR_DXEN			BIT(0)
 
+#define DDRPHYC_DXNDLLCR_DLLSRST		BIT(30)
 #define DDRPHYC_DXNDLLCR_DLLDIS			BIT(31)
 #define DDRPHYC_DXNDLLCR_SDPHASE_MASK		GENMASK(17, 14)
 #define DDRPHYC_DXNDLLCR_SDPHASE_SHIFT		14
diff --git a/drivers/ram/stm32mp1/stm32mp1_interactive.c b/drivers/ram/stm32mp1/stm32mp1_interactive.c
new file mode 100644
index 0000000..cc9b2e7
--- /dev/null
+++ b/drivers/ram/stm32mp1/stm32mp1_interactive.c
@@ -0,0 +1,483 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common.h>
+#include <console.h>
+#include <cli.h>
+#include <clk.h>
+#include <malloc.h>
+#include <ram.h>
+#include <reset.h>
+#include "stm32mp1_ddr.h"
+#include "stm32mp1_tests.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+enum ddr_command {
+	DDR_CMD_HELP,
+	DDR_CMD_INFO,
+	DDR_CMD_FREQ,
+	DDR_CMD_RESET,
+	DDR_CMD_PARAM,
+	DDR_CMD_PRINT,
+	DDR_CMD_EDIT,
+	DDR_CMD_STEP,
+	DDR_CMD_NEXT,
+	DDR_CMD_GO,
+	DDR_CMD_TEST,
+	DDR_CMD_TUNING,
+	DDR_CMD_UNKNOWN,
+};
+
+const char *step_str[] = {
+	[STEP_DDR_RESET] = "DDR_RESET",
+	[STEP_CTL_INIT] = "DDR_CTRL_INIT_DONE",
+	[STEP_PHY_INIT] = "DDR PHY_INIT_DONE",
+	[STEP_DDR_READY] = "DDR_READY",
+	[STEP_RUN] = "RUN"
+};
+
+enum ddr_command stm32mp1_get_command(char *cmd, int argc)
+{
+	const char *cmd_string[DDR_CMD_UNKNOWN] = {
+		[DDR_CMD_HELP] = "help",
+		[DDR_CMD_INFO] = "info",
+		[DDR_CMD_FREQ] = "freq",
+		[DDR_CMD_RESET] = "reset",
+		[DDR_CMD_PARAM] = "param",
+		[DDR_CMD_PRINT] = "print",
+		[DDR_CMD_EDIT] = "edit",
+		[DDR_CMD_STEP] = "step",
+		[DDR_CMD_NEXT] = "next",
+		[DDR_CMD_GO] = "go",
+#ifdef CONFIG_STM32MP1_DDR_TESTS
+		[DDR_CMD_TEST] = "test",
+#endif
+#ifdef CONFIG_STM32MP1_DDR_TUNING
+		[DDR_CMD_TUNING] = "tuning",
+#endif
+	};
+	/* min and max number of argument */
+	const char cmd_arg[DDR_CMD_UNKNOWN][2] = {
+		[DDR_CMD_HELP] = { 0, 0 },
+		[DDR_CMD_INFO] = { 0, 255 },
+		[DDR_CMD_FREQ] = { 0, 1 },
+		[DDR_CMD_RESET] = { 0, 0 },
+		[DDR_CMD_PARAM] = { 0, 2 },
+		[DDR_CMD_PRINT] = { 0, 1 },
+		[DDR_CMD_EDIT] = { 2, 2 },
+		[DDR_CMD_STEP] = { 0, 1 },
+		[DDR_CMD_NEXT] = { 0, 0 },
+		[DDR_CMD_GO] = { 0, 0 },
+#ifdef CONFIG_STM32MP1_DDR_TESTS
+		[DDR_CMD_TEST] = { 0, 255 },
+#endif
+#ifdef CONFIG_STM32MP1_DDR_TUNING
+		[DDR_CMD_TUNING] = { 0, 255 },
+#endif
+	};
+	int i;
+
+	for (i = 0; i < DDR_CMD_UNKNOWN; i++)
+		if (!strcmp(cmd, cmd_string[i])) {
+			if (argc - 1 < cmd_arg[i][0]) {
+				printf("no enought argument (min=%d)\n",
+				       cmd_arg[i][0]);
+				return DDR_CMD_UNKNOWN;
+			} else if (argc - 1 > cmd_arg[i][1]) {
+				printf("too many argument (max=%d)\n",
+				       cmd_arg[i][1]);
+				return DDR_CMD_UNKNOWN;
+			} else {
+				return i;
+			}
+		}
+
+	printf("unknown command %s\n", cmd);
+	return DDR_CMD_UNKNOWN;
+}
+
+static void stm32mp1_do_usage(void)
+{
+	const char *usage = {
+		"commands:\n\n"
+		"help                       displays help\n"
+		"info                       displays DDR information\n"
+		"info  <param> <val>        changes DDR information\n"
+		"      with <param> = step, name, size or speed\n"
+		"freq                       displays the DDR PHY frequency in kHz\n"
+		"freq  <freq>               changes the DDR PHY frequency\n"
+		"param [type|reg]           prints input parameters\n"
+		"param <reg> <val>          edits parameters in step 0\n"
+		"print [type|reg]           dumps registers\n"
+		"edit <reg> <val>           modifies one register\n"
+		"step                       lists the available step\n"
+		"step <n>                   go to the step <n>\n"
+		"next                       goes to the next step\n"
+		"go                         continues the U-Boot SPL execution\n"
+		"reset                      reboots machine\n"
+#ifdef CONFIG_STM32MP1_DDR_TESTS
+		"test [help] | <n> [...]    lists (with help) or executes test <n>\n"
+#endif
+#ifdef CONFIG_STM32MP1_DDR_TUNING
+		"tuning [help] | <n> [...]  lists (with help) or execute tuning <n>\n"
+#endif
+		"\nwith for [type|reg]:\n"
+		"  all registers if absent\n"
+		"  <type> = ctl, phy\n"
+		"           or one category (static, timing, map, perf, cal, dyn)\n"
+		"  <reg> = name of the register\n"
+	};
+
+	puts(usage);
+}
+
+static bool stm32mp1_check_step(enum stm32mp1_ddr_interact_step step,
+				enum stm32mp1_ddr_interact_step expected)
+{
+	if (step != expected) {
+		printf("invalid step %d:%s expecting %d:%s\n",
+		       step, step_str[step],
+		       expected,
+		       step_str[expected]);
+		return false;
+	}
+	return true;
+}
+
+static void stm32mp1_do_info(struct ddr_info *priv,
+			     struct stm32mp1_ddr_config *config,
+			     enum stm32mp1_ddr_interact_step step,
+			     int argc, char * const argv[])
+{
+	unsigned long value;
+	static char *ddr_name;
+
+	if (argc == 1) {
+		printf("step = %d : %s\n", step, step_str[step]);
+		printf("name = %s\n", config->info.name);
+		printf("size = 0x%x\n", config->info.size);
+		printf("speed = %d kHz\n", config->info.speed);
+		return;
+	}
+
+	if (argc < 3) {
+		printf("no enought parameter\n");
+		return;
+	}
+	if (!strcmp(argv[1], "name")) {
+		u32 i, name_len = 0;
+
+		for (i = 2; i < argc; i++)
+			name_len += strlen(argv[i]) + 1;
+		if (ddr_name)
+			free(ddr_name);
+		ddr_name = malloc(name_len);
+		config->info.name = ddr_name;
+		if (!ddr_name) {
+			printf("alloc error, length %d\n", name_len);
+			return;
+		}
+		strcpy(ddr_name, argv[2]);
+		for (i = 3; i < argc; i++) {
+			strcat(ddr_name, " ");
+			strcat(ddr_name, argv[i]);
+		}
+		printf("name = %s\n", ddr_name);
+		return;
+	}
+	if (!strcmp(argv[1], "size")) {
+		if (strict_strtoul(argv[2], 16, &value) < 0) {
+			printf("invalid value %s\n", argv[2]);
+		} else {
+			config->info.size = value;
+			printf("size = 0x%x\n", config->info.size);
+		}
+		return;
+	}
+	if (!strcmp(argv[1], "speed")) {
+		if (strict_strtoul(argv[2], 10, &value) < 0) {
+			printf("invalid value %s\n", argv[2]);
+		} else {
+			config->info.speed = value;
+			printf("speed = %d kHz\n", config->info.speed);
+			value = clk_get_rate(&priv->clk);
+			printf("DDRPHY = %ld kHz\n", value / 1000);
+		}
+		return;
+	}
+	printf("argument %s invalid\n", argv[1]);
+}
+
+static bool stm32mp1_do_freq(struct ddr_info *priv,
+			     int argc, char * const argv[])
+{
+	unsigned long ddrphy_clk;
+
+	if (argc == 2) {
+		if (strict_strtoul(argv[1], 0, &ddrphy_clk) < 0) {
+			printf("invalid argument %s", argv[1]);
+			return false;
+		}
+		if (clk_set_rate(&priv->clk, ddrphy_clk * 1000)) {
+			printf("ERROR: update failed!\n");
+			return false;
+		}
+	}
+	ddrphy_clk = clk_get_rate(&priv->clk);
+	printf("DDRPHY = %ld kHz\n", ddrphy_clk / 1000);
+	if (argc == 2)
+		return true;
+	return false;
+}
+
+static void stm32mp1_do_param(enum stm32mp1_ddr_interact_step step,
+			      const struct stm32mp1_ddr_config *config,
+			      int argc, char * const argv[])
+{
+	switch (argc) {
+	case 1:
+		stm32mp1_dump_param(config, NULL);
+		break;
+	case 2:
+		if (stm32mp1_dump_param(config, argv[1]))
+			printf("invalid argument %s\n",
+			       argv[1]);
+		break;
+	case 3:
+		if (!stm32mp1_check_step(step, STEP_DDR_RESET))
+			return;
+		stm32mp1_edit_param(config, argv[1], argv[2]);
+		break;
+	}
+}
+
+static void stm32mp1_do_print(struct ddr_info *priv,
+			      int argc, char * const argv[])
+{
+	switch (argc) {
+	case 1:
+		stm32mp1_dump_reg(priv, NULL);
+		break;
+	case 2:
+		if (stm32mp1_dump_reg(priv, argv[1]))
+			printf("invalid argument %s\n",
+			       argv[1]);
+		break;
+	}
+}
+
+static int stm32mp1_do_step(enum stm32mp1_ddr_interact_step step,
+			    int argc, char * const argv[])
+{
+	int i;
+	unsigned long value;
+
+	switch (argc) {
+	case 1:
+		for (i = 0; i < ARRAY_SIZE(step_str); i++)
+			printf("%d:%s\n", i, step_str[i]);
+		break;
+
+	case 2:
+		if ((strict_strtoul(argv[1], 0,
+				    &value) < 0) ||
+				    value >= ARRAY_SIZE(step_str)) {
+			printf("invalid argument %s\n",
+			       argv[1]);
+			goto end;
+		}
+
+		if (value != STEP_DDR_RESET &&
+		    value <= step) {
+			printf("invalid target %d:%s, current step is %d:%s\n",
+			       (int)value, step_str[value],
+			       step, step_str[step]);
+			goto end;
+		}
+		printf("step to %d:%s\n",
+		       (int)value, step_str[value]);
+		return (int)value;
+	};
+
+end:
+	return step;
+}
+
+#if defined(CONFIG_STM32MP1_DDR_TESTS) || defined(CONFIG_STM32MP1_DDR_TUNING)
+static const char * const s_result[] = {
+		[TEST_PASSED] = "Pass",
+		[TEST_FAILED] = "Failed",
+		[TEST_ERROR] = "Error"
+};
+
+static void stm32mp1_ddr_subcmd(struct ddr_info *priv,
+				int argc, char *argv[],
+				const struct test_desc array[],
+				const int array_nb)
+{
+	int i;
+	unsigned long value;
+	int result;
+	char string[50] = "";
+
+	if (argc == 1) {
+		printf("%s:%d\n", argv[0], array_nb);
+		for (i = 0; i < array_nb; i++)
+			printf("%d:%s:%s\n",
+			       i, array[i].name, array[i].usage);
+		return;
+	}
+	if (argc > 1 && !strcmp(argv[1], "help")) {
+		printf("%s:%d\n", argv[0], array_nb);
+		for (i = 0; i < array_nb; i++)
+			printf("%d:%s:%s:%s\n", i,
+			       array[i].name, array[i].usage, array[i].help);
+		return;
+	}
+
+	if ((strict_strtoul(argv[1], 0, &value) <  0) ||
+	    value >= array_nb) {
+		sprintf(string, "invalid argument %s",
+			argv[1]);
+		result = TEST_FAILED;
+		goto end;
+	}
+
+	if (argc > (array[value].max_args + 2)) {
+		sprintf(string, "invalid nb of args %d, max %d",
+			argc - 2, array[value].max_args);
+		result = TEST_FAILED;
+		goto end;
+	}
+
+	printf("execute %d:%s\n", (int)value, array[value].name);
+	clear_ctrlc();
+	result = array[value].fct(priv->ctl, priv->phy,
+				  string, argc - 2, &argv[2]);
+
+end:
+	printf("Result: %s [%s]\n", s_result[result], string);
+}
+#endif
+
+bool stm32mp1_ddr_interactive(void *priv,
+			      enum stm32mp1_ddr_interact_step step,
+			      const struct stm32mp1_ddr_config *config)
+{
+	const char *prompt = "DDR>";
+	char buffer[CONFIG_SYS_CBSIZE];
+	char *argv[CONFIG_SYS_MAXARGS + 1];	/* NULL terminated */
+	int argc;
+	static int next_step = -1;
+
+	if (next_step < 0 && step == STEP_DDR_RESET) {
+#ifdef CONFIG_STM32MP1_DDR_INTERACTIVE_FORCE
+		gd->flags &= ~(GD_FLG_SILENT |
+			       GD_FLG_DISABLE_CONSOLE);
+		next_step = STEP_DDR_RESET;
+#else
+		unsigned long start = get_timer(0);
+
+		while (1) {
+			if (tstc() && (getc() == 'd')) {
+				next_step = STEP_DDR_RESET;
+				break;
+			}
+			if (get_timer(start) > 100)
+				break;
+		}
+#endif
+	}
+
+	debug("** step %d ** %s / %d\n", step, step_str[step], next_step);
+
+	if (next_step < 0)
+		return false;
+
+	if (step < 0 || step > ARRAY_SIZE(step_str)) {
+		printf("** step %d ** INVALID\n", step);
+		return false;
+	}
+
+	printf("%d:%s\n", step, step_str[step]);
+	printf("%s\n", prompt);
+
+	if (next_step > step)
+		return false;
+
+	while (next_step == step) {
+		cli_readline_into_buffer(prompt, buffer, 0);
+		argc = cli_simple_parse_line(buffer, argv);
+		if (!argc)
+			continue;
+
+		switch (stm32mp1_get_command(argv[0], argc)) {
+		case DDR_CMD_HELP:
+			stm32mp1_do_usage();
+			break;
+
+		case DDR_CMD_INFO:
+			stm32mp1_do_info(priv,
+					 (struct stm32mp1_ddr_config *)config,
+					 step, argc, argv);
+			break;
+
+		case DDR_CMD_FREQ:
+			if (stm32mp1_do_freq(priv, argc, argv))
+				next_step = STEP_DDR_RESET;
+			break;
+
+		case DDR_CMD_RESET:
+			do_reset(NULL, 0, 0, NULL);
+			break;
+
+		case DDR_CMD_PARAM:
+			stm32mp1_do_param(step, config, argc, argv);
+			break;
+
+		case DDR_CMD_PRINT:
+			stm32mp1_do_print(priv, argc, argv);
+			break;
+
+		case DDR_CMD_EDIT:
+			stm32mp1_edit_reg(priv, argv[1], argv[2]);
+			break;
+
+		case DDR_CMD_GO:
+			next_step = STEP_RUN;
+			break;
+
+		case DDR_CMD_NEXT:
+			next_step = step + 1;
+			break;
+
+		case DDR_CMD_STEP:
+			next_step = stm32mp1_do_step(step, argc, argv);
+			break;
+
+#ifdef CONFIG_STM32MP1_DDR_TESTS
+		case DDR_CMD_TEST:
+			if (!stm32mp1_check_step(step, STEP_DDR_READY))
+				continue;
+			stm32mp1_ddr_subcmd(priv, argc, argv, test, test_nb);
+			break;
+#endif
+
+#ifdef CONFIG_STM32MP1_DDR_TUNING
+		case DDR_CMD_TUNING:
+			if (!stm32mp1_check_step(step, STEP_DDR_READY))
+				continue;
+			stm32mp1_ddr_subcmd(priv, argc, argv,
+					    tuning, tuning_nb);
+			break;
+#endif
+
+		default:
+			break;
+		}
+	}
+	return next_step == STEP_DDR_RESET;
+}
diff --git a/drivers/ram/stm32mp1/stm32mp1_ram.c b/drivers/ram/stm32mp1/stm32mp1_ram.c
index e45a3b2..84e39d0 100644
--- a/drivers/ram/stm32mp1/stm32mp1_ram.c
+++ b/drivers/ram/stm32mp1/stm32mp1_ram.c
@@ -20,7 +20,7 @@
 	"ddrphyc" /* LAST clock => used for get_rate() */
 };
 
-int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint16_t mem_speed)
+int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed)
 {
 	unsigned long ddrphy_clk;
 	unsigned long ddr_clk;
@@ -43,13 +43,13 @@
 	priv->clk = clk;
 	ddrphy_clk = clk_get_rate(&priv->clk);
 
-	debug("DDR: mem_speed (%d MHz), RCC %d MHz\n",
-	      mem_speed, (u32)(ddrphy_clk / 1000 / 1000));
+	debug("DDR: mem_speed (%d kHz), RCC %d kHz\n",
+	      mem_speed, (u32)(ddrphy_clk / 1000));
 	/* max 10% frequency delta */
-	ddr_clk = abs(ddrphy_clk - mem_speed * 1000 * 1000);
-	if (ddr_clk > (mem_speed * 1000 * 100)) {
-		pr_err("DDR expected freq %d MHz, current is %d MHz\n",
-		       mem_speed, (u32)(ddrphy_clk / 1000 / 1000));
+	ddr_clk = abs(ddrphy_clk - mem_speed * 1000);
+	if (ddr_clk > (mem_speed * 100)) {
+		pr_err("DDR expected freq %d kHz, current is %d kHz\n",
+		       mem_speed, (u32)(ddrphy_clk / 1000));
 		return -EINVAL;
 	}
 
@@ -102,8 +102,8 @@
 		debug("%s: %s[0x%x] = %d\n", __func__,
 		      param[idx].name, param[idx].size, ret);
 		if (ret) {
-			pr_err("%s: Cannot read %s\n",
-			       __func__, param[idx].name);
+			pr_err("%s: Cannot read %s, error=%d\n",
+			       __func__, param[idx].name, ret);
 			return -EINVAL;
 		}
 	}
diff --git a/drivers/ram/stm32mp1/stm32mp1_tests.c b/drivers/ram/stm32mp1/stm32mp1_tests.c
new file mode 100644
index 0000000..b6fb2a9
--- /dev/null
+++ b/drivers/ram/stm32mp1/stm32mp1_tests.c
@@ -0,0 +1,1426 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
+ */
+#include <common.h>
+#include <console.h>
+#include <asm/io.h>
+#include <linux/log2.h>
+#include "stm32mp1_tests.h"
+
+#define ADDR_INVALID	0xFFFFFFFF
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int get_bufsize(char *string, int argc, char *argv[], int arg_nb,
+		       size_t *bufsize, size_t default_size)
+{
+	unsigned long value;
+
+	if (argc > arg_nb) {
+		if (strict_strtoul(argv[arg_nb], 0, &value) < 0) {
+			sprintf(string, "invalid %d parameter %s",
+				arg_nb, argv[arg_nb]);
+			return -1;
+		}
+		if (value > STM32_DDR_SIZE || value == 0) {
+			sprintf(string, "invalid size %s", argv[arg_nb]);
+			return -1;
+		}
+		if (value & 0x3) {
+			sprintf(string, "unaligned size %s",
+				argv[arg_nb]);
+			return -1;
+		}
+		*bufsize = value;
+	} else {
+		if (default_size != STM32_DDR_SIZE)
+			*bufsize = default_size;
+		else
+			*bufsize = get_ram_size((long *)STM32_DDR_BASE,
+						STM32_DDR_SIZE);
+	}
+	return 0;
+}
+
+static int get_nb_loop(char *string, int argc, char *argv[], int arg_nb,
+		       u32 *nb_loop, u32 default_nb_loop)
+{
+	unsigned long value;
+
+	if (argc > arg_nb) {
+		if (strict_strtoul(argv[arg_nb], 0, &value) < 0) {
+			sprintf(string, "invalid %d parameter %s",
+				arg_nb, argv[arg_nb]);
+			return -1;
+		}
+		if (value == 0)
+			printf("WARNING: infinite loop requested\n");
+		*nb_loop = value;
+	} else {
+		*nb_loop = default_nb_loop;
+	}
+
+	return 0;
+}
+
+static int get_addr(char *string, int argc, char *argv[], int arg_nb,
+		    u32 *addr)
+{
+	unsigned long value;
+
+	if (argc > arg_nb) {
+		if (strict_strtoul(argv[arg_nb], 16, &value) < 0) {
+			sprintf(string, "invalid %d parameter %s",
+				arg_nb, argv[arg_nb]);
+			return -1;
+		}
+		if (value < STM32_DDR_BASE) {
+			sprintf(string, "too low address %s", argv[arg_nb]);
+			return -1;
+		}
+		if (value & 0x3 && value != ADDR_INVALID) {
+			sprintf(string, "unaligned address %s",
+				argv[arg_nb]);
+			return -1;
+		}
+		*addr = value;
+	} else {
+		*addr = STM32_DDR_BASE;
+	}
+
+	return 0;
+}
+
+static int get_pattern(char *string, int argc, char *argv[], int arg_nb,
+		       u32 *pattern, u32 default_pattern)
+{
+	unsigned long value;
+
+	if (argc > arg_nb) {
+		if (strict_strtoul(argv[arg_nb], 16, &value) < 0) {
+			sprintf(string, "invalid %d parameter %s",
+				arg_nb, argv[arg_nb]);
+			return -1;
+		}
+		*pattern = value;
+	} else {
+		*pattern = default_pattern;
+	}
+
+	return 0;
+}
+
+static u32 check_addr(u32 addr, u32 value)
+{
+	u32 data = readl(addr);
+
+	if (value !=  data) {
+		printf("0x%08x: 0x%08x <=> 0x%08x", addr, data, value);
+		data = readl(addr);
+		printf("(2nd read: 0x%08x)", data);
+		if (value == data)
+			printf("- read error");
+		else
+			printf("- write error");
+		printf("\n");
+		return -1;
+	}
+	return 0;
+}
+
+static int progress(u32 offset)
+{
+	if (!(offset & 0xFFFFFF)) {
+		putc('.');
+		if (ctrlc()) {
+			printf("\ntest interrupted!\n");
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static int test_loop_end(u32 *loop, u32 nb_loop, u32 progress)
+{
+	(*loop)++;
+	if (nb_loop && *loop >= nb_loop)
+		return 1;
+	if ((*loop) % progress)
+		return 0;
+	/* allow to interrupt the test only for progress step */
+	if (ctrlc()) {
+		printf("test interrupted!\n");
+		return 1;
+	}
+	printf("loop #%d\n", *loop);
+	return 0;
+}
+
+/**********************************************************************
+ *
+ * Function:    memTestDataBus()
+ *
+ * Description: Test the data bus wiring in a memory region by
+ *              performing a walking 1's test at a fixed address
+ *              within that region.  The address is selected
+ *              by the caller.
+ *
+ * Notes:
+ *
+ * Returns:     0 if the test succeeds.
+ *              A non-zero result is the first pattern that failed.
+ *
+ **********************************************************************/
+static u32 databus(u32 *address)
+{
+	u32 pattern;
+	u32 read_value;
+
+	/* Perform a walking 1's test at the given address. */
+	for (pattern = 1; pattern != 0; pattern <<= 1) {
+		/* Write the test pattern. */
+		writel(pattern, address);
+
+		/* Read it back (immediately is okay for this test). */
+		read_value = readl(address);
+		debug("%x: %x <=> %x\n",
+		      (u32)address, read_value, pattern);
+
+		if (read_value != pattern)
+			return pattern;
+	}
+
+	return 0;
+}
+
+/**********************************************************************
+ *
+ * Function:    memTestAddressBus()
+ *
+ * Description: Test the address bus wiring in a memory region by
+ *              performing a walking 1's test on the relevant bits
+ *              of the address and checking for aliasing. This test
+ *              will find single-bit address failures such as stuck
+ *              -high, stuck-low, and shorted pins.  The base address
+ *              and size of the region are selected by the caller.
+ *
+ * Notes:       For best results, the selected base address should
+ *              have enough LSB 0's to guarantee single address bit
+ *              changes.  For example, to test a 64-Kbyte region,
+ *              select a base address on a 64-Kbyte boundary.  Also,
+ *              select the region size as a power-of-two--if at all
+ *              possible.
+ *
+ * Returns:     NULL if the test succeeds.
+ *              A non-zero result is the first address at which an
+ *              aliasing problem was uncovered.  By examining the
+ *              contents of memory, it may be possible to gather
+ *              additional information about the problem.
+ *
+ **********************************************************************/
+static u32 *addressbus(u32 *address, u32 nb_bytes)
+{
+	u32 mask = (nb_bytes / sizeof(u32) - 1);
+	u32 offset;
+	u32 test_offset;
+	u32 read_value;
+
+	u32 pattern     = 0xAAAAAAAA;
+	u32 antipattern = 0x55555555;
+
+	/* Write the default pattern at each of the power-of-two offsets. */
+	for (offset = 1; (offset & mask) != 0; offset <<= 1)
+		writel(pattern, &address[offset]);
+
+	/* Check for address bits stuck high. */
+	test_offset = 0;
+	writel(antipattern, &address[test_offset]);
+
+	for (offset = 1; (offset & mask) != 0; offset <<= 1) {
+		read_value = readl(&address[offset]);
+		debug("%x: %x <=> %x\n",
+		      (u32)&address[offset], read_value, pattern);
+		if (read_value != pattern)
+			return &address[offset];
+	}
+
+	writel(pattern, &address[test_offset]);
+
+	/* Check for address bits stuck low or shorted. */
+	for (test_offset = 1; (test_offset & mask) != 0; test_offset <<= 1) {
+		writel(antipattern, &address[test_offset]);
+		if (readl(&address[0]) != pattern)
+			return &address[test_offset];
+
+		for (offset = 1; (offset & mask) != 0; offset <<= 1) {
+			if (readl(&address[offset]) != pattern &&
+			    offset != test_offset)
+				return &address[test_offset];
+		}
+		writel(pattern, &address[test_offset]);
+	}
+
+	return NULL;
+}
+
+/**********************************************************************
+ *
+ * Function:    memTestDevice()
+ *
+ * Description: Test the integrity of a physical memory device by
+ *              performing an increment/decrement test over the
+ *              entire region.  In the process every storage bit
+ *              in the device is tested as a zero and a one.  The
+ *              base address and the size of the region are
+ *              selected by the caller.
+ *
+ * Notes:
+ *
+ * Returns:     NULL if the test succeeds.
+ *
+ *              A non-zero result is the first address at which an
+ *              incorrect value was read back.  By examining the
+ *              contents of memory, it may be possible to gather
+ *              additional information about the problem.
+ *
+ **********************************************************************/
+static u32 *memdevice(u32 *address, u32 nb_bytes)
+{
+	u32 offset;
+	u32 nb_words = nb_bytes / sizeof(u32);
+
+	u32 pattern;
+	u32 antipattern;
+
+	puts("Fill with pattern");
+	/* Fill memory with a known pattern. */
+	for (pattern = 1, offset = 0; offset < nb_words; pattern++, offset++) {
+		writel(pattern, &address[offset]);
+		if (progress(offset))
+			return NULL;
+	}
+
+	puts("\nCheck and invert pattern");
+	/* Check each location and invert it for the second pass. */
+	for (pattern = 1, offset = 0; offset < nb_words; pattern++, offset++) {
+		if (readl(&address[offset]) != pattern)
+			return &address[offset];
+
+		antipattern = ~pattern;
+		writel(antipattern, &address[offset]);
+		if (progress(offset))
+			return NULL;
+	}
+
+	puts("\nCheck inverted pattern");
+	/* Check each location for the inverted pattern and zero it. */
+	for (pattern = 1, offset = 0; offset < nb_words; pattern++, offset++) {
+		antipattern = ~pattern;
+		if (readl(&address[offset]) != antipattern)
+			return &address[offset];
+		if (progress(offset))
+			return NULL;
+	}
+	printf("\n");
+
+	return NULL;
+}
+
+static enum test_result databuswalk0(struct stm32mp1_ddrctl *ctl,
+				     struct stm32mp1_ddrphy *phy,
+				     char *string, int argc, char *argv[])
+{
+	int i;
+	u32 loop = 0, nb_loop;
+	u32 addr;
+	u32 error = 0;
+	u32 data;
+
+	if (get_nb_loop(string, argc, argv, 0, &nb_loop, 100))
+		return TEST_ERROR;
+	if (get_addr(string, argc, argv, 1, &addr))
+		return TEST_ERROR;
+
+	printf("running %d loops at 0x%x\n", nb_loop, addr);
+	while (!error) {
+		for (i = 0; i < 32; i++)
+			writel(~(1 << i), addr + 4 * i);
+		for (i = 0; i < 32; i++) {
+			data = readl(addr + 4 * i);
+			if (~(1 << i) !=  data) {
+				error |= 1 << i;
+				debug("%x: error %x expected %x => error:%x\n",
+				      addr + 4 * i, data, ~(1 << i), error);
+			}
+		}
+		if (test_loop_end(&loop, nb_loop, 1000))
+			break;
+		for (i = 0; i < 32; i++)
+			writel(0, addr + 4 * i);
+	}
+	if (error) {
+		sprintf(string, "loop %d: error for bits 0x%x",
+			loop, error);
+		return TEST_FAILED;
+	}
+	sprintf(string, "no error for %d loops", loop);
+	return TEST_PASSED;
+}
+
+static enum test_result databuswalk1(struct stm32mp1_ddrctl *ctl,
+				     struct stm32mp1_ddrphy *phy,
+				     char *string, int argc, char *argv[])
+{
+	int i;
+	u32 loop = 0, nb_loop;
+	u32 addr;
+	u32 error = 0;
+	u32 data;
+
+	if (get_nb_loop(string, argc, argv, 0, &nb_loop, 100))
+		return TEST_ERROR;
+	if (get_addr(string, argc, argv, 1, &addr))
+		return TEST_ERROR;
+	printf("running %d loops at 0x%x\n", nb_loop, addr);
+	while (!error) {
+		for (i = 0; i < 32; i++)
+			writel(1 << i, addr + 4 * i);
+		for (i = 0; i < 32; i++) {
+			data = readl(addr + 4 * i);
+			if ((1 << i) !=  data) {
+				error |= 1 << i;
+				debug("%x: error %x expected %x => error:%x\n",
+				      addr + 4 * i, data, (1 << i), error);
+			}
+		}
+		if (test_loop_end(&loop, nb_loop, 1000))
+			break;
+		for (i = 0; i < 32; i++)
+			writel(0, addr + 4 * i);
+	}
+	if (error) {
+		sprintf(string, "loop %d: error for bits 0x%x",
+			loop, error);
+		return TEST_FAILED;
+	}
+	sprintf(string, "no error for %d loops", loop);
+	return TEST_PASSED;
+}
+
+static enum test_result test_databus(struct stm32mp1_ddrctl *ctl,
+				     struct stm32mp1_ddrphy *phy,
+				     char *string, int argc, char *argv[])
+{
+	u32 addr;
+	u32 error;
+
+	if (get_addr(string, argc, argv, 0, &addr))
+		return TEST_ERROR;
+	error = databus((u32 *)addr);
+	if (error) {
+		sprintf(string, "0x%x: error for bits 0x%x",
+			addr, error);
+		return TEST_FAILED;
+	}
+	sprintf(string, "address 0x%x", addr);
+	return TEST_PASSED;
+}
+
+static enum test_result test_addressbus(struct stm32mp1_ddrctl *ctl,
+					struct stm32mp1_ddrphy *phy,
+					char *string, int argc, char *argv[])
+{
+	u32 addr;
+	u32 bufsize;
+	u32 error;
+
+	if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
+		return TEST_ERROR;
+	if (!is_power_of_2(bufsize)) {
+		sprintf(string, "size 0x%x is not a power of 2",
+			(u32)bufsize);
+		return TEST_ERROR;
+	}
+	if (get_addr(string, argc, argv, 1, &addr))
+		return TEST_ERROR;
+
+	error = (u32)addressbus((u32 *)addr, bufsize);
+	if (error) {
+		sprintf(string, "0x%x: error for address 0x%x",
+			addr, error);
+		return TEST_FAILED;
+	}
+	sprintf(string, "address 0x%x, size 0x%x",
+		addr, bufsize);
+	return TEST_PASSED;
+}
+
+static enum test_result test_memdevice(struct stm32mp1_ddrctl *ctl,
+				       struct stm32mp1_ddrphy *phy,
+				       char *string, int argc, char *argv[])
+{
+	u32 addr;
+	size_t bufsize;
+	u32 error;
+
+	if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
+		return TEST_ERROR;
+	if (get_addr(string, argc, argv, 1, &addr))
+		return TEST_ERROR;
+	error = (u32)memdevice((u32 *)addr, (unsigned long)bufsize);
+	if (error) {
+		sprintf(string, "0x%x: error for address 0x%x",
+			addr, error);
+		return TEST_FAILED;
+	}
+	sprintf(string, "address 0x%x, size 0x%x",
+		addr, bufsize);
+	return TEST_PASSED;
+}
+
+/**********************************************************************
+ *
+ * Function:    sso
+ *
+ * Description: Test the Simultaneous Switching Output.
+ *              Verifies succes sive reads and writes to the same memory word,
+ *              holding one bit constant while toggling all other data bits
+ *              simultaneously
+ *              => stress the data bus over an address range
+ *
+ *              The CPU writes to each address in the given range.
+ *              For each bit, first the CPU holds the bit at 1 while
+ *              toggling the other bits, and then the CPU holds the bit at 0
+ *              while toggling the other bits.
+ *              After each write, the CPU reads the address that was written
+ *              to verify that it contains the correct data
+ *
+ **********************************************************************/
+static enum test_result test_sso(struct stm32mp1_ddrctl *ctl,
+				 struct stm32mp1_ddrphy *phy,
+				 char *string, int argc, char *argv[])
+{
+	int i, j;
+	u32 addr, bufsize, remaining, offset;
+	u32 error = 0;
+	u32 data;
+
+	if (get_bufsize(string, argc, argv, 0, &bufsize, 4))
+		return TEST_ERROR;
+	if (get_addr(string, argc, argv, 1, &addr))
+		return TEST_ERROR;
+
+	printf("running sso at 0x%x length 0x%x", addr, bufsize);
+	offset = addr;
+	remaining = bufsize;
+	while (remaining) {
+		for (i = 0; i < 32; i++) {
+			/* write pattern. */
+			for (j = 0; j < 6; j++) {
+				switch (j) {
+				case 0:
+				case 2:
+					data = 1 << i;
+					break;
+				case 3:
+				case 5:
+					data = ~(1 << i);
+					break;
+				case 1:
+					data = ~0x0;
+					break;
+				case 4:
+					data = 0x0;
+					break;
+				}
+
+				writel(data, offset);
+				error = check_addr(offset, data);
+				if (error)
+					goto end;
+			}
+		}
+		offset += 4;
+		remaining -= 4;
+		if (progress(offset << 7))
+			goto end;
+	}
+	puts("\n");
+
+end:
+	if (error) {
+		sprintf(string, "error for pattern 0x%x @0x%x",
+			data, offset);
+		return TEST_FAILED;
+	}
+	sprintf(string, "no error for sso at 0x%x length 0x%x", addr, bufsize);
+	return TEST_PASSED;
+}
+
+/**********************************************************************
+ *
+ * Function:    Random
+ *
+ * Description: Verifies r/w with pseudo-ramdom value on one region
+ *              + write the region (individual access)
+ *              + memcopy to the 2nd region (try to use burst)
+ *              + verify the 2 regions
+ *
+ **********************************************************************/
+static enum test_result test_random(struct stm32mp1_ddrctl *ctl,
+				    struct stm32mp1_ddrphy *phy,
+				    char *string, int argc, char *argv[])
+{
+	u32 addr, offset, value = 0;
+	size_t bufsize;
+	u32 loop = 0, nb_loop;
+	u32 error = 0;
+	unsigned int seed;
+
+	if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
+		return TEST_ERROR;
+	if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
+		return TEST_ERROR;
+	if (get_addr(string, argc, argv, 2, &addr))
+		return TEST_ERROR;
+
+	printf("running %d loops at 0x%x\n", nb_loop, addr);
+	while (!error) {
+		seed = rand();
+		for (offset = addr; offset < addr + bufsize; offset += 4)
+			writel(rand(), offset);
+
+		memcpy((void *)addr + bufsize, (void *)addr, bufsize);
+
+		srand(seed);
+		for (offset = addr; offset < addr + 2 * bufsize; offset += 4) {
+			if (offset == (addr + bufsize))
+				srand(seed);
+			value = rand();
+			error = check_addr(offset, value);
+			if (error)
+				break;
+			if (progress(offset))
+				return TEST_FAILED;
+		}
+		if (test_loop_end(&loop, nb_loop, 100))
+			break;
+	}
+
+	if (error) {
+		sprintf(string,
+			"loop %d: error for address 0x%x: 0x%x expected 0x%x",
+			loop, offset, readl(offset), value);
+		return TEST_FAILED;
+	}
+	sprintf(string, "no error for %d loops, size 0x%x",
+		loop, bufsize);
+	return TEST_PASSED;
+}
+
+/**********************************************************************
+ *
+ * Function:    noise
+ *
+ * Description: Verifies r/w while forcing switching of all data bus lines.
+ *              optimised 4 iteration write/read/write/read cycles...
+ *              for pattern and inversed pattern
+ *
+ **********************************************************************/
+void do_noise(u32 addr, u32 pattern, u32 *result)
+{
+	__asm__("push {R0-R11}");
+	__asm__("mov r0, %0" : : "r" (addr));
+	__asm__("mov r1, %0" : : "r" (pattern));
+	__asm__("mov r11, %0" : : "r" (result));
+
+	__asm__("mvn r2, r1");
+
+	__asm__("str r1, [r0]");
+	__asm__("ldr r3, [r0]");
+	__asm__("str r2, [r0]");
+	__asm__("ldr r4, [r0]");
+
+	__asm__("str r1, [r0]");
+	__asm__("ldr r5, [r0]");
+	__asm__("str r2, [r0]");
+	__asm__("ldr r6, [r0]");
+
+	__asm__("str r1, [r0]");
+	__asm__("ldr r7, [r0]");
+	__asm__("str r2, [r0]");
+	__asm__("ldr r8, [r0]");
+
+	__asm__("str r1, [r0]");
+	__asm__("ldr r9, [r0]");
+	__asm__("str r2, [r0]");
+	__asm__("ldr r10, [r0]");
+
+	__asm__("stmia R11!, {R3-R10}");
+
+	__asm__("pop {R0-R11}");
+}
+
+static enum test_result test_noise(struct stm32mp1_ddrctl *ctl,
+				   struct stm32mp1_ddrphy *phy,
+				   char *string, int argc, char *argv[])
+{
+	u32 addr, pattern;
+	u32 result[8];
+	int i;
+	enum test_result res = TEST_PASSED;
+
+	if (get_pattern(string, argc, argv, 0, &pattern, 0xFFFFFFFF))
+		return TEST_ERROR;
+	if (get_addr(string, argc, argv, 1, &addr))
+		return TEST_ERROR;
+
+	printf("running noise for 0x%x at 0x%x\n", pattern, addr);
+
+	do_noise(addr, pattern, result);
+
+	for (i = 0; i < 0x8;) {
+		if (check_addr((u32)&result[i++], pattern))
+			res = TEST_FAILED;
+		if (check_addr((u32)&result[i++], ~pattern))
+			res = TEST_FAILED;
+	}
+
+	return res;
+}
+
+/**********************************************************************
+ *
+ * Function:    noise_burst
+ *
+ * Description: Verifies r/w while forcing switching of all data bus lines.
+ *              optimised write loop witrh store multiple to use burst
+ *              for pattern and inversed pattern
+ *
+ **********************************************************************/
+void do_noise_burst(u32 addr, u32 pattern, size_t bufsize)
+{
+	__asm__("push {R0-R9}");
+	__asm__("mov r0, %0" : : "r" (addr));
+	__asm__("mov r1, %0" : : "r" (pattern));
+	__asm__("mov r9, %0" : : "r" (bufsize));
+
+	__asm__("mvn r2, r1");
+	__asm__("mov r3, r1");
+	__asm__("mov r4, r2");
+	__asm__("mov r5, r1");
+	__asm__("mov r6, r2");
+	__asm__("mov r7, r1");
+	__asm__("mov r8, r2");
+
+	__asm__("loop1:");
+	__asm__("stmia R0!, {R1-R8}");
+	__asm__("stmia R0!, {R1-R8}");
+	__asm__("stmia R0!, {R1-R8}");
+	__asm__("stmia R0!, {R1-R8}");
+	__asm__("subs r9, r9, #128");
+	__asm__("bge loop1");
+	__asm__("pop {R0-R9}");
+}
+
+/* chunk size enough to allow interruption with Ctrl-C*/
+#define CHUNK_SIZE	0x8000000
+static enum test_result test_noise_burst(struct stm32mp1_ddrctl *ctl,
+					 struct stm32mp1_ddrphy *phy,
+					 char *string, int argc, char *argv[])
+{
+	u32 addr, offset, pattern;
+	size_t bufsize, remaining, size;
+	int i;
+	enum test_result res = TEST_PASSED;
+
+	if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
+		return TEST_ERROR;
+	if (get_pattern(string, argc, argv, 1, &pattern, 0xFFFFFFFF))
+		return TEST_ERROR;
+	if (get_addr(string, argc, argv, 2, &addr))
+		return TEST_ERROR;
+
+	printf("running noise burst for 0x%x at 0x%x + 0x%x",
+	       pattern, addr, bufsize);
+
+	offset = addr;
+	remaining = bufsize;
+	size = CHUNK_SIZE;
+	while (remaining) {
+		if (remaining < size)
+			size = remaining;
+		do_noise_burst(offset, pattern, size);
+		remaining -= size;
+		offset += size;
+		if (progress(offset)) {
+			res = TEST_FAILED;
+			goto end;
+		}
+	}
+	puts("\ncheck buffer");
+	for (i = 0; i < bufsize;) {
+		if (check_addr(addr + i, pattern))
+			res = TEST_FAILED;
+		i += 4;
+		if (check_addr(addr + i, ~pattern))
+			res = TEST_FAILED;
+		i += 4;
+		if (progress(i)) {
+			res = TEST_FAILED;
+			goto end;
+		}
+	}
+end:
+	puts("\n");
+	return res;
+}
+
+/**********************************************************************
+ *
+ * Function:    pattern test
+ *
+ * Description: optimized loop for read/write pattern (array of 8 u32)
+ *
+ **********************************************************************/
+#define PATTERN_SIZE	8
+static enum test_result test_loop(const u32 *pattern, u32 *address,
+				  const u32 bufsize)
+{
+	int i;
+	int j;
+	enum test_result res = TEST_PASSED;
+	u32 *offset, testsize, remaining;
+
+	offset = address;
+	remaining = bufsize;
+	while (remaining) {
+		testsize = bufsize > 0x1000000 ? 0x1000000 : bufsize;
+
+		__asm__("push {R0-R10}");
+		__asm__("mov r0, %0" : : "r" (pattern));
+		__asm__("mov r1, %0" : : "r" (offset));
+		__asm__("mov r2, %0" : : "r" (testsize));
+		__asm__("ldmia r0!, {R3-R10}");
+
+		__asm__("loop2:");
+		__asm__("stmia r1!, {R3-R10}");
+		__asm__("stmia r1!, {R3-R10}");
+		__asm__("stmia r1!, {R3-R10}");
+		__asm__("stmia r1!, {R3-R10}");
+		__asm__("subs r2, r2, #8");
+		__asm__("bge loop2");
+		__asm__("pop {R0-R10}");
+
+		offset += testsize;
+		remaining -= testsize;
+		if (progress((u32)offset)) {
+			res = TEST_FAILED;
+			goto end;
+		}
+	}
+
+	puts("\ncheck buffer");
+	for (i = 0; i < bufsize; i += PATTERN_SIZE * 4) {
+		for (j = 0; j < PATTERN_SIZE; j++, address++)
+			if (check_addr((u32)address, pattern[j])) {
+				res = TEST_FAILED;
+				goto end;
+			}
+		if (progress(i)) {
+			res = TEST_FAILED;
+			goto end;
+		}
+	}
+
+end:
+	puts("\n");
+	return res;
+}
+
+const u32 pattern_div1_x16[PATTERN_SIZE] = {
+	0x0000FFFF, 0x0000FFFF, 0x0000FFFF, 0x0000FFFF,
+	0x0000FFFF, 0x0000FFFF, 0x0000FFFF, 0x0000FFFF
+};
+
+const u32 pattern_div2_x16[PATTERN_SIZE] = {
+	0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+	0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000
+};
+
+const u32 pattern_div4_x16[PATTERN_SIZE] = {
+	0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+	0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000
+};
+
+const u32 pattern_div4_x32[PATTERN_SIZE] = {
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000
+};
+
+const u32 pattern_mostly_zero_x16[PATTERN_SIZE] = {
+	0x00000000, 0x00000000, 0x00000000, 0x0000FFFF,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000
+};
+
+const u32 pattern_mostly_zero_x32[PATTERN_SIZE] = {
+	0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000
+};
+
+const u32 pattern_mostly_one_x16[PATTERN_SIZE] = {
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000FFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+};
+
+const u32 pattern_mostly_one_x32[PATTERN_SIZE] = {
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+};
+
+#define NB_PATTERN	5
+static enum test_result test_freq_pattern(struct stm32mp1_ddrctl *ctl,
+					  struct stm32mp1_ddrphy *phy,
+					  char *string, int argc, char *argv[])
+{
+	const u32 * const patterns_x16[NB_PATTERN] = {
+		pattern_div1_x16,
+		pattern_div2_x16,
+		pattern_div4_x16,
+		pattern_mostly_zero_x16,
+		pattern_mostly_one_x16,
+	};
+	const u32 * const patterns_x32[NB_PATTERN] = {
+		pattern_div2_x16,
+		pattern_div4_x16,
+		pattern_div4_x32,
+		pattern_mostly_zero_x32,
+		pattern_mostly_one_x32
+	};
+	const char *patterns_comments[NB_PATTERN] = {
+		"switching at frequency F/1",
+		"switching at frequency F/2",
+		"switching at frequency F/4",
+		"mostly zero",
+		"mostly one"
+	};
+
+	enum test_result res = TEST_PASSED, pattern_res;
+	int i, bus_width;
+	const u32 **patterns;
+	u32 bufsize;
+
+	if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
+		return TEST_ERROR;
+
+	switch (readl(&ctl->mstr) & DDRCTRL_MSTR_DATA_BUS_WIDTH_MASK) {
+	case DDRCTRL_MSTR_DATA_BUS_WIDTH_HALF:
+	case DDRCTRL_MSTR_DATA_BUS_WIDTH_QUARTER:
+		bus_width = 16;
+		break;
+	default:
+		bus_width = 32;
+		break;
+	}
+
+	printf("running test pattern at 0x%08x length 0x%x width = %d\n",
+	       STM32_DDR_BASE, bufsize, bus_width);
+
+	patterns =
+		(const u32 **)(bus_width == 16 ? patterns_x16 : patterns_x32);
+
+	for (i = 0; i < NB_PATTERN; i++) {
+		printf("test data pattern %s:", patterns_comments[i]);
+		pattern_res = test_loop(patterns[i], (u32 *)STM32_DDR_BASE,
+					bufsize);
+		if (pattern_res != TEST_PASSED)	{
+			printf("Failed\n");
+			return pattern_res;
+		}
+		printf("Passed\n");
+	}
+
+	return res;
+}
+
+/**********************************************************************
+ *
+ * Function:    pattern test with size
+ *
+ * Description: loop for write pattern
+ *
+ **********************************************************************/
+
+static enum test_result test_loop_size(const u32 *pattern, u32 size,
+				       u32 *address,
+				       const u32 bufsize)
+{
+	int i, j;
+	enum test_result res = TEST_PASSED;
+	u32 *p = address;
+
+	for (i = 0; i < bufsize; i += size * 4) {
+		for (j = 0; j < size ; j++, p++)
+			*p = pattern[j];
+		if (progress(i)) {
+			res = TEST_FAILED;
+			goto end;
+		}
+	}
+
+	puts("\ncheck buffer");
+	p = address;
+	for (i = 0; i < bufsize; i += size * 4) {
+		for (j = 0; j < size; j++, p++)
+			if (check_addr((u32)p, pattern[j])) {
+				res = TEST_FAILED;
+				goto end;
+			}
+		if (progress(i)) {
+			res = TEST_FAILED;
+			goto end;
+		}
+	}
+
+end:
+	puts("\n");
+	return res;
+}
+
+static enum test_result test_checkboard(struct stm32mp1_ddrctl *ctl,
+					struct stm32mp1_ddrphy *phy,
+					char *string, int argc, char *argv[])
+{
+	enum test_result res = TEST_PASSED;
+	u32 bufsize, nb_loop, loop = 0, addr;
+	int i;
+
+	u32 checkboard[2] = {0x55555555, 0xAAAAAAAA};
+
+	if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
+		return TEST_ERROR;
+	if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
+		return TEST_ERROR;
+	if (get_addr(string, argc, argv, 2, &addr))
+		return TEST_ERROR;
+
+	printf("running %d loops at 0x%08x length 0x%x\n",
+	       nb_loop, addr, bufsize);
+	while (1) {
+		for (i = 0; i < 2; i++) {
+			res = test_loop_size(checkboard, 2, (u32 *)addr,
+					     bufsize);
+			if (res)
+				return res;
+			checkboard[0] = ~checkboard[0];
+			checkboard[1] = ~checkboard[1];
+		}
+		if (test_loop_end(&loop, nb_loop, 1))
+			break;
+	}
+	sprintf(string, "no error for %d loops at 0x%08x length 0x%x",
+		loop, addr, bufsize);
+
+	return res;
+}
+
+static enum test_result test_blockseq(struct stm32mp1_ddrctl *ctl,
+				      struct stm32mp1_ddrphy *phy,
+				      char *string, int argc, char *argv[])
+{
+	enum test_result res = TEST_PASSED;
+	u32 bufsize, nb_loop, loop = 0, addr, value;
+	int i;
+
+	if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
+		return TEST_ERROR;
+	if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
+		return TEST_ERROR;
+	if (get_addr(string, argc, argv, 2, &addr))
+		return TEST_ERROR;
+
+	printf("running %d loops at 0x%08x length 0x%x\n",
+	       nb_loop, addr, bufsize);
+	while (1) {
+		for (i = 0; i < 256; i++) {
+			value = i | i << 8 | i << 16 | i << 24;
+			printf("pattern = %08x", value);
+			res = test_loop_size(&value, 1, (u32 *)addr, bufsize);
+			if (res != TEST_PASSED)
+				return res;
+		}
+		if (test_loop_end(&loop, nb_loop, 1))
+			break;
+	}
+	sprintf(string, "no error for %d loops at 0x%08x length 0x%x",
+		loop, addr, bufsize);
+
+	return res;
+}
+
+static enum test_result test_walkbit0(struct stm32mp1_ddrctl *ctl,
+				      struct stm32mp1_ddrphy *phy,
+				      char *string, int argc, char *argv[])
+{
+	enum test_result res = TEST_PASSED;
+	u32 bufsize, nb_loop, loop = 0, addr, value;
+	int i;
+
+	if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
+		return TEST_ERROR;
+	if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
+		return TEST_ERROR;
+	if (get_addr(string, argc, argv, 2, &addr))
+		return TEST_ERROR;
+
+	printf("running %d loops at 0x%08x length 0x%x\n",
+	       nb_loop, addr, bufsize);
+	while (1) {
+		for (i = 0; i < 64; i++) {
+			if (i < 32)
+				value = 1 << i;
+			else
+				value = 1 << (63 - i);
+
+			printf("pattern = %08x", value);
+			res = test_loop_size(&value, 1, (u32 *)addr, bufsize);
+			if (res != TEST_PASSED)
+				return res;
+		}
+		if (test_loop_end(&loop, nb_loop, 1))
+			break;
+	}
+	sprintf(string, "no error for %d loops at 0x%08x length 0x%x",
+		loop, addr, bufsize);
+
+	return res;
+}
+
+static enum test_result test_walkbit1(struct stm32mp1_ddrctl *ctl,
+				      struct stm32mp1_ddrphy *phy,
+				      char *string, int argc, char *argv[])
+{
+	enum test_result res = TEST_PASSED;
+	u32 bufsize, nb_loop, loop = 0, addr, value;
+	int i;
+
+	if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
+		return TEST_ERROR;
+	if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
+		return TEST_ERROR;
+	if (get_addr(string, argc, argv, 2, &addr))
+		return TEST_ERROR;
+
+	printf("running %d loops at 0x%08x length 0x%x\n",
+	       nb_loop, addr, bufsize);
+	while (1) {
+		for (i = 0; i < 64; i++) {
+			if (i < 32)
+				value = ~(1 << i);
+			else
+				value = ~(1 << (63 - i));
+
+			printf("pattern = %08x", value);
+			res = test_loop_size(&value, 1, (u32 *)addr, bufsize);
+			if (res != TEST_PASSED)
+				return res;
+		}
+		if (test_loop_end(&loop, nb_loop, 1))
+			break;
+	}
+	sprintf(string, "no error for %d loops at 0x%08x length 0x%x",
+		loop, addr, bufsize);
+
+	return res;
+}
+
+/*
+ * try to catch bad bits which are dependent on the current values of
+ * surrounding bits in either the same word32
+ */
+static enum test_result test_bitspread(struct stm32mp1_ddrctl *ctl,
+				       struct stm32mp1_ddrphy *phy,
+				       char *string, int argc, char *argv[])
+{
+	enum test_result res = TEST_PASSED;
+	u32 bufsize, nb_loop, loop = 0, addr, bitspread[4];
+	int i, j;
+
+	if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
+		return TEST_ERROR;
+	if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
+		return TEST_ERROR;
+	if (get_addr(string, argc, argv, 2, &addr))
+		return TEST_ERROR;
+
+	printf("running %d loops at 0x%08x length 0x%x\n",
+	       nb_loop, addr, bufsize);
+	while (1) {
+		for (i = 1; i < 32; i++) {
+			for (j = 0; j < i; j++) {
+				if (i < 32)
+					bitspread[0] = (1 << i) | (1 << j);
+				else
+					bitspread[0] = (1 << (63 - i)) |
+						       (1 << (63 - j));
+				bitspread[1] = bitspread[0];
+				bitspread[2] = ~bitspread[0];
+				bitspread[3] = ~bitspread[0];
+				printf("pattern = %08x", bitspread[0]);
+
+				res = test_loop_size(bitspread, 4, (u32 *)addr,
+						     bufsize);
+				if (res != TEST_PASSED)
+					return res;
+			}
+		}
+		if (test_loop_end(&loop, nb_loop, 1))
+			break;
+	}
+	sprintf(string, "no error for %d loops at 0x%08x length 0x%x",
+		loop, addr, bufsize);
+
+	return res;
+}
+
+static enum test_result test_bitflip(struct stm32mp1_ddrctl *ctl,
+				     struct stm32mp1_ddrphy *phy,
+				     char *string, int argc, char *argv[])
+{
+	enum test_result res = TEST_PASSED;
+	u32 bufsize, nb_loop, loop = 0, addr;
+	int i;
+
+	u32 bitflip[4];
+
+	if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
+		return TEST_ERROR;
+	if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
+		return TEST_ERROR;
+	if (get_addr(string, argc, argv, 2, &addr))
+		return TEST_ERROR;
+
+	printf("running %d loops at 0x%08x length 0x%x\n",
+	       nb_loop, addr, bufsize);
+	while (1) {
+		for (i = 0; i < 32; i++) {
+			bitflip[0] = 1 << i;
+			bitflip[1] = bitflip[0];
+			bitflip[2] = ~bitflip[0];
+			bitflip[3] = bitflip[2];
+			printf("pattern = %08x", bitflip[0]);
+
+			res = test_loop_size(bitflip, 4, (u32 *)addr, bufsize);
+			if (res != TEST_PASSED)
+				return res;
+		}
+		if (test_loop_end(&loop, nb_loop, 1))
+			break;
+	}
+	sprintf(string, "no error for %d loops at 0x%08x length 0x%x",
+		loop, addr, bufsize);
+
+	return res;
+}
+
+/**********************************************************************
+ *
+ * Function: infinite read access to DDR
+ *
+ * Description: continuous read the same pattern at the same address
+ *
+ **********************************************************************/
+static enum test_result test_read(struct stm32mp1_ddrctl *ctl,
+				  struct stm32mp1_ddrphy *phy,
+				  char *string, int argc, char *argv[])
+{
+	u32 *addr;
+	u32 data;
+	u32 loop = 0;
+	bool random = false;
+
+	if (get_addr(string, argc, argv, 0, (u32 *)&addr))
+		return TEST_ERROR;
+
+	if ((u32)addr == ADDR_INVALID) {
+		printf("random ");
+		random = true;
+	}
+
+	printf("running at 0x%08x\n", (u32)addr);
+
+	while (1) {
+		if (random)
+			addr = (u32 *)(STM32_DDR_BASE +
+			       (rand() & (STM32_DDR_SIZE - 1) & ~0x3));
+		data = readl(addr);
+		if (test_loop_end(&loop, 0, 1000))
+			break;
+	}
+	sprintf(string, "0x%x: %x", (u32)addr, data);
+
+	return TEST_PASSED;
+}
+
+/**********************************************************************
+ *
+ * Function: infinite write access to DDR
+ *
+ * Description: continuous write the same pattern at the same address
+ *
+ **********************************************************************/
+static enum test_result test_write(struct stm32mp1_ddrctl *ctl,
+				   struct stm32mp1_ddrphy *phy,
+				   char *string, int argc, char *argv[])
+{
+	u32 *addr;
+	u32 data = 0xA5A5AA55;
+	u32 loop = 0;
+	bool random = false;
+
+	if (get_addr(string, argc, argv, 0, (u32 *)&addr))
+		return TEST_ERROR;
+
+	if ((u32)addr == ADDR_INVALID) {
+		printf("random ");
+		random = true;
+	}
+
+	printf("running at 0x%08x\n", (u32)addr);
+
+	while (1) {
+		if (random) {
+			addr = (u32 *)(STM32_DDR_BASE +
+			       (rand() & (STM32_DDR_SIZE - 1) & ~0x3));
+			data = rand();
+		}
+		writel(data, addr);
+		if (test_loop_end(&loop, 0, 1000))
+			break;
+	}
+	sprintf(string, "0x%x: %x", (u32)addr, data);
+
+	return TEST_PASSED;
+}
+
+#define NB_TEST_INFINITE 2
+static enum test_result test_all(struct stm32mp1_ddrctl *ctl,
+				 struct stm32mp1_ddrphy *phy,
+				 char *string, int argc, char *argv[])
+{
+	enum test_result res = TEST_PASSED, result;
+	int i, nb_error = 0;
+	u32 loop = 0, nb_loop;
+
+	if (get_nb_loop(string, argc, argv, 0, &nb_loop, 1))
+		return TEST_ERROR;
+
+	while (!nb_error) {
+		/* execute all the test except the lasts which are infinite */
+		for (i = 1; i < test_nb - NB_TEST_INFINITE; i++) {
+			printf("execute %d:%s\n", (int)i, test[i].name);
+			result = test[i].fct(ctl, phy, string, 0, NULL);
+			printf("result %d:%s = ", (int)i, test[i].name);
+			if (result != TEST_PASSED) {
+				nb_error++;
+				res = TEST_FAILED;
+				puts("Failed");
+			} else {
+				puts("Passed");
+			}
+			puts("\n\n");
+		}
+		printf("loop %d: %d/%d test failed\n\n\n",
+		       loop + 1, nb_error, test_nb - NB_TEST_INFINITE);
+		if (test_loop_end(&loop, nb_loop, 1))
+			break;
+	}
+	if (res != TEST_PASSED) {
+		sprintf(string, "loop %d: %d/%d test failed", loop, nb_error,
+			test_nb - NB_TEST_INFINITE);
+	} else {
+		sprintf(string, "loop %d: %d tests passed", loop,
+			test_nb - NB_TEST_INFINITE);
+	}
+	return res;
+}
+
+/****************************************************************
+ * TEST Description
+ ****************************************************************/
+
+const struct test_desc test[] = {
+	{test_all, "All", "[loop]", "Execute all tests", 1 },
+	{test_databus, "Simple DataBus", "[addr]",
+	 "Verifies each data line by walking 1 on fixed address",
+	 1
+	 },
+	{databuswalk0, "DataBusWalking0", "[loop] [addr]",
+	 "Verifies each data bus signal can be driven low (32 word burst)",
+	 2
+	},
+	{databuswalk1, "DataBusWalking1", "[loop] [addr]",
+	 "Verifies each data bus signal can be driven high (32 word burst)",
+	 2
+	},
+	{test_addressbus, "AddressBus", "[size] [addr]",
+	 "Verifies each relevant bits of the address and checking for aliasing",
+	 2
+	 },
+	{test_memdevice, "MemDevice", "[size] [addr]",
+	 "Test the integrity of a physical memory (test every storage bit in the region)",
+	 2
+	 },
+	{test_sso, "SimultaneousSwitchingOutput", "[size] [addr] ",
+	 "Stress the data bus over an address range",
+	 2
+	},
+	{test_noise, "Noise", "[pattern] [addr]",
+	 "Verifies r/w while forcing switching of all data bus lines.",
+	 3
+	},
+	{test_noise_burst, "NoiseBurst", "[size] [pattern] [addr]",
+	 "burst transfers while forcing switching of the data bus lines",
+	 3
+	},
+	{test_random, "Random", "[size] [loop] [addr]",
+	 "Verifies r/w and memcopy(burst for pseudo random value.",
+	 3
+	},
+	{test_freq_pattern, "FrequencySelectivePattern ", "[size]",
+	 "write & test patterns: Mostly Zero, Mostly One and F/n",
+	 1
+	},
+	{test_blockseq, "BlockSequential", "[size] [loop] [addr]",
+	 "test incremental pattern",
+	 3
+	},
+	{test_checkboard, "Checkerboard", "[size] [loop] [addr]",
+	 "test checker pattern",
+	 3
+	},
+	{test_bitspread, "BitSpread", "[size] [loop] [addr]",
+	 "test Bit Spread pattern",
+	 3
+	},
+	{test_bitflip, "BitFlip", "[size] [loop] [addr]",
+	 "test Bit Flip pattern",
+	 3
+	},
+	{test_walkbit0, "WalkingOnes", "[size] [loop] [addr]",
+	 "test Walking Ones pattern",
+	 3
+	},
+	{test_walkbit1, "WalkingZeroes", "[size] [loop] [addr]",
+	 "test Walking Zeroes pattern",
+	 3
+	},
+	/* need to the the 2 last one (infinite) : skipped for test all */
+	{test_read, "infinite read", "[addr]",
+	 "basic test : infinite read access", 1},
+	{test_write, "infinite write", "[addr]",
+	 "basic test : infinite write access", 1},
+};
+
+const int test_nb = ARRAY_SIZE(test);
diff --git a/drivers/ram/stm32mp1/stm32mp1_tests.h b/drivers/ram/stm32mp1/stm32mp1_tests.h
new file mode 100644
index 0000000..55f5d6d
--- /dev/null
+++ b/drivers/ram/stm32mp1/stm32mp1_tests.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
+/*
+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
+ */
+
+#ifndef _RAM_STM32MP1_TESTS_H_
+#define _RAM_STM32MP1_TESTS_H_
+
+#include "stm32mp1_ddr_regs.h"
+
+enum test_result {
+	TEST_PASSED,
+	TEST_FAILED,
+	TEST_ERROR
+};
+
+struct test_desc {
+	enum test_result (*fct)(struct stm32mp1_ddrctl *ctl,
+				struct stm32mp1_ddrphy *phy,
+				char *string,
+				int argc, char *argv[]);
+	const char *name;
+	const char *usage;
+	const char *help;
+	u8 max_args;
+};
+
+extern const struct test_desc test[];
+extern const int test_nb;
+
+extern const struct test_desc tuning[];
+extern const int tuning_nb;
+
+#endif
diff --git a/drivers/ram/stm32mp1/stm32mp1_tuning.c b/drivers/ram/stm32mp1/stm32mp1_tuning.c
new file mode 100644
index 0000000..4e1c1fa
--- /dev/null
+++ b/drivers/ram/stm32mp1/stm32mp1_tuning.c
@@ -0,0 +1,1380 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
+ */
+#include <common.h>
+#include <console.h>
+#include <clk.h>
+#include <ram.h>
+#include <reset.h>
+#include <asm/io.h>
+
+#include "stm32mp1_ddr_regs.h"
+#include "stm32mp1_ddr.h"
+#include "stm32mp1_tests.h"
+
+#define MAX_DQS_PHASE_IDX _144deg
+#define MAX_DQS_UNIT_IDX 7
+#define MAX_GSL_IDX 5
+#define MAX_GPS_IDX 3
+
+/* Number of bytes used in this SW. ( min 1--> max 4). */
+#define NUM_BYTES 4
+
+enum dqs_phase_enum {
+	_36deg = 0,
+	_54deg = 1,
+	_72deg = 2,
+	_90deg = 3,
+	_108deg = 4,
+	_126deg = 5,
+	_144deg = 6
+};
+
+/* BIST Result struct */
+struct BIST_result {
+	/* Overall test result:
+	 * 0 Fail (any bit failed) ,
+	 * 1 Success (All bits success)
+	 */
+	bool test_result;
+	/* 1: true, all fail /  0: False, not all bits fail */
+	bool all_bits_fail;
+	bool bit_i_test_result[8];  /* 0 fail / 1 success */
+};
+
+/* a struct that defines tuning parameters of a byte. */
+struct tuning_position {
+	u8 phase; /* DQS phase */
+	u8 unit; /* DQS unit delay */
+	u32 bits_delay; /* Bits deskew in this byte */
+};
+
+/* 36deg, 54deg, 72deg, 90deg, 108deg, 126deg, 144deg */
+const u8 dx_dll_phase[7] = {3, 2, 1, 0, 14, 13, 12};
+
+static u8 BIST_error_max = 1;
+static u32 BIST_seed = 0x1234ABCD;
+
+static u8 get_nb_bytes(struct stm32mp1_ddrctl *ctl)
+{
+	u32 data_bus = readl(&ctl->mstr) & DDRCTRL_MSTR_DATA_BUS_WIDTH_MASK;
+	u8 nb_bytes = NUM_BYTES;
+
+	switch (data_bus) {
+	case DDRCTRL_MSTR_DATA_BUS_WIDTH_HALF:
+		nb_bytes /= 2;
+		break;
+	case DDRCTRL_MSTR_DATA_BUS_WIDTH_QUARTER:
+		nb_bytes /= 4;
+		break;
+	default:
+		break;
+	}
+
+	return nb_bytes;
+}
+
+static void itm_soft_reset(struct stm32mp1_ddrphy *phy)
+{
+	stm32mp1_ddrphy_init(phy, DDRPHYC_PIR_ITMSRST);
+}
+
+/* Read DQ unit delay register and provides the retrieved value for DQS
+ * We are assuming that we have the same delay when clocking
+ * by DQS and when clocking by DQSN
+ */
+static u8 DQ_unit_index(struct stm32mp1_ddrphy *phy, u8 byte, u8 bit)
+{
+	u32 index;
+	u32 addr = DXNDQTR(phy, byte);
+
+	/* We are assuming that we have the same delay when clocking by DQS
+	 * and when clocking by DQSN : use only the low bits
+	 */
+	index = (readl(addr) >> DDRPHYC_DXNDQTR_DQDLY_SHIFT(bit))
+		& DDRPHYC_DXNDQTR_DQDLY_LOW_MASK;
+
+	pr_debug("%s: [%x]: %x => DQ unit index = %x\n",
+		 __func__, addr, readl(addr), index);
+
+	return index;
+}
+
+/* Sets the DQS phase delay for a byte lane.
+ *phase delay is specified by giving the index of the desired delay
+ * in the dx_dll_phase array.
+ */
+static void DQS_phase_delay(struct stm32mp1_ddrphy *phy, u8 byte, u8 phase_idx)
+{
+	u8 sdphase_val = 0;
+
+	/*	Write DXNDLLCR.SDPHASE = dx_dll_phase(phase_index); */
+	sdphase_val = dx_dll_phase[phase_idx];
+	clrsetbits_le32(DXNDLLCR(phy, byte),
+			DDRPHYC_DXNDLLCR_SDPHASE_MASK,
+			sdphase_val << DDRPHYC_DXNDLLCR_SDPHASE_SHIFT);
+}
+
+/* Sets the DQS unit delay for a byte lane.
+ * unit delay is specified by giving the index of the desired delay
+ * for dgsdly and dqsndly (same value).
+ */
+static void DQS_unit_delay(struct stm32mp1_ddrphy *phy,
+			   u8 byte, u8 unit_dly_idx)
+{
+	/* Write the same value in DXNDQSTR.DQSDLY and DXNDQSTR.DQSNDLY */
+	clrsetbits_le32(DXNDQSTR(phy, byte),
+			DDRPHYC_DXNDQSTR_DQSDLY_MASK |
+			DDRPHYC_DXNDQSTR_DQSNDLY_MASK,
+			(unit_dly_idx << DDRPHYC_DXNDQSTR_DQSDLY_SHIFT) |
+			(unit_dly_idx << DDRPHYC_DXNDQSTR_DQSNDLY_SHIFT));
+
+	/* After changing this value, an ITM soft reset (PIR.ITMSRST=1,
+	 * plus PIR.INIT=1) must be issued.
+	 */
+	stm32mp1_ddrphy_init(phy, DDRPHYC_PIR_ITMSRST);
+}
+
+/* Sets the DQ unit delay for a bit line in particular byte lane.
+ * unit delay is specified by giving the desired delay
+ */
+static void set_DQ_unit_delay(struct stm32mp1_ddrphy *phy,
+			      u8 byte, u8 bit,
+			      u8 dq_delay_index)
+{
+	u8 dq_bit_delay_val = dq_delay_index | (dq_delay_index << 2);
+
+	/* same value on delay for clock DQ an DQS_b */
+	clrsetbits_le32(DXNDQTR(phy, byte),
+			DDRPHYC_DXNDQTR_DQDLY_MASK
+			<< DDRPHYC_DXNDQTR_DQDLY_SHIFT(bit),
+			dq_bit_delay_val << DDRPHYC_DXNDQTR_DQDLY_SHIFT(bit));
+}
+
+static void set_r0dgsl_delay(struct stm32mp1_ddrphy *phy,
+			     u8 byte, u8 r0dgsl_idx)
+{
+	clrsetbits_le32(DXNDQSTR(phy, byte),
+			DDRPHYC_DXNDQSTR_R0DGSL_MASK,
+			r0dgsl_idx << DDRPHYC_DXNDQSTR_R0DGSL_SHIFT);
+}
+
+static void set_r0dgps_delay(struct stm32mp1_ddrphy *phy,
+			     u8 byte, u8 r0dgps_idx)
+{
+	clrsetbits_le32(DXNDQSTR(phy, byte),
+			DDRPHYC_DXNDQSTR_R0DGPS_MASK,
+			r0dgps_idx << DDRPHYC_DXNDQSTR_R0DGPS_SHIFT);
+}
+
+/* Basic BIST configuration for data lane tests. */
+static void config_BIST(struct stm32mp1_ddrphy *phy)
+{
+	/* Selects the SDRAM bank address to be used during BIST. */
+	u32 bbank = 0;
+	/* Selects the SDRAM row address to be used during BIST. */
+	u32 brow = 0;
+	/* Selects the SDRAM column address to be used during BIST. */
+	u32 bcol = 0;
+	/* Selects the value by which the SDRAM address is incremented
+	 * for each write/read access.
+	 */
+	u32 bainc = 0x00000008;
+	/* Specifies the maximum SDRAM rank to be used during BIST.
+	 * The default value is set to maximum ranks minus 1.
+	 * must be 0 with single rank
+	 */
+	u32 bmrank = 0;
+	/* Selects the SDRAM rank to be used during BIST.
+	 * must be 0 with single rank
+	 */
+	u32 brank = 0;
+	/* Specifies the maximum SDRAM bank address to be used during
+	 * BIST before the address & increments to the next rank.
+	 */
+	u32 bmbank = 1;
+	/* Specifies the maximum SDRAM row address to be used during
+	 * BIST before the address & increments to the next bank.
+	 */
+	u32 bmrow = 0x7FFF; /* To check */
+	/* Specifies the maximum SDRAM column address to be used during
+	 * BIST before the address & increments to the next row.
+	 */
+	u32 bmcol = 0x3FF;  /* To check */
+	u32 bmode_conf = 0x00000001;  /* DRam mode */
+	u32 bdxen_conf = 0x00000001;  /* BIST on Data byte */
+	u32 bdpat_conf = 0x00000002;  /* Select LFSR pattern */
+
+	/*Setup BIST for DRAM mode,  and LFSR-random data pattern.*/
+	/*Write BISTRR.BMODE = 1?b1;*/
+	/*Write BISTRR.BDXEN = 1?b1;*/
+	/*Write BISTRR.BDPAT = 2?b10;*/
+
+	/* reset BIST */
+	writel(0x3, &phy->bistrr);
+
+	writel((bmode_conf << 3) | (bdxen_conf << 14) | (bdpat_conf << 17),
+	       &phy->bistrr);
+
+	/*Setup BIST Word Count*/
+	/*Write BISTWCR.BWCNT = 16?b0008;*/
+	writel(0x00000200, &phy->bistwcr); /* A multiple of BL/2 */
+
+	writel(bcol | (brow << 12) | (bbank << 28), &phy->bistar0);
+	writel(brank | (bmrank << 2) | (bainc << 4), &phy->bistar1);
+
+	/* To check this line : */
+	writel(bmcol | (bmrow << 12) | (bmbank << 28), &phy->bistar2);
+}
+
+/* Select the Byte lane to be tested by BIST. */
+static void BIST_datx8_sel(struct stm32mp1_ddrphy *phy, u8 datx8)
+{
+	clrsetbits_le32(&phy->bistrr,
+			DDRPHYC_BISTRR_BDXSEL_MASK,
+			datx8 << DDRPHYC_BISTRR_BDXSEL_SHIFT);
+
+	/*(For example, selecting Byte Lane 3, BISTRR.BDXSEL = 4?b0011)*/
+	/* Write BISTRR.BDXSEL = datx8; */
+}
+
+/* Perform BIST Write_Read test on a byte lane and return test result. */
+static void BIST_test(struct stm32mp1_ddrphy *phy, u8 byte,
+		      struct BIST_result *bist)
+{
+	bool result = true; /* BIST_SUCCESS */
+	u32 cnt = 0;
+	u32 error = 0;
+
+	bist->test_result = true;
+
+run:
+	itm_soft_reset(phy);
+
+	/*Perform BIST Reset*/
+	/* Write BISTRR.BINST = 3?b011; */
+	clrsetbits_le32(&phy->bistrr,
+			0x00000007,
+			0x00000003);
+
+	/*Re-seed LFSR*/
+	/* Write BISTLSR.SEED = 32'h1234ABCD; */
+	if (BIST_seed)
+		writel(BIST_seed, &phy->bistlsr);
+	else
+		writel(rand(), &phy->bistlsr);
+
+	/* some delay to reset BIST */
+	mdelay(1);
+
+	/*Perform BIST Run*/
+	clrsetbits_le32(&phy->bistrr,
+			0x00000007,
+			0x00000001);
+	/* Write BISTRR.BINST = 3?b001; */
+
+	/* Wait for a number of CTL clocks before reading BIST register*/
+	/* Wait 300 ctl_clk cycles;  ... IS it really needed?? */
+	/* Perform BIST Instruction Stop*/
+	/* Write BISTRR.BINST = 3?b010;*/
+
+	/* poll on BISTGSR.BDONE. If 0, wait.  ++TODO Add timeout */
+	while (!(readl(&phy->bistgsr) & DDRPHYC_BISTGSR_BDDONE))
+		;
+
+	/*Check if received correct number of words*/
+	/* if (Read BISTWCSR.DXWCNT = Read BISTWCR.BWCNT) */
+	if (((readl(&phy->bistwcsr)) >> DDRPHYC_BISTWCSR_DXWCNT_SHIFT) ==
+	    readl(&phy->bistwcr)) {
+		/*Determine if there is a data comparison error*/
+		/* if (Read BISTGSR.BDXERR = 1?b0) */
+		if (readl(&phy->bistgsr) & DDRPHYC_BISTGSR_BDXERR)
+			result = false; /* BIST_FAIL; */
+		else
+			result = true; /* BIST_SUCCESS; */
+	} else {
+		result = false; /* BIST_FAIL; */
+	}
+
+	/* loop while success */
+	cnt++;
+	if (result && cnt != 1000)
+		goto run;
+
+	if (!result)
+		error++;
+
+	if (error < BIST_error_max) {
+		if (cnt != 1000)
+			goto run;
+		bist->test_result = true;
+	} else {
+		bist->test_result = false;
+	}
+}
+
+/* After running the deskew algo, this function applies the new DQ delays
+ * by reading them from the array "deskew_delay"and writing in PHY registers.
+ * The bits that are not deskewed parfectly (too much skew on them,
+ * or data eye very wide) are marked in the array deskew_non_converge.
+ */
+static void apply_deskew_results(struct stm32mp1_ddrphy *phy, u8 byte,
+				 u8 deskew_delay[NUM_BYTES][8],
+				 u8 deskew_non_converge[NUM_BYTES][8])
+{
+	u8  bit_i;
+	u8  index;
+
+	for (bit_i = 0; bit_i < 8; bit_i++) {
+		set_DQ_unit_delay(phy, byte, bit_i, deskew_delay[byte][bit_i]);
+		index = DQ_unit_index(phy, byte, bit_i);
+		pr_debug("Byte %d ; bit %d : The new DQ delay (%d) index=%d [delta=%d, 3 is the default]",
+			 byte, bit_i, deskew_delay[byte][bit_i],
+			 index, index - 3);
+		printf("Byte %d, bit %d, DQ delay = %d",
+		       byte, bit_i, deskew_delay[byte][bit_i]);
+		if (deskew_non_converge[byte][bit_i] == 1)
+			pr_debug(" - not converged : still more skew");
+		printf("\n");
+	}
+}
+
+/* DQ Bit de-skew algorithm.
+ * Deskews data lines as much as possible.
+ * 1. Add delay to DQS line until finding the failure
+ *    (normally a hold time violation)
+ * 2. Reduce DQS line by small steps until finding the very first time
+ *    we go back to "Pass" condition.
+ * 3. For each DQ line, Reduce DQ delay until finding the very first failure
+ *    (normally a hold time fail)
+ * 4. When all bits are at their first failure delay, we can consider them
+ *    aligned.
+ * Handle conrer situation (Can't find Pass-fail, or fail-pass transitions
+ * at any step)
+ * TODO Provide a return Status. Improve doc
+ */
+static enum test_result bit_deskew(struct stm32mp1_ddrctl *ctl,
+				   struct stm32mp1_ddrphy *phy, char *string)
+{
+	/* New DQ delay value (index), set during Deskew algo */
+	u8 deskew_delay[NUM_BYTES][8];
+	/*If there is still skew on a bit, mark this bit. */
+	u8 deskew_non_converge[NUM_BYTES][8];
+	struct BIST_result result;
+	s8 dqs_unit_delay_index = 0;
+	u8 datx8 = 0;
+	u8 bit_i = 0;
+	s8 phase_idx = 0;
+	s8 bit_i_delay_index = 0;
+	u8 success = 0;
+	struct tuning_position last_right_ok;
+	u8 force_stop = 0;
+	u8 fail_found;
+	u8 error = 0;
+	u8 nb_bytes = get_nb_bytes(ctl);
+	/* u8 last_pass_dqs_unit = 0; */
+
+	memset(deskew_delay, 0, sizeof(deskew_delay));
+	memset(deskew_non_converge, 0, sizeof(deskew_non_converge));
+
+	/*Disable DQS Drift Compensation*/
+	clrbits_le32(&phy->pgcr, DDRPHYC_PGCR_DFTCMP);
+	/*Disable all bytes*/
+	/* Disable automatic power down of DLL and IOs when disabling
+	 * a byte (To avoid having to add programming and  delay
+	 * for a DLL re-lock when later re-enabling a disabled Byte Lane)
+	 */
+	clrbits_le32(&phy->pgcr, DDRPHYC_PGCR_PDDISDX);
+
+	/* Disable all data bytes */
+	clrbits_le32(&phy->dx0gcr, DDRPHYC_DXNGCR_DXEN);
+	clrbits_le32(&phy->dx1gcr, DDRPHYC_DXNGCR_DXEN);
+	clrbits_le32(&phy->dx2gcr, DDRPHYC_DXNGCR_DXEN);
+	clrbits_le32(&phy->dx3gcr, DDRPHYC_DXNGCR_DXEN);
+
+	/* Config the BIST block */
+	config_BIST(phy);
+	pr_debug("BIST Config done.\n");
+
+	/* Train each byte */
+	for (datx8 = 0; datx8 < nb_bytes; datx8++) {
+		if (ctrlc()) {
+			sprintf(string, "interrupted at byte %d/%d, error=%d",
+				datx8 + 1, nb_bytes, error);
+			return TEST_FAILED;
+		}
+		pr_debug("\n======================\n");
+		pr_debug("Start deskew byte %d .\n", datx8);
+		pr_debug("======================\n");
+		/* Enable Byte (DXNGCR, bit DXEN) */
+		setbits_le32(DXNGCR(phy, datx8), DDRPHYC_DXNGCR_DXEN);
+
+		/* Select the byte lane for comparison of read data */
+		BIST_datx8_sel(phy, datx8);
+
+		/* Set all DQDLYn to maximum value. All bits within the byte
+		 * will be delayed with DQSTR = 2 instead of max = 3
+		 * to avoid inter bits fail influence
+		 */
+		writel(0xAAAAAAAA, DXNDQTR(phy, datx8));
+
+		/* Set the DQS phase delay to 90 DEG (default).
+		 * What is defined here is the index of the desired config
+		 * in the PHASE array.
+		 */
+		phase_idx = _90deg;
+
+		/* Set DQS unit delay to the max value. */
+		dqs_unit_delay_index = MAX_DQS_UNIT_IDX;
+		DQS_unit_delay(phy, datx8, dqs_unit_delay_index);
+		DQS_phase_delay(phy, datx8, phase_idx);
+
+		/* Issue a DLL soft reset */
+		clrbits_le32(DXNDLLCR(phy, datx8), DDRPHYC_DXNDLLCR_DLLSRST);
+		setbits_le32(DXNDLLCR(phy, datx8), DDRPHYC_DXNDLLCR_DLLSRST);
+
+		/* Test this typical init condition */
+		BIST_test(phy, datx8, &result);
+		success = result.test_result;
+
+		/* If the test pass in this typical condition,
+		 * start the algo with it.
+		 * Else, look for Pass init condition
+		 */
+		if (!success) {
+			pr_debug("Fail at init condtion. Let's look for a good init condition.\n");
+			success = 0; /* init */
+			/* Make sure we start with a PASS condition before
+			 * looking for a fail condition.
+			 * Find the first PASS PHASE condition
+			 */
+
+			/* escape if we find a PASS */
+			pr_debug("increase Phase idx\n");
+			while (!success && (phase_idx <= MAX_DQS_PHASE_IDX)) {
+				DQS_phase_delay(phy, datx8, phase_idx);
+				BIST_test(phy, datx8, &result);
+				success = result.test_result;
+				phase_idx++;
+			}
+			/* if ended with success
+			 * ==>> Restore the fist success condition
+			 */
+			if (success)
+				phase_idx--; /* because it ended with ++ */
+		}
+		if (ctrlc()) {
+			sprintf(string, "interrupted at byte %d/%d, error=%d",
+				datx8 + 1, nb_bytes, error);
+			return TEST_FAILED;
+		}
+		/* We couldn't find a successful condition, its seems
+		 * we have hold violation, lets try reduce DQS_unit Delay
+		 */
+		if (!success) {
+			/* We couldn't find a successful condition, its seems
+			 * we have hold violation, lets try reduce DQS_unit
+			 * Delay
+			 */
+			pr_debug("Still fail. Try decrease DQS Unit delay\n");
+
+			phase_idx = 0;
+			dqs_unit_delay_index = 0;
+			DQS_phase_delay(phy, datx8, phase_idx);
+
+			/* escape if we find a PASS */
+			while (!success &&
+			       (dqs_unit_delay_index <=
+				MAX_DQS_UNIT_IDX)) {
+				DQS_unit_delay(phy, datx8,
+					       dqs_unit_delay_index);
+				BIST_test(phy, datx8, &result);
+				success = result.test_result;
+				dqs_unit_delay_index++;
+			}
+			if (success) {
+				/* Restore the first success condition*/
+				dqs_unit_delay_index--;
+				/* last_pass_dqs_unit = dqs_unit_delay_index;*/
+				DQS_unit_delay(phy, datx8,
+					       dqs_unit_delay_index);
+			} else {
+				/* No need to continue,
+				 * there is no pass region.
+				 */
+				force_stop = 1;
+			}
+		}
+
+		/* There is an initial PASS condition
+		 * Look for the first failing condition by PHASE stepping.
+		 * This part of the algo can finish without converging.
+		 */
+		if (force_stop) {
+			printf("Result: Failed ");
+			printf("[Cannot Deskew lines, ");
+			printf("there is no PASS region]\n");
+			error++;
+			continue;
+		}
+		if (ctrlc()) {
+			sprintf(string, "interrupted at byte %d/%d, error=%d",
+				datx8 + 1, nb_bytes, error);
+			return TEST_FAILED;
+		}
+
+		pr_debug("there is a pass region for phase idx %d\n",
+			 phase_idx);
+		pr_debug("Step1: Find the first failing condition\n");
+		/* Look for the first failing condition by PHASE stepping.
+		 * This part of the algo can finish without converging.
+		 */
+
+		/* escape if we find a fail (hold time violation)
+		 * condition at any bit or if out of delay range.
+		 */
+		while (success && (phase_idx <= MAX_DQS_PHASE_IDX)) {
+			DQS_phase_delay(phy, datx8, phase_idx);
+			BIST_test(phy, datx8, &result);
+			success = result.test_result;
+			phase_idx++;
+		}
+		if (ctrlc()) {
+			sprintf(string, "interrupted at byte %d/%d, error=%d",
+				datx8 + 1, nb_bytes, error);
+			return TEST_FAILED;
+		}
+
+		/* if the loop ended with a failing condition at any bit,
+		 * lets look for the first previous success condition by unit
+		 * stepping (minimal delay)
+		 */
+		if (!success) {
+			pr_debug("Fail region (PHASE) found phase idx %d\n",
+				 phase_idx);
+			pr_debug("Let's look for first success by DQS Unit steps\n");
+			/* This part, the algo always converge */
+			phase_idx--;
+
+			/* escape if we find a success condition
+			 * or if out of delay range.
+			 */
+			while (!success && dqs_unit_delay_index >= 0) {
+				DQS_unit_delay(phy, datx8,
+					       dqs_unit_delay_index);
+				BIST_test(phy, datx8, &result);
+				success = result.test_result;
+				dqs_unit_delay_index--;
+			}
+			/* if the loop ended with a success condition,
+			 * the last delay Right OK (before hold violation)
+			 *  condition is then defined as following:
+			 */
+			if (success) {
+				/* Hold the dely parameters of the the last
+				 * delay Right OK condition.
+				 * -1 to get back to current condition
+				 */
+				last_right_ok.phase = phase_idx;
+				/*+1 to get back to current condition */
+				last_right_ok.unit = dqs_unit_delay_index + 1;
+				last_right_ok.bits_delay = 0xFFFFFFFF;
+				pr_debug("Found %d\n", dqs_unit_delay_index);
+			} else {
+				/* the last OK condition is then with the
+				 * previous phase_idx.
+				 * -2 instead of -1 because at the last
+				 * iteration of the while(),
+				 * we incremented phase_idx
+				 */
+				last_right_ok.phase = phase_idx - 1;
+				/* Nominal+1. Because we want the previous
+				 * delay after reducing the phase delay.
+				 */
+				last_right_ok.unit = 1;
+				last_right_ok.bits_delay = 0xFFFFFFFF;
+				pr_debug("Not Found : try previous phase %d\n",
+					 phase_idx - 1);
+
+				DQS_phase_delay(phy, datx8, phase_idx - 1);
+				dqs_unit_delay_index = 0;
+				success = true;
+				while (success &&
+				       (dqs_unit_delay_index <
+					MAX_DQS_UNIT_IDX)) {
+					DQS_unit_delay(phy, datx8,
+						       dqs_unit_delay_index);
+					BIST_test(phy, datx8, &result);
+					success = result.test_result;
+					dqs_unit_delay_index++;
+					pr_debug("dqs_unit_delay_index = %d, result = %d\n",
+						 dqs_unit_delay_index, success);
+				}
+
+				if (!success) {
+					last_right_ok.unit =
+						 dqs_unit_delay_index - 1;
+				} else {
+					last_right_ok.unit = 0;
+					pr_debug("ERROR: failed region not FOUND");
+				}
+			}
+		} else {
+			/* we can't find a failing  condition at all bits
+			 * ==> Just hold the last test condition
+			 * (the max DQS delay)
+			 * which is the most likely,
+			 * the closest to a hold violation
+			 * If we can't find a Fail condition after
+			 * the Pass region, stick at this position
+			 * In order to have max chances to find a fail
+			 * when reducing DQ delays.
+			 */
+			last_right_ok.phase = MAX_DQS_PHASE_IDX;
+			last_right_ok.unit = MAX_DQS_UNIT_IDX;
+			last_right_ok.bits_delay = 0xFFFFFFFF;
+			pr_debug("Can't find the a fail condition\n");
+		}
+
+		/* step 2:
+		 * if we arrive at this stage, it means that we found the last
+		 * Right OK condition (by tweeking the DQS delay). Or we simply
+		 * pushed DQS delay to the max
+		 * This means that by reducing the delay on some DQ bits,
+		 * we should find a failing condition.
+		 */
+		printf("Byte %d, DQS unit = %d, phase = %d\n",
+		       datx8, last_right_ok.unit, last_right_ok.phase);
+		pr_debug("Step2, unit = %d, phase = %d, bits delay=%x\n",
+			 last_right_ok.unit, last_right_ok.phase,
+			 last_right_ok.bits_delay);
+
+		/* Restore the last_right_ok condtion. */
+		DQS_unit_delay(phy, datx8, last_right_ok.unit);
+		DQS_phase_delay(phy, datx8, last_right_ok.phase);
+		writel(last_right_ok.bits_delay, DXNDQTR(phy, datx8));
+
+		/* train each bit
+		 * reduce delay on each bit, and perform a write/read test
+		 * and stop at the very first time it fails.
+		 * the goal is the find the first failing condition
+		 * for each bit.
+		 * When we achieve this condition<  for all the bits,
+		 * we are sure they are aligned (+/- step resolution)
+		 */
+		fail_found = 0;
+		for (bit_i = 0; bit_i < 8; bit_i++) {
+			if (ctrlc()) {
+				sprintf(string,
+					"interrupted at byte %d/%d, error=%d",
+					datx8 + 1, nb_bytes, error);
+				return error;
+			}
+			pr_debug("deskewing bit %d:\n", bit_i);
+			success = 1; /* init */
+			/* Set all DQDLYn to maximum value.
+			 * Only bit_i will be down-delayed
+			 * ==> if we have a fail, it will be definitely
+			 *     from bit_i
+			 */
+			writel(0xFFFFFFFF, DXNDQTR(phy, datx8));
+			/* Arriving at this stage,
+			 * we have a success condition with delay = 3;
+			 */
+			bit_i_delay_index = 3;
+
+			/* escape if bit delay is out of range or
+			 * if a fatil occurs
+			 */
+			while ((bit_i_delay_index >= 0) && success) {
+				set_DQ_unit_delay(phy, datx8,
+						  bit_i,
+						  bit_i_delay_index);
+				BIST_test(phy, datx8, &result);
+				success = result.test_result;
+				bit_i_delay_index--;
+			}
+
+			/* if escape with a fail condition
+			 * ==> save this position for bit_i
+			 */
+			if (!success) {
+				/* save the delay position.
+				 * Add 1 because the while loop ended with a --,
+				 * and that we need to hold the last success
+				 *  delay
+				 */
+				deskew_delay[datx8][bit_i] =
+					bit_i_delay_index + 2;
+				if (deskew_delay[datx8][bit_i] > 3)
+					deskew_delay[datx8][bit_i] = 3;
+
+				/* A flag that states we found at least a fail
+				 * at one bit.
+				 */
+				fail_found = 1;
+				pr_debug("Fail found on bit %d, for delay = %d => deskew[%d][%d] = %d\n",
+					 bit_i, bit_i_delay_index + 1,
+					 datx8, bit_i,
+					 deskew_delay[datx8][bit_i]);
+			} else {
+				/* if we can find a success condition by
+				 * back-delaying this bit, just set the delay
+				 * to 0 (the best deskew
+				 * possible) and mark the bit.
+				 */
+				deskew_delay[datx8][bit_i] = 0;
+				/* set a flag that will be used later
+				 * in the report.
+				 */
+				deskew_non_converge[datx8][bit_i] = 1;
+				pr_debug("Fail not found on bit %d => deskew[%d][%d] = %d\n",
+					 bit_i, datx8, bit_i,
+					 deskew_delay[datx8][bit_i]);
+			}
+		}
+		pr_debug("**********byte %d tuning complete************\n",
+			 datx8);
+		/* If we can't find any failure by back delaying DQ lines,
+		 * hold the default values
+		 */
+		if (!fail_found) {
+			for (bit_i = 0; bit_i < 8; bit_i++)
+				deskew_delay[datx8][bit_i] = 0;
+			pr_debug("The Deskew algorithm can't converge, there is too much margin in your design. Good job!\n");
+		}
+
+		apply_deskew_results(phy, datx8, deskew_delay,
+				     deskew_non_converge);
+		/* Restore nominal value for DQS delay */
+		DQS_phase_delay(phy, datx8, 3);
+		DQS_unit_delay(phy, datx8, 3);
+		/* disable byte after byte bits deskew */
+		clrbits_le32(DXNGCR(phy, datx8), DDRPHYC_DXNGCR_DXEN);
+	}  /* end of byte deskew */
+
+	/* re-enable all data bytes */
+	setbits_le32(&phy->dx0gcr, DDRPHYC_DXNGCR_DXEN);
+	setbits_le32(&phy->dx1gcr, DDRPHYC_DXNGCR_DXEN);
+	setbits_le32(&phy->dx2gcr, DDRPHYC_DXNGCR_DXEN);
+	setbits_le32(&phy->dx3gcr, DDRPHYC_DXNGCR_DXEN);
+
+	if (error) {
+		sprintf(string, "error = %d", error);
+		return TEST_FAILED;
+	}
+
+	return TEST_PASSED;
+} /* end function */
+
+/* Trim DQS timings and set it in the centre of data eye.
+ * Look for a PPPPF region, then look for a FPPP region and finally select
+ * the mid of the FPPPPPF region
+ */
+static enum test_result eye_training(struct stm32mp1_ddrctl *ctl,
+				     struct stm32mp1_ddrphy *phy, char *string)
+{
+	/*Stores the DQS trim values (PHASE index, unit index) */
+	u8 eye_training_val[NUM_BYTES][2];
+	u8 byte = 0;
+	struct BIST_result result;
+	s8 dqs_unit_delay_index = 0;
+	s8 phase_idx = 0;
+	s8 dqs_unit_delay_index_pass = 0;
+	s8 phase_idx_pass = 0;
+	u8 success = 0;
+	u8 left_phase_bound_found, right_phase_bound_found;
+	u8 left_unit_bound_found, right_unit_bound_found;
+	u8 left_bound_found, right_bound_found;
+	struct tuning_position left_bound, right_bound;
+	u8 error = 0;
+	u8 nb_bytes = get_nb_bytes(ctl);
+
+	/*Disable DQS Drift Compensation*/
+	clrbits_le32(&phy->pgcr, DDRPHYC_PGCR_DFTCMP);
+	/*Disable all bytes*/
+	/* Disable automatic power down of DLL and IOs when disabling a byte
+	 * (To avoid having to add programming and  delay
+	 * for a DLL re-lock when later re-enabling a disabled Byte Lane)
+	 */
+	clrbits_le32(&phy->pgcr, DDRPHYC_PGCR_PDDISDX);
+
+	/*Disable all data bytes */
+	clrbits_le32(&phy->dx0gcr, DDRPHYC_DXNGCR_DXEN);
+	clrbits_le32(&phy->dx1gcr, DDRPHYC_DXNGCR_DXEN);
+	clrbits_le32(&phy->dx2gcr, DDRPHYC_DXNGCR_DXEN);
+	clrbits_le32(&phy->dx3gcr, DDRPHYC_DXNGCR_DXEN);
+
+	/* Config the BIST block */
+	config_BIST(phy);
+
+	for (byte = 0; byte < nb_bytes; byte++) {
+		if (ctrlc()) {
+			sprintf(string, "interrupted at byte %d/%d, error=%d",
+				byte + 1, nb_bytes, error);
+			return TEST_FAILED;
+		}
+		right_bound.phase = 0;
+		right_bound.unit = 0;
+
+		left_bound.phase = 0;
+		left_bound.unit = 0;
+
+		left_phase_bound_found = 0;
+		right_phase_bound_found = 0;
+
+		left_unit_bound_found = 0;
+		right_unit_bound_found = 0;
+
+		left_bound_found = 0;
+		right_bound_found = 0;
+
+		/* Enable Byte (DXNGCR, bit DXEN) */
+		setbits_le32(DXNGCR(phy, byte), DDRPHYC_DXNGCR_DXEN);
+
+		/* Select the byte lane for comparison of read data */
+		BIST_datx8_sel(phy, byte);
+
+		/* Set DQS phase delay to the nominal value. */
+		phase_idx = _90deg;
+		phase_idx_pass = phase_idx;
+
+		/* Set DQS unit delay to the nominal value. */
+		dqs_unit_delay_index = 3;
+		dqs_unit_delay_index_pass = dqs_unit_delay_index;
+		success = 0;
+
+		pr_debug("STEP0: Find Init delay\n");
+		/* STEP0: Find Init delay: a delay that put the system
+		 * in a "Pass" condition then (TODO) update
+		 * dqs_unit_delay_index_pass & phase_idx_pass
+		 */
+		DQS_unit_delay(phy, byte, dqs_unit_delay_index);
+		DQS_phase_delay(phy, byte, phase_idx);
+		BIST_test(phy, byte, &result);
+		success = result.test_result;
+		/* If we have a fail in the nominal condition */
+		if (!success) {
+			/* Look at the left */
+			while (phase_idx >= 0 && !success) {
+				phase_idx--;
+				DQS_phase_delay(phy, byte, phase_idx);
+				BIST_test(phy, byte, &result);
+				success = result.test_result;
+			}
+		}
+		if (!success) {
+			/* if we can't find pass condition,
+			 * then look at the right
+			 */
+			phase_idx = _90deg;
+			while (phase_idx <= MAX_DQS_PHASE_IDX &&
+			       !success) {
+				phase_idx++;
+				DQS_phase_delay(phy, byte,
+						phase_idx);
+				BIST_test(phy, byte, &result);
+				success = result.test_result;
+			}
+		}
+		/* save the pass condition */
+		if (success) {
+			phase_idx_pass = phase_idx;
+		} else {
+			printf("Result: Failed ");
+			printf("[Cannot DQS timings, ");
+			printf("there is no PASS region]\n");
+			error++;
+			continue;
+		}
+
+		if (ctrlc()) {
+			sprintf(string, "interrupted at byte %d/%d, error=%d",
+				byte + 1, nb_bytes, error);
+			return TEST_FAILED;
+		}
+		pr_debug("STEP1: Find LEFT PHASE DQS Bound\n");
+		/* STEP1: Find LEFT PHASE DQS Bound */
+		while ((phase_idx >= 0) &&
+		       (phase_idx <= MAX_DQS_PHASE_IDX) &&
+		       !left_phase_bound_found) {
+			DQS_unit_delay(phy, byte,
+				       dqs_unit_delay_index);
+			DQS_phase_delay(phy, byte,
+					phase_idx);
+			BIST_test(phy, byte, &result);
+			success = result.test_result;
+
+			/*TODO: Manage the case were at the beginning
+			 * there is already a fail
+			 */
+			if (!success) {
+				/* the last pass condition */
+				left_bound.phase = ++phase_idx;
+				left_phase_bound_found = 1;
+			} else if (success) {
+				phase_idx--;
+			}
+		}
+		if (!left_phase_bound_found) {
+			left_bound.phase = 0;
+			phase_idx = 0;
+		}
+		/* If not found, lets take 0 */
+
+		if (ctrlc()) {
+			sprintf(string, "interrupted at byte %d/%d, error=%d",
+				byte + 1, nb_bytes, error);
+			return TEST_FAILED;
+		}
+		pr_debug("STEP2: Find UNIT left bound\n");
+		/* STEP2: Find UNIT left bound */
+		while ((dqs_unit_delay_index >= 0) &&
+		       !left_unit_bound_found) {
+			DQS_unit_delay(phy, byte,
+				       dqs_unit_delay_index);
+			DQS_phase_delay(phy, byte, phase_idx);
+			BIST_test(phy, byte, &result);
+			success = result.test_result;
+			if (!success) {
+				left_bound.unit =
+					++dqs_unit_delay_index;
+				left_unit_bound_found = 1;
+				left_bound_found = 1;
+			} else if (success) {
+				dqs_unit_delay_index--;
+			}
+		}
+
+		/* If not found, lets take 0 */
+		if (!left_unit_bound_found)
+			left_bound.unit = 0;
+
+		if (ctrlc()) {
+			sprintf(string, "interrupted at byte %d/%d, error=%d",
+				byte + 1, nb_bytes, error);
+			return TEST_FAILED;
+		}
+		pr_debug("STEP3: Find PHase right bound\n");
+		/* STEP3: Find PHase right bound, start with "pass"
+		 * condition
+		 */
+
+		/* Set DQS phase delay to the pass value. */
+		phase_idx = phase_idx_pass;
+
+		/* Set DQS unit delay to the pass value. */
+		dqs_unit_delay_index = dqs_unit_delay_index_pass;
+
+		while ((phase_idx <= MAX_DQS_PHASE_IDX) &&
+		       !right_phase_bound_found) {
+			DQS_unit_delay(phy, byte,
+				       dqs_unit_delay_index);
+			DQS_phase_delay(phy, byte, phase_idx);
+			BIST_test(phy, byte, &result);
+			success = result.test_result;
+			if (!success) {
+				/* the last pass condition */
+				right_bound.phase = --phase_idx;
+				right_phase_bound_found = 1;
+			} else if (success) {
+				phase_idx++;
+			}
+		}
+
+		/* If not found, lets take the max value */
+		if (!right_phase_bound_found) {
+			right_bound.phase = MAX_DQS_PHASE_IDX;
+			phase_idx = MAX_DQS_PHASE_IDX;
+		}
+
+		if (ctrlc()) {
+			sprintf(string, "interrupted at byte %d/%d, error=%d",
+				byte + 1, nb_bytes, error);
+			return TEST_FAILED;
+		}
+		pr_debug("STEP4: Find UNIT right bound\n");
+		/* STEP4: Find UNIT right bound */
+		while ((dqs_unit_delay_index <= MAX_DQS_UNIT_IDX) &&
+		       !right_unit_bound_found) {
+			DQS_unit_delay(phy, byte,
+				       dqs_unit_delay_index);
+			DQS_phase_delay(phy, byte, phase_idx);
+			BIST_test(phy, byte, &result);
+			success = result.test_result;
+			if (!success) {
+				right_bound.unit =
+					--dqs_unit_delay_index;
+				right_unit_bound_found = 1;
+				right_bound_found = 1;
+			} else if (success) {
+				dqs_unit_delay_index++;
+			}
+		}
+		/* If not found, lets take the max value */
+		if (!right_unit_bound_found)
+			right_bound.unit = MAX_DQS_UNIT_IDX;
+
+		/* If we found a regular FAil Pass FAil pattern
+		 * FFPPPPPPFF
+		 * OR PPPPPFF  Or FFPPPPP
+		 */
+
+		if (left_bound_found || right_bound_found) {
+			eye_training_val[byte][0] = (right_bound.phase +
+						 left_bound.phase) / 2;
+			eye_training_val[byte][1] = (right_bound.unit +
+						 left_bound.unit) / 2;
+
+			/* If we already lost 1/2PHASE Tuning,
+			 * let's try to recover by ++ on unit
+			 */
+			if (((right_bound.phase + left_bound.phase) % 2 == 1) &&
+			    eye_training_val[byte][1] != MAX_DQS_UNIT_IDX)
+				eye_training_val[byte][1]++;
+			pr_debug("** found phase : %d -  %d & unit %d - %d\n",
+				 right_bound.phase, left_bound.phase,
+				 right_bound.unit, left_bound.unit);
+			pr_debug("** calculating mid region: phase: %d  unit: %d (nominal is 3)\n",
+				 eye_training_val[byte][0],
+				 eye_training_val[byte][1]);
+		} else {
+			/* PPPPPPPPPP, we're already good.
+			 * Set nominal values.
+			 */
+			eye_training_val[byte][0] = 3;
+			eye_training_val[byte][1] = 3;
+		}
+		DQS_phase_delay(phy, byte, eye_training_val[byte][0]);
+		DQS_unit_delay(phy, byte, eye_training_val[byte][1]);
+
+		printf("Byte %d, DQS unit = %d, phase = %d\n",
+		       byte,
+		       eye_training_val[byte][1],
+		       eye_training_val[byte][0]);
+	}
+
+	if (error) {
+		sprintf(string, "error = %d", error);
+		return TEST_FAILED;
+	}
+
+	return TEST_PASSED;
+}
+
+static void display_reg_results(struct stm32mp1_ddrphy *phy, u8 byte)
+{
+	u8 i = 0;
+
+	printf("Byte %d Dekew result, bit0 delay, bit1 delay...bit8 delay\n  ",
+	       byte);
+
+	for (i = 0; i < 8; i++)
+		printf("%d ", DQ_unit_index(phy, byte, i));
+	printf("\n");
+
+	printf("dxndllcr: [%08x] val:%08x\n",
+	       DXNDLLCR(phy, byte),
+	       readl(DXNDLLCR(phy, byte)));
+	printf("dxnqdstr: [%08x] val:%08x\n",
+	       DXNDQSTR(phy, byte),
+	       readl(DXNDQSTR(phy, byte)));
+	printf("dxndqtr: [%08x] val:%08x\n",
+	       DXNDQTR(phy, byte),
+	       readl(DXNDQTR(phy, byte)));
+}
+
+/* analyse the dgs gating log table, and determine the midpoint.*/
+static u8 set_midpoint_read_dqs_gating(struct stm32mp1_ddrphy *phy, u8 byte,
+				       u8 dqs_gating[NUM_BYTES]
+						    [MAX_GSL_IDX + 1]
+						    [MAX_GPS_IDX + 1])
+{
+	/* stores the dqs gate values (gsl index, gps index) */
+	u8 dqs_gate_values[NUM_BYTES][2];
+	u8 gsl_idx, gps_idx = 0;
+	u8 left_bound_idx[2] = {0, 0};
+	u8 right_bound_idx[2] = {0, 0};
+	u8 left_bound_found = 0;
+	u8 right_bound_found = 0;
+	u8 intermittent = 0;
+	u8 value;
+
+	for (gsl_idx = 0; gsl_idx <= MAX_GSL_IDX; gsl_idx++) {
+		for (gps_idx = 0; gps_idx <= MAX_GPS_IDX; gps_idx++) {
+			value = dqs_gating[byte][gsl_idx][gps_idx];
+			if (value == 1 && left_bound_found == 0) {
+				left_bound_idx[0] = gsl_idx;
+				left_bound_idx[1] = gps_idx;
+				left_bound_found = 1;
+			} else if (value == 0 &&
+				   left_bound_found == 1 &&
+				   !right_bound_found) {
+				if (gps_idx == 0) {
+					right_bound_idx[0] = gsl_idx - 1;
+					right_bound_idx[1] = MAX_GPS_IDX;
+				} else {
+					right_bound_idx[0] = gsl_idx;
+					right_bound_idx[1] = gps_idx - 1;
+				}
+				right_bound_found = 1;
+			} else if (value == 1 &&
+				   right_bound_found == 1) {
+				intermittent = 1;
+			}
+		}
+	}
+
+	/* if only ppppppp is found, there is no mid region. */
+	if (left_bound_idx[0] == 0 && left_bound_idx[1] == 0 &&
+	    right_bound_idx[0] == 0 && right_bound_idx[1] == 0)
+		intermittent = 1;
+
+	/*if we found a regular fail pass fail pattern ffppppppff
+	 * or pppppff  or ffppppp
+	 */
+	if (!intermittent) {
+		/*if we found a regular fail pass fail pattern ffppppppff
+		 * or pppppff  or ffppppp
+		 */
+		if (left_bound_found || right_bound_found) {
+			pr_debug("idx0(%d): %d %d      idx1(%d) : %d %d\n",
+				 left_bound_found,
+				 right_bound_idx[0], left_bound_idx[0],
+				 right_bound_found,
+				 right_bound_idx[1], left_bound_idx[1]);
+			dqs_gate_values[byte][0] =
+				(right_bound_idx[0] + left_bound_idx[0]) / 2;
+			dqs_gate_values[byte][1] =
+				(right_bound_idx[1] + left_bound_idx[1]) / 2;
+			/* if we already lost 1/2gsl tuning,
+			 * let's try to recover by ++ on gps
+			 */
+			if (((right_bound_idx[0] +
+			      left_bound_idx[0]) % 2 == 1) &&
+			    dqs_gate_values[byte][1] != MAX_GPS_IDX)
+				dqs_gate_values[byte][1]++;
+			/* if we already lost 1/2gsl tuning and gps is on max*/
+			else if (((right_bound_idx[0] +
+				   left_bound_idx[0]) % 2 == 1) &&
+				 dqs_gate_values[byte][1] == MAX_GPS_IDX) {
+				dqs_gate_values[byte][1] = 0;
+				dqs_gate_values[byte][0]++;
+			}
+			/* if we have gsl left and write limit too close
+			 * (difference=1)
+			 */
+			if (((right_bound_idx[0] - left_bound_idx[0]) == 1)) {
+				dqs_gate_values[byte][1] = (left_bound_idx[1] +
+							    right_bound_idx[1] +
+							    4) / 2;
+				if (dqs_gate_values[byte][1] >= 4) {
+					dqs_gate_values[byte][0] =
+						right_bound_idx[0];
+					dqs_gate_values[byte][1] -= 4;
+				} else {
+					dqs_gate_values[byte][0] =
+						left_bound_idx[0];
+				}
+			}
+			pr_debug("*******calculating mid region: system latency: %d  phase: %d********\n",
+				 dqs_gate_values[byte][0],
+				 dqs_gate_values[byte][1]);
+			pr_debug("*******the nominal values were system latency: 0  phase: 2*******\n");
+			set_r0dgsl_delay(phy, byte, dqs_gate_values[byte][0]);
+			set_r0dgps_delay(phy, byte, dqs_gate_values[byte][1]);
+		}
+	} else {
+		/* if intermitant, restore defaut values */
+		pr_debug("dqs gating:no regular fail/pass/fail found. defaults values restored.\n");
+		set_r0dgsl_delay(phy, byte, 0);
+		set_r0dgps_delay(phy, byte, 2);
+	}
+
+	/* return 0 if intermittent or if both left_bound
+	 * and right_bound are not found
+	 */
+	return !(intermittent || (left_bound_found && right_bound_found));
+}
+
+static enum test_result read_dqs_gating(struct stm32mp1_ddrctl *ctl,
+					struct stm32mp1_ddrphy *phy,
+					char *string)
+{
+	/* stores the log of pass/fail */
+	u8 dqs_gating[NUM_BYTES][MAX_GSL_IDX + 1][MAX_GPS_IDX + 1];
+	u8 byte, gsl_idx, gps_idx = 0;
+	struct BIST_result result;
+	u8 success = 0;
+	u8 nb_bytes = get_nb_bytes(ctl);
+
+	memset(dqs_gating, 0x0, sizeof(dqs_gating));
+
+	/*disable dqs drift compensation*/
+	clrbits_le32(&phy->pgcr, DDRPHYC_PGCR_DFTCMP);
+	/*disable all bytes*/
+	/* disable automatic power down of dll and ios when disabling a byte
+	 * (to avoid having to add programming and  delay
+	 * for a dll re-lock when later re-enabling a disabled byte lane)
+	 */
+	clrbits_le32(&phy->pgcr, DDRPHYC_PGCR_PDDISDX);
+
+	/* disable all data bytes */
+	clrbits_le32(&phy->dx0gcr, DDRPHYC_DXNGCR_DXEN);
+	clrbits_le32(&phy->dx1gcr, DDRPHYC_DXNGCR_DXEN);
+	clrbits_le32(&phy->dx2gcr, DDRPHYC_DXNGCR_DXEN);
+	clrbits_le32(&phy->dx3gcr, DDRPHYC_DXNGCR_DXEN);
+
+	/* config the bist block */
+	config_BIST(phy);
+
+	for (byte = 0; byte < nb_bytes; byte++) {
+		if (ctrlc()) {
+			sprintf(string, "interrupted at byte %d/%d",
+				byte + 1, nb_bytes);
+			return TEST_FAILED;
+		}
+		/* enable byte x (dxngcr, bit dxen) */
+		setbits_le32(DXNGCR(phy, byte), DDRPHYC_DXNGCR_DXEN);
+
+		/* select the byte lane for comparison of read data */
+		BIST_datx8_sel(phy, byte);
+		for (gsl_idx = 0; gsl_idx <= MAX_GSL_IDX; gsl_idx++) {
+			for (gps_idx = 0; gps_idx <= MAX_GPS_IDX; gps_idx++) {
+				if (ctrlc()) {
+					sprintf(string,
+						"interrupted at byte %d/%d",
+						byte + 1, nb_bytes);
+					return TEST_FAILED;
+				}
+				/* write cfg to dxndqstr */
+				set_r0dgsl_delay(phy, byte, gsl_idx);
+				set_r0dgps_delay(phy, byte, gps_idx);
+
+				BIST_test(phy, byte, &result);
+				success = result.test_result;
+				if (success)
+					dqs_gating[byte][gsl_idx][gps_idx] = 1;
+				itm_soft_reset(phy);
+			}
+		}
+		set_midpoint_read_dqs_gating(phy, byte, dqs_gating);
+		/* dummy reads */
+		readl(0xc0000000);
+		readl(0xc0000000);
+	}
+
+	/* re-enable drift compensation */
+	/* setbits_le32(&phy->pgcr, DDRPHYC_PGCR_DFTCMP); */
+	return TEST_PASSED;
+}
+
+/****************************************************************
+ * TEST
+ ****************************************************************
+ */
+static enum test_result do_read_dqs_gating(struct stm32mp1_ddrctl *ctl,
+					   struct stm32mp1_ddrphy *phy,
+					   char *string, int argc,
+					   char *argv[])
+{
+	u32 rfshctl3 = readl(&ctl->rfshctl3);
+	u32 pwrctl = readl(&ctl->pwrctl);
+	enum test_result res;
+
+	stm32mp1_refresh_disable(ctl);
+	res = read_dqs_gating(ctl, phy, string);
+	stm32mp1_refresh_restore(ctl, rfshctl3, pwrctl);
+
+	return res;
+}
+
+static enum test_result do_bit_deskew(struct stm32mp1_ddrctl *ctl,
+				      struct stm32mp1_ddrphy *phy,
+				      char *string, int argc, char *argv[])
+{
+	u32 rfshctl3 = readl(&ctl->rfshctl3);
+	u32 pwrctl = readl(&ctl->pwrctl);
+	enum test_result res;
+
+	stm32mp1_refresh_disable(ctl);
+	res = bit_deskew(ctl, phy, string);
+	stm32mp1_refresh_restore(ctl, rfshctl3, pwrctl);
+
+	return res;
+}
+
+static enum test_result do_eye_training(struct stm32mp1_ddrctl *ctl,
+					struct stm32mp1_ddrphy *phy,
+					char *string, int argc, char *argv[])
+{
+	u32 rfshctl3 = readl(&ctl->rfshctl3);
+	u32 pwrctl = readl(&ctl->pwrctl);
+	enum test_result res;
+
+	stm32mp1_refresh_disable(ctl);
+	res = eye_training(ctl, phy, string);
+	stm32mp1_refresh_restore(ctl, rfshctl3, pwrctl);
+
+	return res;
+}
+
+static enum test_result do_display(struct stm32mp1_ddrctl *ctl,
+				   struct stm32mp1_ddrphy *phy,
+				   char *string, int argc, char *argv[])
+{
+	int byte;
+	u8 nb_bytes = get_nb_bytes(ctl);
+
+	for (byte = 0; byte < nb_bytes; byte++)
+		display_reg_results(phy, byte);
+
+	return TEST_PASSED;
+}
+
+static enum test_result do_bist_config(struct stm32mp1_ddrctl *ctl,
+				       struct stm32mp1_ddrphy *phy,
+				       char *string, int argc, char *argv[])
+{
+	unsigned long value;
+
+	if (argc > 0) {
+		if (strict_strtoul(argv[0], 0, &value) < 0) {
+			sprintf(string, "invalid nbErr %s", argv[0]);
+			return TEST_FAILED;
+		}
+		BIST_error_max = value;
+	}
+	if (argc > 1) {
+		if (strict_strtoul(argv[1], 0, &value) < 0) {
+			sprintf(string, "invalid Seed %s", argv[1]);
+			return TEST_FAILED;
+		}
+		BIST_seed = value;
+	}
+	printf("Bist.nbErr = %d\n", BIST_error_max);
+	if (BIST_seed)
+		printf("Bist.Seed = 0x%x\n", BIST_seed);
+	else
+		printf("Bist.Seed = random\n");
+
+	return TEST_PASSED;
+}
+
+/****************************************************************
+ * TEST Description
+ ****************************************************************
+ */
+
+const struct test_desc tuning[] = {
+	{do_read_dqs_gating, "Read DQS gating",
+		"software read DQS Gating", "", 0 },
+	{do_bit_deskew, "Bit de-skew", "", "", 0 },
+	{do_eye_training, "Eye Training", "or DQS training", "", 0 },
+	{do_display, "Display registers", "", "", 0 },
+	{do_bist_config, "Bist config", "[nbErr] [seed]",
+	 "configure Bist test", 2},
+};
+
+const int tuning_nb = ARRAY_SIZE(tuning);
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index fcbb0a8..8a447fd 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -559,6 +559,14 @@
 	  Choose this option to add support for UART driver on the Marvell
 	  Armada 3700 SoC. The base address is configured via DT.
 
+config MCFUART
+	bool "Freescale ColdFire UART support"
+        help
+          Choose this option to add support for UART driver on the ColdFire
+          SoC's family. The serial communication channel provides a full-duplex
+          asynchronous/synchronous receiver and transmitter deriving an
+          operating frequency from the internal bus clock or an external clock.
+
 config MXC_UART
 	bool "IMX serial port support"
 	depends on MX5 || MX6
diff --git a/drivers/serial/mcfuart.c b/drivers/serial/mcfuart.c
index 1371049..066e5a1 100644
--- a/drivers/serial/mcfuart.c
+++ b/drivers/serial/mcfuart.c
@@ -5,6 +5,9 @@
  *
  * Modified to add device model (DM) support
  * (C) Copyright 2015  Angelo Dureghello <angelo@sysam.it>
+ *
+ * Modified to add DM and fdt support, removed non DM code
+ * (C) Copyright 2018  Angelo Dureghello <angelo@sysam.it>
  */
 
 /*
@@ -78,83 +81,6 @@
 	writeb(UART_UCR_RX_ENABLED | UART_UCR_TX_ENABLED, &uart->ucr);
 }
 
-#ifndef CONFIG_DM_SERIAL
-
-static int mcf_serial_init(void)
-{
-	uart_t *uart_base;
-	int port_idx;
-
-	uart_base = (uart_t *)CONFIG_SYS_UART_BASE;
-	port_idx = CONFIG_SYS_UART_PORT;
-
-	return mcf_serial_init_common(uart_base, port_idx, gd->baudrate);
-}
-
-static void mcf_serial_putc(const char c)
-{
-	uart_t *uart = (uart_t *)CONFIG_SYS_UART_BASE;
-
-	if (c == '\n')
-		serial_putc('\r');
-
-	/* Wait for last character to go. */
-	while (!(readb(&uart->usr) & UART_USR_TXRDY))
-		;
-
-	writeb(c, &uart->utb);
-}
-
-static int mcf_serial_getc(void)
-{
-	uart_t *uart = (uart_t *)CONFIG_SYS_UART_BASE;
-
-	/* Wait for a character to arrive. */
-	while (!(readb(&uart->usr) & UART_USR_RXRDY))
-		;
-
-	return readb(&uart->urb);
-}
-
-static void mcf_serial_setbrg(void)
-{
-	uart_t *uart = (uart_t *)CONFIG_SYS_UART_BASE;
-
-	mcf_serial_setbrg_common(uart, gd->baudrate);
-}
-
-static int mcf_serial_tstc(void)
-{
-	uart_t *uart = (uart_t *)CONFIG_SYS_UART_BASE;
-
-	return readb(&uart->usr) & UART_USR_RXRDY;
-}
-
-static struct serial_device mcf_serial_drv = {
-	.name	= "mcf_serial",
-	.start	= mcf_serial_init,
-	.stop	= NULL,
-	.setbrg	= mcf_serial_setbrg,
-	.putc	= mcf_serial_putc,
-	.puts	= default_serial_puts,
-	.getc	= mcf_serial_getc,
-	.tstc	= mcf_serial_tstc,
-};
-
-void mcf_serial_initialize(void)
-{
-	serial_register(&mcf_serial_drv);
-}
-
-__weak struct serial_device *default_serial_console(void)
-{
-	return &mcf_serial_drv;
-}
-
-#endif
-
-#ifdef CONFIG_DM_SERIAL
-
 static int coldfire_serial_probe(struct udevice *dev)
 {
 	struct coldfire_serial_platdata *plat = dev->platdata;
@@ -212,6 +138,23 @@
 	return 0;
 }
 
+static int coldfire_ofdata_to_platdata(struct udevice *dev)
+{
+	struct coldfire_serial_platdata *plat = dev_get_platdata(dev);
+	fdt_addr_t addr_base;
+
+	addr_base = devfdt_get_addr(dev);
+	if (addr_base == FDT_ADDR_T_NONE)
+		return -ENODEV;
+
+	plat->base = (uint32_t)addr_base;
+
+	plat->port = dev->seq;
+	plat->baudrate = gd->baudrate;
+
+	return 0;
+}
+
 static const struct dm_serial_ops coldfire_serial_ops = {
 	.putc = coldfire_serial_putc,
 	.pending = coldfire_serial_pending,
@@ -219,11 +162,18 @@
 	.setbrg = coldfire_serial_setbrg,
 };
 
+static const struct udevice_id coldfire_serial_ids[] = {
+	{ .compatible = "fsl,mcf-uart" },
+	{ }
+};
+
 U_BOOT_DRIVER(serial_coldfire) = {
 	.name = "serial_coldfire",
 	.id = UCLASS_SERIAL,
+	.of_match = coldfire_serial_ids,
+	.ofdata_to_platdata = coldfire_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct coldfire_serial_platdata),
 	.probe = coldfire_serial_probe,
 	.ops = &coldfire_serial_ops,
 	.flags = DM_FLAG_PRE_RELOC,
 };
-#endif
diff --git a/drivers/serial/serial_stm32.c b/drivers/serial/serial_stm32.c
index e31c87b..cca8b70 100644
--- a/drivers/serial/serial_stm32.c
+++ b/drivers/serial/serial_stm32.c
@@ -269,7 +269,6 @@
 	_stm32_serial_setbrg(base, uart_info,
 			     CONFIG_DEBUG_UART_CLOCK,
 			     CONFIG_BAUDRATE);
-	printf("DEBUG done\n");
 }
 
 static inline void _debug_uart_putc(int c)
@@ -278,7 +277,7 @@
 	struct stm32_uart_info *uart_info = _debug_uart_info();
 
 	while (_stm32_serial_putc(base, uart_info, c) == -EAGAIN)
-		WATCHDOG_RESET();
+		;
 }
 
 DEBUG_UART_FUNCS
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index c3a829d..7044da3 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -87,6 +87,12 @@
 	  used to access the SPI NOR flash on platforms embedding this
 	  Cadence IP core.
 
+config CF_SPI
+        bool "ColdFire SPI driver"
+        help
+          Enable the ColdFire SPI driver. This driver can be used on
+          some m68k SoCs.
+
 config DESIGNWARE_SPI
 	bool "Designware SPI driver"
 	help
diff --git a/drivers/spi/cf_spi.c b/drivers/spi/cf_spi.c
index 522631c..923ff6f 100644
--- a/drivers/spi/cf_spi.c
+++ b/drivers/spi/cf_spi.c
@@ -6,23 +6,28 @@
  *
  * Copyright (C) 2004-2009 Freescale Semiconductor, Inc.
  * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
+ *
+ * Support for DM and DT, non-DM code removed.
+ * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
+ *
+ * TODO: fsl_dspi.c should work as a driver for the DSPI module.
  */
 
 #include <common.h>
+#include <dm.h>
+#include <dm/platform_data/spi_coldfire.h>
 #include <spi.h>
 #include <malloc.h>
-#include <asm/immap.h>
+#include <asm/coldfire/dspi.h>
+#include <asm/io.h>
 
-struct cf_spi_slave {
-	struct spi_slave slave;
+struct coldfire_spi_priv {
+	struct dspi *regs;
 	uint baudrate;
+	int mode;
 	int charbit;
 };
 
-extern void cfspi_port_conf(void);
-extern int cfspi_claim_bus(uint bus, uint cs);
-extern void cfspi_release_bus(uint bus, uint cs);
-
 DECLARE_GLOBAL_DATA_PTR;
 
 #ifndef CONFIG_SPI_IDLE_VAL
@@ -33,163 +38,193 @@
 #endif
 #endif
 
+/*
+ * DSPI specific mode
+ *
+ * bit 31 - 28: Transfer size 3 to 16 bits
+ *     27 - 26: PCS to SCK delay prescaler
+ *     25 - 24: After SCK delay prescaler
+ *     23 - 22: Delay after transfer prescaler
+ *     21     : Allow overwrite for bit 31-22 and bit 20-8
+ *     20     : Double baud rate
+ *     19 - 16: PCS to SCK delay scaler
+ *     15 - 12: After SCK delay scaler
+ *     11 -  8: Delay after transfer scaler
+ *      7 -  0: SPI_CPHA, SPI_CPOL, SPI_LSB_FIRST
+ */
+#define SPI_MODE_MOD			0x00200000
+#define SPI_MODE_DBLRATE		0x00100000
+
+#define SPI_MODE_XFER_SZ_MASK		0xf0000000
+#define SPI_MODE_DLY_PRE_MASK		0x0fc00000
+#define SPI_MODE_DLY_SCA_MASK		0x000fff00
+
-#if defined(CONFIG_CF_DSPI)
-/* DSPI specific mode */
-#define SPI_MODE_MOD	0x00200000
-#define SPI_DBLRATE	0x00100000
+#define MCF_FRM_SZ_16BIT		DSPI_CTAR_TRSZ(0xf)
+#define MCF_DSPI_SPEED_BESTMATCH	0x7FFFFFFF
+#define MCF_DSPI_MAX_CTAR_REGS		8
 
-static inline struct cf_spi_slave *to_cf_spi_slave(struct spi_slave *slave)
+/* Default values */
+#define MCF_DSPI_DEFAULT_SCK_FREQ	10000000
+#define MCF_DSPI_DEFAULT_MAX_CS		4
+#define MCF_DSPI_DEFAULT_MODE		0
+
+#define MCF_DSPI_DEFAULT_CTAR		(DSPI_CTAR_TRSZ(7) | \
+					DSPI_CTAR_PCSSCK_1CLK | \
+					DSPI_CTAR_PASC(0) | \
+					DSPI_CTAR_PDT(0) | \
+					DSPI_CTAR_CSSCK(0) | \
+					DSPI_CTAR_ASC(0) | \
+					DSPI_CTAR_DT(1) | \
+					DSPI_CTAR_BR(6))
+
+#define MCF_CTAR_MODE_MASK		(MCF_FRM_SZ_16BIT | \
+					DSPI_CTAR_PCSSCK(3) | \
+					DSPI_CTAR_PASC_7CLK | \
+					DSPI_CTAR_PDT(3) | \
+					DSPI_CTAR_CSSCK(0x0f) | \
+					DSPI_CTAR_ASC(0x0f) | \
+					DSPI_CTAR_DT(0x0f))
+
+#define setup_ctrl(ctrl, cs)	((ctrl & 0xFF000000) | ((1 << cs) << 16))
+
+static inline void cfspi_tx(struct coldfire_spi_priv *cfspi,
+			    u32 ctrl, u16 data)
 {
-	return container_of(slave, struct cf_spi_slave, slave);
+	/*
+	 * Need to check fifo level here
+	 */
+	while ((readl(&cfspi->regs->sr) & 0x0000F000) >= 0x4000)
+		;
+
+	writel(ctrl | data, &cfspi->regs->tfr);
 }
 
-static void cfspi_init(void)
+static inline u16 cfspi_rx(struct coldfire_spi_priv *cfspi)
 {
-	volatile dspi_t *dspi = (dspi_t *) MMAP_DSPI;
 
-	cfspi_port_conf();	/* port configuration */
-
-	dspi->mcr = DSPI_MCR_MSTR | DSPI_MCR_CSIS7 | DSPI_MCR_CSIS6 |
-	    DSPI_MCR_CSIS5 | DSPI_MCR_CSIS4 | DSPI_MCR_CSIS3 |
-	    DSPI_MCR_CSIS2 | DSPI_MCR_CSIS1 | DSPI_MCR_CSIS0 |
-	    DSPI_MCR_CRXF | DSPI_MCR_CTXF;
+	while ((readl(&cfspi->regs->sr) & 0x000000F0) == 0)
+		;
 
-	/* Default setting in platform configuration */
-#ifdef CONFIG_SYS_DSPI_CTAR0
-	dspi->ctar[0] = CONFIG_SYS_DSPI_CTAR0;
-#endif
-#ifdef CONFIG_SYS_DSPI_CTAR1
-	dspi->ctar[1] = CONFIG_SYS_DSPI_CTAR1;
-#endif
-#ifdef CONFIG_SYS_DSPI_CTAR2
-	dspi->ctar[2] = CONFIG_SYS_DSPI_CTAR2;
-#endif
-#ifdef CONFIG_SYS_DSPI_CTAR3
-	dspi->ctar[3] = CONFIG_SYS_DSPI_CTAR3;
-#endif
-#ifdef CONFIG_SYS_DSPI_CTAR4
-	dspi->ctar[4] = CONFIG_SYS_DSPI_CTAR4;
-#endif
-#ifdef CONFIG_SYS_DSPI_CTAR5
-	dspi->ctar[5] = CONFIG_SYS_DSPI_CTAR5;
-#endif
-#ifdef CONFIG_SYS_DSPI_CTAR6
-	dspi->ctar[6] = CONFIG_SYS_DSPI_CTAR6;
-#endif
-#ifdef CONFIG_SYS_DSPI_CTAR7
-	dspi->ctar[7] = CONFIG_SYS_DSPI_CTAR7;
-#endif
+	return readw(&cfspi->regs->rfr);
 }
 
-static void cfspi_tx(u32 ctrl, u16 data)
+static int coldfire_spi_claim_bus(struct udevice *dev)
 {
-	volatile dspi_t *dspi = (dspi_t *) MMAP_DSPI;
+	struct udevice *bus = dev->parent;
+	struct coldfire_spi_priv *cfspi = dev_get_priv(bus);
+	struct dspi *dspi = cfspi->regs;
+	struct dm_spi_slave_platdata *slave_plat =
+		dev_get_parent_platdata(dev);
+
+	if ((in_be32(&dspi->sr) & DSPI_SR_TXRXS) != DSPI_SR_TXRXS)
+		return -1;
+
+	/* Clear FIFO and resume transfer */
+	clrbits_be32(&dspi->mcr, DSPI_MCR_CTXF | DSPI_MCR_CRXF);
 
-	while ((dspi->sr & 0x0000F000) >= 4) ;
+	dspi_chip_select(slave_plat->cs);
 
-	dspi->tfr = (ctrl | data);
+	return 0;
 }
 
-static u16 cfspi_rx(void)
+static int coldfire_spi_release_bus(struct udevice *dev)
 {
-	volatile dspi_t *dspi = (dspi_t *) MMAP_DSPI;
+	struct udevice *bus = dev->parent;
+	struct coldfire_spi_priv *cfspi = dev_get_priv(bus);
+	struct dspi *dspi = cfspi->regs;
+	struct dm_spi_slave_platdata *slave_plat =
+		dev_get_parent_platdata(dev);
+
+	/* Clear FIFO */
+	clrbits_be32(&dspi->mcr, DSPI_MCR_CTXF | DSPI_MCR_CRXF);
 
-	while ((dspi->sr & 0x000000F0) == 0) ;
+	dspi_chip_unselect(slave_plat->cs);
 
-	return (dspi->rfr & 0xFFFF);
+	return 0;
 }
 
-static int cfspi_xfer(struct spi_slave *slave, uint bitlen, const void *dout,
-		      void *din, ulong flags)
+static int coldfire_spi_xfer(struct udevice *dev, unsigned int bitlen,
+			     const void *dout, void *din,
+			     unsigned long flags)
 {
-	struct cf_spi_slave *cfslave = to_cf_spi_slave(slave);
+	struct udevice *bus = dev_get_parent(dev);
+	struct coldfire_spi_priv *cfspi = dev_get_priv(bus);
+	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
 	u16 *spi_rd16 = NULL, *spi_wr16 = NULL;
 	u8 *spi_rd = NULL, *spi_wr = NULL;
-	static u32 ctrl = 0;
+	static u32 ctrl;
 	uint len = bitlen >> 3;
 
-	if (cfslave->charbit == 16) {
+	if (cfspi->charbit == 16) {
 		bitlen >>= 1;
-		spi_wr16 = (u16 *) dout;
-		spi_rd16 = (u16 *) din;
+		spi_wr16 = (u16 *)dout;
+		spi_rd16 = (u16 *)din;
 	} else {
-		spi_wr = (u8 *) dout;
-		spi_rd = (u8 *) din;
+		spi_wr = (u8 *)dout;
+		spi_rd = (u8 *)din;
 	}
 
 	if ((flags & SPI_XFER_BEGIN) == SPI_XFER_BEGIN)
 		ctrl |= DSPI_TFR_CONT;
 
-	ctrl = (ctrl & 0xFF000000) | ((1 << slave->cs) << 16);
+	ctrl = setup_ctrl(ctrl, slave_plat->cs);
 
 	if (len > 1) {
 		int tmp_len = len - 1;
+
 		while (tmp_len--) {
-			if (dout != NULL) {
-				if (cfslave->charbit == 16)
-					cfspi_tx(ctrl, *spi_wr16++);
+			if (dout) {
+				if (cfspi->charbit == 16)
+					cfspi_tx(cfspi, ctrl, *spi_wr16++);
 				else
-					cfspi_tx(ctrl, *spi_wr++);
-				cfspi_rx();
+					cfspi_tx(cfspi, ctrl, *spi_wr++);
+				cfspi_rx(cfspi);
 			}
 
-			if (din != NULL) {
-				cfspi_tx(ctrl, CONFIG_SPI_IDLE_VAL);
-				if (cfslave->charbit == 16)
-					*spi_rd16++ = cfspi_rx();
+			if (din) {
+				cfspi_tx(cfspi, ctrl, CONFIG_SPI_IDLE_VAL);
+				if (cfspi->charbit == 16)
+					*spi_rd16++ = cfspi_rx(cfspi);
 				else
-					*spi_rd++ = cfspi_rx();
+					*spi_rd++ = cfspi_rx(cfspi);
 			}
 		}
 
 		len = 1;	/* remaining byte */
 	}
 
-	if ((flags & SPI_XFER_END) == SPI_XFER_END)
+	if (flags & SPI_XFER_END)
 		ctrl &= ~DSPI_TFR_CONT;
 
 	if (len) {
-		if (dout != NULL) {
-			if (cfslave->charbit == 16)
-				cfspi_tx(ctrl, *spi_wr16);
+		if (dout) {
+			if (cfspi->charbit == 16)
+				cfspi_tx(cfspi, ctrl, *spi_wr16);
 			else
-				cfspi_tx(ctrl, *spi_wr);
-			cfspi_rx();
+				cfspi_tx(cfspi, ctrl, *spi_wr);
+			cfspi_rx(cfspi);
 		}
 
-		if (din != NULL) {
-			cfspi_tx(ctrl, CONFIG_SPI_IDLE_VAL);
-			if (cfslave->charbit == 16)
-				*spi_rd16 = cfspi_rx();
+		if (din) {
+			cfspi_tx(cfspi, ctrl, CONFIG_SPI_IDLE_VAL);
+			if (cfspi->charbit == 16)
+				*spi_rd16 = cfspi_rx(cfspi);
 			else
-				*spi_rd = cfspi_rx();
+				*spi_rd = cfspi_rx(cfspi);
 		}
 	} else {
 		/* dummy read */
-		cfspi_tx(ctrl, CONFIG_SPI_IDLE_VAL);
-		cfspi_rx();
+		cfspi_tx(cfspi, ctrl, CONFIG_SPI_IDLE_VAL);
+		cfspi_rx(cfspi);
 	}
 
 	return 0;
 }
 
-static struct spi_slave *cfspi_setup_slave(struct cf_spi_slave *cfslave,
-					   uint mode)
+static int coldfire_spi_set_speed(struct udevice *bus, uint max_hz)
 {
-	/*
-	 * bit definition for mode:
-	 * bit 31 - 28: Transfer size 3 to 16 bits
-	 *     27 - 26: PCS to SCK delay prescaler
-	 *     25 - 24: After SCK delay prescaler
-	 *     23 - 22: Delay after transfer prescaler
-	 *     21     : Allow overwrite for bit 31-22 and bit 20-8
-	 *     20     : Double baud rate
-	 *     19 - 16: PCS to SCK delay scaler
-	 *     15 - 12: After SCK delay scaler
-	 *     11 -  8: Delay after transfer scaler
-	 *      7 -  0: SPI_CPHA, SPI_CPOL, SPI_LSB_FIRST
-	 */
-	volatile dspi_t *dspi = (dspi_t *) MMAP_DSPI;
+	struct coldfire_spi_priv *cfspi = dev_get_priv(bus);
+	struct dspi *dspi = cfspi->regs;
 	int prescaler[] = { 2, 3, 5, 7 };
 	int scaler[] = {
 		2, 4, 6, 8,
@@ -198,57 +233,41 @@
 		4096, 8192, 16384, 32768
 	};
 	int i, j, pbrcnt, brcnt, diff, tmp, dbr = 0;
-	int best_i, best_j, bestmatch = 0x7FFFFFFF, baud_speed;
-	u32 bus_setup = 0;
+	int best_i, best_j, bestmatch = MCF_DSPI_SPEED_BESTMATCH, baud_speed;
+	u32 bus_setup;
+
+	cfspi->baudrate = max_hz;
+
+	/* Read current setup */
+	bus_setup = readl(&dspi->ctar[bus->seq]);
 
 	tmp = (prescaler[3] * scaler[15]);
 	/* Maximum and minimum baudrate it can handle */
-	if ((cfslave->baudrate > (gd->bus_clk >> 1)) ||
-	    (cfslave->baudrate < (gd->bus_clk / tmp))) {
+	if ((cfspi->baudrate > (gd->bus_clk >> 1)) ||
+	    (cfspi->baudrate < (gd->bus_clk / tmp))) {
 		printf("Exceed baudrate limitation: Max %d - Min %d\n",
 		       (int)(gd->bus_clk >> 1), (int)(gd->bus_clk / tmp));
-		return NULL;
+		return -1;
 	}
 
 	/* Activate Double Baud when it exceed 1/4 the bus clk */
-	if ((CONFIG_SYS_DSPI_CTAR0 & DSPI_CTAR_DBR) ||
-	    (cfslave->baudrate > (gd->bus_clk / (prescaler[0] * scaler[0])))) {
+	if ((bus_setup & DSPI_CTAR_DBR) ||
+	    (cfspi->baudrate > (gd->bus_clk / (prescaler[0] * scaler[0])))) {
 		bus_setup |= DSPI_CTAR_DBR;
 		dbr = 1;
 	}
 
-	if (mode & SPI_CPOL)
-		bus_setup |= DSPI_CTAR_CPOL;
-	if (mode & SPI_CPHA)
-		bus_setup |= DSPI_CTAR_CPHA;
-	if (mode & SPI_LSB_FIRST)
-		bus_setup |= DSPI_CTAR_LSBFE;
-
 	/* Overwrite default value set in platform configuration file */
-	if (mode & SPI_MODE_MOD) {
-
-		if ((mode & 0xF0000000) == 0)
-			bus_setup |=
-			    dspi->ctar[cfslave->slave.bus] & 0x78000000;
-		else
-			bus_setup |= ((mode & 0xF0000000) >> 1);
-
+	if (cfspi->mode & SPI_MODE_MOD) {
 		/*
 		 * Check to see if it is enabled by default in platform
 		 * config, or manual setting passed by mode parameter
 		 */
-		if (mode & SPI_DBLRATE) {
+		if (cfspi->mode & SPI_MODE_DBLRATE) {
 			bus_setup |= DSPI_CTAR_DBR;
 			dbr = 1;
 		}
-		bus_setup |= (mode & 0x0FC00000) >> 4;	/* PSCSCK, PASC, PDT */
-		bus_setup |= (mode & 0x000FFF00) >> 4;	/* CSSCK, ASC, DT */
-	} else
-		bus_setup |= (dspi->ctar[cfslave->slave.bus] & 0x78FCFFF0);
-
-	cfslave->charbit =
-	    ((dspi->ctar[cfslave->slave.bus] & 0x78000000) ==
-	     0x78000000) ? 16 : 8;
+	}
 
 	pbrcnt = sizeof(prescaler) / sizeof(int);
 	brcnt = sizeof(scaler) / sizeof(int);
@@ -259,10 +278,10 @@
 		for (j = 0; j < brcnt; j++) {
 			tmp = (baud_speed / scaler[j]) * (1 + dbr);
 
-			if (tmp > cfslave->baudrate)
-				diff = tmp - cfslave->baudrate;
+			if (tmp > cfspi->baudrate)
+				diff = tmp - cfspi->baudrate;
 			else
-				diff = cfslave->baudrate - tmp;
+				diff = cfspi->baudrate - tmp;
 
 			if (diff < bestmatch) {
 				bestmatch = diff;
@@ -271,65 +290,174 @@
 			}
 		}
 	}
+
+	bus_setup &= ~(DSPI_CTAR_PBR(0x03) | DSPI_CTAR_BR(0x0f));
 	bus_setup |= (DSPI_CTAR_PBR(best_i) | DSPI_CTAR_BR(best_j));
-	dspi->ctar[cfslave->slave.bus] = bus_setup;
+	writel(bus_setup, &dspi->ctar[bus->seq]);
 
-	return &cfslave->slave;
+	return 0;
 }
-#endif				/* CONFIG_CF_DSPI */
 
-#ifdef CONFIG_CMD_SPI
-int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+static int coldfire_spi_set_mode(struct udevice *bus, uint mode)
 {
-	if (((cs >= 0) && (cs < 8)) && ((bus >= 0) && (bus < 8)))
-		return 1;
-	else
-		return 0;
-}
+	struct coldfire_spi_priv *cfspi = dev_get_priv(bus);
+	struct dspi *dspi = cfspi->regs;
+	u32 bus_setup = 0;
 
-void spi_init(void)
-{
-	cfspi_init();
-}
+	cfspi->mode = mode;
 
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
-				  unsigned int max_hz, unsigned int mode)
-{
-	struct cf_spi_slave *cfslave;
+	if (cfspi->mode & SPI_CPOL)
+		bus_setup |= DSPI_CTAR_CPOL;
+	if (cfspi->mode & SPI_CPHA)
+		bus_setup |= DSPI_CTAR_CPHA;
+	if (cfspi->mode & SPI_LSB_FIRST)
+		bus_setup |= DSPI_CTAR_LSBFE;
 
-	if (!spi_cs_is_valid(bus, cs))
-		return NULL;
+	/* Overwrite default value set in platform configuration file */
+	if (cfspi->mode & SPI_MODE_MOD) {
+		if ((cfspi->mode & SPI_MODE_XFER_SZ_MASK) == 0)
+			bus_setup |=
+			    readl(&dspi->ctar[bus->seq]) & MCF_FRM_SZ_16BIT;
+		else
+			bus_setup |=
+			    ((cfspi->mode & SPI_MODE_XFER_SZ_MASK) >> 1);
+
+		/* PSCSCK, PASC, PDT */
+		bus_setup |= (cfspi->mode & SPI_MODE_DLY_PRE_MASK) >> 4;
+		/* CSSCK, ASC, DT */
+		bus_setup |= (cfspi->mode & SPI_MODE_DLY_SCA_MASK) >> 4;
+	} else {
+		bus_setup |=
+			(readl(&dspi->ctar[bus->seq]) & MCF_CTAR_MODE_MASK);
+	}
 
-	cfslave = spi_alloc_slave(struct cf_spi_slave, bus, cs);
-	if (!cfslave)
-		return NULL;
+	cfspi->charbit =
+		((readl(&dspi->ctar[bus->seq]) & MCF_FRM_SZ_16BIT) ==
+			MCF_FRM_SZ_16BIT) ? 16 : 8;
 
-	cfslave->baudrate = max_hz;
+	setbits_be32(&dspi->ctar[bus->seq], bus_setup);
 
-	/* specific setup */
-	return cfspi_setup_slave(cfslave, mode);
+	return 0;
 }
 
-void spi_free_slave(struct spi_slave *slave)
+static int coldfire_spi_probe(struct udevice *bus)
 {
-	struct cf_spi_slave *cfslave = to_cf_spi_slave(slave);
+	struct coldfire_spi_platdata *plat = dev_get_platdata(bus);
+	struct coldfire_spi_priv *cfspi = dev_get_priv(bus);
+	struct dspi *dspi = cfspi->regs;
+	int i;
 
-	free(cfslave);
-}
+	cfspi->regs = (struct dspi *)plat->regs_addr;
 
-int spi_claim_bus(struct spi_slave *slave)
-{
-	return cfspi_claim_bus(slave->bus, slave->cs);
+	cfspi->baudrate = plat->speed_hz;
+	cfspi->mode = plat->mode;
+
+	for (i = 0; i < MCF_DSPI_MAX_CTAR_REGS; i++) {
+		unsigned int ctar = 0;
+
+		if (plat->ctar[i][0] == 0)
+			break;
+
+		ctar = DSPI_CTAR_TRSZ(plat->ctar[i][0]) |
+			DSPI_CTAR_PCSSCK(plat->ctar[i][1]) |
+			DSPI_CTAR_PASC(plat->ctar[i][2]) |
+			DSPI_CTAR_PDT(plat->ctar[i][3]) |
+			DSPI_CTAR_CSSCK(plat->ctar[i][4]) |
+			DSPI_CTAR_ASC(plat->ctar[i][5]) |
+			DSPI_CTAR_DT(plat->ctar[i][6]) |
+			DSPI_CTAR_BR(plat->ctar[i][7]);
+
+		writel(ctar, &cfspi->regs->ctar[i]);
+	}
+
+	/* Default CTARs */
+	for (i = 0; i < MCF_DSPI_MAX_CTAR_REGS; i++)
+		writel(MCF_DSPI_DEFAULT_CTAR, &dspi->ctar[i]);
+
+	dspi->mcr = DSPI_MCR_MSTR | DSPI_MCR_CSIS7 | DSPI_MCR_CSIS6 |
+	    DSPI_MCR_CSIS5 | DSPI_MCR_CSIS4 | DSPI_MCR_CSIS3 |
+	    DSPI_MCR_CSIS2 | DSPI_MCR_CSIS1 | DSPI_MCR_CSIS0 |
+	    DSPI_MCR_CRXF | DSPI_MCR_CTXF;
+
+	return 0;
 }
 
-void spi_release_bus(struct spi_slave *slave)
+void spi_init(void)
 {
-	cfspi_release_bus(slave->bus, slave->cs);
 }
 
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
-	     void *din, unsigned long flags)
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
+static int coldfire_dspi_ofdata_to_platdata(struct udevice *bus)
 {
-	return cfspi_xfer(slave, bitlen, dout, din, flags);
+	fdt_addr_t addr;
+	struct coldfire_spi_platdata *plat = bus->platdata;
+	const void *blob = gd->fdt_blob;
+	int node = dev_of_offset(bus);
+	int *ctar, len;
+
+	addr = devfdt_get_addr(bus);
+	if (addr == FDT_ADDR_T_NONE)
+		return -ENOMEM;
+
+	plat->regs_addr = addr;
+
+	plat->num_cs = fdtdec_get_int(blob, node, "num-cs",
+				      MCF_DSPI_DEFAULT_MAX_CS);
+
+	plat->speed_hz = fdtdec_get_int(blob, node, "spi-max-frequency",
+					MCF_DSPI_DEFAULT_SCK_FREQ);
+
+	plat->mode = fdtdec_get_int(blob, node, "spi-mode",
+				    MCF_DSPI_DEFAULT_MODE);
+
+	memset(plat->ctar, 0, sizeof(plat->ctar));
+
+	ctar = (int *)fdt_getprop(blob, node, "ctar-params", &len);
+
+	if (ctar && len) {
+		int i, q, ctar_regs;
+
+		ctar_regs = len / sizeof(unsigned int) / MAX_CTAR_FIELDS;
+
+		if (ctar_regs > MAX_CTAR_REGS)
+			ctar_regs = MAX_CTAR_REGS;
+
+		for (i = 0; i < ctar_regs; i++) {
+			for (q = 0; q < MAX_CTAR_FIELDS; q++)
+				plat->ctar[i][q] = *ctar++;
+		}
+	}
+
+	debug("DSPI: regs=%pa, max-frequency=%d, num-cs=%d, mode=%d\n",
+	      (void *)plat->regs_addr,
+	       plat->speed_hz, plat->num_cs, plat->mode);
+
+	return 0;
 }
-#endif				/* CONFIG_CMD_SPI */
+
+static const struct udevice_id coldfire_spi_ids[] = {
+	{ .compatible = "fsl,mcf-dspi" },
+	{ }
+};
+#endif
+
+static const struct dm_spi_ops coldfire_spi_ops = {
+	.claim_bus	= coldfire_spi_claim_bus,
+	.release_bus	= coldfire_spi_release_bus,
+	.xfer		= coldfire_spi_xfer,
+	.set_speed	= coldfire_spi_set_speed,
+	.set_mode	= coldfire_spi_set_mode,
+};
+
+U_BOOT_DRIVER(coldfire_spi) = {
+	.name = "spi_coldfire",
+	.id = UCLASS_SPI,
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
+	.of_match = coldfire_spi_ids,
+	.ofdata_to_platdata = coldfire_dspi_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct coldfire_spi_platdata),
+#endif
+	.probe = coldfire_spi_probe,
+	.ops = &coldfire_spi_ops,
+	.priv_auto_alloc_size = sizeof(struct coldfire_spi_priv),
+};
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 23e7e71..b8f8e7a 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -75,8 +75,12 @@
 	struct usb_ehci *ehci = NULL;
 	struct ehci_fsl_priv *priv = container_of(ctrl, struct ehci_fsl_priv,
 						   ehci);
-
+#ifdef CONFIG_PPC
+	ehci = (struct usb_ehci *)lower_32_bits(priv->hcd_base);
+#else
 	ehci = (struct usb_ehci *)priv->hcd_base;
+#endif
+
 	if (ehci_fsl_init(priv, ehci, priv->ehci.hccr, priv->ehci.hcor) < 0)
 		return -ENXIO;
 
@@ -103,7 +107,11 @@
 		debug("Can't get the EHCI register base address\n");
 		return -ENXIO;
 	}
+#ifdef CONFIG_PPC
+	ehci = (struct usb_ehci *)lower_32_bits(priv->hcd_base);
+#else
 	ehci = (struct usb_ehci *)priv->hcd_base;
+#endif
 	hccr = (struct ehci_hccr *)(&ehci->caplength);
 	hcor = (struct ehci_hcor *)
 		((void *)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
diff --git a/env/Kconfig b/env/Kconfig
index 70858d3..1e10c7a 100644
--- a/env/Kconfig
+++ b/env/Kconfig
@@ -470,7 +470,7 @@
 	  It's a string of the EXT4 file name. This file use to store the
 	  environment (explicit path to the file)
 
-if ARCH_ROCKCHIP || ARCH_SUNXI || ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_VERSAL || ARC
+if ARCH_ROCKCHIP || ARCH_SUNXI || ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_VERSAL || ARC || ARCH_STM32MP
 
 config ENV_OFFSET
 	hex "Environment Offset"
diff --git a/env/common.c b/env/common.c
index 324502e..bd340fe 100644
--- a/env/common.c
+++ b/env/common.c
@@ -23,7 +23,10 @@
 #include <env_default.h>
 
 struct hsearch_data env_htab = {
+#if CONFIG_IS_ENABLED(ENV_SUPPORT)
+	/* defined in flags.c, only compile with ENV_SUPPORT */
 	.change_ok = env_flags_validate,
+#endif
 };
 
 /*
@@ -225,7 +228,9 @@
 #if defined(CONFIG_NEEDS_MANUAL_RELOC)
 	env_reloc();
 	env_fix_drivers();
-	env_htab.change_ok += gd->reloc_off;
+
+	if (env_htab.change_ok)
+		env_htab.change_ok += gd->reloc_off;
 #endif
 	if (gd->env_valid == ENV_INVALID) {
 #if defined(CONFIG_ENV_IS_NOWHERE) || defined(CONFIG_SPL_BUILD)
diff --git a/include/configs/M52277EVB.h b/include/configs/M52277EVB.h
index 514733e..a9c260d 100644
--- a/include/configs/M52277EVB.h
+++ b/include/configs/M52277EVB.h
@@ -103,17 +103,6 @@
 /* DSPI and Serial Flash */
 #define CONFIG_CF_DSPI
 #define CONFIG_SYS_SBFHDR_SIZE		0x7
-#ifdef CONFIG_CMD_SPI
-#	define CONFIG_SYS_DSPI_CS2
-
-#	define CONFIG_SYS_DSPI_CTAR0	(DSPI_CTAR_TRSZ(7) | \
-					 DSPI_CTAR_PCSSCK_1CLK | \
-					 DSPI_CTAR_PASC(0) | \
-					 DSPI_CTAR_PDT(0) | \
-					 DSPI_CTAR_CSSCK(0) | \
-					 DSPI_CTAR_ASC(0) | \
-					 DSPI_CTAR_DT(1))
-#endif
 
 /* Input, PCI, Flexbus, and VCO */
 #define CONFIG_EXTRA_CLOCK
diff --git a/include/configs/M54418TWR.h b/include/configs/M54418TWR.h
index f7b0669..e07684d 100644
--- a/include/configs/M54418TWR.h
+++ b/include/configs/M54418TWR.h
@@ -152,18 +152,6 @@
 #define CONFIG_CF_DSPI
 #define CONFIG_SERIAL_FLASH
 #define CONFIG_SYS_SBFHDR_SIZE		0x7
-#ifdef CONFIG_CMD_SPI
-
-#	define CONFIG_SYS_DSPI_CTAR0	(DSPI_CTAR_TRSZ(7) | \
-					 DSPI_CTAR_PCSSCK_1CLK | \
-					 DSPI_CTAR_PASC(0) | \
-					 DSPI_CTAR_PDT(0) | \
-					 DSPI_CTAR_CSSCK(0) | \
-					 DSPI_CTAR_ASC(0) | \
-					 DSPI_CTAR_DT(1))
-#	define CONFIG_SYS_DSPI_CTAR1	(CONFIG_SYS_DSPI_CTAR0)
-#	define CONFIG_SYS_DSPI_CTAR2	(CONFIG_SYS_DSPI_CTAR0)
-#endif
 
 /* Input, PCI, Flexbus, and VCO */
 #define CONFIG_EXTRA_CLOCK
diff --git a/include/configs/M54451EVB.h b/include/configs/M54451EVB.h
index 57c8572..2bd0e62 100644
--- a/include/configs/M54451EVB.h
+++ b/include/configs/M54451EVB.h
@@ -117,18 +117,6 @@
 #define CONFIG_CF_DSPI
 #define CONFIG_SERIAL_FLASH
 #define CONFIG_SYS_SBFHDR_SIZE		0x7
-#ifdef CONFIG_CMD_SPI
-
-#	define CONFIG_SYS_DSPI_CTAR0	(DSPI_CTAR_TRSZ(7) | \
-					 DSPI_CTAR_PCSSCK_1CLK | \
-					 DSPI_CTAR_PASC(0) | \
-					 DSPI_CTAR_PDT(0) | \
-					 DSPI_CTAR_CSSCK(0) | \
-					 DSPI_CTAR_ASC(0) | \
-					 DSPI_CTAR_DT(1))
-#	define CONFIG_SYS_DSPI_CTAR1	(CONFIG_SYS_DSPI_CTAR0)
-#	define CONFIG_SYS_DSPI_CTAR2	(CONFIG_SYS_DSPI_CTAR0)
-#endif
 
 /* Input, PCI, Flexbus, and VCO */
 #define CONFIG_EXTRA_CLOCK
diff --git a/include/configs/M54455EVB.h b/include/configs/M54455EVB.h
index 448dfc9..d73101f 100644
--- a/include/configs/M54455EVB.h
+++ b/include/configs/M54455EVB.h
@@ -143,16 +143,6 @@
 /* DSPI and Serial Flash */
 #define CONFIG_CF_DSPI
 #define CONFIG_SYS_SBFHDR_SIZE		0x13
-#ifdef CONFIG_CMD_SPI
-
-#	define CONFIG_SYS_DSPI_CTAR0		(DSPI_CTAR_TRSZ(7) | \
-					 DSPI_CTAR_PCSSCK_1CLK | \
-					 DSPI_CTAR_PASC(0) | \
-					 DSPI_CTAR_PDT(0) | \
-					 DSPI_CTAR_CSSCK(0) | \
-					 DSPI_CTAR_ASC(0) | \
-					 DSPI_CTAR_DT(1))
-#endif
 
 /* PCI */
 #ifdef CONFIG_CMD_PCI
diff --git a/include/configs/stm32mp1.h b/include/configs/stm32mp1.h
index fd6c97a..e8be51a 100644
--- a/include/configs/stm32mp1.h
+++ b/include/configs/stm32mp1.h
@@ -23,11 +23,6 @@
 #endif
 
 /*
- * malloc() pool size
- */
-#define CONFIG_SYS_MALLOC_LEN			SZ_32M
-
-/*
  * Configuration of the external SRAM memory used by U-Boot
  */
 #define CONFIG_SYS_SDRAM_BASE			STM32_DDR_BASE
@@ -43,11 +38,6 @@
  */
 #define CONFIG_SYS_LOAD_ADDR			STM32_DDR_BASE
 
-/*
- * Env parameters
- */
-#define CONFIG_ENV_SIZE				SZ_4K
-
 /* ATAGs */
 #define CONFIG_CMDLINE_TAG
 #define CONFIG_SETUP_MEMORY_TAGS
@@ -95,8 +85,6 @@
  * for nand boot, boot with on ubifs partition on nand
  * for nor boot, use the default order
  */
-#define CONFIG_PREBOOT
-
 #define STM32MP_BOOTCMD "bootcmd_stm32mp=" \
 	"echo \"Boot over ${boot_device}${boot_instance}!\";" \
 	"if test ${boot_device} = serial || test ${boot_device} = usb;" \
diff --git a/include/configs/stmark2.h b/include/configs/stmark2.h
index 17f92d8..3596658 100644
--- a/include/configs/stmark2.h
+++ b/include/configs/stmark2.h
@@ -68,17 +68,6 @@
 
 #define CONFIG_SYS_SBFHDR_SIZE		0x7
 
-#define CONFIG_SYS_DSPI_CTAR0		(DSPI_CTAR_TRSZ(7) | \
-					DSPI_CTAR_PCSSCK_1CLK | \
-					DSPI_CTAR_PASC(0) | \
-					DSPI_CTAR_PDT(0) | \
-					DSPI_CTAR_CSSCK(0) | \
-					DSPI_CTAR_ASC(0) | \
-					DSPI_CTAR_DT(1) | \
-					DSPI_CTAR_BR(6))
-#define CONFIG_SYS_DSPI_CTAR1		(CONFIG_SYS_DSPI_CTAR0)
-#define CONFIG_SYS_DSPI_CTAR2		(CONFIG_SYS_DSPI_CTAR0)
-
 /* Input, PCI, Flexbus, and VCO */
 #define CONFIG_EXTRA_CLOCK
 
diff --git a/include/dm/platform_data/spi_coldfire.h b/include/dm/platform_data/spi_coldfire.h
new file mode 100644
index 0000000..8ad8eae
--- /dev/null
+++ b/include/dm/platform_data/spi_coldfire.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2018  Angelo Dureghello <angelo@sysam.it>
+ */
+
+#ifndef __spi_coldfire_h
+#define __spi_coldfire_h
+
+#define MAX_CTAR_REGS		8
+#define MAX_CTAR_FIELDS		8
+
+/*
+ * struct coldfire_spi_platdata - information about a coldfire spi module
+ *
+ * @regs_addr: base address for module registers
+ * @speed_hz: default SCK frequency
+ * @mode: default SPI mode
+ * @num_cs: number of DSPI chipselect signals
+ */
+struct coldfire_spi_platdata {
+	fdt_addr_t regs_addr;
+	uint speed_hz;
+	uint mode;
+	uint num_cs;
+	uint ctar[MAX_CTAR_REGS][MAX_CTAR_FIELDS];
+};
+
+#endif /* __spi_coldfire_h */
+
diff --git a/tools/stm32image.c b/tools/stm32image.c
index 08b32ba..ff3ec5f 100644
--- a/tools/stm32image.c
+++ b/tools/stm32image.c
@@ -14,6 +14,8 @@
 #define HEADER_VERSION_V1	0x1
 /* default option : bit0 => no signature */
 #define HEADER_DEFAULT_OPTION	(cpu_to_le32(0x00000001))
+/* default binary type for U-Boot */
+#define HEADER_TYPE_UBOOT	(cpu_to_le32(0x00000000))
 
 struct stm32_header {
 	uint32_t magic_number;
@@ -29,7 +31,8 @@
 	uint32_t option_flags;
 	uint32_t ecdsa_algorithm;
 	uint32_t ecdsa_public_key[64 / 4];
-	uint32_t padding[84 / 4];
+	uint32_t padding[83 / 4];
+	uint32_t binary_type;
 };
 
 static struct stm32_header stm32image_header;
@@ -43,6 +46,7 @@
 	ptr->header_version[VER_MAJOR_IDX] = HEADER_VERSION_V1;
 	ptr->option_flags = HEADER_DEFAULT_OPTION;
 	ptr->ecdsa_algorithm = 1;
+	ptr->binary_type = HEADER_TYPE_UBOOT;
 }
 
 static uint32_t stm32image_checksum(void *start, uint32_t len)
@@ -112,6 +116,8 @@
 	       le32_to_cpu(stm32hdr->image_checksum));
 	printf("Option     : 0x%08x\n",
 	       le32_to_cpu(stm32hdr->option_flags));
+	printf("BinaryType : 0x%08x\n",
+	       le32_to_cpu(stm32hdr->binary_type));
 }
 
 static void stm32image_set_header(void *ptr, struct stat *sbuf, int ifd,