From 88ee5ba68c14d16ff8c8dcd96e94539c6b0312d5 Mon Sep 17 00:00:00 2001
From: Peter Vicman <peter.vicman@gmail.com>
Date: Fri, 7 Aug 2015 21:33:31 +0200
Subject: [PATCH] udoo board support

---
 arch/arm/cpu/armv7/cpu.c               |  14 +
 arch/arm/imx-common/Makefile           |   2 +
 arch/arm/imx-common/cmd_plotmsg.c      |  74 ++++
 arch/arm/imx-common/sata.c             |  33 ++
 arch/arm/include/asm/imx-common/sata.h |  17 +
 board/udoo/1066mhz_4x256mx16_dl.cfg    |  58 ++++
 board/udoo/1066mhz_4x256mx16_q.cfg     |  63 ++++
 board/udoo/Makefile                    |  30 ++
 board/udoo/clocks.cfg                  |  31 ++
 board/udoo/ddr-setup_dl.cfg            |  85 +++++
 board/udoo/ddr-setup_q.cfg             |  87 +++++
 board/udoo/udoo.c                      | 607 +++++++++++++++++++++++++++++++++
 board/udoo/udoo.cfg                    |  41 +++
 board/udoo/udoo_spl.c                  | 404 ++++++++++++++++++++++
 boards.cfg                             |   3 +
 common/Makefile                        |   1 +
 common/cmd_multiboot.c                 | 312 +++++++++++++++++
 drivers/video/cfb_console.c            |  12 +
 include/configs/udoo.h                 | 302 ++++++++++++++++
 include/micrel.h                       |   5 +
 include/video.h                        |   2 +
 21 files changed, 2183 insertions(+)
 create mode 100644 arch/arm/imx-common/cmd_plotmsg.c
 create mode 100644 arch/arm/imx-common/sata.c
 create mode 100644 arch/arm/include/asm/imx-common/sata.h
 create mode 100644 board/udoo/1066mhz_4x256mx16_dl.cfg
 create mode 100644 board/udoo/1066mhz_4x256mx16_q.cfg
 create mode 100644 board/udoo/Makefile
 create mode 100644 board/udoo/clocks.cfg
 create mode 100644 board/udoo/ddr-setup_dl.cfg
 create mode 100644 board/udoo/ddr-setup_q.cfg
 create mode 100644 board/udoo/udoo.c
 create mode 100644 board/udoo/udoo.cfg
 create mode 100644 board/udoo/udoo_spl.c
 create mode 100644 common/cmd_multiboot.c
 create mode 100644 include/configs/udoo.h

diff --git a/arch/arm/cpu/armv7/cpu.c b/arch/arm/cpu/armv7/cpu.c
index 01cdb7e..654e526 100644
--- a/arch/arm/cpu/armv7/cpu.c
+++ b/arch/arm/cpu/armv7/cpu.c
@@ -20,10 +20,20 @@
 #include <asm/system.h>
 #include <asm/cache.h>
 #include <asm/armv7.h>
+#include <asm/gpio.h>
 #include <linux/compiler.h>
 
 void __weak cpu_cache_initialization(void){}
 
+#if (defined(MACH_TYPE_UDOO) || defined(CONFIG_VIDEO_ENABLED))
+static void do_disable_lvds()
+{
+        gpio_direction_output(IMX_GPIO_NR(1, 2), 0); /* LVDS power On */
+        gpio_direction_output(IMX_GPIO_NR(1, 4), 0); /* LVDS backlight On */
+        return;
+}
+#endif
+
 int cleanup_before_linux(void)
 {
 	/*
@@ -66,5 +76,9 @@ int cleanup_before_linux(void)
 	 */
 	cpu_cache_initialization();
 
+#if (defined(MACH_TYPE_UDOO) || defined(CONFIG_VIDEO_ENABLED))
+	do_disable_lvds();
+#endif
+
 	return 0;
 }
diff --git a/arch/arm/imx-common/Makefile b/arch/arm/imx-common/Makefile
index 727a052..f619bbc 100644
--- a/arch/arm/imx-common/Makefile
+++ b/arch/arm/imx-common/Makefile
@@ -17,12 +17,14 @@ endif
 ifeq ($(SOC),$(filter $(SOC),mx5 mx6))
 COBJS-y	+= timer.o cpu.o speed.o
 COBJS-$(CONFIG_I2C_MXC) += i2c-mxv7.o
+COBJS-$(CONFIG_CMD_SATA) += sata.o
 endif
 ifeq ($(SOC),$(filter $(SOC),mx6 mxs))
 COBJS-y	+= misc.o
 endif
 COBJS-$(CONFIG_CMD_BMODE) += cmd_bmode.o
 COBJS-$(CONFIG_CMD_HDMIDETECT) += cmd_hdmidet.o
+COBJS-$(CONFIG_CMD_PLOTMSG) += cmd_plotmsg.o
 COBJS	:= $(sort $(COBJS-y))
 
 SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
diff --git a/arch/arm/imx-common/cmd_plotmsg.c b/arch/arm/imx-common/cmd_plotmsg.c
new file mode 100644
index 0000000..55890d4
--- /dev/null
+++ b/arch/arm/imx-common/cmd_plotmsg.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2013 Seco USA Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <bmp_logo.h>
+#include <video.h>
+
+#define MAX_LEN		160
+#define X_MARGIN	10
+#define Y_PADDING	20
+
+static int do_plotmsg(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	int i = 1;
+	static int y = 30;
+	int x;
+	char msg[MAX_LEN];
+
+	if (argc == 1)
+		return CMD_RET_USAGE;
+
+	if (y < BMP_LOGO_HEIGHT)
+		x = BMP_LOGO_WIDTH + X_MARGIN;
+	else
+		x = X_MARGIN;
+
+	msg[0] = 0;
+
+	if ((strcmp(argv[1], "-r") == 0) && (y > 30)) {
+		int f;
+		i++;
+		y -= Y_PADDING;
+		for (f=0; f < MAX_LEN/10; f++)
+			strcat(msg, "          ");
+		udoo_video_drawstring(x, y, msg);
+		strcpy(msg, argv[i]);
+		i++;
+	}
+
+	if (strcmp(argv[1], "-u") == 0) {
+		i++;
+		x = X_MARGIN;
+		y = ((BMP_LOGO_HEIGHT / Y_PADDING) * Y_PADDING) + Y_PADDING;
+		strcpy(msg, argv[i]);
+		i++;
+	}
+		
+	while(i < argc) {
+		if ((strlen(msg) + strlen(argv[i])) < MAX_LEN) {
+			if  (i == 1) {
+				strcpy(msg, argv[i]);
+			} else {
+				strcat(msg, " ");
+				strcat(msg, argv[i]);
+			}
+		} else
+			printf("Warn: Max text length reached (max %d characters permetted).\n", MAX_LEN);
+		i++;
+	}
+
+	udoo_video_drawstring(x, y, msg);
+	y += Y_PADDING;
+	return 0;
+}
+
+U_BOOT_CMD(plotmsg, 50, 1, do_plotmsg,
+	"Plot text message on current display (HDMI or LVDS).\n" \
+	  "\t -r Overwrite last message.\n" \
+	  "\t -u Start writing just under Logo.",
+	"[-r|-u] message ..."
+);
diff --git a/arch/arm/imx-common/sata.c b/arch/arm/imx-common/sata.c
new file mode 100644
index 0000000..00b3d92
--- /dev/null
+++ b/arch/arm/imx-common/sata.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <asm/imx-common/iomux-v3.h> 
+#include <asm/arch/iomux.h> 
+#include <asm/io.h> 
+
+int sata_setup(void)
+{
+	struct iomuxc_base_regs *const iomuxc_regs
+		= (struct iomuxc_base_regs *) IOMUXC_BASE_ADDR;
+
+	int ret = enable_sata_clock();
+	if (ret)
+		return ret;
+
+	clrsetbits_le32(&iomuxc_regs->gpr[13],
+			IOMUXC_GPR13_SATA_MASK,
+			IOMUXC_GPR13_SATA_PHY_8_RXEQ_3P0DB
+			|IOMUXC_GPR13_SATA_PHY_7_SATA2M
+			|IOMUXC_GPR13_SATA_SPEED_3G
+			|(3<<IOMUXC_GPR13_SATA_PHY_6_SHIFT)
+			|IOMUXC_GPR13_SATA_SATA_PHY_5_SS_DISABLED
+			|IOMUXC_GPR13_SATA_SATA_PHY_4_ATTEN_9_16
+			|IOMUXC_GPR13_SATA_PHY_3_TXBOOST_0P00_DB
+			|IOMUXC_GPR13_SATA_PHY_2_TX_1P104V
+			|IOMUXC_GPR13_SATA_PHY_1_SLOW);
+
+	return 0;
+}
diff --git a/arch/arm/include/asm/imx-common/sata.h b/arch/arm/include/asm/imx-common/sata.h
new file mode 100644
index 0000000..40fbf77
--- /dev/null
+++ b/arch/arm/include/asm/imx-common/sata.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __IMX_SATA_H_
+#define __IMX_SATA_H_
+
+/*
+ * SATA setup for i.mx6 quad based platform
+ */
+
+int sata_setup(void);
+
+#endif
+
diff --git a/board/udoo/1066mhz_4x256mx16_dl.cfg b/board/udoo/1066mhz_4x256mx16_dl.cfg
new file mode 100644
index 0000000..e37c9f9
--- /dev/null
+++ b/board/udoo/1066mhz_4x256mx16_dl.cfg
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2013 Seco USA Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+
+DATA 4, MX6_MMDC_P0_MDPDC,	0x0002002D
+DATA 4, MX6_MMDC_P0_MDOTC,	0x00333040
+
+DATA 4, MX6_MMDC_P0_MDCFG0,	0x3F4352F3
+DATA 4, MX6_MMDC_P0_MDCFG1,	0xB66D8B63
+DATA 4, MX6_MMDC_P0_MDCFG2,	0x01FF00DB
+
+DATA 4, MX6_MMDC_P0_MDMISC,	0x00001740
+DATA 4, MX6_MMDC_P0_MDSCR,	0x00008000
+DATA 4, MX6_MMDC_P0_MDRWD,	0x000026D2
+
+
+DATA 4, MX6_MMDC_P0_MDOR,	0x00431023
+DATA 4, MX6_MMDC_P0_MDASP,	0x00000027
+DATA 4, MX6_MMDC_P0_MDCTL,	0x831A0000
+
+DATA 4, MX6_MMDC_P0_MDSCR,	0x02008032
+DATA 4, MX6_MMDC_P0_MDSCR,	0x00008033
+DATA 4, MX6_MMDC_P0_MDSCR,	0x00048031
+DATA 4, MX6_MMDC_P0_MDSCR,	0x05208030
+DATA 4, MX6_MMDC_P0_MDSCR,	0x04008040
+
+DATA 4, MX6_MMDC_P0_MPZQHWCTRL,	0xa1390003
+DATA 4, MX6_MMDC_P1_MPZQHWCTRL,	0xa1390003
+
+DATA 4, MX6_MMDC_P0_MDREF,	0x00007800
+
+DATA 4, MX6_MMDC_P0_MPODTCTRL,	0x00022227
+DATA 4, MX6_MMDC_P1_MPODTCTRL,	0x00022227
+
+DATA 4, MX6_MMDC_P0_MPDGCTRL0,	0x425C0251
+DATA 4, MX6_MMDC_P0_MPDGCTRL1,	0x021B021E
+DATA 4, MX6_MMDC_P1_MPDGCTRL0,	0x021B021E
+DATA 4, MX6_MMDC_P1_MPDGCTRL1,	0x01730200
+
+DATA 4, MX6_MMDC_P0_MPRDDLCTL,	0x45474C45
+DATA 4, MX6_MMDC_P1_MPRDDLCTL,	0x44464744
+DATA 4, MX6_MMDC_P0_MPWRDLCTL,	0x3F3F3336
+DATA 4, MX6_MMDC_P1_MPWRDLCTL,	0x32383630
+
+DATA 4, MX6_MMDC_P0_MPWLDECTRL0,	0x002F0038
+DATA 4, MX6_MMDC_P0_MPWLDECTRL1,	0x001F001F
+DATA 4, MX6_MMDC_P1_MPWLDECTRL0,	0x001F001F
+DATA 4, MX6_MMDC_P1_MPWLDECTRL1,	0x001F001F
+
+DATA 4, MX6_MMDC_P0_MPMUR0,	0x00000000
+DATA 4, MX6_MMDC_P1_MPMUR0,	0x00000000
+
+DATA 4, MX6_MMDC_P0_MDPDC,	0x0002556D
+DATA 4, MX6_MMDC_P0_MAPSR,	0x00011006
+DATA 4, MX6_MMDC_P0_MDSCR,	0x00000000
diff --git a/board/udoo/1066mhz_4x256mx16_q.cfg b/board/udoo/1066mhz_4x256mx16_q.cfg
new file mode 100644
index 0000000..1da61a4
--- /dev/null
+++ b/board/udoo/1066mhz_4x256mx16_q.cfg
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2013 Seco USA Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+
+DATA 4, MX6_MMDC_P0_MDPDC,	0x00020036
+DATA 4, MX6_MMDC_P0_MDOTC,	0x09444040
+
+DATA 4, MX6_MMDC_P0_MDCFG0,	0x54597955
+DATA 4, MX6_MMDC_P0_MDCFG1,	0xFF328F64
+DATA 4, MX6_MMDC_P0_MDCFG2,	0x01FF00DB
+
+DATA 4, MX6_MMDC_P0_MDMISC,	0x00001740
+DATA 4, MX6_MMDC_P0_MDSCR,	0x00008000
+DATA 4, MX6_MMDC_P0_MDRWD,	0x000026D2
+
+#ifdef ONEGIGA
+DATA 4, MX6_MMDC_P0_MDOR,	0x00591023
+DATA 4, MX6_MMDC_P0_MDASP,	0x00000027
+DATA 4, MX6_MMDC_P0_MDCTL,	0x831A0000
+#else
+DATA 4, MX6_MMDC_P0_MDOR,	0x008E1023
+DATA 4, MX6_MMDC_P0_MDASP,	0x00000047
+DATA 4, MX6_MMDC_P0_MDCTL,	0x841A0000
+#endif
+
+DATA 4, MX6_MMDC_P0_MDSCR,	0x04088032
+DATA 4, MX6_MMDC_P0_MDSCR,	0x00008033
+DATA 4, MX6_MMDC_P0_MDSCR,	0x00048031
+DATA 4, MX6_MMDC_P0_MDSCR,	0x09408030
+DATA 4, MX6_MMDC_P0_MDSCR,	0x04008040
+
+DATA 4, MX6_MMDC_P0_MPZQHWCTRL,	0xA1380003
+DATA 4, MX6_MMDC_P1_MPZQHWCTRL,	0xA1380003
+
+DATA 4, MX6_MMDC_P0_MDREF,	0x00005800
+
+DATA 4, MX6_MMDC_P0_MPODTCTRL,	0x00011117
+DATA 4, MX6_MMDC_P1_MPODTCTRL,	0x00011117
+
+DATA 4, MX6_MMDC_P0_MPDGCTRL0,	0x43510360
+DATA 4, MX6_MMDC_P0_MPDGCTRL1,	0x0342033F
+DATA 4, MX6_MMDC_P1_MPDGCTRL0,	0x033F033F
+DATA 4, MX6_MMDC_P1_MPDGCTRL1,	0x03290266
+
+DATA 4, MX6_MMDC_P0_MPRDDLCTL,	0x4B3E4141
+DATA 4, MX6_MMDC_P1_MPRDDLCTL,	0x47413B4A
+DATA 4, MX6_MMDC_P0_MPWRDLCTL,	0x42404843
+DATA 4, MX6_MMDC_P1_MPWRDLCTL,	0x4C3F4C45
+
+DATA 4, MX6_MMDC_P0_MPWLDECTRL0,	0x00350035
+DATA 4, MX6_MMDC_P0_MPWLDECTRL1,	0x001F001F
+DATA 4, MX6_MMDC_P1_MPWLDECTRL0,	0x00010001
+DATA 4, MX6_MMDC_P1_MPWLDECTRL1,	0x00010001
+
+DATA 4, MX6_MMDC_P0_MPMUR0,	0x00000800
+DATA 4, MX6_MMDC_P1_MPMUR0,	0x00000800
+
+DATA 4, MX6_MMDC_P0_MDPDC,	0x00025576
+DATA 4, MX6_MMDC_P0_MAPSR,	0x00011006
+DATA 4, MX6_MMDC_P0_MDSCR,	0x00000000
diff --git a/board/udoo/Makefile b/board/udoo/Makefile
new file mode 100644
index 0000000..e00a898
--- /dev/null
+++ b/board/udoo/Makefile
@@ -0,0 +1,30 @@
+#
+# (C) Copyright 2013 Freescale Semiconductor, Inc.
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+include $(TOPDIR)/config.mk
+
+LIB    = $(obj)lib$(BOARD).o
+
+COBJS  := udoo.o
+
+ifdef CONFIG_SPL_BUILD
+COBJS  += udoo_spl.o
+endif
+
+SRCS   := $(COBJS:.o=.c)
+OBJS   := $(addprefix $(obj),$(COBJS))
+
+$(LIB):        $(obj).depend $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/udoo/clocks.cfg b/board/udoo/clocks.cfg
new file mode 100644
index 0000000..2acf001
--- /dev/null
+++ b/board/udoo/clocks.cfg
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2013 Seco USA Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ * Device Configuration Data (DCD)
+ *
+ * Each entry must have the format:
+ * Addr-type           Address        Value
+ *
+ * where:
+ *      Addr-type register length (1,2 or 4 bytes)
+ *      Address   absolute address of the register
+ *      value     value to be stored in the register
+ */
+
+/* set the default clock gate to save power */
+DATA 4, CCM_CCGR0, 0x00C03F3F
+DATA 4, CCM_CCGR1, 0x0030FC03
+DATA 4, CCM_CCGR2, 0x0FFFC000
+DATA 4, CCM_CCGR3, 0x3FF00000
+DATA 4, CCM_CCGR4, 0x00FFF300
+DATA 4, CCM_CCGR5, 0x0F0000C3
+DATA 4, CCM_CCGR6, 0x000003FF
+
+/* enable AXI cache for VDOA/VPU/IPU */
+DATA 4, MX6_IOMUXC_GPR4, 0xF00000CF
+/* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */
+DATA 4, MX6_IOMUXC_GPR6, 0x007F007F
+DATA 4, MX6_IOMUXC_GPR7, 0x007F007F
+
diff --git a/board/udoo/ddr-setup_dl.cfg b/board/udoo/ddr-setup_dl.cfg
new file mode 100644
index 0000000..fa82c4d
--- /dev/null
+++ b/board/udoo/ddr-setup_dl.cfg
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2013 Seco USA Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ * Device Configuration Data (DCD)
+ *
+ * Each entry must have the format:
+ * Addr-type           Address        Value
+ *
+ * where:
+ *      Addr-type register length (1,2 or 4 bytes)
+ *      Address   absolute address of the register
+ *      value     value to be stored in the register
+ */
+
+/*
+ * DDR3 settings
+ * MX6Q    ddr is limited to 1066 Mhz	currently 1056 MHz(528 MHz clock),
+ *	   memory bus width: 64 bits	x16/x32/x64
+ * MX6DL   ddr is limited to 800 MHz(400 MHz clock)
+ *	   memory bus width: 64 bits	x16/x32/x64
+ * MX6SOLO ddr is limited to 800 MHz(400 MHz clock)
+ *	   memory bus width: 32 bits	x16/x32
+ */
+DATA 4, MX6_IOM_DRAM_SDQS0,	0x00000028
+DATA 4, MX6_IOM_DRAM_SDQS1,	0x00000028
+DATA 4, MX6_IOM_DRAM_SDQS2,	0x00000028
+DATA 4, MX6_IOM_DRAM_SDQS3,	0x00000028
+DATA 4, MX6_IOM_DRAM_SDQS4,	0x00000028
+DATA 4, MX6_IOM_DRAM_SDQS5,	0x00000028
+DATA 4, MX6_IOM_DRAM_SDQS6,	0x00000028
+DATA 4, MX6_IOM_DRAM_SDQS7,	0x00000028
+
+DATA 4, MX6_IOM_GRP_B0DS,	0x00000028
+DATA 4, MX6_IOM_GRP_B1DS,	0x00000028
+DATA 4, MX6_IOM_GRP_B2DS,	0x00000028
+DATA 4, MX6_IOM_GRP_B3DS,	0x00000028
+DATA 4, MX6_IOM_GRP_B4DS,	0x00000028
+DATA 4, MX6_IOM_GRP_B5DS,	0x00000028
+DATA 4, MX6_IOM_GRP_B6DS,	0x00000028
+DATA 4, MX6_IOM_GRP_B7DS,	0x00000028
+DATA 4, MX6_IOM_GRP_ADDDS,	0x00000028
+
+DATA 4, MX6_IOM_GRP_CTLDS,	0x00000028
+
+DATA 4, MX6_IOM_DRAM_DQM0,	0x00000028
+DATA 4, MX6_IOM_DRAM_DQM1,	0x00000028
+DATA 4, MX6_IOM_DRAM_DQM2,	0x00000028
+DATA 4, MX6_IOM_DRAM_DQM3,	0x00000028
+DATA 4, MX6_IOM_DRAM_DQM4,	0x00000028
+DATA 4, MX6_IOM_DRAM_DQM5,	0x00000028
+DATA 4, MX6_IOM_DRAM_DQM6,	0x00000028
+DATA 4, MX6_IOM_DRAM_DQM7,	0x00000028
+
+DATA 4, MX6_IOM_DRAM_CAS,	0x00000028
+DATA 4, MX6_IOM_DRAM_RAS,	0x00000028
+DATA 4, MX6_IOM_DRAM_SDCLK_0,	0x00000028
+DATA 4, MX6_IOM_DRAM_SDCLK_1,	0x00000028
+
+DATA 4, MX6_IOM_DRAM_RESET,	0x00000028
+
+DATA 4, MX6_IOM_DRAM_SDODT0,	0x00000028
+DATA 4, MX6_IOM_DRAM_SDODT1,	0x00000028
+
+/* (differential input) */
+DATA 4, MX6_IOM_DDRMODE_CTL,	0x00020000
+/* (differential input) */
+DATA 4, MX6_IOM_GRP_DDRMODE,	0x00020000
+/* disable ddr pullups */
+DATA 4, MX6_IOM_GRP_DDRPKE,	0x00000000
+DATA 4, MX6_IOM_DRAM_SDBA2,	0x00000000
+/* 40 Ohm drive strength for cs0/1,sdba2,cke0/1,sdwe */
+DATA 4, MX6_IOM_GRP_DDR_TYPE,	0x000C0000
+
+/* Read data DQ Byte0-3 delay */
+DATA 4, MX6_MMDC_P0_MPRDDQBY0DL,	0x33333333
+DATA 4, MX6_MMDC_P0_MPRDDQBY1DL,	0x33333333
+DATA 4, MX6_MMDC_P0_MPRDDQBY2DL,	0x33333333
+DATA 4, MX6_MMDC_P0_MPRDDQBY3DL,	0x33333333
+DATA 4, MX6_MMDC_P1_MPRDDQBY0DL,	0x33333333
+DATA 4, MX6_MMDC_P1_MPRDDQBY1DL,	0x33333333
+DATA 4, MX6_MMDC_P1_MPRDDQBY2DL,	0x33333333
+DATA 4, MX6_MMDC_P1_MPRDDQBY3DL,	0x33333333
+
diff --git a/board/udoo/ddr-setup_q.cfg b/board/udoo/ddr-setup_q.cfg
new file mode 100644
index 0000000..12d5627
--- /dev/null
+++ b/board/udoo/ddr-setup_q.cfg
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2013 Seco USA Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ * Device Configuration Data (DCD)
+ *
+ * Each entry must have the format:
+ * Addr-type           Address        Value
+ *
+ * where:
+ *      Addr-type register length (1,2 or 4 bytes)
+ *      Address   absolute address of the register
+ *      value     value to be stored in the register
+ */
+
+/*
+ * DDR3 settings
+ * MX6Q    ddr is limited to 1066 Mhz	currently 1056 MHz(528 MHz clock),
+ *	   memory bus width: 64 bits	x16/x32/x64
+ * MX6DL   ddr is limited to 800 MHz(400 MHz clock)
+ *	   memory bus width: 64 bits	x16/x32/x64
+ * MX6SOLO ddr is limited to 800 MHz(400 MHz clock)
+ *	   memory bus width: 32 bits	x16/x32
+ */
+DATA 4, MX6_IOM_DRAM_SDQS0,	0x00000030
+DATA 4, MX6_IOM_DRAM_SDQS1,	0x00000030
+DATA 4, MX6_IOM_DRAM_SDQS2,	0x00000030
+DATA 4, MX6_IOM_DRAM_SDQS3,	0x00000030
+DATA 4, MX6_IOM_DRAM_SDQS4,	0x00000030
+DATA 4, MX6_IOM_DRAM_SDQS5,	0x00000030
+DATA 4, MX6_IOM_DRAM_SDQS6,	0x00000030
+DATA 4, MX6_IOM_DRAM_SDQS7,	0x00000030
+
+DATA 4, MX6_IOM_GRP_B0DS,	0x00000030
+DATA 4, MX6_IOM_GRP_B1DS,	0x00000030
+DATA 4, MX6_IOM_GRP_B2DS,	0x00000030
+DATA 4, MX6_IOM_GRP_B3DS,	0x00000030
+DATA 4, MX6_IOM_GRP_B4DS,	0x00000030
+DATA 4, MX6_IOM_GRP_B5DS,	0x00000030
+DATA 4, MX6_IOM_GRP_B6DS,	0x00000030
+DATA 4, MX6_IOM_GRP_B7DS,	0x00000030
+DATA 4, MX6_IOM_GRP_ADDDS,	0x00000030
+/* 40 Ohm drive strength for cs0/1,sdba2,cke0/1,sdwe */
+DATA 4, MX6_IOM_GRP_CTLDS,	0x00000030
+
+DATA 4, MX6_IOM_DRAM_DQM0,	0x00020030
+DATA 4, MX6_IOM_DRAM_DQM1,	0x00020030
+DATA 4, MX6_IOM_DRAM_DQM2,	0x00020030
+DATA 4, MX6_IOM_DRAM_DQM3,	0x00020030
+DATA 4, MX6_IOM_DRAM_DQM4,	0x00020030
+DATA 4, MX6_IOM_DRAM_DQM5,	0x00020030
+DATA 4, MX6_IOM_DRAM_DQM6,	0x00020030
+DATA 4, MX6_IOM_DRAM_DQM7,	0x00020030
+
+DATA 4, MX6_IOM_DRAM_CAS,	0x00020030
+DATA 4, MX6_IOM_DRAM_RAS,	0x00020030
+DATA 4, MX6_IOM_DRAM_SDCLK_0,	0x00020030
+DATA 4, MX6_IOM_DRAM_SDCLK_1,	0x00020030
+
+DATA 4, MX6_IOM_DRAM_RESET,	0x00020030
+DATA 4, MX6_IOM_DRAM_SDCKE0,	0x00003000
+DATA 4, MX6_IOM_DRAM_SDCKE1,	0x00003000
+
+DATA 4, MX6_IOM_DRAM_SDODT0,	0x00003030
+DATA 4, MX6_IOM_DRAM_SDODT1,	0x00003030
+
+/* (differential input) */
+DATA 4, MX6_IOM_DDRMODE_CTL,	0x00020000
+/* (differential input) */
+DATA 4, MX6_IOM_GRP_DDRMODE,	0x00020000
+/* disable ddr pullups */
+DATA 4, MX6_IOM_GRP_DDRPKE,	0x00000000
+DATA 4, MX6_IOM_DRAM_SDBA2,	0x00000000
+/* 40 Ohm drive strength for cs0/1,sdba2,cke0/1,sdwe */
+DATA 4, MX6_IOM_GRP_DDR_TYPE,	0x000C0000
+
+/* Read data DQ Byte0-3 delay */
+DATA 4, MX6_MMDC_P0_MPRDDQBY0DL,	0x33333333
+DATA 4, MX6_MMDC_P0_MPRDDQBY1DL,	0x33333333
+DATA 4, MX6_MMDC_P0_MPRDDQBY2DL,	0x33333333
+DATA 4, MX6_MMDC_P0_MPRDDQBY3DL,	0x33333333
+DATA 4, MX6_MMDC_P1_MPRDDQBY0DL,	0x33333333
+DATA 4, MX6_MMDC_P1_MPRDDQBY1DL,	0x33333333
+DATA 4, MX6_MMDC_P1_MPRDDQBY2DL,	0x33333333
+DATA 4, MX6_MMDC_P1_MPRDDQBY3DL,	0x33333333
+
diff --git a/board/udoo/udoo.c b/board/udoo/udoo.c
new file mode 100644
index 0000000..f5efa86
--- /dev/null
+++ b/board/udoo/udoo.c
@@ -0,0 +1,607 @@
+/*
+ * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Fabio Estevam <fabio.estevam@freescale.com>
+ *         Adapted for SPL support by Peter Vicman <peter.vicman@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/iomux.h>
+#include <malloc.h>
+#include <asm/arch/mx6-pins.h>
+#include <asm/errno.h>
+#include <asm/gpio.h>
+#include <asm/imx-common/iomux-v3.h>
+#include <asm/imx-common/sata.h>
+#include <mmc.h>
+#include <fsl_esdhc.h>
+#include <asm/arch/crm_regs.h>
+#include <asm/io.h>
+#include <asm/arch/sys_proto.h>
+#include <micrel.h>
+#include <miiphy.h>
+#include <netdev.h>
+#include <linux/fb.h>
+#include <ipu_pixfmt.h>
+#include <asm/arch/crm_regs.h>
+#include <asm/arch/mxc_hdmi.h>
+#include <command.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* copied from u-boot-2015.07/arch/arm/include/asm/imx-common/iomux-v3.h */
+/* macros for declaring and using pinmux array */
+#if defined(CONFIG_MX6QDL)
+#define IOMUX_PADS(x) (MX6Q_##x), (MX6DL_##x)
+#define SETUP_IOMUX_PAD(def)					\
+if (is_cpu_type(MXC_CPU_MX6Q)) {				\
+	imx_iomux_v3_setup_multiple_pads(MX6Q_##def);			\
+} else {							\
+	imx_iomux_v3_setup_multiple_pads(MX6DL_##def);			\
+}
+#define SETUP_IOMUX_PADS(x)					\
+	spl_imx_iomux_v3_setup_multiple_pads(x, ARRAY_SIZE(x)/2)
+
+#elif defined(CONFIG_MX6Q) || defined(CONFIG_MX6D)
+#define IOMUX_PADS(x) MX6_##x
+#define SETUP_IOMUX_PAD(def)					\
+	imx_iomux_v3_setup_pad(MX6Q_##def);
+#define SETUP_IOMUX_PADS(x)					\
+	spl_imx_iomux_v3_setup_multiple_pads(x, ARRAY_SIZE(x))
+
+#else
+#define IOMUX_PADS(x) MX6_##x
+#define SETUP_IOMUX_PAD(def)					\
+	imx_iomux_v3_setup_pad(MX6DL_##def);
+#define SETUP_IOMUX_PADS(x)					\
+	spl_imx_iomux_v3_setup_multiple_pads(x, ARRAY_SIZE(x))
+#endif
+
+#define UART_PAD_CTRL  (PAD_CTL_PUS_100K_UP |			\
+	PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm |			\
+	PAD_CTL_SRE_FAST  | PAD_CTL_HYS)
+
+#define ENET_PAD_CTRL  (PAD_CTL_PUS_100K_UP |                   \
+	PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
+
+#define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP |			\
+	PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm |			\
+	PAD_CTL_SRE_FAST  | PAD_CTL_HYS)
+
+#define WDT_EN		IMX_GPIO_NR(5, 4)
+#define WDT_TRG		IMX_GPIO_NR(3, 19)
+
+/* copied from u-boot-2015.07/arch/arm/imx-common/iomux-v3.c */
+#define MXC_CPU_MX6D            0x64
+
+/* configures a list of pads within declared with IOMUX_PADS macro */
+static void spl_imx_iomux_v3_setup_multiple_pads(iomux_v3_cfg_t const *pad_list,
+				      unsigned count)
+{
+	iomux_v3_cfg_t const *p = pad_list;
+	int stride;
+	int i;
+
+#if defined(CONFIG_MX6QDL)
+	stride = 2;
+	if (!is_cpu_type(MXC_CPU_MX6Q) && !is_cpu_type(MXC_CPU_MX6D))
+		p += 1;
+#else
+	stride = 1;
+#endif
+	for (i = 0; i < count; i++) {
+		imx_iomux_v3_setup_pad(*p);
+		p += stride;
+	}
+}
+
+int dram_init(void)
+{
+	gd->ram_size = (phys_size_t)CONFIG_DDR_MB * 1024 * 1024;
+
+	return 0;
+}
+
+static iomux_v3_cfg_t const uart2_pads[] = {
+	IOMUX_PADS(PAD_EIM_D26__UART2_TXD | MUX_PAD_CTRL(UART_PAD_CTRL)),
+	IOMUX_PADS(PAD_EIM_D27__UART2_RXD | MUX_PAD_CTRL(UART_PAD_CTRL)),
+};
+
+static iomux_v3_cfg_t const usdhc3_pads[] = {
+	IOMUX_PADS(PAD_SD3_CLK__USDHC3_CLK   | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
+	IOMUX_PADS(PAD_SD3_CMD__USDHC3_CMD   | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
+	IOMUX_PADS(PAD_SD3_DAT0__USDHC3_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
+	IOMUX_PADS(PAD_SD3_DAT1__USDHC3_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
+	IOMUX_PADS(PAD_SD3_DAT2__USDHC3_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
+	IOMUX_PADS(PAD_SD3_DAT3__USDHC3_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
+};
+
+static iomux_v3_cfg_t const wdog_pads[] = {
+	IOMUX_PADS(PAD_EIM_A24__GPIO_5_4 | MUX_PAD_CTRL(NO_PAD_CTRL)),
+	IOMUX_PADS(PAD_EIM_D19__GPIO_3_19),
+};
+
+static iomux_v3_cfg_t const lvds_pads[] = {
+	IOMUX_PADS(PAD_GPIO_2__GPIO_1_2 | MUX_PAD_CTRL(NO_PAD_CTRL)),
+	IOMUX_PADS(PAD_GPIO_4__GPIO_1_4 | MUX_PAD_CTRL(NO_PAD_CTRL)),
+};
+
+int mx6_rgmii_rework(struct phy_device *phydev)
+{
+	/* 
+	 * Bug: Apparently uDoo does not works with Gigabit switches...
+	 * Limiting speed to 10/100Mbps, and setting master mode, seems to 
+	 * be the only way to have a successfull PHY auto negotiation.
+	 * How to fix: Understand why Linux kernel do not have this issue.
+	 */
+	phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, 0x1c00);
+
+        /* control data pad skew - devaddr = 0x02, register = 0x04 */
+        ksz9031_phy_extended_write(phydev, 0x02, 
+				   MII_KSZ9031_EXT_RGMII_CTRL_SIG_SKEW, 
+				   MII_KSZ9031_MOD_DATA_NO_POST_INC, 0x0000);
+        /* rx data pad skew - devaddr = 0x02, register = 0x05 */
+        ksz9031_phy_extended_write(phydev, 0x02, 
+				   MII_KSZ9031_EXT_RGMII_RX_DATA_SKEW, 
+				   MII_KSZ9031_MOD_DATA_NO_POST_INC, 0x0000);
+        /* tx data pad skew - devaddr = 0x02, register = 0x05 */
+        ksz9031_phy_extended_write(phydev, 0x02,
+				   MII_KSZ9031_EXT_RGMII_TX_DATA_SKEW,
+				   MII_KSZ9031_MOD_DATA_NO_POST_INC, 0x0000);
+        /* gtx and rx clock pad skew - devaddr = 0x02, register = 0x08 */
+
+        ksz9031_phy_extended_write(phydev, 0x02,
+				   MII_KSZ9031_EXT_RGMII_CLOCK_SKEW,
+				   MII_KSZ9031_MOD_DATA_NO_POST_INC, 0x03FF);
+	return 0;
+}
+
+static iomux_v3_cfg_t const enet_pads1[] = {
+	IOMUX_PADS(PAD_ENET_MDIO__ENET_MDIO		| MUX_PAD_CTRL(ENET_PAD_CTRL)),
+	IOMUX_PADS(PAD_ENET_MDC__ENET_MDC		| MUX_PAD_CTRL(ENET_PAD_CTRL)),
+	IOMUX_PADS(PAD_RGMII_TXC__ENET_RGMII_TXC	| MUX_PAD_CTRL(ENET_PAD_CTRL)),
+	IOMUX_PADS(PAD_RGMII_TD0__ENET_RGMII_TD0	| MUX_PAD_CTRL(ENET_PAD_CTRL)),
+	IOMUX_PADS(PAD_RGMII_TD1__ENET_RGMII_TD1	| MUX_PAD_CTRL(ENET_PAD_CTRL)),
+	IOMUX_PADS(PAD_RGMII_TD2__ENET_RGMII_TD2	| MUX_PAD_CTRL(ENET_PAD_CTRL)),
+	IOMUX_PADS(PAD_RGMII_TD3__ENET_RGMII_TD3	| MUX_PAD_CTRL(ENET_PAD_CTRL)),
+	IOMUX_PADS(PAD_RGMII_TX_CTL__RGMII_TX_CTL	| MUX_PAD_CTRL(ENET_PAD_CTRL)),
+	IOMUX_PADS(PAD_ENET_REF_CLK__ENET_TX_CLK	| MUX_PAD_CTRL(ENET_PAD_CTRL)),
+	IOMUX_PADS(PAD_RGMII_RXC__ENET_RGMII_RXC	| MUX_PAD_CTRL(ENET_PAD_CTRL)),
+	/* RGMII reset */
+	IOMUX_PADS(PAD_EIM_D23__GPIO_3_23		| MUX_PAD_CTRL(NO_PAD_CTRL)),
+	/* alimentazione ethernet*/
+	IOMUX_PADS(PAD_EIM_EB3__GPIO_2_31		| MUX_PAD_CTRL(NO_PAD_CTRL)),
+	/* pin 32 - 1 - (MODE0) all */
+	IOMUX_PADS(PAD_RGMII_RD0__GPIO_6_25		| MUX_PAD_CTRL(NO_PAD_CTRL)),
+	/* pin 31 - 1 - (MODE1) all */
+	IOMUX_PADS(PAD_RGMII_RD1__GPIO_6_27		| MUX_PAD_CTRL(NO_PAD_CTRL)),
+	/* pin 28 - 1 - (MODE2) all */
+	IOMUX_PADS(PAD_RGMII_RD2__GPIO_6_28		| MUX_PAD_CTRL(NO_PAD_CTRL)),
+	/* pin 27 - 1 - (MODE3) all */
+	IOMUX_PADS(PAD_RGMII_RD3__GPIO_6_29		| MUX_PAD_CTRL(NO_PAD_CTRL)),
+	/* pin 33 - 1 - (CLK125_EN) 125Mhz clockout enabled */
+	IOMUX_PADS(PAD_RGMII_RX_CTL__GPIO_6_24		| MUX_PAD_CTRL(NO_PAD_CTRL)),
+};
+
+static iomux_v3_cfg_t const enet_pads2[] = {
+	IOMUX_PADS(PAD_RGMII_RD0__ENET_RGMII_RD0	| MUX_PAD_CTRL(ENET_PAD_CTRL)),
+	IOMUX_PADS(PAD_RGMII_RD1__ENET_RGMII_RD1	| MUX_PAD_CTRL(ENET_PAD_CTRL)),
+	IOMUX_PADS(PAD_RGMII_RD2__ENET_RGMII_RD2	| MUX_PAD_CTRL(ENET_PAD_CTRL)),
+	IOMUX_PADS(PAD_RGMII_RD3__ENET_RGMII_RD3	| MUX_PAD_CTRL(ENET_PAD_CTRL)),
+	IOMUX_PADS(PAD_RGMII_RX_CTL__RGMII_RX_CTL	| MUX_PAD_CTRL(ENET_PAD_CTRL)),
+};
+
+static void setup_iomux_enet(void)
+{
+	SETUP_IOMUX_PADS(enet_pads1);
+	udelay(20);
+	gpio_direction_output(IMX_GPIO_NR(2, 31), 1); /* Power on enet */
+
+	gpio_direction_output(IMX_GPIO_NR(3, 23), 0); /* assert PHY rst */
+
+	gpio_direction_output(IMX_GPIO_NR(6, 24), 1);
+	gpio_direction_output(IMX_GPIO_NR(6, 25), 1);
+	gpio_direction_output(IMX_GPIO_NR(6, 27), 1);
+	gpio_direction_output(IMX_GPIO_NR(6, 28), 1);
+	gpio_direction_output(IMX_GPIO_NR(6, 29), 1);
+	udelay(1000);
+
+	gpio_set_value(IMX_GPIO_NR(3, 23), 1); /* deassert PHY rst */
+
+	/* Need delay 100ms to exit from reset. */
+	udelay(1000 * 100);
+
+	gpio_free(IMX_GPIO_NR(6, 24));
+	gpio_free(IMX_GPIO_NR(6, 25));
+	gpio_free(IMX_GPIO_NR(6, 27));
+	gpio_free(IMX_GPIO_NR(6, 28));
+	gpio_free(IMX_GPIO_NR(6, 29));
+
+	SETUP_IOMUX_PADS(enet_pads2);
+}
+
+static void setup_iomux_uart(void)
+{
+	SETUP_IOMUX_PADS(uart2_pads);
+}
+
+static void setup_iomux_wdog(void)
+{
+	SETUP_IOMUX_PADS(wdog_pads);
+	gpio_direction_output(WDT_TRG, 0);
+	gpio_direction_output(WDT_EN, 1);
+	gpio_direction_input(WDT_TRG);
+}
+
+static struct fsl_esdhc_cfg usdhc_cfg = { USDHC3_BASE_ADDR };
+
+int board_mmc_getcd(struct mmc *mmc)
+{
+	return 1; /* Always present */
+}
+
+int board_eth_init(bd_t *bis)
+{
+	uint32_t base = IMX_FEC_BASE;
+	struct mii_dev *bus = NULL;
+	struct phy_device *phydev = NULL;
+	int ret;
+
+	setup_iomux_enet();
+
+#ifdef CONFIG_FEC_MXC
+	bus = fec_get_miibus(base, -1);
+	if (!bus)
+		return 0;
+	/* scan phy 4,5,6,7 */
+	phydev = phy_find_by_mask(bus, (0xf << 4), PHY_INTERFACE_MODE_RGMII);
+
+	if (!phydev) {
+		free(bus);
+		return 0;
+	}
+	printf("using phy at %d\n", phydev->addr);
+	ret  = fec_probe(bis, -1, base, bus, phydev);
+	if (ret) {
+		printf("FEC MXC: %s:failed\n", __func__);
+		free(phydev);
+		free(bus);
+	}
+#endif
+	return 0;
+}
+
+int board_mmc_init(bd_t *bis)
+{
+	SETUP_IOMUX_PADS(usdhc3_pads);
+	usdhc_cfg.sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
+	usdhc_cfg.max_bus_width = 4;
+
+	return fsl_esdhc_initialize(bis, &usdhc_cfg);
+}
+
+#if defined(CONFIG_VIDEO_IPUV3)
+
+struct display_info_t {
+        int     bus;
+        int     addr;
+        int     pixfmt;
+        int     (*detect)(struct display_info_t const *dev);
+        void    (*enable)(struct display_info_t const *dev);
+        struct  fb_videomode mode;
+};
+
+static int detect_hdmi(struct display_info_t const *dev)
+{
+        struct hdmi_regs *hdmi  = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
+        return readb(&hdmi->phy_stat0) & HDMI_DVI_STAT;
+}
+
+static void do_enable_hdmi(struct display_info_t const *dev)
+{
+        imx_enable_hdmi_phy();
+}
+
+static int detect_lvds(struct display_info_t const *dev)
+{
+        return 0;
+}
+
+static void do_enable_lvds(struct display_info_t const *dev)
+{
+	SETUP_IOMUX_PADS(lvds_pads);
+	gpio_direction_output(IMX_GPIO_NR(1, 2), 1); /* LVDS power On */
+	gpio_direction_output(IMX_GPIO_NR(1, 4), 1); /* LVDS backlight On */
+        return;
+}
+
+static struct display_info_t const displays[] = {{
+        .bus    = -1,
+        .addr   = -1,
+        .pixfmt = IPU_PIX_FMT_RGB666,
+        .detect = detect_lvds,
+        .enable = do_enable_lvds,
+        .mode   = {
+		// Rif. 800x480 Panel UMSH-8596MD-20T
+		// To activate write "setenv panel LDB-WVGA" or leave empty.
+		.name           = "LDB-WVGA",
+		.refresh        = 60,
+		.xres           = 800,
+		.yres           = 480,
+		.pixclock       = 15385,
+		.left_margin    = 220,
+		.right_margin   = 40,
+		.upper_margin   = 21,
+		.lower_margin   = 7,
+		.hsync_len      = 60,
+		.vsync_len      = 10,
+		.sync           = 0,
+		.vmode          = FB_VMODE_NONINTERLACED
+} }, {
+        .bus    = -1,
+        .addr   = 0,
+        .pixfmt = IPU_PIX_FMT_RGB24,
+        .detect = detect_hdmi,
+        .enable = do_enable_hdmi,
+        .mode   = {
+		.name           = "HDMI",
+		.refresh        = 60,
+		.xres           = 1024,
+		.yres           = 768,
+		.pixclock       = 15385,
+		.left_margin    = 220,
+		.right_margin   = 40,
+		.upper_margin   = 21,
+		.lower_margin   = 7,
+		.hsync_len      = 60,
+		.vsync_len      = 10,
+		.sync           = FB_SYNC_EXT,
+		.vmode          = FB_VMODE_NONINTERLACED
+} }, {
+        .bus    = -1,
+        .addr   = -1,
+        .pixfmt = IPU_PIX_FMT_RGB666,
+        .detect = detect_lvds,
+        .enable = do_enable_lvds,
+        .mode   = {
+		// Rif. Panel 1024x768 - UMSH-8596MD-15T - G156XW01V0
+		// To activate write "setenv panel LDB-XGA".
+		.name           = "LDB-XGA",
+		.refresh        = 60,
+		.xres           = 1024,
+		.yres           = 768,
+		.pixclock       = 15385,
+		.left_margin    = 220,
+		.right_margin   = 40,
+		.upper_margin   = 21,
+		.lower_margin   = 7,
+		.hsync_len      = 60,
+		.vsync_len      = 10,
+		.sync           = 0,
+		.vmode          = FB_VMODE_NONINTERLACED
+} }, {
+        .bus    = -1,
+        .addr   = -1,
+        .pixfmt = IPU_PIX_FMT_RGB24,
+        .detect = detect_lvds,
+        .enable = do_enable_lvds,
+        .mode   = {
+		// Rif. 1366x768 Panel CHIMEI M156B3-LA1
+		// To activate write "setenv panel LDB-WXGA".
+		.name           = "LDB-WXGA",
+		.refresh        = 59,
+		.xres           = 1368,
+		.yres           = 768,
+		.pixclock       = 13890,
+		.left_margin    = 220,
+		.right_margin   = 40,
+		.upper_margin   = 21,
+		.lower_margin   = 7,
+		.hsync_len      = 60,
+		.vsync_len      = 10,
+		.sync           = 0,
+		.vmode          = FB_VMODE_NONINTERLACED
+} }, 
+};
+
+int board_video_skip(void)
+{
+        int i;
+        int ret;
+        char const *panel = getenv("panel");
+
+        if (!panel) {
+                for (i = 0; i < ARRAY_SIZE(displays); i++) {
+                        struct display_info_t const *dev = displays+i;
+                        if (dev->detect(dev)) {
+                                panel = dev->mode.name;
+                                printf("auto-detected panel %s\n", panel);
+                                break;
+                        }
+                }
+                if (!panel) {
+                        panel = displays[0].mode.name;
+                        printf("No panel detected: default to %s\n", panel);
+                        i = 0;
+                }
+        } else {
+                for (i = 0; i < ARRAY_SIZE(displays); i++) {
+                        if (!strcmp(panel, displays[i].mode.name))
+                                break;
+                }
+        }
+        if (i < ARRAY_SIZE(displays)) {
+                ret = ipuv3_fb_init(&displays[i].mode, 0,
+                                    displays[i].pixfmt);
+                if (!ret) {
+                        displays[i].enable(displays+i);
+                        printf("Display: %s (%ux%u)\n",
+                               displays[i].mode.name,
+                               displays[i].mode.xres,
+                               displays[i].mode.yres);
+                } else {
+                        printf("LCD %s cannot be configured: %d\n",
+                               displays[i].mode.name, ret);
+                }
+        } else {
+                printf("unsupported panel %s\n", panel);
+                ret = -EINVAL;
+        }
+        return (0 != ret);
+}
+
+static void setup_display(void)
+{
+	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+	struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
+	int reg;
+
+	enable_ipu_clock();
+	imx_setup_hdmi();
+
+	/* Turn on LDB0,IPU DI0 clocks */
+	reg = __raw_readl(&mxc_ccm->CCGR3);
+	reg |=  MXC_CCM_CCGR3_LDB_DI0_MASK;
+	writel(reg, &mxc_ccm->CCGR3);
+
+	/* set LDB0, LDB1 clk select to 011/011 */
+	reg = readl(&mxc_ccm->cs2cdr);
+	reg &= ~(MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK
+		 |MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK);
+	reg |= (3<<MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET);
+	writel(reg, &mxc_ccm->cs2cdr);
+
+	reg = readl(&mxc_ccm->cscmr2);
+	reg |= MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV;
+	writel(reg, &mxc_ccm->cscmr2);
+
+	reg = readl(&mxc_ccm->chsccdr);
+	reg |= (CHSCCDR_CLK_SEL_LDB_DI0
+		<< MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET);
+	writel(reg, &mxc_ccm->chsccdr);
+
+	reg = IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES
+		|IOMUXC_GPR2_DI1_VS_POLARITY_ACTIVE_HIGH
+		|IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW
+		|IOMUXC_GPR2_BIT_MAPPING_CH1_SPWG
+		|IOMUXC_GPR2_DATA_WIDTH_CH1_18BIT
+		|IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG
+		|IOMUXC_GPR2_DATA_WIDTH_CH0_18BIT
+		|IOMUXC_GPR2_LVDS_CH1_MODE_DISABLED
+		|IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0;
+	writel(reg, &iomux->gpr[2]);
+
+	reg = readl(&iomux->gpr[3]);
+	reg = (reg & ~(IOMUXC_GPR3_LVDS0_MUX_CTL_MASK
+			|IOMUXC_GPR3_HDMI_MUX_CTL_MASK))
+		| (IOMUXC_GPR3_MUX_SRC_IPU1_DI0
+		<<IOMUXC_GPR3_LVDS0_MUX_CTL_OFFSET);
+	writel(reg, &iomux->gpr[3]);
+}
+
+/*
+ * Show device feature strings on current display
+ * around uDOO Logo.
+ */
+void show_boot_messages(void) 
+{
+	int i;
+	ulong cycles = 0;
+	int repeatable;
+	char *plotmsg_cmd[2];
+#if defined(CONFIG_MX6DL)
+	char *boot_messages[7] = {
+"UDOO Board 2013",
+"CPU Freescale i.MX6 DualLite 1GHz",
+"dual ARMv7 Cortex-A9 core",
+"1GB RAM DDR3",
+"Vivante GC880 GPU",
+"Atmel SAM3X8E ARM Cortex-M3 CPU",
+"Arduino-compatible R3 1.0 pinout",
+};
+#else
+	char *boot_messages[7] = {
+"UDOO Board 2013",
+"CPU Freescale i.MX6 Quad/Dual 1GHz",
+"quad/dual ARMv7 Cortex-A9 core",
+"1GB RAM DDR3",
+"Vivante GC2000 / GC880",
+"Atmel SAM3X8E ARM Cortex-M3 CPU",
+"Arduino-compatible R3 1.0 pinout",
+};
+#endif
+
+	for (i=0; i<7; i++) {
+		plotmsg_cmd[0] = "plotmsg";
+		plotmsg_cmd[1] = boot_messages[i];
+		cmd_process(0, 2, plotmsg_cmd, &repeatable, &cycles);
+	}
+}
+#endif /* CONFIG_VIDEO_IPUV3 */
+
+int board_early_init_f(void)
+{
+#if defined(CONFIG_VIDEO_IPUV3)
+        setup_display();
+#endif
+	setup_iomux_wdog();
+	setup_iomux_uart();
+
+	return 0;
+}
+
+int board_late_init(void)
+{
+	if (is_cpu_type(MXC_CPU_MX6Q))
+		setenv("board_rev", "MX6Q");
+	else
+		setenv("board_rev", "MX6DL");
+
+	return 0;
+}
+
+int board_phy_config(struct phy_device *phydev)
+{
+	mx6_rgmii_rework(phydev);
+	if (phydev->drv->config)
+		phydev->drv->config(phydev);
+
+	return 0;
+}
+
+/*
+ * Do not overwrite the console
+ * Use always serial for U-Boot console
+ */
+int overwrite_console(void)
+{
+#if defined(CONFIG_VIDEO_IPUV3)
+	show_boot_messages();
+#endif
+        return 1;
+}
+
+int board_init(void)
+{
+	/* address of boot parameters */
+	gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
+
+#ifdef CONFIG_CMD_SATA
+	if (is_cpu_type(MXC_CPU_MX6Q))
+		sata_setup();
+#endif
+	return 0;
+}
+
+int checkboard(void)
+{
+	if (is_cpu_type(MXC_CPU_MX6Q))
+		puts("Board: Udoo Quad\n");
+	else
+		puts("Board: Udoo DualLite\n"); 
+
+	return 0;
+}
diff --git a/board/udoo/udoo.cfg b/board/udoo/udoo.cfg
new file mode 100644
index 0000000..2519f14
--- /dev/null
+++ b/board/udoo/udoo.cfg
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013 Seco USA Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ * Refer doc/README.imximage for more details about how-to configure
+ * and create imximage boot image
+ *
+ * The syntax is taken as close as possible with the kwbimage
+ */
+
+/* image version */
+IMAGE_VERSION 2
+
+/*
+ * Boot Device : one of
+ * spi, sd (the board has no nand neither onenand)
+ */
+BOOT_FROM      sd
+
+#define __ASSEMBLY__
+#include <config.h>
+
+#ifndef CONFIG_SPL
+#include "asm/arch/mx6-ddr.h"
+#endif
+
+#include "asm/arch/iomux.h"
+#include "asm/arch/crm_regs.h"
+
+#ifndef CONFIG_SPL
+#if defined(CONFIG_MX6Q)
+#include "ddr-setup_q.cfg"
+#include "1066mhz_4x256mx16_q.cfg"
+#else
+#include "ddr-setup_dl.cfg"
+#include "1066mhz_4x256mx16_dl.cfg"
+#endif
+#endif
+
+#include "clocks.cfg"
diff --git a/board/udoo/udoo_spl.c b/board/udoo/udoo_spl.c
new file mode 100644
index 0000000..db5044a
--- /dev/null
+++ b/board/udoo/udoo_spl.c
@@ -0,0 +1,404 @@
+/*
+ * Author: Tungyi Lin <tungyilin1127@gmail.com>
+ *
+ * Derived from EDM_CF_IMX6 code by TechNexion,Inc
+ * Ported to SolidRun microSOM by Rabeeh Khoury <rabeeh@solid-run.com>
+ * Ported to Udoo from mx6_cubox-i_spl.c by Peter Vicman <peter.vicman@gmail.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/sys_proto.h>
+#ifdef CONFIG_SPL
+#include <spl.h>
+#include <libfdt.h>
+#endif
+#include <asm/arch/iomux.h>
+#include <asm/arch/mx6-pins.h>
+#include <asm/gpio.h>
+#include <asm/arch-mx6/crm_regs.h>
+#include "asm/arch/mx6_ddr_regs.h"
+
+#define CONFIG_SPL_STACK	0x0091FFB8
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define UART_PAD_CTRL  (PAD_CTL_PUS_100K_UP | \
+        PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \
+        PAD_CTL_SRE_FAST  | PAD_CTL_HYS)
+
+static void spl_mx6dl_dram_setup_iomux(void)
+{
+	volatile struct mx6sdl_iomux_ddr_regs *mx6dl_ddr_iomux;
+	volatile struct mx6sdl_iomux_grp_regs *mx6dl_grp_iomux;
+
+	mx6dl_ddr_iomux = (struct mx6sdl_iomux_ddr_regs *) MX6SDL_IOM_DDR_BASE;
+	mx6dl_grp_iomux = (struct mx6sdl_iomux_grp_regs *) MX6SDL_IOM_GRP_BASE;
+
+	/* ddr-setup_dl.cfg */
+	mx6dl_ddr_iomux->dram_sdqs0 = 0x00000028;
+	mx6dl_ddr_iomux->dram_sdqs1 = 0x00000028;
+	mx6dl_ddr_iomux->dram_sdqs2 = 0x00000028;
+	mx6dl_ddr_iomux->dram_sdqs3 = 0x00000028;
+	mx6dl_ddr_iomux->dram_sdqs4 = 0x00000028;
+	mx6dl_ddr_iomux->dram_sdqs5 = 0x00000028;
+	mx6dl_ddr_iomux->dram_sdqs6 = 0x00000028;
+	mx6dl_ddr_iomux->dram_sdqs7 = 0x00000028;
+
+	mx6dl_grp_iomux->grp_b0ds = 0x00000028;
+	mx6dl_grp_iomux->grp_b1ds = 0x00000028;
+	mx6dl_grp_iomux->grp_b2ds = 0x00000028;
+	mx6dl_grp_iomux->grp_b3ds = 0x00000028;
+	mx6dl_grp_iomux->grp_b4ds = 0x00000028;
+	mx6dl_grp_iomux->grp_b5ds = 0x00000028;
+	mx6dl_grp_iomux->grp_b6ds = 0x00000028;
+	mx6dl_grp_iomux->grp_b7ds = 0x00000028;
+	mx6dl_grp_iomux->grp_addds = 0x00000028;
+
+	mx6dl_grp_iomux->grp_ctlds = 0x00000028;
+
+	mx6dl_ddr_iomux->dram_dqm0 = 0x00000028;
+	mx6dl_ddr_iomux->dram_dqm1 = 0x00000028;
+	mx6dl_ddr_iomux->dram_dqm2 = 0x00000028;
+	mx6dl_ddr_iomux->dram_dqm3 = 0x00000028;
+	mx6dl_ddr_iomux->dram_dqm4 = 0x00000028;
+	mx6dl_ddr_iomux->dram_dqm5 = 0x00000028;
+	mx6dl_ddr_iomux->dram_dqm6 = 0x00000028;
+	mx6dl_ddr_iomux->dram_dqm7 = 0x00000028;
+
+	mx6dl_ddr_iomux->dram_cas = 0x00000028;
+	mx6dl_ddr_iomux->dram_ras = 0x00000028;
+	mx6dl_ddr_iomux->dram_sdclk_0 = 0x00000028;
+	mx6dl_ddr_iomux->dram_sdclk_1 = 0x00000028;
+
+	mx6dl_ddr_iomux->dram_reset = 0x00000028;
+
+	mx6dl_ddr_iomux->dram_sdodt0 = 0x00000028;
+	mx6dl_ddr_iomux->dram_sdodt1 = 0x00000028;
+
+	/* (differential input) */
+	mx6dl_grp_iomux->grp_ddrmode_ctl = 0x00020000;
+	/* (differential input) */
+	mx6dl_grp_iomux->grp_ddrmode = 0x00020000;
+	/* disable ddr pullups */
+	mx6dl_grp_iomux->grp_ddrpke = 0x00000000;
+	mx6dl_ddr_iomux->dram_sdba2 = 0x00000000;
+	/* 40 Ohm drive strength for cs0/1,sdba2,cke0/1,sdwe */
+	mx6dl_grp_iomux->grp_ddr_type = 0x000C0000;
+}
+
+static void spl_mx6q_dram_setup_iomux(void)
+{
+	volatile struct mx6qd_iomux_ddr_regs *mx6q_ddr_iomux;
+	volatile struct mx6qd_iomux_grp_regs *mx6q_grp_iomux;
+
+	mx6q_ddr_iomux = (struct mx6qd_iomux_ddr_regs *) MX6DQ_IOM_DDR_BASE;
+	mx6q_grp_iomux = (struct mx6qd_iomux_grp_regs *) MX6DQ_IOM_GRP_BASE;
+
+	/* ddr-setup_q.cfg */
+	mx6q_ddr_iomux->dram_sdqs0 = 0x00000030;
+	mx6q_ddr_iomux->dram_sdqs1 = 0x00000030;
+	mx6q_ddr_iomux->dram_sdqs2 = 0x00000030;
+	mx6q_ddr_iomux->dram_sdqs3 = 0x00000030;
+	mx6q_ddr_iomux->dram_sdqs4 = 0x00000030;
+	mx6q_ddr_iomux->dram_sdqs5 = 0x00000030;
+	mx6q_ddr_iomux->dram_sdqs6 = 0x00000030;
+	mx6q_ddr_iomux->dram_sdqs7 = 0x00000030;
+
+	mx6q_grp_iomux->grp_b0ds = 0x00000030;
+	mx6q_grp_iomux->grp_b1ds = 0x00000030;
+	mx6q_grp_iomux->grp_b2ds = 0x00000030;
+	mx6q_grp_iomux->grp_b3ds = 0x00000030;
+	mx6q_grp_iomux->grp_b4ds = 0x00000030;
+	mx6q_grp_iomux->grp_b5ds = 0x00000030;
+	mx6q_grp_iomux->grp_b6ds = 0x00000030;
+	mx6q_grp_iomux->grp_b7ds = 0x00000030;
+	mx6q_grp_iomux->grp_addds = 0x00000030;
+	/* 40 Ohm drive strength for cs0/1,sdba2,cke0/1,sdwe */
+	mx6q_grp_iomux->grp_ctlds = 0x00000030;
+
+	mx6q_ddr_iomux->dram_dqm0 = 0x00020030;
+	mx6q_ddr_iomux->dram_dqm1 = 0x00020030;
+	mx6q_ddr_iomux->dram_dqm2 = 0x00020030;
+	mx6q_ddr_iomux->dram_dqm3 = 0x00020030;
+	mx6q_ddr_iomux->dram_dqm4 = 0x00020030;
+	mx6q_ddr_iomux->dram_dqm5 = 0x00020030;
+	mx6q_ddr_iomux->dram_dqm6 = 0x00020030;
+	mx6q_ddr_iomux->dram_dqm7 = 0x00020030;
+
+	mx6q_ddr_iomux->dram_cas = 0x00020030;
+	mx6q_ddr_iomux->dram_ras = 0x00020030;
+	mx6q_ddr_iomux->dram_sdclk_0 = 0x00020030;
+	mx6q_ddr_iomux->dram_sdclk_1 = 0x00020030;
+
+	mx6q_ddr_iomux->dram_reset = 0x00020030;
+	mx6q_ddr_iomux->dram_sdcke0 = 0x00003000;
+	mx6q_ddr_iomux->dram_sdcke1 = 0x00003000;
+
+	mx6q_ddr_iomux->dram_sdodt0 = 0x00003030;
+	mx6q_ddr_iomux->dram_sdodt1 = 0x00003030;
+
+	/* (differential input) */
+	mx6q_grp_iomux->grp_ddrmode_ctl = 0x00020000;
+	/* (differential input) */
+	mx6q_grp_iomux->grp_ddrmode = 0x00020000;
+	/* disable ddr pullups */
+	mx6q_grp_iomux->grp_ddrpke = 0x00000000;
+	mx6q_ddr_iomux->dram_sdba2 = 0x00000000;
+	/* 40 Ohm drive strength for cs0/1,sdba2,cke0/1,sdwe */
+	mx6q_grp_iomux->grp_ddr_type = 0x000c0000;
+}
+
+/* Udoo DualLite 1GByte memory
+   Micron MT41K128M16JT-125 */
+static void spl_dram_init_mx6dl_1g(void)
+{
+	volatile struct mmdc_p_regs *mmdc_p0;
+	volatile struct mmdc_p_regs *mmdc_p1;
+	mmdc_p0 = (struct mmdc_p_regs *) MMDC_P0_BASE_ADDR;
+	mmdc_p1 = (struct mmdc_p_regs *) MMDC_P1_BASE_ADDR;
+
+	/* end of ddr-setup_dl.cfg */
+	/* Read data DQ Byte0-3 delay */
+	mmdc_p0->mprddqby0dl = 0x33333333;
+	mmdc_p0->mprddqby1dl = 0x33333333;
+	mmdc_p0->mprddqby2dl = 0x33333333;
+	mmdc_p0->mprddqby3dl = 0x33333333;
+ 	mmdc_p1->mprddqby0dl = 0x33333333;
+ 	mmdc_p1->mprddqby1dl = 0x33333333;
+ 	mmdc_p1->mprddqby2dl = 0x33333333;
+ 	mmdc_p1->mprddqby3dl = 0x33333333;
+
+  /* 1066mhz_4x256mx16_dl.cfg */
+	mmdc_p0->mdpdc = 0x0002002D;
+	mmdc_p0->mdotc = 0x00333040;
+
+	mmdc_p0->mdcfg0 = 0x3F4352F3;
+	mmdc_p0->mdcfg1 = 0xB66D8B63;
+	mmdc_p0->mdcfg2 = 0x01FF00DB;
+
+	mmdc_p0->mdmisc = 0x00001740;
+	mmdc_p0->mdscr = 0x00008000;
+	mmdc_p0->mdrwd = 0x000026D2;
+
+	mmdc_p0->mdor = 0x00431023;
+	mmdc_p0->mdasp = 0x00000027;
+	mmdc_p0->mdctl = 0x831A0000;
+
+	mmdc_p0->mdscr = 0x02008032;
+	mmdc_p0->mdscr = 0x00008033;
+	mmdc_p0->mdscr = 0x00048031;
+	mmdc_p0->mdscr = 0x05208030;
+	mmdc_p0->mdscr = 0x04008040;
+
+	mmdc_p0->mpzqhwctrl = 0xa1390003;
+	mmdc_p1->mpzqhwctrl = 0xa1390003;
+
+	mmdc_p0->mdref = 0x00007800;
+
+	mmdc_p0->mpodtctrl = 0x00022227;
+	mmdc_p1->mpodtctrl = 0x00022227;
+
+	mmdc_p0->mpdgctrl0 = 0x425C0251;
+	mmdc_p0->mpdgctrl1 = 0x021B021E;
+	mmdc_p1->mpdgctrl0 = 0x021B021E;
+	mmdc_p1->mpdgctrl1 = 0x01730200;
+
+	mmdc_p0->mprddlctl = 0x45474C45;
+	mmdc_p1->mprddlctl = 0x44464744;
+	mmdc_p0->mpwrdlctl = 0x3F3F3336;
+	mmdc_p1->mpwrdlctl = 0x32383630;
+
+	mmdc_p0->mpwldectrl0 = 0x002F0038;
+	mmdc_p0->mpwldectrl1 = 0x001F001F;
+	mmdc_p1->mpwldectrl0 = 0x001F001F;
+	mmdc_p1->mpwldectrl1 = 0x001F001F;
+
+	mmdc_p0->mpmur0 = 0x00000000;
+	mmdc_p1->mpmur0 = 0x00000000;
+
+	mmdc_p0->mdpdc = 0x0002556D;
+	mmdc_p0->mapsr = 0x00011006;
+	mmdc_p0->mdscr = 0x00000000;
+}
+
+/* Udoo Quad 1GByte memory
+   Micron MT41K128M16JT-125 */
+static void spl_dram_init_mx6q_1g(void)
+{
+	volatile struct mmdc_p_regs *mmdc_p0;
+	volatile struct mmdc_p_regs *mmdc_p1;
+	mmdc_p0 = (struct mmdc_p_regs *) MMDC_P0_BASE_ADDR;
+	mmdc_p1 = (struct mmdc_p_regs *) MMDC_P1_BASE_ADDR;
+
+	/* end of ddr-setup_q.cfg */
+	/* Read data DQ Byte0-3 delay */
+	mmdc_p0->mprddqby0dl = 0x33333333;
+	mmdc_p0->mprddqby1dl = 0x33333333;
+	mmdc_p0->mprddqby2dl = 0x33333333;
+	mmdc_p0->mprddqby3dl = 0x33333333;
+ 	mmdc_p1->mprddqby0dl = 0x33333333;
+ 	mmdc_p1->mprddqby1dl = 0x33333333;
+ 	mmdc_p1->mprddqby2dl = 0x33333333;
+ 	mmdc_p1->mprddqby3dl = 0x33333333;
+
+  /* 1066mhz_4x256mx16_q.cfg */
+	mmdc_p0->mdpdc = 0x00020036;
+	mmdc_p0->mdotc = 0x09444040;
+
+	mmdc_p0->mdcfg0 = 0x54597955;
+	mmdc_p0->mdcfg1 = 0xFF328F64;
+	mmdc_p0->mdcfg2 = 0x01FF00DB;
+
+	mmdc_p0->mdmisc = 0x00001740;
+	mmdc_p0->mdscr = 0x00008000;
+	mmdc_p0->mdrwd = 0x000026D2;
+
+	mmdc_p0->mdor = 0x00591023;
+	mmdc_p0->mdasp = 0x00000027;
+	mmdc_p0->mdctl = 0x831A0000;
+
+	mmdc_p0->mdscr = 0x04088032;
+	mmdc_p0->mdscr = 0x00008033;
+	mmdc_p0->mdscr = 0x00048031;
+	mmdc_p0->mdscr = 0x09408030;
+	mmdc_p0->mdscr = 0x04008040;
+
+	mmdc_p0->mpzqhwctrl = 0xA1380003;
+	mmdc_p1->mpzqhwctrl = 0xA1380003;
+
+	mmdc_p0->mdref = 0x00005800;
+
+	mmdc_p0->mpodtctrl = 0x00011117;
+	mmdc_p1->mpodtctrl = 0x00011117;
+
+	mmdc_p0->mpdgctrl0 = 0x43510360;
+	mmdc_p0->mpdgctrl1 = 0x0342033F;
+	mmdc_p1->mpdgctrl0 = 0x033F033F;
+	mmdc_p1->mpdgctrl1 = 0x03290266;
+
+	mmdc_p0->mprddlctl = 0x4B3E4141;
+	mmdc_p1->mprddlctl = 0x47413B4A;
+	mmdc_p0->mpwrdlctl = 0x42404843;
+	mmdc_p1->mpwrdlctl = 0x4C3F4C45;
+
+	mmdc_p0->mpwldectrl0 = 0x00350035;
+	mmdc_p0->mpwldectrl1 = 0x001F001F;
+	mmdc_p1->mpwldectrl0 = 0x00010001;
+	mmdc_p1->mpwldectrl1 = 0x00010001;
+
+	mmdc_p0->mpmur0 = 0x00000800;
+	mmdc_p1->mpmur0 = 0x00000800;
+
+	mmdc_p0->mdpdc = 0x00025576;
+	mmdc_p0->mapsr = 0x00011006;
+	mmdc_p0->mdscr = 0x00000000;
+}
+
+static void spl_dram_init(void)
+{
+	if (is_cpu_type(MXC_CPU_MX6Q)) {
+		spl_mx6q_dram_setup_iomux();
+		spl_dram_init_mx6q_1g();
+	} else {
+		spl_mx6dl_dram_setup_iomux();
+		spl_dram_init_mx6dl_1g();
+	}
+}
+
+static void prefetch_enable(void)
+{
+#ifdef CONFIG_SYS_PL310_BASE
+	u32 reg;
+
+	writel(0x30000003, CONFIG_SYS_PL310_BASE + 0xf60);
+
+	reg = readl(CONFIG_SYS_PL310_BASE + 0x104);
+	reg |= (1 << 30);
+	writel(reg, CONFIG_SYS_PL310_BASE + 0x104);
+#endif
+}
+
+/* copied from u-boot-2015.07 */
+static void ccgr_init(void)
+{
+	struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+
+	/* set the default clock gate to save power */
+	writel(0x00C03F3F, &ccm->CCGR0);
+	writel(0x0030FC03, &ccm->CCGR1);
+	writel(0x0FFFC000, &ccm->CCGR2);
+	writel(0x3FF00000, &ccm->CCGR3);
+	writel(0x00FFF300, &ccm->CCGR4);
+	writel(0x0F0000C3, &ccm->CCGR5);
+	writel(0x000003FF, &ccm->CCGR6);
+}
+
+/* copied from u-boot-2015.07 */
+static void gpr_init(void)
+{
+	struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
+
+	/* enable AXI cache for VDOA/VPU/IPU */
+	writel(0xF00000CF, &iomux->gpr[4]);
+	/* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */
+	writel(0x007F007F, &iomux->gpr[6]);
+	writel(0x007F007F, &iomux->gpr[7]);
+}
+
+void board_init_f(ulong dummy)
+{
+	/* Set the stack pointer. */
+	asm volatile("mov sp, %0\n" : : "r"(CONFIG_SPL_STACK));
+
+	spl_dram_init();
+	ccgr_init();
+	gpr_init();
+	arch_cpu_init();
+
+	/* Clear the BSS. */
+	memset(__bss_start, 0, __bss_end - __bss_start);
+
+	/* Set global data pointer. */
+	gd = &gdata;
+	gd->ram_size = CONFIG_DDR_MB * 1024 * 1024;	/* both have 1 GB */;
+
+	board_early_init_f();
+
+	timer_init();
+	preloader_console_init();
+	prefetch_enable();
+
+	board_init_r(NULL, 0);
+}
+
+void spl_board_init(void)
+{
+	return;	/* nothing for now */
+}
+
+#ifdef CONFIG_SPL_OS_BOOT
+
+int spl_start_uboot(void)
+{
+	return 1;		/* u-boot must be started */
+}
+
+#endif
+
+u32 spl_boot_device(void)
+{
+	printf("Boot Device: microSD card\n");
+	return BOOT_DEVICE_MMC2;
+}
+
+u32 spl_boot_mode(void)
+{
+	return MMCSD_MODE;	/* only microSD card */
+}
+
+void reset_cpu(ulong addr)
+{
+	__REG16(WDOG1_BASE_ADDR) = 4;
+}
diff --git a/boards.cfg b/boards.cfg
index 9480005..64c0cee 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -286,6 +286,9 @@ Active  arm         armv7          mx5         freescale       mx53smd
 Active  arm         armv7          mx5         genesi          mx51_efikamx        mx51_efikamx                         mx51_efikamx:MACH_TYPE=MACH_TYPE_MX51_EFIKAMX,IMX_CONFIG=board/genesi/mx51_efikamx/imximage_mx.cfg                                -
 Active  arm         armv7          mx5         genesi          mx51_efikamx        mx51_efikasb                         mx51_efikamx:MACH_TYPE=MACH_TYPE_MX51_EFIKASB,IMX_CONFIG=board/genesi/mx51_efikamx/imximage_sb.cfg                                -
 Active  arm         armv7          mx5         ttcontrol       vision2             vision2                              vision2:IMX_CONFIG=board/ttcontrol/vision2/imximage_hynix.cfg                                                                     Stefano Babic <sbabic@denx.de>
+Active  arm         armv7          mx6         -               udoo		             udoo                                 udoo:IMX_CONFIG=board/udoo/udoo.cfg,MX6QDL,SPL,DDR_MB=1024   Fabio Estevam <fabio.estevam@freescale.com>
+Active  arm         armv7          mx6         -               udoo		             udoo_dl                              udoo:IMX_CONFIG=board/udoo/udoo.cfg,MX6DL,DDR_MB=1024        Fabio Estevam <fabio.estevam@freescale.com>
+Active  arm         armv7          mx6         -               udoo		             udoo_quad                            udoo:IMX_CONFIG=board/udoo/udoo.cfg,MX6Q,DDR_MB=1024         Fabio Estevam <fabio.estevam@freescale.com>
 Active  arm         armv7          mx6         -               wandboard           wandboard_dl                         wandboard:IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6dl.cfg,MX6DL,DDR_MB=1024                                                  Fabio Estevam <fabio.estevam@freescale.com>
 Active  arm         armv7          mx6         -               wandboard           wandboard_quad                       wandboard:IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6q2g.cfg,MX6Q,DDR_MB=2048                                                  Fabio Estevam <fabio.estevam@freescale.com>
 Active  arm         armv7          mx6         -               wandboard           wandboard_solo                       wandboard:IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6s.cfg,MX6S,DDR_MB=512                                                     Fabio Estevam <fabio.estevam@freescale.com>
diff --git a/common/Makefile b/common/Makefile
index 97dd76e..27a1b36 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -54,6 +54,7 @@ COBJS-$(CONFIG_ENV_IS_IN_UBI) += env_ubi.o
 COBJS-$(CONFIG_ENV_IS_NOWHERE) += env_nowhere.o
 
 # command
+COBJS-$(CONFIG_CMD_MULTIBOOT) += cmd_multiboot.o
 COBJS-$(CONFIG_CMD_AMBAPP) += cmd_ambapp.o
 COBJS-$(CONFIG_SOURCE) += cmd_source.o
 COBJS-$(CONFIG_CMD_SOURCE) += cmd_source.o
diff --git a/common/cmd_multiboot.c b/common/cmd_multiboot.c
new file mode 100644
index 0000000..79df3d8
--- /dev/null
+++ b/common/cmd_multiboot.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright 2000-2013
+ * Giuseppe Pagano, Seco s.r.l., giuseppe.pagano@seco.com.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+
+#define DEF_bootargs_defaults "console=ttymxc1,115200 root=/dev/mmcblk0p${sd_part} rootwait rw fixrtc rootflags=barrier=1 fbmem=24M video=mxcfb0:dev=hdmi,1920x1080M@60,if=RGB24"
+#define DEF_bootcmd_defaults "plotmsg -u Booting from mmcblk0p${sd_part}. Please wait...; mmc dev 0; ext2load mmc 0:${sd_part} 0x10800000 /boot/uImage; bootm 0x10800000"
+
+#define msleep(a) udelay(a * 1000)
+int default_boot = 1;
+
+void do_show_environment(int ch, char *bootvars) {
+	char tempstr[500];
+	char settempstr[500];
+	char env_var_name[300];
+
+	sprintf(env_var_name, "%s_run_%d", bootvars, ch);
+	if (getenv(env_var_name) != NULL) {
+		strcpy (tempstr, getenv(env_var_name));
+		printf("  %s\n", tempstr);
+	} else {
+		sprintf(env_var_name, "%s_%d", bootvars, ch);
+		if (getenv(env_var_name) != NULL) {
+			strcpy (tempstr, getenv(env_var_name));
+			printf("  setenv %s '%s'\n", bootvars, tempstr);
+		} else {
+			sprintf(env_var_name, "sd_part_%d", ch);
+			if (getenv(env_var_name) != NULL) {
+				strcpy(tempstr, getenv(env_var_name));
+				printf("  setenv sd_part '%s'\n", tempstr);
+			} else {
+				printf("  setenv sd_part '%d'\n", ch);
+			}
+			if (strcmp(bootvars, "bootargs") == 0) {
+				if (getenv("bootargs_defaults") != NULL) {
+					strcpy(tempstr, strdup(getenv("bootargs_defaults")));
+					printf("  bootargs_defaults='%s'\n", tempstr);
+				} else {
+					strcpy(tempstr, DEF_bootargs_defaults);
+				}
+				sprintf(settempstr, "  setenv bootargs '%s'\n", tempstr);
+				printf(settempstr);
+			} else {
+				if (getenv("bootcmd_defaults") != NULL) {
+					strcpy(tempstr, strdup(getenv("bootcmd_defaults")));
+					printf("  bootcmd_defaults='%s'\n", tempstr);
+				} else {
+					strcpy(tempstr, DEF_bootcmd_defaults);
+				}
+				sprintf(settempstr, "  setenv bootcmd '%s'\n", tempstr);
+				printf(settempstr);
+			}
+		}
+	}
+}
+
+void do_detailed_environment(void) {
+	int counter = 1;
+	char *boot_descr;
+	char boot_descr_opt[300];
+
+	sprintf(boot_descr_opt, "boot_descr_1");
+	printf ("\nShowing multiboot possible action.\n");
+
+	while (getenv(boot_descr_opt) != NULL) {
+		sprintf(boot_descr_opt, "boot_descr_%d", counter);
+		boot_descr = strdup(getenv(boot_descr_opt));
+		if (getenv(boot_descr_opt) == NULL) {
+			break;
+		}
+		printf("%d) %s.\n", counter, boot_descr);
+		do_show_environment(counter, "bootargs");
+		do_show_environment(counter, "bootcmd");
+		printf("  boot\n");
+		counter++;
+	}
+	return;
+}
+
+int show_multioption(void) {
+	int counter = 1;
+	char *boot_descr;
+	char  boot_descr_opt[300];
+	char *default_boot_str;
+
+	sprintf(boot_descr_opt, "boot_descr_1");
+	printf ("Chose system you want to boot.\n");
+
+	if (getenv("default_boot") != NULL) {
+		default_boot_str = strdup(getenv("default_boot"));
+		default_boot = default_boot_str[0] - '0';
+	}
+
+	while (getenv(boot_descr_opt) != NULL) {
+		sprintf(boot_descr_opt, "boot_descr_%d", counter);
+		boot_descr = strdup(getenv(boot_descr_opt));
+		if (getenv(boot_descr_opt) == NULL) {
+			printf("  p) Show what would be done.\n");
+			printf("  q) Quit.\n");
+			break;
+		}
+		if (counter == default_boot)
+			printf("> %d) %s.\n", counter, boot_descr);
+		else
+			printf("  %d) %s.\n", counter, boot_descr);
+		counter++;
+	}
+	if ((counter > 1) && (default_boot >= counter)) {
+		printf("Warn ! Invalid default_boot value: ->%c<- (non numeric or not existing entry).\n", default_boot_str[0]);
+	        default_boot = 1;
+	}
+	printf ("  > ");
+	return --counter;
+}
+
+int do_detailed_help(void) {
+
+	printf("\n\tHow to setup u-boot environment for multiboot utility.\n");
+
+	printf("\nStep 1) Define as much \"boot_descr_X\" variable as you need assigning to it\n");
+	printf("\ta title rapresenting bootable system number X. \n");
+	printf("\t(Eg. \"setenv boot_descr_1 Linux\").\n");
+
+	printf("\nStep 2) Define default booting entry via \"default_boot\" variable.\n");
+	printf("\t(Eg. \"setenv default_boot 2\").\n");
+
+	printf("\nStep 3) For each configured bootable system there are 3 levels of variable\n");
+	printf("\tdefinitions which override each other in the following order:\n");
+	printf("\t  \"bootargs_run_X\" OVERRIDES \"bootargs_X\" OVERRIDES \"sd_part_X\"\n");
+	printf("\t  \"bootcmd_run_X\" OVERRIDES \"bootcmd_X\" OVERRIDES \"sd_part_X\"\n");
+	printf("\tIf one of the described variable is missing the next one will be used.\n");  
+
+	printf("\nHere the meaning of multiboot configuration variable:\n");  
+
+	printf("  - bootargs_run_X (where X can be 1, 2, 3, ...)\n");
+	printf(" String contained in \"bootargs_run_X\" will be executed inside multiboot\n");
+	printf(" environment with the following command: \"run bootargs_run_X\".\n");
+
+	printf("  - bootargs_X (where X can be 1, 2, 3, ...)\n");
+	printf(" String contained in \"bootargs_X\" will be adopted as bootargs environment.\n");
+
+	printf("  - sd_part_X (where X can be 1, 2, 3, ...)\n");
+	printf(" uSD partition number \"sd_part_X\" to be used as root device filesystem.\n");
+
+	printf("  - bootargs_defaults\n");
+	printf(" Current value for bootargs_defaults is:\n");
+	if (getenv("bootargs_defaults") != NULL)
+		printf("  bootargs_defaults='%s'\n", getenv("bootargs_defaults"));
+	else
+		printf("  bootargs_defaults='%s'\n", DEF_bootargs_defaults);
+	printf("\n");
+
+	printf("  - bootcmd_run_X (where X can be 1, 2, 3, ...)\n");
+	printf(" String contained in \"bootcmd_run_X\" will be executed inside multiboot\n");
+	printf(" environment with the following command: \"run bootcmd_run_X\".\n");
+
+	printf("  - bootcmd_X (where X can be 1, 2, 3, ...)\n");
+	printf(" String contained in \"bootcmd_X\" will be used as bootcmd environment.\n");
+
+	printf("  - sd_part_X (where X can be 1, 2, 3, ...)\n");
+	printf(" uSD partition number \"sd_part_X\" will be used to load uImage from.\n");
+
+	printf("  - bootcmd_default\n");
+	printf(" Current value for bootcmd_default is:\n");
+	if (getenv("bootcmd_defaults") != NULL)
+		printf("  bootcmd_defaults='%s'\n", getenv("bootcmd_defaults"));
+	else
+		printf("  bootcmd_defaults='%s'\n", DEF_bootcmd_defaults);
+	printf("\n");
+
+
+	printf("If your system need multiboot customized environment it will be necessary to\n");
+	printf("define some boot*_X variable or change \"bootargs_defaults\" and \"bootcmd_default\".\n");
+	printf("When no variable is defined, multiboot will use /dev/sda1 for system 1,\n");
+	printf("use /dev/sda2 for system 2, /dev/sda3 for system 3, and so on.\n");
+
+	return 0;
+}
+
+void do_set_environment(char ch, char *bootvars) {
+	char tempstr[500];
+	char settempstr[500];
+	char env_var_name[300];
+
+	sprintf(env_var_name, "%s_run_%c", bootvars, ch);
+	if (getenv(env_var_name) != NULL) {
+		strcpy (tempstr, getenv(env_var_name));
+		run_command(tempstr, 0);
+	} else {
+		sprintf(env_var_name, "%s_%c", bootvars, ch);
+		if (getenv(env_var_name) != NULL) {
+			strcpy (tempstr, getenv(env_var_name));
+			setenv(bootvars, tempstr);
+		} else {
+			sprintf(env_var_name, "sd_part_%c", ch);
+			if (getenv(env_var_name) != NULL) {
+				strcpy(tempstr, getenv(env_var_name));
+				setenv("sd_part", tempstr);
+			} else {
+				setenv("sd_part", ch);
+			}
+			if (strcmp(bootvars, "bootargs") == 0) {
+				if (getenv("bootargs_defaults") != NULL) {
+					strcpy(tempstr, strdup(getenv("bootargs_defaults")));
+				} else {
+					strcpy(tempstr, DEF_bootargs_defaults);
+				}
+				sprintf(settempstr, "setenv bootargs %s", tempstr);
+				run_command(settempstr, 0);
+			} else {
+				if (getenv("bootcmd_defaults") != NULL) {
+					strcpy(tempstr, strdup(getenv("bootcmd_defaults")));
+				} else {
+					strcpy(tempstr, DEF_bootcmd_defaults);
+				}
+				sprintf(settempstr, "setenv bootcmd %s", tempstr);
+				run_command(settempstr, 0);
+			}
+		}
+	}
+	return;
+}
+
+void do_chooseboot(int sec) {
+	int timeout;
+	int first_round = 0;
+	int num_of_possibility;
+	char n[1];
+	char ch;
+
+	do {
+		if (first_round > 0)
+			printf ("\nInvalid option. Valid choice are from 1 to %d.\n", num_of_possibility);
+		num_of_possibility = show_multioption();
+		sprintf(n, "%d", num_of_possibility);
+		ch = (char)(((int)'0') + default_boot);
+		
+		if (num_of_possibility == 0) {
+			printf("No bootable system defined: \"boot_descr_1\" is empty! \n  Giving up.\n");
+			return;
+		}
+
+		if ( sec == 99 ) {
+			ch = getc();
+			printf("%c\n", ch);
+		} else {
+			timeout = sec * 10;
+			while (timeout > 0) {
+				if (tstc()) {
+					ch = getc();
+					printf("%c\n", ch);
+					break;
+				}
+				msleep(100);
+				timeout--;
+			}
+		}
+
+		if (ch == 'q')
+			return;
+
+		if (ch == 'p') {
+			sec = 99;
+			do_detailed_environment();
+		}
+		first_round = 1;
+	} while ((ch < '1') || (ch > n[0]));
+
+	do_set_environment(ch, "bootargs");
+	do_set_environment(ch, "bootcmd");
+
+	run_command("boot", 0);
+}
+
+static int do_multiboot(cmd_tbl_t *cmd, int flag, int argc, char * const argv[])
+{
+	int sec = 5;
+
+        if (argc > 2)
+                return cmd_usage(cmd);
+
+        if (argc == 2 && ((strcmp(argv[1], "help") == 0) || strcmp(argv[1], "h") == 0))  {
+                return cmd_usage(cmd);
+        }
+
+        if (argc == 2 && (strcmp(argv[1], "d") == 0))  {
+		return do_detailed_help();
+        }
+	
+	if (argc == 2 && ((argv[1] >= '0') || (argv[1] <= '9')))
+		sec = argv[1][0] - '0';
+
+        if (argc == 2 && (strcmp(argv[1], "W") == 0))
+		sec = 99;
+
+        printf ("\nUDOO interactive multiboot utility.\n");
+
+	do_chooseboot(sec);
+	return 0;
+}
+
+U_BOOT_CMD(
+	multiboot,	CONFIG_SYS_MAXARGS,	1,	do_multiboot,
+	"manage a multiboot startup",
+	"[args..]\n"
+	" - d Print detailed help.\n - [0-9, W] Seconds before default entry (if empty 5 sec). W = Wait forever"
+);
diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c
index c6f58c2..9293e8d 100644
--- a/drivers/video/cfb_console.c
+++ b/drivers/video/cfb_console.c
@@ -2036,7 +2036,11 @@ static void *video_logo(void)
 	if (board_cfb_skip())
 		return 0;
 
+#ifndef MACH_TYPE_UDOO
 	sprintf(info, " %s", version_string);
+#else
+	sprintf(info, " %s", BOARD_INFO_STRING);
+#endif
 
 	space = (VIDEO_LINE_LEN / 2 - VIDEO_INFO_X) / VIDEO_FONT_WIDTH;
 	len = strlen(info);
@@ -2219,6 +2223,14 @@ static int video_init(void)
 	return 0;
 }
 
+void udoo_video_drawstring(int xx, int yy, unsigned char *s) 
+{
+	video_drawstring(xx, yy, s);
+	if (cfb_do_flush_cache)
+		flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
+	return;
+}
+
 /*
  * Implement a weak default function for boards that optionally
  * need to skip the video initialization.
diff --git a/include/configs/udoo.h b/include/configs/udoo.h
new file mode 100644
index 0000000..6d2c1b1
--- /dev/null
+++ b/include/configs/udoo.h
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ *
+ * Configuration settings for UDOO board.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include "mx6_common.h"
+#include <asm/arch/imx-regs.h>
+#include <asm/imx-common/gpio.h>
+#include <asm/sizes.h>
+
+#ifdef CONFIG_SPL
+#include "imx6_spl.h"
+#define CONFIG_SPL_MMC_SUPPORT
+#define CONFIG_SPL_FAT_SUPPORT
+#endif
+
+#define CONFIG_MX6
+#define CONFIG_DISPLAY_CPUINFO
+#define CONFIG_DISPLAY_BOARDINFO
+
+#define MACH_TYPE_UDOO		4800
+#define CONFIG_MACH_TYPE	MACH_TYPE_UDOO
+
+#define CONFIG_CMDLINE_TAG
+#define CONFIG_SETUP_MEMORY_TAGS
+#define CONFIG_INITRD_TAG
+#define CONFIG_REVISION_TAG
+
+/* disable L2 cache support */
+#define CONFIG_SYS_L2CACHE_OFF
+
+/* Size of malloc() pool */
+#define CONFIG_SYS_MALLOC_LEN		(10 * SZ_1M)
+
+#define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_BOARD_LATE_INIT
+#define CONFIG_MXC_GPIO
+
+#define CONFIG_MXC_UART
+#define CONFIG_MXC_UART_BASE		UART2_BASE
+
+/* SATA Configs */
+
+#if defined(CONFIG_MX6Q)
+#define CONFIG_CMD_SATA
+#endif
+#ifdef CONFIG_CMD_SATA
+#define CONFIG_DWC_AHSATA
+#define CONFIG_SYS_SATA_MAX_DEVICE	1
+#define CONFIG_DWC_AHSATA_PORT_ID	0
+#define CONFIG_DWC_AHSATA_BASE_ADDR	SATA_ARB_BASE_ADDR
+#define CONFIG_LBA48
+#define CONFIG_LIBATA
+#endif
+
+/* Network support */
+
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_MII
+#define CONFIG_CMD_NET
+#define CONFIG_FEC_MXC
+#define CONFIG_MII
+#define IMX_FEC_BASE                    ENET_BASE_ADDR
+#define CONFIG_FEC_XCV_TYPE             RGMII
+#define CONFIG_ETHPRIME                 "FEC"
+#define CONFIG_FEC_MXC_PHYADDR          6
+#define CONFIG_PHYLIB
+#define CONFIG_PHY_MICREL
+#define CONFIG_PHY_MICREL_KSZ9031
+
+/* allow to overwrite serial and ethaddr */
+#define CONFIG_ENV_OVERWRITE
+#define CONFIG_CONS_INDEX		1
+#define CONFIG_BAUDRATE			115200
+
+/* HDMI or LVDS Display Configuration */
+#define CONFIG_VIDEO_ENABLED
+#ifdef CONFIG_VIDEO_ENABLED
+#define CONFIG_VIDEO
+#define CONFIG_VIDEO_IPUV3
+#define CONFIG_CFB_CONSOLE
+#define CONFIG_VGA_AS_SINGLE_DEVICE
+#define CONFIG_SYS_CONSOLE_IS_IN_ENV
+#define CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE
+#define CONFIG_VIDEO_BMP_RLE8
+#define CONFIG_SPLASH_SCREEN
+#define CONFIG_SPLASH_SCREEN_ALIGN
+#define CONFIG_BMP_16BPP
+#define CONFIG_VIDEO_LOGO
+#define CONFIG_VIDEO_BMP_LOGO
+#define CONFIG_IPUV3_CLK 260000000
+#define CONFIG_CONSOLE_MUX
+#define CONFIG_CMD_HDMIDETECT
+#define CONFIG_CMD_PLOTMSG
+#define CONFIG_IMX_HDMI
+#define BOARD_INFO_STRING  "u-boot-imx-2013-10 on:"
+#endif
+
+/* Command definition */
+#include <config_cmd_default.h>
+
+#undef CONFIG_CMD_IMLS
+
+#define CONFIG_CMD_MULTIBOOT
+#define CONFIG_CMD_BMODE
+#define CONFIG_CMD_SETEXPR
+
+#define CONFIG_BOOTDELAY		1
+
+#define CONFIG_SYS_MEMTEST_START	0x10000000
+#define CONFIG_SYS_MEMTEST_END		(CONFIG_SYS_MEMTEST_START + 500 * SZ_1M)
+#define CONFIG_LOADADDR			0x12000000
+#define CONFIG_SYS_TEXT_BASE		0x17800000
+
+/* MMC Configuration */
+#define CONFIG_FSL_ESDHC
+#define CONFIG_FSL_USDHC
+#define CONFIG_SYS_FSL_ESDHC_ADDR	0
+
+#define CONFIG_MMC
+#define CONFIG_CMD_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_BOUNCE_BUFFER
+#define CONFIG_CMD_EXT2
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_EXT4
+#define CONFIG_CMD_FS_GENERIC
+#define CONFIG_DOS_PARTITION
+
+#define CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	"zImage=KERNEL\0" \
+	"script=boot.scr\0" \
+	"image=${zImage}\0" \
+	"console=ttymxc1\0" \
+	"splashpos=m,m\0" \
+	"fdt_high=0xffffffff\0" \
+	"initrd_high=0xffffffff\0" \
+	"fdt_file=undefined\0" \
+	"fdt_addr=0x18000000\0" \
+	"boot_fdt=try\0" \
+	"ip_dyn=yes\0" \
+	"optargs=\0" \
+	"video=\0" \
+	"mmcdev=0\0" \
+	"mmcpart=1\0" \
+	"mmcroot=/dev/mmcblk0p2 ro\0" \
+	"mmcrootfstype=ext4 rootwait\0" \
+	"update_sd_firmware_filename=u-boot.imx\0" \
+	"update_sd_firmware=" \
+		"if test ${ip_dyn} = yes; then " \
+			"setenv get_cmd dhcp; " \
+		"else " \
+			"setenv get_cmd tftp; " \
+		"fi; " \
+		"if mmc dev ${mmcdev}; then "	\
+			"if ${get_cmd} ${update_sd_firmware_filename}; then " \
+				"setexpr fw_sz ${filesize} / 0x200; " \
+				"setexpr fw_sz ${fw_sz} + 1; "	\
+				"mmc write ${loadaddr} 0x2 ${fw_sz}; " \
+			"fi; "	\
+		"fi\0" \
+	"mmcargs=setenv bootargs console=${console},${baudrate} " \
+		"${optargs} " \
+		"root=${mmcroot} " \
+		"rootfstype=${mmcrootfstype} " \
+		"video=${video}\0" \
+	"loadbootenv=load mmc ${mmcdev}:${mmcpart} ${loadaddr} uEnv.txt\0" \
+	"importbootenv=echo Importing environment from mmc (uEnv.txt)...; " \
+		"env import -t $loadaddr $filesize\0" \
+	"loadbootscript=" \
+		"fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};\0" \
+	"bootscript=echo Running bootscript from mmc ...; " \
+		"source\0" \
+	"loadimage=load mmc ${mmcdev}:${mmcpart} ${loadaddr} ${zImage}\0" \
+	"loadzimage=load mmc ${mmcdev}:${mmcpart} ${loadaddr} ${zImage}\0" \
+	"loadfdt=load mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}\0" \
+	"mmcboot=echo Booting from mmc ...; " \
+		"run mmcargs; " \
+		"bootz ${loadaddr} - ${fdt_addr};\0" \
+	"mmcbootdefault=echo Booting from mmc ...; " \
+		"if test ${boot_fdt} = yes || test ${boot_fdt} = try; then " \
+			"if run loadfdt; then " \
+				"bootz ${loadaddr} - ${fdt_addr}; " \
+			"else " \
+				"if test ${boot_fdt} = try; then " \
+					"bootz ${loadaddr}; " \
+				"else " \
+					"echo WARN: Cannot load the DT; " \
+				"fi; " \
+			"fi; " \
+		"else " \
+			"bootz ${loadaddr}; " \
+		"fi;\0" \
+	"netargs=setenv bootargs console=${console},${baudrate} " \
+		"root=/dev/nfs " \
+	"ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp\0" \
+		"netboot=echo Booting from net ...; " \
+		"run netargs; " \
+		"if test ${ip_dyn} = yes; then " \
+			"setenv get_cmd dhcp; " \
+		"else " \
+			"setenv get_cmd tftp; " \
+		"fi; " \
+		"${get_cmd} ${image}; " \
+		"if test ${boot_fdt} = yes || test ${boot_fdt} = try; then " \
+			"if ${get_cmd} ${fdt_addr} ${fdt_file}; then " \
+				"bootz ${loadaddr} - ${fdt_addr}; " \
+			"else " \
+				"if test ${boot_fdt} = try; then " \
+					"bootz; " \
+				"else " \
+					"echo WARN: Cannot load the DT; " \
+				"fi; " \
+			"fi; " \
+		"else " \
+			"bootz; " \
+		"fi;\0" \
+		"findfdt=" \
+			"if test $board_rev = MX6Q ; then " \
+				"setenv fdt_file imx6q-udoo.dtb; fi; " \
+			"if test $board_rev = MX6DL ; then " \
+				"setenv fdt_file imx6dl-udoo.dtb; fi; " \
+			"if test $fdt_file = undefined; then " \
+				"echo WARNING: Could not determine dtb to use; fi; \0"
+
+#define CONFIG_BOOTCOMMAND \
+	"run findfdt; " \
+	"mmc dev ${mmcdev};" \
+	"if mmc rescan; then " \
+		"echo SD/MMC found on device ${mmcdev};" \
+		"if run loadbootenv; then " \
+			"run importbootenv;" \
+		"fi;" \
+		"echo Checking if uenvcmd is set ...;" \
+		"if test -n $uenvcmd; then " \
+			"echo Running uenvcmd ...;" \
+			"run uenvcmd;" \
+		"fi;" \
+		"echo Running default loadimage ...;" \
+		"if run loadimage; then " \
+			"run loadfdt;" \
+			"run mmcboot;" \
+		"fi;" \
+	"fi;"
+
+/* Miscellaneous configurable options */
+#define CONFIG_SYS_LONGHELP
+#define CONFIG_SYS_HUSH_PARSER
+#define CONFIG_SYS_PROMPT	       "UDOO board => "
+#define CONFIG_AUTO_COMPLETE
+#define CONFIG_SYS_CBSIZE		256
+
+/* Print Buffer Size */
+#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+#define CONFIG_SYS_MAXARGS	       16
+#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE
+
+#define CONFIG_SYS_LOAD_ADDR		CONFIG_LOADADDR
+#define CONFIG_SYS_HZ			1000
+
+#define CONFIG_CMDLINE_EDITING
+
+/* Physical Memory Map */
+#define ONEGIGA	       		       1
+#define CONFIG_NR_DRAM_BANKS	 1
+#define PHYS_SDRAM	 MMDC0_ARB_BASE_ADDR
+
+#define CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM
+#define CONFIG_SYS_INIT_RAM_ADDR	IRAM_BASE_ADDR
+#define CONFIG_SYS_INIT_RAM_SIZE	IRAM_SIZE
+
+#define CONFIG_SYS_INIT_SP_OFFSET \
+	(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
+#define CONFIG_SYS_INIT_SP_ADDR \
+	(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)
+
+/* FLASH and environment organization */
+#define CONFIG_SYS_NO_FLASH
+
+#define CONFIG_ENV_SIZE			(8 * 1024)
+
+#define CONFIG_ENV_IS_IN_MMC
+#define CONFIG_ENV_OFFSET		(6 * 128 * 1024)  // 0x000C0000
+#define CONFIG_SYS_MMC_ENV_DEV		0
+
+#define CONFIG_OF_LIBFDT
+#define CONFIG_CMD_BOOTZ
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+#define CONFIG_CMD_CACHE
+#endif
+
+#endif			       /* __CONFIG_H * */
diff --git a/include/micrel.h b/include/micrel.h
index e1c62d8..1d72b50 100644
--- a/include/micrel.h
+++ b/include/micrel.h
@@ -15,6 +15,11 @@
 #define MII_KSZ9031_MOD_DATA_POST_INC_RW	0x8000
 #define MII_KSZ9031_MOD_DATA_POST_INC_W		0xC000
 
+#define MII_KSZ9031_EXT_RGMII_CTRL_SIG_SKEW    0x4
+#define MII_KSZ9031_EXT_RGMII_RX_DATA_SKEW     0x5
+#define MII_KSZ9031_EXT_RGMII_TX_DATA_SKEW     0x6
+#define MII_KSZ9031_EXT_RGMII_CLOCK_SKEW       0x8
+
 struct phy_device;
 int ksz9021_phy_extended_write(struct phy_device *phydev, int regnum, u16 val);
 int ksz9021_phy_extended_read(struct phy_device *phydev, int regnum);
diff --git a/include/video.h b/include/video.h
index 0ff857b..0f9a56f 100644
--- a/include/video.h
+++ b/include/video.h
@@ -14,6 +14,8 @@
 int	video_init	(void *videobase);
 void	video_putc	(const char c);
 void	video_puts	(const char *s);
+void 	udoo_video_drawstring(int xx, int yy, unsigned char *s);
+
 
 /**
  * Display a BMP format bitmap on the screen
-- 
1.8.1.2

