mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH] i.MX6 xload and Utilite support
@ 2015-07-16  8:50 Sascha Hauer
  2015-07-16  8:50 ` [PATCH 01/11] ARM: i.MX6: Add i.MX6 entry function Sascha Hauer
                   ` (10 more replies)
  0 siblings, 11 replies; 12+ messages in thread
From: Sascha Hauer @ 2015-07-16  8:50 UTC (permalink / raw)
  To: Barebox List

This series adds support for the Utilite Mini Computer. Like several
other i.MX6 based boards this one also wants to setup the SDRAM from
code rather than from a DCD table. This has previously limited the
barebox image size to the internal SRAM size. This series overcomes
this limitation. We now create the i.MX image from the pblx image
instead of the complete image including payload. With this the ROM
code only loads the initial portion to SRAM and we can setup the
SDRAM there. Afterwards we have to load the remaining image ourselves,
but it turned out require only very little code to load an image
from the SPI NOR flash. This series implements this mechanism for
i.MX6 on SPI NOR flash only, support for other SoCs and other devices
needs to be added to get this working in other cases.

Sascha

----------------------------------------------------------------
Sascha Hauer (11):
      ARM: i.MX6: Add i.MX6 entry function
      ARM: i.MX6: remove unnecessary includes
      ARM: i.MX6: add function to get bootsource in pbl
      memsize: Compile for PBL aswell
      ARM: i.MX: compile boot.c for pbl aswell
      ARM: i.MX6: create cpu_is() functions for use in PBL
      images: i.MX: Create target for SRAM images
      spi: i.MX: move register defines to include/
      ARM: i.MX: Add SPI xload code
      ARM: i.MX6: Add DDR setup code from U-Boot
      ARM: initial cm-fx6 support

 arch/arm/boards/Makefile                           |   1 +
 arch/arm/boards/cm-fx6/Makefile                    |   3 +
 arch/arm/boards/cm-fx6/board.c                     |  74 +++
 .../boards/cm-fx6/flash-header-mx6-cm-fx6.imxcfg   |   3 +
 arch/arm/boards/cm-fx6/lowlevel.c                  | 363 ++++++++++++++
 arch/arm/boards/datamodul-edm-qmx6/board.c         |   1 -
 arch/arm/boards/dfi-fs700-m60/lowlevel.c           |   1 -
 arch/arm/boards/embest-riotboard/lowlevel.c        |   1 -
 arch/arm/boards/phytec-phycard-imx6/lowlevel.c     |   1 -
 arch/arm/boards/phytec-phyflex-imx6/lowlevel.c     |   1 -
 arch/arm/boards/tqma6x/board.c                     |   1 -
 arch/arm/boards/tqma6x/lowlevel.c                  |   1 -
 arch/arm/boards/variscite-mx6/lowlevel.c           |   1 -
 arch/arm/configs/imx_v7_defconfig                  |   1 +
 arch/arm/dts/Makefile                              |   1 +
 arch/arm/dts/imx6q-cm-fx6.dts                      |  29 ++
 arch/arm/dts/imx6q-cm-fx6.dtsi                     |  99 ++++
 arch/arm/dts/imx6q-utilite.dts                     |  42 ++
 arch/arm/dts/imx6qdl-cm-fx6.dtsi                   | 463 ++++++++++++++++++
 arch/arm/mach-imx/Kconfig                          |   4 +
 arch/arm/mach-imx/Makefile                         |   6 +-
 arch/arm/mach-imx/boot.c                           |  38 +-
 arch/arm/mach-imx/esdctl.c                         |  11 +
 arch/arm/mach-imx/imx6-mmdc.c                      | 544 +++++++++++++++++++++
 arch/arm/mach-imx/include/mach/esdctl.h            |   2 +-
 arch/arm/mach-imx/include/mach/generic.h           |   2 +
 arch/arm/mach-imx/include/mach/imx6-mmdc.h         | 274 +++++++++++
 arch/arm/mach-imx/include/mach/imx6.h              |  41 +-
 arch/arm/mach-imx/include/mach/xload.h             |   7 +
 arch/arm/mach-imx/xload-spi.c                      | 160 ++++++
 common/Makefile                                    |   2 +-
 drivers/spi/imx_spi.c                              |  80 +--
 images/Makefile.imx                                |  21 +
 include/spi/imx-spi.h                              |  83 ++++
 34 files changed, 2230 insertions(+), 132 deletions(-)
 create mode 100644 arch/arm/boards/cm-fx6/Makefile
 create mode 100644 arch/arm/boards/cm-fx6/board.c
 create mode 100644 arch/arm/boards/cm-fx6/flash-header-mx6-cm-fx6.imxcfg
 create mode 100644 arch/arm/boards/cm-fx6/lowlevel.c
 create mode 100644 arch/arm/dts/imx6q-cm-fx6.dts
 create mode 100644 arch/arm/dts/imx6q-cm-fx6.dtsi
 create mode 100644 arch/arm/dts/imx6q-utilite.dts
 create mode 100644 arch/arm/dts/imx6qdl-cm-fx6.dtsi
 create mode 100644 arch/arm/mach-imx/include/mach/xload.h
 create mode 100644 arch/arm/mach-imx/xload-spi.c
 create mode 100644 include/spi/imx-spi.h

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 01/11] ARM: i.MX6: Add i.MX6 entry function
  2015-07-16  8:50 [PATCH] i.MX6 xload and Utilite support Sascha Hauer
@ 2015-07-16  8:50 ` Sascha Hauer
  2015-07-16  8:50 ` [PATCH 02/11] ARM: i.MX6: remove unnecessary includes Sascha Hauer
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Sascha Hauer @ 2015-07-16  8:50 UTC (permalink / raw)
  To: Barebox List

Add a i.MX6 specific entry function which automatically detects the SDRAM
size. The prototype has already been present, but it was never implemented.
Rename it to imx6q_ since the other variants need other functions.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-imx/esdctl.c              | 11 +++++++++++
 arch/arm/mach-imx/include/mach/esdctl.h |  2 +-
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/esdctl.c b/arch/arm/mach-imx/esdctl.c
index a8ef854..2f9f5e9 100644
--- a/arch/arm/mach-imx/esdctl.c
+++ b/arch/arm/mach-imx/esdctl.c
@@ -576,3 +576,14 @@ void __noreturn imx53_barebox_entry(void *boarddata)
 
 	barebox_arm_entry(base, size, boarddata);
 }
+
+void __noreturn imx6q_barebox_entry(void *boarddata)
+{
+	u64 size_cs0 = imx6_mmdc_sdram_size((void *)MX6_MMDC_P0_BASE_ADDR, 0);
+	u64 size_cs1 = imx6_mmdc_sdram_size((void *)MX6_MMDC_P0_BASE_ADDR, 1);
+	u64 total    = size_cs0 + size_cs1;
+
+	resource_size_t size = min(total, (u64)IMX6_MAX_SDRAM_SIZE);
+
+	barebox_arm_entry(0x10000000, size, boarddata);
+}
diff --git a/arch/arm/mach-imx/include/mach/esdctl.h b/arch/arm/mach-imx/include/mach/esdctl.h
index 468a928..cf8d89d 100644
--- a/arch/arm/mach-imx/include/mach/esdctl.h
+++ b/arch/arm/mach-imx/include/mach/esdctl.h
@@ -135,7 +135,7 @@ void __noreturn imx31_barebox_entry(void *boarddata);
 void __noreturn imx35_barebox_entry(void *boarddata);
 void __noreturn imx51_barebox_entry(void *boarddata);
 void __noreturn imx53_barebox_entry(void *boarddata);
-void __noreturn imx6_barebox_entry(void *boarddata);
+void __noreturn imx6q_barebox_entry(void *boarddata);
 void imx_esdctl_disable(void);
 #endif
 
-- 
2.1.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 02/11] ARM: i.MX6: remove unnecessary includes
  2015-07-16  8:50 [PATCH] i.MX6 xload and Utilite support Sascha Hauer
  2015-07-16  8:50 ` [PATCH 01/11] ARM: i.MX6: Add i.MX6 entry function Sascha Hauer
@ 2015-07-16  8:50 ` Sascha Hauer
  2015-07-16  8:50 ` [PATCH 03/11] ARM: i.MX6: add function to get bootsource in pbl Sascha Hauer
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Sascha Hauer @ 2015-07-16  8:50 UTC (permalink / raw)
  To: Barebox List

Most files including imx6-mmdc.h do not actually use anything from
it. Clean this up.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/boards/datamodul-edm-qmx6/board.c     | 1 -
 arch/arm/boards/dfi-fs700-m60/lowlevel.c       | 1 -
 arch/arm/boards/embest-riotboard/lowlevel.c    | 1 -
 arch/arm/boards/phytec-phycard-imx6/lowlevel.c | 1 -
 arch/arm/boards/phytec-phyflex-imx6/lowlevel.c | 1 -
 arch/arm/boards/tqma6x/board.c                 | 1 -
 arch/arm/boards/tqma6x/lowlevel.c              | 1 -
 arch/arm/boards/variscite-mx6/lowlevel.c       | 1 -
 8 files changed, 8 deletions(-)

diff --git a/arch/arm/boards/datamodul-edm-qmx6/board.c b/arch/arm/boards/datamodul-edm-qmx6/board.c
index 81356e6..96c7fbe 100644
--- a/arch/arm/boards/datamodul-edm-qmx6/board.c
+++ b/arch/arm/boards/datamodul-edm-qmx6/board.c
@@ -38,7 +38,6 @@
 #include <mach/devices-imx6.h>
 #include <mach/imx6-regs.h>
 #include <mach/iomux-mx6.h>
-#include <mach/imx6-mmdc.h>
 #include <mach/generic.h>
 #include <mach/imx6.h>
 #include <mach/bbu.h>
diff --git a/arch/arm/boards/dfi-fs700-m60/lowlevel.c b/arch/arm/boards/dfi-fs700-m60/lowlevel.c
index b9b498e..a22f66a 100644
--- a/arch/arm/boards/dfi-fs700-m60/lowlevel.c
+++ b/arch/arm/boards/dfi-fs700-m60/lowlevel.c
@@ -19,7 +19,6 @@
 #include <asm/mmu.h>
 #include <asm/barebox-arm-head.h>
 #include <asm/barebox-arm.h>
-#include <mach/imx6-mmdc.h>
 #include <mach/imx6-regs.h>
 #include <mach/generic.h>
 
diff --git a/arch/arm/boards/embest-riotboard/lowlevel.c b/arch/arm/boards/embest-riotboard/lowlevel.c
index 59010da..d26bc98 100644
--- a/arch/arm/boards/embest-riotboard/lowlevel.c
+++ b/arch/arm/boards/embest-riotboard/lowlevel.c
@@ -7,7 +7,6 @@
 #include <asm/sections.h>
 #include <asm/cache.h>
 #include <asm/mmu.h>
-#include <mach/imx6-mmdc.h>
 #include <mach/imx6.h>
 
 extern char __dtb_imx6s_riotboard_start[];
diff --git a/arch/arm/boards/phytec-phycard-imx6/lowlevel.c b/arch/arm/boards/phytec-phycard-imx6/lowlevel.c
index d85a1ab..09ab645 100644
--- a/arch/arm/boards/phytec-phycard-imx6/lowlevel.c
+++ b/arch/arm/boards/phytec-phycard-imx6/lowlevel.c
@@ -21,7 +21,6 @@
 #include <asm/sections.h>
 #include <asm/cache.h>
 #include <asm/mmu.h>
-#include <mach/imx6-mmdc.h>
 #include <mach/imx6.h>
 
 static inline void setup_uart(void)
diff --git a/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c b/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c
index cd37f88..82c0244 100644
--- a/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c
+++ b/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c
@@ -22,7 +22,6 @@
 #include <asm/sections.h>
 #include <asm/cache.h>
 #include <asm/mmu.h>
-#include <mach/imx6-mmdc.h>
 #include <mach/imx6.h>
 
 static inline void setup_uart(void)
diff --git a/arch/arm/boards/tqma6x/board.c b/arch/arm/boards/tqma6x/board.c
index 97cce60..9c52c8a 100644
--- a/arch/arm/boards/tqma6x/board.c
+++ b/arch/arm/boards/tqma6x/board.c
@@ -38,7 +38,6 @@
 #include <mach/devices-imx6.h>
 #include <mach/imx6-regs.h>
 #include <mach/iomux-mx6.h>
-#include <mach/imx6-mmdc.h>
 #include <mach/generic.h>
 #include <mach/imx6.h>
 #include <mach/bbu.h>
diff --git a/arch/arm/boards/tqma6x/lowlevel.c b/arch/arm/boards/tqma6x/lowlevel.c
index aec84b1..52afee4 100644
--- a/arch/arm/boards/tqma6x/lowlevel.c
+++ b/arch/arm/boards/tqma6x/lowlevel.c
@@ -21,7 +21,6 @@
 #include <asm/sections.h>
 #include <asm/cache.h>
 #include <asm/mmu.h>
-#include <mach/imx6-mmdc.h>
 #include <mach/imx6.h>
 
 extern char __dtb_imx6q_mba6x_start[];
diff --git a/arch/arm/boards/variscite-mx6/lowlevel.c b/arch/arm/boards/variscite-mx6/lowlevel.c
index b0b930d..5cb738a 100644
--- a/arch/arm/boards/variscite-mx6/lowlevel.c
+++ b/arch/arm/boards/variscite-mx6/lowlevel.c
@@ -23,7 +23,6 @@
 #include <asm/sections.h>
 #include <asm/cache.h>
 #include <asm/mmu.h>
-#include <mach/imx6-mmdc.h>
 #include <mach/imx6.h>
 
 static inline void setup_uart(void)
-- 
2.1.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 03/11] ARM: i.MX6: add function to get bootsource in pbl
  2015-07-16  8:50 [PATCH] i.MX6 xload and Utilite support Sascha Hauer
  2015-07-16  8:50 ` [PATCH 01/11] ARM: i.MX6: Add i.MX6 entry function Sascha Hauer
  2015-07-16  8:50 ` [PATCH 02/11] ARM: i.MX6: remove unnecessary includes Sascha Hauer
@ 2015-07-16  8:50 ` Sascha Hauer
  2015-07-16  8:50 ` [PATCH 04/11] memsize: Compile for PBL aswell Sascha Hauer
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Sascha Hauer @ 2015-07-16  8:50 UTC (permalink / raw)
  To: Barebox List

In the pbl the regular bootsource_get cannot be used. Add a function
which returns the bootsource directly with values from the hardware.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-imx/boot.c                 | 38 ++++++++++++++++++--------------
 arch/arm/mach-imx/include/mach/generic.h |  2 ++
 2 files changed, 24 insertions(+), 16 deletions(-)

diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c
index 4416011..376e370 100644
--- a/arch/arm/mach-imx/boot.c
+++ b/arch/arm/mach-imx/boot.c
@@ -21,6 +21,7 @@
 #include <mach/generic.h>
 #include <mach/imx25-regs.h>
 #include <mach/imx35-regs.h>
+#include <mach/imx6-regs.h>
 
 /* [CTRL][TYPE] */
 static const enum bootsource locations[4][4] = {
@@ -214,10 +215,9 @@ void imx53_boot_save_loc(void __iomem *src_base)
 #define IMX6_SRC_SBMR1	0x04
 #define IMX6_SRC_SBMR2	0x1c
 
-void imx6_boot_save_loc(void __iomem *src_base)
+void imx6_get_boot_source(enum bootsource *src, int *instance)
 {
-	enum bootsource src = BOOTSOURCE_UNKNOWN;
-	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
+	void __iomem *src_base = IOMEM(MX6_SRC_BASE_ADDR);
 	uint32_t sbmr1 = readl(src_base + IMX6_SRC_SBMR1);
 	uint32_t sbmr2 = readl(src_base + IMX6_SRC_SBMR2);
 	uint32_t boot_cfg_4_2_0;
@@ -231,14 +231,12 @@ void imx6_boot_save_loc(void __iomem *src_base)
 	case 2: /* internal boot */
 		goto internal_boot;
 	case 1: /* Serial Downloader */
-		src = BOOTSOURCE_SERIAL;
+		*src = BOOTSOURCE_SERIAL;
 		break;
 	case 3: /* reserved */
 		break;
 	};
 
-	bootsource_set(src);
-
 	return;
 
 internal_boot:
@@ -246,28 +244,28 @@ internal_boot:
 	/* BOOT_CFG1[7:4] */
 	switch ((sbmr1 >> 4) & 0xf) {
 	case 2:
-		src = BOOTSOURCE_HD;
+		*src = BOOTSOURCE_HD;
 		break;
 	case 3:
 		/* BOOT_CFG4[2:0] */
 		boot_cfg_4_2_0 = (sbmr1 >> 24) & 0x7;
 
 		if (boot_cfg_4_2_0 > 4) {
-			src = BOOTSOURCE_I2C;
-			instance = boot_cfg_4_2_0 - 5;
+			*src = BOOTSOURCE_I2C;
+			*instance = boot_cfg_4_2_0 - 5;
 		} else {
-			src = BOOTSOURCE_SPI;
-			instance = boot_cfg_4_2_0;
+			*src = BOOTSOURCE_SPI;
+			*instance = boot_cfg_4_2_0;
 		}
 		break;
 	case 4:
 	case 5:
 	case 6:
 	case 7:
-		src = BOOTSOURCE_MMC;
+		*src = BOOTSOURCE_MMC;
 
 		/* BOOT_CFG2[4:3] */
-		instance = (sbmr1 >> 11) & 0x3;
+		*instance = (sbmr1 >> 11) & 0x3;
 		break;
 	default:
 		break;
@@ -275,10 +273,18 @@ internal_boot:
 
 	/* BOOT_CFG1[7:0] */
 	if (sbmr1 & (1 << 7))
-		src = BOOTSOURCE_NAND;
+		*src = BOOTSOURCE_NAND;
+
+	return;
+}
+
+void imx6_boot_save_loc(void __iomem *src_base)
+{
+	enum bootsource src = BOOTSOURCE_UNKNOWN;
+	int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
+
+	imx6_get_boot_source(&src, &instance);
 
 	bootsource_set(src);
 	bootsource_set_instance(instance);
-
-	return;
 }
diff --git a/arch/arm/mach-imx/include/mach/generic.h b/arch/arm/mach-imx/include/mach/generic.h
index d4b6a1f..46fe388 100644
--- a/arch/arm/mach-imx/include/mach/generic.h
+++ b/arch/arm/mach-imx/include/mach/generic.h
@@ -3,6 +3,7 @@
 
 #include <linux/compiler.h>
 #include <linux/types.h>
+#include <bootsource.h>
 
 u64 imx_uid(void);
 
@@ -12,6 +13,7 @@ void imx27_boot_save_loc(void __iomem *sysctrl_base);
 void imx51_boot_save_loc(void __iomem *src_base);
 void imx53_boot_save_loc(void __iomem *src_base);
 void imx6_boot_save_loc(void __iomem *src_base);
+void imx6_get_boot_source(enum bootsource *src, int *instance);
 
 int imx1_init(void);
 int imx21_init(void);
-- 
2.1.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 04/11] memsize: Compile for PBL aswell
  2015-07-16  8:50 [PATCH] i.MX6 xload and Utilite support Sascha Hauer
                   ` (2 preceding siblings ...)
  2015-07-16  8:50 ` [PATCH 03/11] ARM: i.MX6: add function to get bootsource in pbl Sascha Hauer
@ 2015-07-16  8:50 ` Sascha Hauer
  2015-07-16  8:50 ` [PATCH 05/11] ARM: i.MX: compile boot.c for pbl aswell Sascha Hauer
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Sascha Hauer @ 2015-07-16  8:50 UTC (permalink / raw)
  To: Barebox List

Detecting the memory size is a domain for PBL, so compile it for PBL
aswell.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 common/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/common/Makefile b/common/Makefile
index 74801f7..ed131c8 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -5,7 +5,7 @@ obj-y				+= clock.o
 obj-y				+= console_common.o
 obj-y				+= startup.o
 obj-y				+= misc.o
-obj-y				+= memsize.o
+obj-pbl-y			+= memsize.o
 obj-y				+= resource.o
 obj-y				+= bootsource.o
 obj-$(CONFIG_AUTO_COMPLETE)	+= complete.o
-- 
2.1.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 05/11] ARM: i.MX: compile boot.c for pbl aswell
  2015-07-16  8:50 [PATCH] i.MX6 xload and Utilite support Sascha Hauer
                   ` (3 preceding siblings ...)
  2015-07-16  8:50 ` [PATCH 04/11] memsize: Compile for PBL aswell Sascha Hauer
@ 2015-07-16  8:50 ` Sascha Hauer
  2015-07-16  8:50 ` [PATCH 06/11] ARM: i.MX6: create cpu_is() functions for use in PBL Sascha Hauer
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Sascha Hauer @ 2015-07-16  8:50 UTC (permalink / raw)
  To: Barebox List

As boot.c now contains code for the pbl compile compile it there
awell. While at it move esdctl.c to obj-pbl-y.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-imx/Makefile | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 458d7b4..9e21429 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -18,9 +18,8 @@ obj-$(CONFIG_IMX_OCOTP)	+= ocotp.o
 obj-$(CONFIG_NAND_IMX) += nand.o
 lwl-$(CONFIG_ARCH_IMX_EXTERNAL_BOOT_NAND) += external-nand-boot.o
 obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-pfd.o clk-gate2.o clk-gate-exclusive.o
-obj-y += devices.o imx.o esdctl.o
-obj-y += boot.o
+obj-y += devices.o imx.o
+obj-pbl-y += esdctl.o boot.o
 obj-$(CONFIG_BAREBOX_UPDATE) += imx-bbu-internal.o
 obj-$(CONFIG_BAREBOX_UPDATE_IMX_EXTERNAL_NAND) += imx-bbu-external-nand.o
-pbl-y += esdctl.o
 lwl-y += cpu_init.o
-- 
2.1.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 06/11] ARM: i.MX6: create cpu_is() functions for use in PBL
  2015-07-16  8:50 [PATCH] i.MX6 xload and Utilite support Sascha Hauer
                   ` (4 preceding siblings ...)
  2015-07-16  8:50 ` [PATCH 05/11] ARM: i.MX: compile boot.c for pbl aswell Sascha Hauer
@ 2015-07-16  8:50 ` Sascha Hauer
  2015-07-16  8:50 ` [PATCH 07/11] images: i.MX: Create target for SRAM images Sascha Hauer
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Sascha Hauer @ 2015-07-16  8:50 UTC (permalink / raw)
  To: Barebox List

The current cpu_is_mx6x() functions need the imx6_cpu_type variable
which make them unsuitable for PBL. Add a set of cpu_mx6_is_mx6x()
functions which can be called from PBL aswell. Unlike the cpu_is_mx6x()
functions the cpu_mx6_is_mx6x() functions assume that they are called on
i.MX6 only.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-imx/include/mach/imx6.h | 41 +++++++++++++++--------------------
 1 file changed, 17 insertions(+), 24 deletions(-)

diff --git a/arch/arm/mach-imx/include/mach/imx6.h b/arch/arm/mach-imx/include/mach/imx6.h
index 3b75421..3ddb6d2 100644
--- a/arch/arm/mach-imx/include/mach/imx6.h
+++ b/arch/arm/mach-imx/include/mach/imx6.h
@@ -48,29 +48,22 @@ static inline int imx6_cpu_type(void)
 	return __imx6_cpu_type();
 }
 
-static inline int cpu_is_mx6s(void)
-{
-	return imx6_cpu_type() == IMX6_CPUTYPE_IMX6S;
-}
-
-static inline int cpu_is_mx6dl(void)
-{
-	return imx6_cpu_type() == IMX6_CPUTYPE_IMX6DL;
-}
-
-static inline int cpu_is_mx6d(void)
-{
-	return imx6_cpu_type() == IMX6_CPUTYPE_IMX6D;
-}
-
-static inline int cpu_is_mx6q(void)
-{
-	return imx6_cpu_type() == IMX6_CPUTYPE_IMX6Q;
-}
-
-static inline int cpu_is_mx6sx(void)
-{
-	return imx6_cpu_type() == IMX6_CPUTYPE_IMX6SX;
-}
+#define DEFINE_MX6_CPU_TYPE(str, type)					\
+	static inline int cpu_mx6_is_##str(void)			\
+	{								\
+		return __imx6_cpu_type() == type;			\
+	}								\
+									\
+	static inline int cpu_is_##str(void)				\
+	{								\
+		if (!cpu_is_mx6())					\
+			return 0;					\
+		return cpu_mx6_is_##str();				\
+	}
+
+DEFINE_MX6_CPU_TYPE(mx6dl, IMX6_CPUTYPE_IMX6DL);
+DEFINE_MX6_CPU_TYPE(mx6q, IMX6_CPUTYPE_IMX6Q);
+DEFINE_MX6_CPU_TYPE(mx6d, IMX6_CPUTYPE_IMX6D);
+DEFINE_MX6_CPU_TYPE(mx6sx, IMX6_CPUTYPE_IMX6SX);
 
 #endif /* __MACH_IMX6_H */
-- 
2.1.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 07/11] images: i.MX: Create target for SRAM images
  2015-07-16  8:50 [PATCH] i.MX6 xload and Utilite support Sascha Hauer
                   ` (5 preceding siblings ...)
  2015-07-16  8:50 ` [PATCH 06/11] ARM: i.MX6: create cpu_is() functions for use in PBL Sascha Hauer
@ 2015-07-16  8:50 ` Sascha Hauer
  2015-07-16  8:50 ` [PATCH 08/11] spi: i.MX: move register defines to include/ Sascha Hauer
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Sascha Hauer @ 2015-07-16  8:50 UTC (permalink / raw)
  To: Barebox List

Some boards like to do their SDRAM setup in code rather than in hardcoded
DCD tables. For these boards the bootloader has to be loaded to the internal
SRAM which is often too small for a full featured barebox. This new SRAM
image type target allows to overcome this limitation. The image created
with the new imx-sram-img rule is a regular imx-image with the difference
that the load size only spans the pblx image and not the whole image including
the payload. The pbl image easily fits into SRAM. The strategy is that this
initial code initializes the SDRAM, loads the whole image to SDRAM and jumps
to it.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 images/Makefile.imx | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/images/Makefile.imx b/images/Makefile.imx
index 6b44958..cdbae8c 100644
--- a/images/Makefile.imx
+++ b/images/Makefile.imx
@@ -14,6 +14,17 @@ $(obj)/%.imximg: $(obj)/% FORCE
 	$(call if_changed,imx_image)
 endif
 
+quiet_cmd_imx_sram_img ?= IMX-SRAM-IMG    $@
+      cmd_imx_sram_img ?= cat $(obj)/$(patsubst %.imx-sram-img,%.pblb,$(2)) > $@; \
+		  $(call size_append, $(obj)/barebox.z) >> $@; \
+		  $(CPP) $(imxcfg_cpp_flags) -o $(imximg-tmp) $(CFG_$(@F)) ; \
+		  $(objtree)/scripts/imx/imx-image -o $@ -b -c $(imximg-tmp) -f $@; \
+		  cat $(obj)/barebox.z >> $@; \
+		  $(objtree)/scripts/fix_size -f $@
+
+$(obj)/%.imx-sram-img: $(obj)/%.pblb $(obj)/barebox.z FORCE
+	$(call if_changed,imx_sram_img,$(@F))
+
 # ----------------------- i.MX25 based boards ---------------------------
 pblx-$(CONFIG_MACH_TX25) += start_imx25_karo_tx25
 FILE_barebox-karo-tx25.img = start_imx25_karo_tx25.pblx
-- 
2.1.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 08/11] spi: i.MX: move register defines to include/
  2015-07-16  8:50 [PATCH] i.MX6 xload and Utilite support Sascha Hauer
                   ` (6 preceding siblings ...)
  2015-07-16  8:50 ` [PATCH 07/11] images: i.MX: Create target for SRAM images Sascha Hauer
@ 2015-07-16  8:50 ` Sascha Hauer
  2015-07-16  8:50 ` [PATCH 09/11] ARM: i.MX: Add SPI xload code Sascha Hauer
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Sascha Hauer @ 2015-07-16  8:50 UTC (permalink / raw)
  To: Barebox List

The register defines will be used by the SPI xload code, so move
them to a place where the xload code can include them.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/spi/imx_spi.c | 80 +------------------------------------------------
 include/spi/imx-spi.h | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 84 insertions(+), 79 deletions(-)
 create mode 100644 include/spi/imx-spi.h

diff --git a/drivers/spi/imx_spi.c b/drivers/spi/imx_spi.c
index be6a4fd..6805d22 100644
--- a/drivers/spi/imx_spi.c
+++ b/drivers/spi/imx_spi.c
@@ -18,6 +18,7 @@
 #include <init.h>
 #include <driver.h>
 #include <spi/spi.h>
+#include <spi/imx-spi.h>
 #include <xfuncs.h>
 #include <io.h>
 #include <of.h>
@@ -31,85 +32,6 @@
 #include <linux/err.h>
 #include <clock.h>
 
-#define CSPI_0_0_RXDATA		0x00
-#define CSPI_0_0_TXDATA		0x04
-#define CSPI_0_0_CTRL		0x08
-#define CSPI_0_0_INT		0x0C
-#define CSPI_0_0_DMA		0x18
-#define CSPI_0_0_STAT		0x0C
-#define CSPI_0_0_PERIOD		0x14
-#define CSPI_0_0_TEST		0x10
-#define CSPI_0_0_RESET		0x1C
-
-#define CSPI_0_0_CTRL_ENABLE		(1 << 10)
-#define CSPI_0_0_CTRL_MASTER		(1 << 11)
-#define CSPI_0_0_CTRL_XCH		(1 << 9)
-#define CSPI_0_0_CTRL_LOWPOL		(1 << 5)
-#define CSPI_0_0_CTRL_PHA		(1 << 6)
-#define CSPI_0_0_CTRL_SSCTL		(1 << 7)
-#define CSPI_0_0_CTRL_HIGHSSPOL 	(1 << 8)
-#define CSPI_0_0_CTRL_CS(x)		(((x) & 0x3) << 19)
-#define CSPI_0_0_CTRL_BITCOUNT(x)	(((x) & 0x1f) << 0)
-#define CSPI_0_0_CTRL_DATARATE(x)	(((x) & 0x7) << 14)
-
-#define CSPI_0_0_CTRL_MAXDATRATE	0x10
-#define CSPI_0_0_CTRL_DATAMASK		0x1F
-#define CSPI_0_0_CTRL_DATASHIFT 	14
-
-#define CSPI_0_0_STAT_TE		(1 << 0)
-#define CSPI_0_0_STAT_TH		(1 << 1)
-#define CSPI_0_0_STAT_TF		(1 << 2)
-#define CSPI_0_0_STAT_RR		(1 << 4)
-#define CSPI_0_0_STAT_RH		(1 << 5)
-#define CSPI_0_0_STAT_RF		(1 << 6)
-#define CSPI_0_0_STAT_RO		(1 << 7)
-
-#define CSPI_0_0_PERIOD_32KHZ		(1 << 15)
-
-#define CSPI_0_0_TEST_LBC		(1 << 14)
-
-#define CSPI_0_0_RESET_START		(1 << 0)
-
-#define CSPI_0_7_RXDATA			0x00
-#define CSPI_0_7_TXDATA			0x04
-#define CSPI_0_7_CTRL			0x08
-#define CSPI_0_7_CTRL_ENABLE		(1 << 0)
-#define CSPI_0_7_CTRL_MASTER		(1 << 1)
-#define CSPI_0_7_CTRL_XCH		(1 << 2)
-#define CSPI_0_7_CTRL_POL		(1 << 4)
-#define CSPI_0_7_CTRL_PHA		(1 << 5)
-#define CSPI_0_7_CTRL_SSCTL		(1 << 6)
-#define CSPI_0_7_CTRL_SSPOL		(1 << 7)
-#define CSPI_0_7_CTRL_CS_SHIFT		12
-#define CSPI_0_7_CTRL_DR_SHIFT		16
-#define CSPI_0_7_CTRL_BL_SHIFT		20
-#define CSPI_0_7_STAT			0x14
-#define CSPI_0_7_STAT_RR		(1 << 3)
-
-#define CSPI_2_3_RXDATA		0x00
-#define CSPI_2_3_TXDATA		0x04
-#define CSPI_2_3_CTRL		0x08
-#define CSPI_2_3_CTRL_ENABLE		(1 <<  0)
-#define CSPI_2_3_CTRL_XCH		(1 <<  2)
-#define CSPI_2_3_CTRL_MODE(cs)	(1 << ((cs) +  4))
-#define CSPI_2_3_CTRL_POSTDIV_OFFSET	8
-#define CSPI_2_3_CTRL_PREDIV_OFFSET	12
-#define CSPI_2_3_CTRL_CS(cs)		((cs) << 18)
-#define CSPI_2_3_CTRL_BL_OFFSET	20
-
-#define CSPI_2_3_CONFIG	0x0c
-#define CSPI_2_3_CONFIG_SCLKPHA(cs)	(1 << ((cs) +  0))
-#define CSPI_2_3_CONFIG_SCLKPOL(cs)	(1 << ((cs) +  4))
-#define CSPI_2_3_CONFIG_SBBCTRL(cs)	(1 << ((cs) +  8))
-#define CSPI_2_3_CONFIG_SSBPOL(cs)	(1 << ((cs) + 12))
-
-#define CSPI_2_3_INT		0x10
-#define CSPI_2_3_INT_TEEN		(1 <<  0)
-#define CSPI_2_3_INT_RREN		(1 <<  3)
-
-#define CSPI_2_3_STAT		0x18
-#define CSPI_2_3_STAT_RR		(1 <<  3)
-
 struct imx_spi {
 	struct spi_master	master;
 	int			*cs_array;
diff --git a/include/spi/imx-spi.h b/include/spi/imx-spi.h
new file mode 100644
index 0000000..560b092
--- /dev/null
+++ b/include/spi/imx-spi.h
@@ -0,0 +1,83 @@
+#ifndef __SPI_IMX_SPI_H
+#define __SPI_IMX_SPI_H
+
+#define CSPI_0_0_RXDATA		0x00
+#define CSPI_0_0_TXDATA		0x04
+#define CSPI_0_0_CTRL		0x08
+#define CSPI_0_0_INT		0x0C
+#define CSPI_0_0_DMA		0x18
+#define CSPI_0_0_STAT		0x0C
+#define CSPI_0_0_PERIOD		0x14
+#define CSPI_0_0_TEST		0x10
+#define CSPI_0_0_RESET		0x1C
+
+#define CSPI_0_0_CTRL_ENABLE		(1 << 10)
+#define CSPI_0_0_CTRL_MASTER		(1 << 11)
+#define CSPI_0_0_CTRL_XCH		(1 << 9)
+#define CSPI_0_0_CTRL_LOWPOL		(1 << 5)
+#define CSPI_0_0_CTRL_PHA		(1 << 6)
+#define CSPI_0_0_CTRL_SSCTL		(1 << 7)
+#define CSPI_0_0_CTRL_HIGHSSPOL 	(1 << 8)
+#define CSPI_0_0_CTRL_CS(x)		(((x) & 0x3) << 19)
+#define CSPI_0_0_CTRL_BITCOUNT(x)	(((x) & 0x1f) << 0)
+#define CSPI_0_0_CTRL_DATARATE(x)	(((x) & 0x7) << 14)
+
+#define CSPI_0_0_CTRL_MAXDATRATE	0x10
+#define CSPI_0_0_CTRL_DATAMASK		0x1F
+#define CSPI_0_0_CTRL_DATASHIFT 	14
+
+#define CSPI_0_0_STAT_TE		(1 << 0)
+#define CSPI_0_0_STAT_TH		(1 << 1)
+#define CSPI_0_0_STAT_TF		(1 << 2)
+#define CSPI_0_0_STAT_RR		(1 << 4)
+#define CSPI_0_0_STAT_RH		(1 << 5)
+#define CSPI_0_0_STAT_RF		(1 << 6)
+#define CSPI_0_0_STAT_RO		(1 << 7)
+
+#define CSPI_0_0_PERIOD_32KHZ		(1 << 15)
+
+#define CSPI_0_0_TEST_LBC		(1 << 14)
+
+#define CSPI_0_0_RESET_START		(1 << 0)
+
+#define CSPI_0_7_RXDATA			0x00
+#define CSPI_0_7_TXDATA			0x04
+#define CSPI_0_7_CTRL			0x08
+#define CSPI_0_7_CTRL_ENABLE		(1 << 0)
+#define CSPI_0_7_CTRL_MASTER		(1 << 1)
+#define CSPI_0_7_CTRL_XCH		(1 << 2)
+#define CSPI_0_7_CTRL_POL		(1 << 4)
+#define CSPI_0_7_CTRL_PHA		(1 << 5)
+#define CSPI_0_7_CTRL_SSCTL		(1 << 6)
+#define CSPI_0_7_CTRL_SSPOL		(1 << 7)
+#define CSPI_0_7_CTRL_CS_SHIFT		12
+#define CSPI_0_7_CTRL_DR_SHIFT		16
+#define CSPI_0_7_CTRL_BL_SHIFT		20
+#define CSPI_0_7_STAT			0x14
+#define CSPI_0_7_STAT_RR		(1 << 3)
+
+#define CSPI_2_3_RXDATA		0x00
+#define CSPI_2_3_TXDATA		0x04
+#define CSPI_2_3_CTRL		0x08
+#define CSPI_2_3_CTRL_ENABLE		(1 <<  0)
+#define CSPI_2_3_CTRL_XCH		(1 <<  2)
+#define CSPI_2_3_CTRL_MODE(cs)	(1 << ((cs) +  4))
+#define CSPI_2_3_CTRL_POSTDIV_OFFSET	8
+#define CSPI_2_3_CTRL_PREDIV_OFFSET	12
+#define CSPI_2_3_CTRL_CS(cs)		((cs) << 18)
+#define CSPI_2_3_CTRL_BL_OFFSET	20
+
+#define CSPI_2_3_CONFIG	0x0c
+#define CSPI_2_3_CONFIG_SCLKPHA(cs)	(1 << ((cs) +  0))
+#define CSPI_2_3_CONFIG_SCLKPOL(cs)	(1 << ((cs) +  4))
+#define CSPI_2_3_CONFIG_SBBCTRL(cs)	(1 << ((cs) +  8))
+#define CSPI_2_3_CONFIG_SSBPOL(cs)	(1 << ((cs) + 12))
+
+#define CSPI_2_3_INT		0x10
+#define CSPI_2_3_INT_TEEN		(1 <<  0)
+#define CSPI_2_3_INT_RREN		(1 <<  3)
+
+#define CSPI_2_3_STAT		0x18
+#define CSPI_2_3_STAT_RR		(1 <<  3)
+
+#endif /* __SPI_IMX_SPI_H */
-- 
2.1.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 09/11] ARM: i.MX: Add SPI xload code
  2015-07-16  8:50 [PATCH] i.MX6 xload and Utilite support Sascha Hauer
                   ` (7 preceding siblings ...)
  2015-07-16  8:50 ` [PATCH 08/11] spi: i.MX: move register defines to include/ Sascha Hauer
@ 2015-07-16  8:50 ` Sascha Hauer
  2015-07-16  8:50 ` [PATCH 10/11] ARM: i.MX6: Add DDR setup code from U-Boot Sascha Hauer
  2015-07-16  8:50 ` [PATCH 11/11] ARM: initial cm-fx6 support Sascha Hauer
  10 siblings, 0 replies; 12+ messages in thread
From: Sascha Hauer @ 2015-07-16  8:50 UTC (permalink / raw)
  To: Barebox List

Add PBL xload code to load an image from SPI NOR flash. Currently implemented
for i.MX6.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-imx/Makefile             |   1 +
 arch/arm/mach-imx/include/mach/xload.h |   7 ++
 arch/arm/mach-imx/xload-spi.c          | 160 +++++++++++++++++++++++++++++++++
 3 files changed, 168 insertions(+)
 create mode 100644 arch/arm/mach-imx/include/mach/xload.h
 create mode 100644 arch/arm/mach-imx/xload-spi.c

diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 9e21429..578676d 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -23,3 +23,4 @@ obj-pbl-y += esdctl.o boot.o
 obj-$(CONFIG_BAREBOX_UPDATE) += imx-bbu-internal.o
 obj-$(CONFIG_BAREBOX_UPDATE_IMX_EXTERNAL_NAND) += imx-bbu-external-nand.o
 lwl-y += cpu_init.o
+pbl-y += xload-spi.o
diff --git a/arch/arm/mach-imx/include/mach/xload.h b/arch/arm/mach-imx/include/mach/xload.h
new file mode 100644
index 0000000..278d148
--- /dev/null
+++ b/arch/arm/mach-imx/include/mach/xload.h
@@ -0,0 +1,7 @@
+#ifndef __MACH_XLOAD_H
+#define __MACH_XLOAD_H
+
+int imx6_spi_load_image(int instance, unsigned int flash_offset, void *buf, int len);
+int imx6_spi_start_image(int instance);
+
+#endif /* __MACH_XLOAD_H */
diff --git a/arch/arm/mach-imx/xload-spi.c b/arch/arm/mach-imx/xload-spi.c
new file mode 100644
index 0000000..a7556b1
--- /dev/null
+++ b/arch/arm/mach-imx/xload-spi.c
@@ -0,0 +1,160 @@
+#include <common.h>
+#include <io.h>
+#include <spi/imx-spi.h>
+#include <mach/imx6-regs.h>
+#include <mach/generic.h>
+#include <bootsource.h>
+#include <asm/sections.h>
+#include <linux/sizes.h>
+
+static int cspi_2_3_read_data(void __iomem *base, u32 *data)
+{
+	u32 r;
+
+	while (1) {
+		if (readl(base + CSPI_2_3_STAT) & CSPI_2_3_STAT_RR)
+			break;
+	}
+
+	r = swab32(readl(base + CSPI_2_3_RXDATA));
+	if (data)
+		*data = r;
+
+	return 0;
+}
+
+static int cspi_2_3_load(void __iomem *base, unsigned int flash_offset, void *buf, int len)
+{
+	int transfer_size = 256;
+	u32 val;
+	int words, adr = 0;
+	int ret;
+
+	val = readl(base + CSPI_2_3_CTRL);
+	val &= ~(0xfff << CSPI_2_3_CTRL_BL_OFFSET);
+	val |= CSPI_2_3_CTRL_ENABLE;
+	writel(val, base + CSPI_2_3_CTRL);
+
+	writel(val, base + CSPI_2_3_CTRL);
+
+	for (adr = 0; adr < len; adr += transfer_size) {
+
+		val |= ((transfer_size + 4) * 8 - 1) << CSPI_2_3_CTRL_BL_OFFSET;
+		writel(val, base + CSPI_2_3_CTRL);
+
+		/* address */
+		writel(swab32(0x3) | (adr + flash_offset), base + CSPI_2_3_TXDATA);
+		writel(val | CSPI_2_3_CTRL_XCH, base + CSPI_2_3_CTRL);
+
+		ret = cspi_2_3_read_data(base, NULL);
+		if (ret)
+			return ret;
+
+		words = 0;
+
+		for (words = 0; words < transfer_size >> 2; words++) {
+			writel(0, base + CSPI_2_3_TXDATA);
+			cspi_2_3_read_data(base, buf);
+			buf += 4;
+		}
+	}
+
+	return 0;
+}
+
+static int imx_image_size(void)
+{
+	uint32_t *image_end = (void *)ld_var(__image_end);
+	uint32_t payload_len, pbl_len, imx_header_len, sizep;
+	void *pg_start;
+
+	pg_start = image_end + 1;
+
+	/* i.MX header is 4k */
+	imx_header_len = SZ_4K;
+
+	/* The length of the PBL image */
+	pbl_len = ld_var(__image_end) - ld_var(_text);
+
+	sizep = 4;
+
+	/* The length of the payload is appended directly behind the PBL */
+	payload_len = *(image_end);
+
+	pr_debug("%s: payload_len: 0x%08x pbl_len: 0x%08x\n",
+			__func__, payload_len, pbl_len);
+
+	return imx_header_len + pbl_len + sizep + payload_len;
+}
+
+/**
+ * imx6_spi_load_image - load an image from SPI NOR
+ * @instance: The SPI controller instance (0..4)
+ * @flash_offset: The offset in flash where the image starts
+ * @buf: The buffer to load the image to
+ * @len: The size to load
+ *
+ * This function loads data from SPI NOR flash on i.MX6. This assumes the
+ * SPI controller has already been initialized and the pinctrl / clocks are
+ * configured correctly. This is the case when the ROM has loaded the initial
+ * portion of the boot loader from exactly this controller.
+ *
+ * Return: 0 if successful, negative error code otherwise
+ */
+int imx6_spi_load_image(int instance, unsigned int flash_offset, void *buf, int len)
+{
+	void *base;
+
+	switch (instance) {
+	case 0:
+		base = IOMEM(MX6_ECSPI1_BASE_ADDR);
+		break;
+	case 1:
+		base = IOMEM(MX6_ECSPI2_BASE_ADDR);
+		break;
+	case 2:
+		base = IOMEM(MX6_ECSPI3_BASE_ADDR);
+		break;
+	case 3:
+		base = IOMEM(MX6_ECSPI4_BASE_ADDR);
+		break;
+	case 4:
+		base = IOMEM(MX6_ECSPI5_BASE_ADDR);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	cspi_2_3_load(base, flash_offset, buf, len);
+
+	return 0;
+}
+
+/**
+ * imx6_spi_start_image - Load and start an image from SPI NOR flash
+ * @instance: The SPI controller instance (0..4)
+ *
+ * This uses imx6_spi_load_image() to load an image from SPI NOR flash.
+ * It is assumed that the image is the currently running barebox image
+ * (This information is used to calculate the length of the image). The
+ * image is started afterwards.
+ *
+ * Return: If successul, this function does not return. A negative error
+ * code is returned when this function fails.
+ */
+int imx6_spi_start_image(int instance)
+{
+	void *buf = (void *)0x10000000;
+	int ret, len;
+	void __noreturn (*bb)(void);
+
+	len = imx_image_size();
+
+	ret = imx6_spi_load_image(instance, 0, buf, len);
+	if (ret)
+		return ret;
+
+	bb = buf;
+
+	bb();
+}
-- 
2.1.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 10/11] ARM: i.MX6: Add DDR setup code from U-Boot
  2015-07-16  8:50 [PATCH] i.MX6 xload and Utilite support Sascha Hauer
                   ` (8 preceding siblings ...)
  2015-07-16  8:50 ` [PATCH 09/11] ARM: i.MX: Add SPI xload code Sascha Hauer
@ 2015-07-16  8:50 ` Sascha Hauer
  2015-07-16  8:50 ` [PATCH 11/11] ARM: initial cm-fx6 support Sascha Hauer
  10 siblings, 0 replies; 12+ messages in thread
From: Sascha Hauer @ 2015-07-16  8:50 UTC (permalink / raw)
  To: Barebox List

Several i.MX6 boards like to do their SDRAM setup in code rather than
in DCD tables. Add the SDRAM setup code from U-Boot to make it easy
to adopt the SDRAM setup from the U-Boot port of these boards.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-imx/imx6-mmdc.c              | 544 +++++++++++++++++++++++++++++
 arch/arm/mach-imx/include/mach/imx6-mmdc.h | 274 +++++++++++++++
 2 files changed, 818 insertions(+)

diff --git a/arch/arm/mach-imx/imx6-mmdc.c b/arch/arm/mach-imx/imx6-mmdc.c
index c460d9b..fb81a15 100644
--- a/arch/arm/mach-imx/imx6-mmdc.c
+++ b/arch/arm/mach-imx/imx6-mmdc.c
@@ -18,6 +18,8 @@
 #include <common.h>
 #include <io.h>
 #include <mach/imx6-mmdc.h>
+#include <mach/imx6-regs.h>
+#include <mach/imx6.h>
 
 int mmdc_do_write_level_calibration(void)
 {
@@ -841,3 +843,545 @@ int mmdc_do_software_calibration(void)
 }
 
 #endif /* MMDC_SOFTWARE_CALIBRATION */
+
+/* Configure MX6SX mmdc iomux */
+void mx6sx_dram_iocfg(unsigned width,
+		      const struct mx6sx_iomux_ddr_regs *ddr,
+		      const struct mx6sx_iomux_grp_regs *grp)
+{
+	struct mx6sx_iomux_ddr_regs *mx6_ddr_iomux;
+	struct mx6sx_iomux_grp_regs *mx6_grp_iomux;
+
+	mx6_ddr_iomux = (struct mx6sx_iomux_ddr_regs *)MX6SX_IOM_DDR_BASE;
+	mx6_grp_iomux = (struct mx6sx_iomux_grp_regs *)MX6SX_IOM_GRP_BASE;
+
+	/* DDR IO TYPE */
+	writel(grp->grp_ddr_type, &mx6_grp_iomux->grp_ddr_type);
+	writel(grp->grp_ddrpke, &mx6_grp_iomux->grp_ddrpke);
+
+	/* CLOCK */
+	writel(ddr->dram_sdclk_0, &mx6_ddr_iomux->dram_sdclk_0);
+
+	/* ADDRESS */
+	writel(ddr->dram_cas, &mx6_ddr_iomux->dram_cas);
+	writel(ddr->dram_ras, &mx6_ddr_iomux->dram_ras);
+	writel(grp->grp_addds, &mx6_grp_iomux->grp_addds);
+
+	/* Control */
+	writel(ddr->dram_reset, &mx6_ddr_iomux->dram_reset);
+	writel(ddr->dram_sdba2, &mx6_ddr_iomux->dram_sdba2);
+	writel(ddr->dram_sdcke0, &mx6_ddr_iomux->dram_sdcke0);
+	writel(ddr->dram_sdcke1, &mx6_ddr_iomux->dram_sdcke1);
+	writel(ddr->dram_odt0, &mx6_ddr_iomux->dram_odt0);
+	writel(ddr->dram_odt1, &mx6_ddr_iomux->dram_odt1);
+	writel(grp->grp_ctlds, &mx6_grp_iomux->grp_ctlds);
+
+	/* Data Strobes */
+	writel(grp->grp_ddrmode_ctl, &mx6_grp_iomux->grp_ddrmode_ctl);
+	writel(ddr->dram_sdqs0, &mx6_ddr_iomux->dram_sdqs0);
+	writel(ddr->dram_sdqs1, &mx6_ddr_iomux->dram_sdqs1);
+	if (width >= 32) {
+		writel(ddr->dram_sdqs2, &mx6_ddr_iomux->dram_sdqs2);
+		writel(ddr->dram_sdqs3, &mx6_ddr_iomux->dram_sdqs3);
+	}
+
+	/* Data */
+	writel(grp->grp_ddrmode, &mx6_grp_iomux->grp_ddrmode);
+	writel(grp->grp_b0ds, &mx6_grp_iomux->grp_b0ds);
+	writel(grp->grp_b1ds, &mx6_grp_iomux->grp_b1ds);
+	if (width >= 32) {
+		writel(grp->grp_b2ds, &mx6_grp_iomux->grp_b2ds);
+		writel(grp->grp_b3ds, &mx6_grp_iomux->grp_b3ds);
+	}
+	writel(ddr->dram_dqm0, &mx6_ddr_iomux->dram_dqm0);
+	writel(ddr->dram_dqm1, &mx6_ddr_iomux->dram_dqm1);
+	if (width >= 32) {
+		writel(ddr->dram_dqm2, &mx6_ddr_iomux->dram_dqm2);
+		writel(ddr->dram_dqm3, &mx6_ddr_iomux->dram_dqm3);
+	}
+}
+
+/* Configure MX6DQ mmdc iomux */
+void mx6dq_dram_iocfg(unsigned width,
+		      const struct mx6dq_iomux_ddr_regs *ddr,
+		      const struct mx6dq_iomux_grp_regs *grp)
+{
+	volatile struct mx6dq_iomux_ddr_regs *mx6_ddr_iomux;
+	volatile struct mx6dq_iomux_grp_regs *mx6_grp_iomux;
+
+	mx6_ddr_iomux = (struct mx6dq_iomux_ddr_regs *)MX6DQ_IOM_DDR_BASE;
+	mx6_grp_iomux = (struct mx6dq_iomux_grp_regs *)MX6DQ_IOM_GRP_BASE;
+
+	/* DDR IO Type */
+	mx6_grp_iomux->grp_ddr_type = grp->grp_ddr_type;
+	mx6_grp_iomux->grp_ddrpke = grp->grp_ddrpke;
+
+	/* Clock */
+	mx6_ddr_iomux->dram_sdclk_0 = ddr->dram_sdclk_0;
+	mx6_ddr_iomux->dram_sdclk_1 = ddr->dram_sdclk_1;
+
+	/* Address */
+	mx6_ddr_iomux->dram_cas = ddr->dram_cas;
+	mx6_ddr_iomux->dram_ras = ddr->dram_ras;
+	mx6_grp_iomux->grp_addds = grp->grp_addds;
+
+	/* Control */
+	mx6_ddr_iomux->dram_reset = ddr->dram_reset;
+	mx6_ddr_iomux->dram_sdcke0 = ddr->dram_sdcke0;
+	mx6_ddr_iomux->dram_sdcke1 = ddr->dram_sdcke1;
+	mx6_ddr_iomux->dram_sdba2 = ddr->dram_sdba2;
+	mx6_ddr_iomux->dram_sdodt0 = ddr->dram_sdodt0;
+	mx6_ddr_iomux->dram_sdodt1 = ddr->dram_sdodt1;
+	mx6_grp_iomux->grp_ctlds = grp->grp_ctlds;
+
+	/* Data Strobes */
+	mx6_grp_iomux->grp_ddrmode_ctl = grp->grp_ddrmode_ctl;
+	mx6_ddr_iomux->dram_sdqs0 = ddr->dram_sdqs0;
+	mx6_ddr_iomux->dram_sdqs1 = ddr->dram_sdqs1;
+	if (width >= 32) {
+		mx6_ddr_iomux->dram_sdqs2 = ddr->dram_sdqs2;
+		mx6_ddr_iomux->dram_sdqs3 = ddr->dram_sdqs3;
+	}
+	if (width >= 64) {
+		mx6_ddr_iomux->dram_sdqs4 = ddr->dram_sdqs4;
+		mx6_ddr_iomux->dram_sdqs5 = ddr->dram_sdqs5;
+		mx6_ddr_iomux->dram_sdqs6 = ddr->dram_sdqs6;
+		mx6_ddr_iomux->dram_sdqs7 = ddr->dram_sdqs7;
+	}
+
+	/* Data */
+	mx6_grp_iomux->grp_ddrmode = grp->grp_ddrmode;
+	mx6_grp_iomux->grp_b0ds = grp->grp_b0ds;
+	mx6_grp_iomux->grp_b1ds = grp->grp_b1ds;
+	if (width >= 32) {
+		mx6_grp_iomux->grp_b2ds = grp->grp_b2ds;
+		mx6_grp_iomux->grp_b3ds = grp->grp_b3ds;
+	}
+	if (width >= 64) {
+		mx6_grp_iomux->grp_b4ds = grp->grp_b4ds;
+		mx6_grp_iomux->grp_b5ds = grp->grp_b5ds;
+		mx6_grp_iomux->grp_b6ds = grp->grp_b6ds;
+		mx6_grp_iomux->grp_b7ds = grp->grp_b7ds;
+	}
+	mx6_ddr_iomux->dram_dqm0 = ddr->dram_dqm0;
+	mx6_ddr_iomux->dram_dqm1 = ddr->dram_dqm1;
+	if (width >= 32) {
+		mx6_ddr_iomux->dram_dqm2 = ddr->dram_dqm2;
+		mx6_ddr_iomux->dram_dqm3 = ddr->dram_dqm3;
+	}
+	if (width >= 64) {
+		mx6_ddr_iomux->dram_dqm4 = ddr->dram_dqm4;
+		mx6_ddr_iomux->dram_dqm5 = ddr->dram_dqm5;
+		mx6_ddr_iomux->dram_dqm6 = ddr->dram_dqm6;
+		mx6_ddr_iomux->dram_dqm7 = ddr->dram_dqm7;
+	}
+}
+
+/* Configure MX6SDL mmdc iomux */
+void mx6sdl_dram_iocfg(unsigned width,
+		       const struct mx6sdl_iomux_ddr_regs *ddr,
+		       const struct mx6sdl_iomux_grp_regs *grp)
+{
+	volatile struct mx6sdl_iomux_ddr_regs *mx6_ddr_iomux;
+	volatile struct mx6sdl_iomux_grp_regs *mx6_grp_iomux;
+
+	mx6_ddr_iomux = (struct mx6sdl_iomux_ddr_regs *)MX6SDL_IOM_DDR_BASE;
+	mx6_grp_iomux = (struct mx6sdl_iomux_grp_regs *)MX6SDL_IOM_GRP_BASE;
+
+	/* DDR IO Type */
+	mx6_grp_iomux->grp_ddr_type = grp->grp_ddr_type;
+	mx6_grp_iomux->grp_ddrpke = grp->grp_ddrpke;
+
+	/* Clock */
+	mx6_ddr_iomux->dram_sdclk_0 = ddr->dram_sdclk_0;
+	mx6_ddr_iomux->dram_sdclk_1 = ddr->dram_sdclk_1;
+
+	/* Address */
+	mx6_ddr_iomux->dram_cas = ddr->dram_cas;
+	mx6_ddr_iomux->dram_ras = ddr->dram_ras;
+	mx6_grp_iomux->grp_addds = grp->grp_addds;
+
+	/* Control */
+	mx6_ddr_iomux->dram_reset = ddr->dram_reset;
+	mx6_ddr_iomux->dram_sdcke0 = ddr->dram_sdcke0;
+	mx6_ddr_iomux->dram_sdcke1 = ddr->dram_sdcke1;
+	mx6_ddr_iomux->dram_sdba2 = ddr->dram_sdba2;
+	mx6_ddr_iomux->dram_sdodt0 = ddr->dram_sdodt0;
+	mx6_ddr_iomux->dram_sdodt1 = ddr->dram_sdodt1;
+	mx6_grp_iomux->grp_ctlds = grp->grp_ctlds;
+
+	/* Data Strobes */
+	mx6_grp_iomux->grp_ddrmode_ctl = grp->grp_ddrmode_ctl;
+	mx6_ddr_iomux->dram_sdqs0 = ddr->dram_sdqs0;
+	mx6_ddr_iomux->dram_sdqs1 = ddr->dram_sdqs1;
+	if (width >= 32) {
+		mx6_ddr_iomux->dram_sdqs2 = ddr->dram_sdqs2;
+		mx6_ddr_iomux->dram_sdqs3 = ddr->dram_sdqs3;
+	}
+	if (width >= 64) {
+		mx6_ddr_iomux->dram_sdqs4 = ddr->dram_sdqs4;
+		mx6_ddr_iomux->dram_sdqs5 = ddr->dram_sdqs5;
+		mx6_ddr_iomux->dram_sdqs6 = ddr->dram_sdqs6;
+		mx6_ddr_iomux->dram_sdqs7 = ddr->dram_sdqs7;
+	}
+
+	/* Data */
+	mx6_grp_iomux->grp_ddrmode = grp->grp_ddrmode;
+	mx6_grp_iomux->grp_b0ds = grp->grp_b0ds;
+	mx6_grp_iomux->grp_b1ds = grp->grp_b1ds;
+	if (width >= 32) {
+		mx6_grp_iomux->grp_b2ds = grp->grp_b2ds;
+		mx6_grp_iomux->grp_b3ds = grp->grp_b3ds;
+	}
+	if (width >= 64) {
+		mx6_grp_iomux->grp_b4ds = grp->grp_b4ds;
+		mx6_grp_iomux->grp_b5ds = grp->grp_b5ds;
+		mx6_grp_iomux->grp_b6ds = grp->grp_b6ds;
+		mx6_grp_iomux->grp_b7ds = grp->grp_b7ds;
+	}
+	mx6_ddr_iomux->dram_dqm0 = ddr->dram_dqm0;
+	mx6_ddr_iomux->dram_dqm1 = ddr->dram_dqm1;
+	if (width >= 32) {
+		mx6_ddr_iomux->dram_dqm2 = ddr->dram_dqm2;
+		mx6_ddr_iomux->dram_dqm3 = ddr->dram_dqm3;
+	}
+	if (width >= 64) {
+		mx6_ddr_iomux->dram_dqm4 = ddr->dram_dqm4;
+		mx6_ddr_iomux->dram_dqm5 = ddr->dram_dqm5;
+		mx6_ddr_iomux->dram_dqm6 = ddr->dram_dqm6;
+		mx6_ddr_iomux->dram_dqm7 = ddr->dram_dqm7;
+	}
+}
+
+static void __udelay(int us)
+{
+	volatile int i;
+
+	for (i = 0; i < us * 1000; i++);
+}
+
+/*
+ * Configure mx6 mmdc registers based on:
+ *  - board-specific memory configuration
+ *  - board-specific calibration data
+ *  - ddr3 chip details
+ *
+ * The various calculations here are derived from the Freescale
+ * i.Mx6DQSDL DDR3 Script Aid spreadsheet (DOC-94917) designed to generate MMDC
+ * configuration registers based on memory system and memory chip parameters.
+ *
+ * The defaults here are those which were specified in the spreadsheet.
+ * For details on each register, refer to the IMX6DQRM and/or IMX6SDLRM
+ * section titled MMDC initialization
+ */
+#define MR(val, ba, cmd, cs1) \
+	((val << 16) | (1 << 15) | (cmd << 4) | (cs1 << 3) | ba)
+
+#define ROUND(a,b)              (((a) + (b) - 1) & ~((b) - 1))
+
+void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
+		  const struct mx6_mmdc_calibration *calib,
+		  const struct mx6_ddr3_cfg *ddr3_cfg)
+{
+	volatile struct mmdc_p_regs *mmdc0;
+	volatile struct mmdc_p_regs *mmdc1;
+
+	u32 val;
+	u8 tcke, tcksrx, tcksre, txpdll, taofpd, taonpd, trrd;
+	u8 todtlon, taxpd, tanpd, tcwl, txp, tfaw, tcl;
+	u8 todt_idle_off = 0x4; /* from DDR3 Script Aid spreadsheet */
+	u16 trcd, trc, tras, twr, tmrd, trtp, trp, twtr, trfc, txs, txpr;
+	u16 cs0_end;
+	u16 tdllk = 0x1ff; /* DLL locking time: 512 cycles (JEDEC DDR3) */
+	u8 coladdr;
+	int clkper; /* clock period in picoseconds */
+	int clock; /* clock freq in MHz */
+	int cs;
+	u16 mem_speed = ddr3_cfg->mem_speed;
+
+	mmdc0 = (struct mmdc_p_regs *)MX6_MMDC_P0_BASE_ADDR;
+	mmdc1 = (struct mmdc_p_regs *)MX6_MMDC_P1_BASE_ADDR;
+
+	/* Limit mem_speed for MX6D/MX6Q */
+	if (cpu_mx6_is_mx6q() || cpu_mx6_is_mx6d()) {
+		if (mem_speed > 1066)
+			mem_speed = 1066; /* 1066 MT/s */
+
+		tcwl = 4;
+	}
+	/* Limit mem_speed for MX6S/MX6DL */
+	else {
+		if (mem_speed > 800)
+			mem_speed = 800;  /* 800 MT/s */
+
+		tcwl = 3;
+	}
+
+	clock = mem_speed / 2;
+	/*
+	 * Data rate of 1066 MT/s requires 533 MHz DDR3 clock, but MX6D/Q supports
+	 * up to 528 MHz, so reduce the clock to fit chip specs
+	 */
+	if (cpu_mx6_is_mx6q() || cpu_mx6_is_mx6d()) {
+		if (clock > 528)
+			clock = 528; /* 528 MHz */
+	}
+
+	clkper = (1000 * 1000) / clock; /* pico seconds */
+	todtlon = tcwl;
+	taxpd = tcwl;
+	tanpd = tcwl;
+
+	switch (ddr3_cfg->density) {
+	case 1: /* 1Gb per chip */
+		trfc = DIV_ROUND_UP(110000, clkper) - 1;
+		txs = DIV_ROUND_UP(120000, clkper) - 1;
+		break;
+	case 2: /* 2Gb per chip */
+		trfc = DIV_ROUND_UP(160000, clkper) - 1;
+		txs = DIV_ROUND_UP(170000, clkper) - 1;
+		break;
+	case 4: /* 4Gb per chip */
+		trfc = DIV_ROUND_UP(260000, clkper) - 1;
+		txs = DIV_ROUND_UP(270000, clkper) - 1;
+		break;
+	case 8: /* 8Gb per chip */
+		trfc = DIV_ROUND_UP(350000, clkper) - 1;
+		txs = DIV_ROUND_UP(360000, clkper) - 1;
+		break;
+	default:
+		/* invalid density */
+		pr_err("invalid chip density\n");
+		hang();
+		break;
+	}
+	txpr = txs;
+
+	switch (mem_speed) {
+	case 800:
+		txp = DIV_ROUND_UP(max(3 * clkper, 7500), clkper) - 1;
+		tcke = DIV_ROUND_UP(max(3 * clkper, 7500), clkper) - 1;
+		if (ddr3_cfg->pagesz == 1) {
+			tfaw = DIV_ROUND_UP(40000, clkper) - 1;
+			trrd = DIV_ROUND_UP(max(4 * clkper, 10000), clkper) - 1;
+		} else {
+			tfaw = DIV_ROUND_UP(50000, clkper) - 1;
+			trrd = DIV_ROUND_UP(max(4 * clkper, 10000), clkper) - 1;
+		}
+		break;
+	case 1066:
+		txp = DIV_ROUND_UP(max(3 * clkper, 7500), clkper) - 1;
+		tcke = DIV_ROUND_UP(max(3 * clkper, 5625), clkper) - 1;
+		if (ddr3_cfg->pagesz == 1) {
+			tfaw = DIV_ROUND_UP(37500, clkper) - 1;
+			trrd = DIV_ROUND_UP(max(4 * clkper, 7500), clkper) - 1;
+		} else {
+			tfaw = DIV_ROUND_UP(50000, clkper) - 1;
+			trrd = DIV_ROUND_UP(max(4 * clkper, 10000), clkper) - 1;
+		}
+		break;
+	default:
+		pr_err("invalid memory speed\n");
+		hang();
+		break;
+	}
+	txpdll = DIV_ROUND_UP(max(10 * clkper, 24000), clkper) - 1;
+	tcksre = DIV_ROUND_UP(max(5 * clkper, 10000), clkper);
+	taonpd = DIV_ROUND_UP(2000, clkper) - 1;
+	tcksrx = tcksre;
+	taofpd = taonpd;
+	twr  = DIV_ROUND_UP(15000, clkper) - 1;
+	tmrd = DIV_ROUND_UP(max(12 * clkper, 15000), clkper) - 1;
+	trc  = DIV_ROUND_UP(ddr3_cfg->trcmin, clkper / 10) - 1;
+	tras = DIV_ROUND_UP(ddr3_cfg->trasmin, clkper / 10) - 1;
+	tcl  = DIV_ROUND_UP(ddr3_cfg->trcd, clkper / 10) - 3;
+	trp  = DIV_ROUND_UP(ddr3_cfg->trcd, clkper / 10) - 1;
+	twtr = ROUND(max(4 * clkper, 7500) / clkper, 1) - 1;
+	trcd = trp;
+	trtp = twtr;
+	cs0_end = 4 * sysinfo->cs_density - 1;
+
+	debug("density:%d Gb (%d Gb per chip)\n",
+	      sysinfo->cs_density, ddr3_cfg->density);
+	debug("clock: %dMHz (%d ps)\n", clock, clkper);
+	debug("memspd:%d\n", mem_speed);
+	debug("tcke=%d\n", tcke);
+	debug("tcksrx=%d\n", tcksrx);
+	debug("tcksre=%d\n", tcksre);
+	debug("taofpd=%d\n", taofpd);
+	debug("taonpd=%d\n", taonpd);
+	debug("todtlon=%d\n", todtlon);
+	debug("tanpd=%d\n", tanpd);
+	debug("taxpd=%d\n", taxpd);
+	debug("trfc=%d\n", trfc);
+	debug("txs=%d\n", txs);
+	debug("txp=%d\n", txp);
+	debug("txpdll=%d\n", txpdll);
+	debug("tfaw=%d\n", tfaw);
+	debug("tcl=%d\n", tcl);
+	debug("trcd=%d\n", trcd);
+	debug("trp=%d\n", trp);
+	debug("trc=%d\n", trc);
+	debug("tras=%d\n", tras);
+	debug("twr=%d\n", twr);
+	debug("tmrd=%d\n", tmrd);
+	debug("tcwl=%d\n", tcwl);
+	debug("tdllk=%d\n", tdllk);
+	debug("trtp=%d\n", trtp);
+	debug("twtr=%d\n", twtr);
+	debug("trrd=%d\n", trrd);
+	debug("txpr=%d\n", txpr);
+	debug("cs0_end=%d\n", cs0_end);
+	debug("ncs=%d\n", sysinfo->ncs);
+	debug("Rtt_wr=%d\n", sysinfo->rtt_wr);
+	debug("Rtt_nom=%d\n", sysinfo->rtt_nom);
+	debug("SRT=%d\n", ddr3_cfg->SRT);
+	debug("tcl=%d\n", tcl);
+	debug("twr=%d\n", twr);
+
+	/*
+	 * board-specific configuration:
+	 *  These values are determined empirically and vary per board layout
+	 *  see:
+	 *   appnote, ddr3 spreadsheet
+	 */
+	mmdc0->mpwldectrl0 = calib->p0_mpwldectrl0;
+	mmdc0->mpwldectrl1 = calib->p0_mpwldectrl1;
+	mmdc0->mpdgctrl0 = calib->p0_mpdgctrl0;
+	mmdc0->mpdgctrl1 = calib->p0_mpdgctrl1;
+	mmdc0->mprddlctl = calib->p0_mprddlctl;
+	mmdc0->mpwrdlctl = calib->p0_mpwrdlctl;
+	if (sysinfo->dsize > 1) {
+		mmdc1->mpwldectrl0 = calib->p1_mpwldectrl0;
+		mmdc1->mpwldectrl1 = calib->p1_mpwldectrl1;
+		mmdc1->mpdgctrl0 = calib->p1_mpdgctrl0;
+		mmdc1->mpdgctrl1 = calib->p1_mpdgctrl1;
+		mmdc1->mprddlctl = calib->p1_mprddlctl;
+		mmdc1->mpwrdlctl = calib->p1_mpwrdlctl;
+	}
+
+	/* Read data DQ Byte0-3 delay */
+	mmdc0->mprddqby0dl = 0x33333333;
+	mmdc0->mprddqby1dl = 0x33333333;
+	if (sysinfo->dsize > 0) {
+		mmdc0->mprddqby2dl = 0x33333333;
+		mmdc0->mprddqby3dl = 0x33333333;
+	}
+
+	if (sysinfo->dsize > 1) {
+		mmdc1->mprddqby0dl = 0x33333333;
+		mmdc1->mprddqby1dl = 0x33333333;
+		mmdc1->mprddqby2dl = 0x33333333;
+		mmdc1->mprddqby3dl = 0x33333333;
+	}
+
+	/* MMDC Termination: rtt_nom:2 RZQ/2(120ohm), rtt_nom:1 RZQ/4(60ohm) */
+	val = (sysinfo->rtt_nom == 2) ? 0x00011117 : 0x00022227;
+	mmdc0->mpodtctrl = val;
+	if (sysinfo->dsize > 1)
+		mmdc1->mpodtctrl = val;
+
+	/* complete calibration */
+	val = (1 << 11); /* Force measurement on delay-lines */
+	mmdc0->mpmur0 = val;
+	if (sysinfo->dsize > 1)
+		mmdc1->mpmur0 = val;
+
+	/* Step 1: configuration request */
+	mmdc0->mdscr = (u32)(1 << 15); /* config request */
+
+	/* Step 2: Timing configuration */
+	mmdc0->mdcfg0 = (trfc << 24) | (txs << 16) | (txp << 13) |
+			(txpdll << 9) | (tfaw << 4) | tcl;
+	mmdc0->mdcfg1 = (trcd << 29) | (trp << 26) | (trc << 21) |
+			(tras << 16) | (1 << 15) /* trpa */ |
+			(twr << 9) | (tmrd << 5) | tcwl;
+	mmdc0->mdcfg2 = (tdllk << 16) | (trtp << 6) | (twtr << 3) | trrd;
+	mmdc0->mdotc = (taofpd << 27) | (taonpd << 24) | (tanpd << 20) |
+		       (taxpd << 16) | (todtlon << 12) | (todt_idle_off << 4);
+	mmdc0->mdasp = cs0_end; /* CS addressing */
+
+	/* Step 3: Configure DDR type */
+	mmdc0->mdmisc = (sysinfo->cs1_mirror << 19) | (sysinfo->walat << 16) |
+			(sysinfo->bi_on << 12) | (sysinfo->mif3_mode << 9) |
+			(sysinfo->ralat << 6);
+
+	/* Step 4: Configure delay while leaving reset */
+	mmdc0->mdor = (txpr << 16) | (sysinfo->sde_to_rst << 8) |
+		      (sysinfo->rst_to_cke << 0);
+
+	/* Step 5: Configure DDR physical parameters (density and burst len) */
+	coladdr = ddr3_cfg->coladdr;
+	if (ddr3_cfg->coladdr == 8)		/* 8-bit COL is 0x3 */
+		coladdr += 4;
+	else if (ddr3_cfg->coladdr == 12)	/* 12-bit COL is 0x4 */
+		coladdr += 1;
+	mmdc0->mdctl =  (ddr3_cfg->rowaddr - 11) << 24 |	/* ROW */
+			(coladdr - 9) << 20 |			/* COL */
+			(1 << 19) |		/* Burst Length = 8 for DDR3 */
+			(sysinfo->dsize << 16);		/* DDR data bus size */
+
+	/* Step 6: Perform ZQ calibration */
+	val = 0xa1390001; /* one-time HW ZQ calib */
+	mmdc0->mpzqhwctrl = val;
+	if (sysinfo->dsize > 1)
+		mmdc1->mpzqhwctrl = val;
+
+	/* Step 7: Enable MMDC with desired chip select */
+	mmdc0->mdctl |= (1 << 31) |			     /* SDE_0 for CS0 */
+			((sysinfo->ncs == 2) ? 1 : 0) << 30; /* SDE_1 for CS1 */
+
+	/* Step 8: Write Mode Registers to Init DDR3 devices */
+	for (cs = 0; cs < sysinfo->ncs; cs++) {
+		/* MR2 */
+		val = (sysinfo->rtt_wr & 3) << 9 | (ddr3_cfg->SRT & 1) << 7 |
+		      ((tcwl - 3) & 3) << 3;
+		debug("MR2 CS%d: 0x%08x\n", cs, (u32)MR(val, 2, 3, cs));
+		mmdc0->mdscr = MR(val, 2, 3, cs);
+		/* MR3 */
+		debug("MR3 CS%d: 0x%08x\n", cs, (u32)MR(0, 3, 3, cs));
+		mmdc0->mdscr = MR(0, 3, 3, cs);
+		/* MR1 */
+		val = ((sysinfo->rtt_nom & 1) ? 1 : 0) << 2 |
+		      ((sysinfo->rtt_nom & 2) ? 1 : 0) << 6;
+		debug("MR1 CS%d: 0x%08x\n", cs, (u32)MR(val, 1, 3, cs));
+		mmdc0->mdscr = MR(val, 1, 3, cs);
+		/* MR0 */
+		val = ((tcl - 1) << 4) |	/* CAS */
+		      (1 << 8)   |		/* DLL Reset */
+		      ((twr - 3) << 9) |	/* Write Recovery */
+		      (sysinfo->pd_fast_exit << 12); /* Precharge PD PLL on */
+		debug("MR0 CS%d: 0x%08x\n", cs, (u32)MR(val, 0, 3, cs));
+		mmdc0->mdscr = MR(val, 0, 3, cs);
+		/* ZQ calibration */
+		val = (1 << 10);
+		mmdc0->mdscr = MR(val, 0, 4, cs);
+	}
+
+	/* Step 10: Power down control and self-refresh */
+	mmdc0->mdpdc = (tcke & 0x7) << 16 |
+			5            << 12 |  /* PWDT_1: 256 cycles */
+			5            <<  8 |  /* PWDT_0: 256 cycles */
+			1            <<  6 |  /* BOTH_CS_PD */
+			(tcksrx & 0x7) << 3 |
+			(tcksre & 0x7);
+	if (!sysinfo->pd_fast_exit)
+		mmdc0->mdpdc |= (1 << 7); /* SLOW_PD */
+	mmdc0->mapsr = 0x00001006; /* ADOPT power down enabled */
+
+	/* Step 11: Configure ZQ calibration: one-time and periodic 1ms */
+	val = 0xa1390003;
+	mmdc0->mpzqhwctrl = val;
+	if (sysinfo->dsize > 1)
+		mmdc1->mpzqhwctrl = val;
+
+	/* Step 12: Configure and activate periodic refresh */
+	mmdc0->mdref = (1 << 14) | /* REF_SEL: Periodic refresh cycle: 32kHz */
+		       (7 << 11);  /* REFR: Refresh Rate - 8 refreshes */
+
+	/* Step 13: Deassert config request - init complete */
+	mmdc0->mdscr = 0x00000000;
+
+	/* wait for auto-ZQ calibration to complete */
+	__udelay(100);
+}
diff --git a/arch/arm/mach-imx/include/mach/imx6-mmdc.h b/arch/arm/mach-imx/include/mach/imx6-mmdc.h
index 6ab8049..9385b34 100644
--- a/arch/arm/mach-imx/include/mach/imx6-mmdc.h
+++ b/arch/arm/mach-imx/include/mach/imx6-mmdc.h
@@ -54,4 +54,278 @@ int mmdc_do_write_level_calibration(void);
 int mmdc_do_dqs_calibration(void);
 void mmdc_print_calibration_results(void);
 
+/* MMDC P0/P1 Registers */
+struct mmdc_p_regs {
+	u32 mdctl;
+	u32 mdpdc;
+	u32 mdotc;
+	u32 mdcfg0;
+	u32 mdcfg1;
+	u32 mdcfg2;
+	u32 mdmisc;
+	u32 mdscr;
+	u32 mdref;
+	u32 res1[2];
+	u32 mdrwd;
+	u32 mdor;
+	u32 res2[3];
+	u32 mdasp;
+	u32 res3[240];
+	u32 mapsr;
+	u32 res4[254];
+	u32 mpzqhwctrl;
+	u32 res5[2];
+	u32 mpwldectrl0;
+	u32 mpwldectrl1;
+	u32 res6;
+	u32 mpodtctrl;
+	u32 mprddqby0dl;
+	u32 mprddqby1dl;
+	u32 mprddqby2dl;
+	u32 mprddqby3dl;
+	u32 res7[4];
+	u32 mpdgctrl0;
+	u32 mpdgctrl1;
+	u32 res8;
+	u32 mprddlctl;
+	u32 res9;
+	u32 mpwrdlctl;
+	u32 res10[25];
+	u32 mpmur0;
+};
+
+#define MX6SX_IOM_DDR_BASE	0x020e0200
+struct mx6sx_iomux_ddr_regs {
+	u32 res1[59];
+	u32 dram_dqm0;
+	u32 dram_dqm1;
+	u32 dram_dqm2;
+	u32 dram_dqm3;
+	u32 dram_ras;
+	u32 dram_cas;
+	u32 res2[2];
+	u32 dram_sdwe_b;
+	u32 dram_odt0;
+	u32 dram_odt1;
+	u32 dram_sdba0;
+	u32 dram_sdba1;
+	u32 dram_sdba2;
+	u32 dram_sdcke0;
+	u32 dram_sdcke1;
+	u32 dram_sdclk_0;
+	u32 dram_sdqs0;
+	u32 dram_sdqs1;
+	u32 dram_sdqs2;
+	u32 dram_sdqs3;
+	u32 dram_reset;
+};
+
+#define MX6SX_IOM_GRP_BASE	0x020e0500
+struct mx6sx_iomux_grp_regs {
+	u32 res1[61];
+	u32 grp_addds;
+	u32 grp_ddrmode_ctl;
+	u32 grp_ddrpke;
+	u32 grp_ddrpk;
+	u32 grp_ddrhys;
+	u32 grp_ddrmode;
+	u32 grp_b0ds;
+	u32 grp_b1ds;
+	u32 grp_ctlds;
+	u32 grp_ddr_type;
+	u32 grp_b2ds;
+	u32 grp_b3ds;
+};
+
+/*
+ * MMDC iomux registers (pinctl/padctl) - (different for IMX6DQ vs IMX6SDL)
+ */
+#define MX6DQ_IOM_DDR_BASE      0x020e0500
+struct mx6dq_iomux_ddr_regs {
+	u32 res1[3];
+	u32 dram_sdqs5;
+	u32 dram_dqm5;
+	u32 dram_dqm4;
+	u32 dram_sdqs4;
+	u32 dram_sdqs3;
+	u32 dram_dqm3;
+	u32 dram_sdqs2;
+	u32 dram_dqm2;
+	u32 res2[16];
+	u32 dram_cas;
+	u32 res3[2];
+	u32 dram_ras;
+	u32 dram_reset;
+	u32 res4[2];
+	u32 dram_sdclk_0;
+	u32 dram_sdba2;
+	u32 dram_sdcke0;
+	u32 dram_sdclk_1;
+	u32 dram_sdcke1;
+	u32 dram_sdodt0;
+	u32 dram_sdodt1;
+	u32 res5;
+	u32 dram_sdqs0;
+	u32 dram_dqm0;
+	u32 dram_sdqs1;
+	u32 dram_dqm1;
+	u32 dram_sdqs6;
+	u32 dram_dqm6;
+	u32 dram_sdqs7;
+	u32 dram_dqm7;
+};
+
+#define MX6DQ_IOM_GRP_BASE      0x020e0700
+struct mx6dq_iomux_grp_regs {
+	u32 res1[18];
+	u32 grp_b7ds;
+	u32 grp_addds;
+	u32 grp_ddrmode_ctl;
+	u32 res2;
+	u32 grp_ddrpke;
+	u32 res3[6];
+	u32 grp_ddrmode;
+	u32 res4[3];
+	u32 grp_b0ds;
+	u32 grp_b1ds;
+	u32 grp_ctlds;
+	u32 res5;
+	u32 grp_b2ds;
+	u32 grp_ddr_type;
+	u32 grp_b3ds;
+	u32 grp_b4ds;
+	u32 grp_b5ds;
+	u32 grp_b6ds;
+};
+
+#define MX6SDL_IOM_DDR_BASE     0x020e0400
+struct mx6sdl_iomux_ddr_regs {
+	u32 res1[25];
+	u32 dram_cas;
+	u32 res2[2];
+	u32 dram_dqm0;
+	u32 dram_dqm1;
+	u32 dram_dqm2;
+	u32 dram_dqm3;
+	u32 dram_dqm4;
+	u32 dram_dqm5;
+	u32 dram_dqm6;
+	u32 dram_dqm7;
+	u32 dram_ras;
+	u32 dram_reset;
+	u32 res3[2];
+	u32 dram_sdba2;
+	u32 dram_sdcke0;
+	u32 dram_sdcke1;
+	u32 dram_sdclk_0;
+	u32 dram_sdclk_1;
+	u32 dram_sdodt0;
+	u32 dram_sdodt1;
+	u32 dram_sdqs0;
+	u32 dram_sdqs1;
+	u32 dram_sdqs2;
+	u32 dram_sdqs3;
+	u32 dram_sdqs4;
+	u32 dram_sdqs5;
+	u32 dram_sdqs6;
+	u32 dram_sdqs7;
+};
+
+#define MX6SDL_IOM_GRP_BASE     0x020e0700
+struct mx6sdl_iomux_grp_regs {
+	u32 res1[18];
+	u32 grp_b7ds;
+	u32 grp_addds;
+	u32 grp_ddrmode_ctl;
+	u32 grp_ddrpke;
+	u32 res2[2];
+	u32 grp_ddrmode;
+	u32 grp_b0ds;
+	u32 res3;
+	u32 grp_ctlds;
+	u32 grp_b1ds;
+	u32 grp_ddr_type;
+	u32 grp_b2ds;
+	u32 grp_b3ds;
+	u32 grp_b4ds;
+	u32 grp_b5ds;
+	u32 res4;
+	u32 grp_b6ds;
+};
+
+/* Device Information: Varies per DDR3 part number and speed grade */
+struct mx6_ddr3_cfg {
+	u16 mem_speed;	/* ie 1600 for DDR3-1600 (800,1066,1333,1600) */
+	u8 density;	/* chip density (Gb) (1,2,4,8) */
+	u8 width;	/* bus width (bits) (4,8,16) */
+	u8 banks;	/* number of banks */
+	u8 rowaddr;	/* row address bits (11-16)*/
+	u8 coladdr;	/* col address bits (9-12) */
+	u8 pagesz;	/* page size (K) (1-2) */
+	u16 trcd;	/* tRCD=tRP=CL (ns*100) */
+	u16 trcmin;	/* tRC min (ns*100) */
+	u16 trasmin;	/* tRAS min (ns*100) */
+	u8 SRT;		/* self-refresh temperature: 0=normal, 1=extended */
+};
+
+/* System Information: Varies per board design, layout, and term choices */
+struct mx6_ddr_sysinfo {
+	u8 dsize;	/* size of bus (in dwords: 0=16bit,1=32bit,2=64bit) */
+	u8 cs_density;	/* density per chip select (Gb) */
+	u8 ncs;		/* number chip selects used (1|2) */
+	char cs1_mirror;/* enable address mirror (0|1) */
+	char bi_on;	/* Bank interleaving enable */
+	u8 rtt_nom;	/* Rtt_Nom (DDR3_RTT_*) */
+	u8 rtt_wr;	/* Rtt_Wr (DDR3_RTT_*) */
+	u8 ralat;	/* Read Additional Latency (0-7) */
+	u8 walat;	/* Write Additional Latency (0-3) */
+	u8 mif3_mode;	/* Command prediction working mode */
+	u8 rst_to_cke;	/* Time from SDE enable to CKE rise */
+	u8 sde_to_rst;	/* Time from SDE enable until DDR reset# is high */
+	u8 pd_fast_exit;/* enable precharge powerdown fast-exit */
+};
+
+/*
+ * Board specific calibration:
+ *   This includes write leveling calibration values as well as DQS gating
+ *   and read/write delays. These values are board/layout/device specific.
+ *   Freescale recommends using the i.MX6 DDR Stress Test Tool V1.0.2
+ *   (DOC-96412) to determine these values over a range of boards and
+ *   temperatures.
+ */
+struct mx6_mmdc_calibration {
+	/* write leveling calibration */
+	u32 p0_mpwldectrl0;
+	u32 p0_mpwldectrl1;
+	u32 p1_mpwldectrl0;
+	u32 p1_mpwldectrl1;
+	/* read DQS gating */
+	u32 p0_mpdgctrl0;
+	u32 p0_mpdgctrl1;
+	u32 p1_mpdgctrl0;
+	u32 p1_mpdgctrl1;
+	/* read delay */
+	u32 p0_mprddlctl;
+	u32 p1_mprddlctl;
+	/* write delay */
+	u32 p0_mpwrdlctl;
+	u32 p1_mpwrdlctl;
+};
+
+/* configure iomux (pinctl/padctl) */
+void mx6dq_dram_iocfg(unsigned width,
+		      const struct mx6dq_iomux_ddr_regs *,
+		      const struct mx6dq_iomux_grp_regs *);
+void mx6sdl_dram_iocfg(unsigned width,
+		       const struct mx6sdl_iomux_ddr_regs *,
+		       const struct mx6sdl_iomux_grp_regs *);
+void mx6sx_dram_iocfg(unsigned width,
+		      const struct mx6sx_iomux_ddr_regs *,
+		      const struct mx6sx_iomux_grp_regs *);
+
+/* configure mx6 mmdc registers */
+void mx6_dram_cfg(const struct mx6_ddr_sysinfo *,
+		  const struct mx6_mmdc_calibration *,
+		  const struct mx6_ddr3_cfg *);
+
 #endif /* __MACH_MMDC_H */
-- 
2.1.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 11/11] ARM: initial cm-fx6 support
  2015-07-16  8:50 [PATCH] i.MX6 xload and Utilite support Sascha Hauer
                   ` (9 preceding siblings ...)
  2015-07-16  8:50 ` [PATCH 10/11] ARM: i.MX6: Add DDR setup code from U-Boot Sascha Hauer
@ 2015-07-16  8:50 ` Sascha Hauer
  10 siblings, 0 replies; 12+ messages in thread
From: Sascha Hauer @ 2015-07-16  8:50 UTC (permalink / raw)
  To: Barebox List

The cm-fx6 board is a module from Compulab with different i.MX6 SoCs.
This module is also found in the Utilite Mini Computer this patch
also adds support for.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/boards/Makefile                           |   1 +
 arch/arm/boards/cm-fx6/Makefile                    |   3 +
 arch/arm/boards/cm-fx6/board.c                     |  74 ++++
 .../boards/cm-fx6/flash-header-mx6-cm-fx6.imxcfg   |   3 +
 arch/arm/boards/cm-fx6/lowlevel.c                  | 363 ++++++++++++++++
 arch/arm/configs/imx_v7_defconfig                  |   1 +
 arch/arm/dts/Makefile                              |   1 +
 arch/arm/dts/imx6q-cm-fx6.dts                      |  29 ++
 arch/arm/dts/imx6q-cm-fx6.dtsi                     |  99 +++++
 arch/arm/dts/imx6q-utilite.dts                     |  42 ++
 arch/arm/dts/imx6qdl-cm-fx6.dtsi                   | 463 +++++++++++++++++++++
 arch/arm/mach-imx/Kconfig                          |   4 +
 images/Makefile.imx                                |  10 +
 13 files changed, 1093 insertions(+)
 create mode 100644 arch/arm/boards/cm-fx6/Makefile
 create mode 100644 arch/arm/boards/cm-fx6/board.c
 create mode 100644 arch/arm/boards/cm-fx6/flash-header-mx6-cm-fx6.imxcfg
 create mode 100644 arch/arm/boards/cm-fx6/lowlevel.c
 create mode 100644 arch/arm/dts/imx6q-cm-fx6.dts
 create mode 100644 arch/arm/dts/imx6q-cm-fx6.dtsi
 create mode 100644 arch/arm/dts/imx6q-utilite.dts
 create mode 100644 arch/arm/dts/imx6qdl-cm-fx6.dtsi

diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile
index d6fc17c..013229d 100644
--- a/arch/arm/boards/Makefile
+++ b/arch/arm/boards/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_MACH_AT91SAM9X5EK)			+= at91sam9x5ek/
 obj-$(CONFIG_MACH_BEAGLE)			+= beagle/
 obj-$(CONFIG_MACH_BEAGLEBONE)			+= beaglebone/
 obj-$(CONFIG_MACH_CANON_A1100)			+= canon-a1100/
+obj-$(CONFIG_MACH_CM_FX6)			+= cm-fx6/
 obj-$(CONFIG_MACH_NITROGEN6X)			+= boundarydevices-nitrogen6x/
 obj-$(CONFIG_MACH_CCMX51)			+= ccxmx51/
 obj-$(CONFIG_MACH_CFA10036)			+= crystalfontz-cfa10036/
diff --git a/arch/arm/boards/cm-fx6/Makefile b/arch/arm/boards/cm-fx6/Makefile
new file mode 100644
index 0000000..3a773bb
--- /dev/null
+++ b/arch/arm/boards/cm-fx6/Makefile
@@ -0,0 +1,3 @@
+obj-y += board.o
+extra-y += flash-header-mx6-cm-fx6.dcd.S flash-header-mx6-cm-fx6.dcd
+lwl-y += lowlevel.o
diff --git a/arch/arm/boards/cm-fx6/board.c b/arch/arm/boards/cm-fx6/board.c
new file mode 100644
index 0000000..a681dea
--- /dev/null
+++ b/arch/arm/boards/cm-fx6/board.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2015 Sascha Hauer, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <common.h>
+#include <init.h>
+#include <environment.h>
+#include <mach/imx6-regs.h>
+#include <mach/bbu.h>
+#include <asm/armlinux.h>
+#include <linux/phy.h>
+#include <mach/generic.h>
+#include <linux/sizes.h>
+#include <mach/imx6.h>
+
+static int phy_fixup(struct phy_device *phydev)
+{
+	unsigned short val;
+
+	/* Ar8031 phy SmartEEE feature cause link status generates glitch,
+	 * which cause ethernet link down/up issue, so disable SmartEEE
+	 */
+	phy_write(phydev, 0xd, 0x3);
+	phy_write(phydev, 0xe, 0x805d);
+	phy_write(phydev, 0xd, 0x4003);
+	val = phy_read(phydev, 0xe);
+	val &= ~(0x1 << 8);
+	phy_write(phydev, 0xe, val);
+
+	/* To enable AR8031 ouput a 125MHz clk from CLK_25M */
+	phy_write(phydev, 0xd, 0x7);
+	phy_write(phydev, 0xe, 0x8016);
+	phy_write(phydev, 0xd, 0x4007);
+
+	val = phy_read(phydev, 0xe);
+	val &= 0xffe3;
+	val |= 0x18;
+	phy_write(phydev, 0xe, val);
+
+	/* introduce tx clock delay */
+	phy_write(phydev, 0x1d, 0x5);
+	val = phy_read(phydev, 0x1e);
+	val |= 0x0100;
+	phy_write(phydev, 0x1e, val);
+
+	return 0;
+}
+
+#define PHY_ID_AR8031	0x004dd074
+
+static int cm_fx6_devices_init(void)
+{
+	if (!of_machine_is_compatible("compulab,cm-fx6"))
+		return 0;
+
+	if (IS_ENABLED(CONFIG_PHYLIB))
+		phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffff, phy_fixup);
+
+	imx6_bbu_internal_spi_i2c_register_handler("spiflash", "/dev/m25p0",
+		BBU_HANDLER_FLAG_DEFAULT);
+
+	return 0;
+}
+coredevice_initcall(cm_fx6_devices_init);
diff --git a/arch/arm/boards/cm-fx6/flash-header-mx6-cm-fx6.imxcfg b/arch/arm/boards/cm-fx6/flash-header-mx6-cm-fx6.imxcfg
new file mode 100644
index 0000000..400a870
--- /dev/null
+++ b/arch/arm/boards/cm-fx6/flash-header-mx6-cm-fx6.imxcfg
@@ -0,0 +1,3 @@
+soc imx6
+loadaddr 0x00907000
+dcdofs 0x400
diff --git a/arch/arm/boards/cm-fx6/lowlevel.c b/arch/arm/boards/cm-fx6/lowlevel.c
new file mode 100644
index 0000000..9c5c33c
--- /dev/null
+++ b/arch/arm/boards/cm-fx6/lowlevel.c
@@ -0,0 +1,363 @@
+#define pr_fmt(fmt) "cm-fx6: " fmt
+
+#include <common.h>
+#include <linux/sizes.h>
+#include <mach/generic.h>
+#include <asm/barebox-arm-head.h>
+#include <asm/barebox-arm.h>
+#include <debug_ll.h>
+#include <io.h>
+#include <mach/imx6-mmdc.h>
+#include <mach/imx6-ddr-regs.h>
+#include <mach/imx6.h>
+#include <mach/xload.h>
+#include <mach/esdctl.h>
+
+enum ddr_config {
+	DDR_16BIT_256MB,
+	DDR_32BIT_512MB,
+	DDR_32BIT_1GB,
+	DDR_64BIT_1GB,
+	DDR_64BIT_2GB,
+	DDR_64BIT_4GB,
+	DDR_UNKNOWN,
+};
+
+static void __udelay(int us)
+{
+	volatile int i;
+
+	for (i = 0; i < us * 1000; i++);
+}
+
+/*
+ * Below DRAM_RESET[DDR_SEL] = 0 which is incorrect according to
+ * Freescale QRM, but this is exactly the value used by the automatic
+ * calibration script and it works also in all our tests, so we leave
+ * it as is at this point.
+ */
+#define CM_FX6_DDR_IOMUX_CFG \
+	.dram_sdqs0	= 0x00000038, \
+	.dram_sdqs1	= 0x00000038, \
+	.dram_sdqs2	= 0x00000038, \
+	.dram_sdqs3	= 0x00000038, \
+	.dram_sdqs4	= 0x00000038, \
+	.dram_sdqs5	= 0x00000038, \
+	.dram_sdqs6	= 0x00000038, \
+	.dram_sdqs7	= 0x00000038, \
+	.dram_dqm0	= 0x00000038, \
+	.dram_dqm1	= 0x00000038, \
+	.dram_dqm2	= 0x00000038, \
+	.dram_dqm3	= 0x00000038, \
+	.dram_dqm4	= 0x00000038, \
+	.dram_dqm5	= 0x00000038, \
+	.dram_dqm6	= 0x00000038, \
+	.dram_dqm7	= 0x00000038, \
+	.dram_cas	= 0x00000038, \
+	.dram_ras	= 0x00000038, \
+	.dram_sdclk_0	= 0x00000038, \
+	.dram_sdclk_1	= 0x00000038, \
+	.dram_sdcke0	= 0x00003000, \
+	.dram_sdcke1	= 0x00003000, \
+	.dram_reset	= 0x00000038, \
+	.dram_sdba2	= 0x00000000, \
+	.dram_sdodt0	= 0x00000038, \
+	.dram_sdodt1	= 0x00000038,
+
+#define CM_FX6_GPR_IOMUX_CFG \
+	.grp_b0ds	= 0x00000038, \
+	.grp_b1ds	= 0x00000038, \
+	.grp_b2ds	= 0x00000038, \
+	.grp_b3ds	= 0x00000038, \
+	.grp_b4ds	= 0x00000038, \
+	.grp_b5ds	= 0x00000038, \
+	.grp_b6ds	= 0x00000038, \
+	.grp_b7ds	= 0x00000038, \
+	.grp_addds	= 0x00000038, \
+	.grp_ddrmode_ctl = 0x00020000, \
+	.grp_ddrpke	= 0x00000000, \
+	.grp_ddrmode	= 0x00020000, \
+	.grp_ctlds	= 0x00000038, \
+	.grp_ddr_type	= 0x000C0000,
+
+static struct mx6sdl_iomux_ddr_regs ddr_iomux_s = { CM_FX6_DDR_IOMUX_CFG };
+static struct mx6sdl_iomux_grp_regs grp_iomux_s = { CM_FX6_GPR_IOMUX_CFG };
+static struct mx6dq_iomux_ddr_regs ddr_iomux_q = { CM_FX6_DDR_IOMUX_CFG };
+static struct mx6dq_iomux_grp_regs grp_iomux_q = { CM_FX6_GPR_IOMUX_CFG };
+
+static struct mx6_mmdc_calibration cm_fx6_calib_s = {
+	.p0_mpwldectrl0	= 0x005B0061,
+	.p0_mpwldectrl1	= 0x004F0055,
+	.p0_mpdgctrl0	= 0x0314030C,
+	.p0_mpdgctrl1	= 0x025C0268,
+	.p0_mprddlctl	= 0x42464646,
+	.p0_mpwrdlctl	= 0x36322C34,
+};
+
+static struct mx6_ddr_sysinfo cm_fx6_sysinfo_s = {
+	.cs1_mirror	= 1,
+	.cs_density	= 16,
+	.bi_on		= 1,
+	.rtt_nom	= 1,
+	.rtt_wr		= 0,
+	.ralat		= 5,
+	.walat		= 1,
+	.mif3_mode	= 3,
+	.rst_to_cke	= 0x23,
+	.sde_to_rst	= 0x10,
+};
+
+static struct mx6_ddr3_cfg cm_fx6_ddr3_cfg_s = {
+	.mem_speed	= 800,
+	.density	= 4,
+	.rowaddr	= 14,
+	.coladdr	= 10,
+	.pagesz		= 2,
+	.trcd		= 1800,
+	.trcmin		= 5200,
+	.trasmin	= 3600,
+	.SRT		= 0,
+};
+
+static void spl_mx6s_dram_init(enum ddr_config dram_config, bool reset)
+{
+	if (reset)
+		((struct mmdc_p_regs *)MX6_MMDC_P0_MDCTL)->mdmisc = 2;
+
+	switch (dram_config) {
+	case DDR_16BIT_256MB:
+		cm_fx6_sysinfo_s.dsize = 0;
+		cm_fx6_sysinfo_s.ncs = 1;
+		break;
+	case DDR_32BIT_512MB:
+		cm_fx6_sysinfo_s.dsize = 1;
+		cm_fx6_sysinfo_s.ncs = 1;
+		break;
+	case DDR_32BIT_1GB:
+		cm_fx6_sysinfo_s.dsize = 1;
+		cm_fx6_sysinfo_s.ncs = 2;
+		break;
+	default:
+		pr_err("Tried to setup invalid DDR configuration\n");
+		hang();
+	}
+
+	mx6_dram_cfg(&cm_fx6_sysinfo_s, &cm_fx6_calib_s, &cm_fx6_ddr3_cfg_s);
+	__udelay(100);
+}
+
+static struct mx6_mmdc_calibration cm_fx6_calib_q = {
+	.p0_mpwldectrl0	= 0x00630068,
+	.p0_mpwldectrl1	= 0x0068005D,
+	.p0_mpdgctrl0	= 0x04140428,
+	.p0_mpdgctrl1	= 0x037C037C,
+	.p0_mprddlctl	= 0x3C30303A,
+	.p0_mpwrdlctl	= 0x3A344038,
+	.p1_mpwldectrl0	= 0x0035004C,
+	.p1_mpwldectrl1	= 0x00170026,
+	.p1_mpdgctrl0	= 0x0374037C,
+	.p1_mpdgctrl1	= 0x0350032C,
+	.p1_mprddlctl	= 0x30322A3C,
+	.p1_mpwrdlctl	= 0x48304A3E,
+};
+
+static struct mx6_ddr_sysinfo cm_fx6_sysinfo_q = {
+	.cs_density	= 16,
+	.cs1_mirror	= 1,
+	.bi_on		= 1,
+	.rtt_nom	= 1,
+	.rtt_wr		= 0,
+	.ralat		= 5,
+	.walat		= 1,
+	.mif3_mode	= 3,
+	.rst_to_cke	= 0x23,
+	.sde_to_rst	= 0x10,
+};
+
+static struct mx6_ddr3_cfg cm_fx6_ddr3_cfg_q = {
+	.mem_speed	= 1066,
+	.density	= 4,
+	.rowaddr	= 14,
+	.coladdr	= 10,
+	.pagesz		= 2,
+	.trcd		= 1324,
+	.trcmin		= 59500,
+	.trasmin	= 9750,
+	.SRT		= 0,
+};
+
+static void spl_mx6q_dram_init(enum ddr_config dram_config, bool reset)
+{
+	if (reset)
+		((struct mmdc_p_regs *)MX6_MMDC_P0_MDCTL)->mdmisc = 2;
+
+	cm_fx6_ddr3_cfg_q.rowaddr = 14;
+	switch (dram_config) {
+	case DDR_16BIT_256MB:
+		cm_fx6_sysinfo_q.dsize = 0;
+		cm_fx6_sysinfo_q.ncs = 1;
+		break;
+	case DDR_32BIT_512MB:
+		cm_fx6_sysinfo_q.dsize = 1;
+		cm_fx6_sysinfo_q.ncs = 1;
+		break;
+	case DDR_64BIT_1GB:
+		cm_fx6_sysinfo_q.dsize = 2;
+		cm_fx6_sysinfo_q.ncs = 1;
+		break;
+	case DDR_64BIT_2GB:
+		cm_fx6_sysinfo_q.dsize = 2;
+		cm_fx6_sysinfo_q.ncs = 2;
+		break;
+	case DDR_64BIT_4GB:
+		cm_fx6_sysinfo_q.dsize = 2;
+		cm_fx6_sysinfo_q.ncs = 2;
+		cm_fx6_ddr3_cfg_q.rowaddr = 15;
+		break;
+	default:
+		pr_err("Tried to setup invalid DDR configuration\n");
+		hang();
+	}
+
+	mx6_dram_cfg(&cm_fx6_sysinfo_q, &cm_fx6_calib_q, &cm_fx6_ddr3_cfg_q);
+	__udelay(100);
+}
+
+static unsigned long cm_fx6_spl_dram_init(void)
+{
+	unsigned long bank1_size, bank2_size;
+	int cpu_type = __imx6_cpu_type();
+
+	if (cpu_type == IMX6_CPUTYPE_IMX6S) {
+		mx6sdl_dram_iocfg(64, &ddr_iomux_s, &grp_iomux_s);
+
+		spl_mx6s_dram_init(DDR_32BIT_1GB, false);
+		bank1_size = get_ram_size((long int *)0x10000000, 0x80000000);
+		bank2_size = get_ram_size((long int *)0x80000000, 0x80000000);
+		if (bank1_size == 0x20000000) {
+			if (bank2_size == 0x20000000)
+				return SZ_1G;
+
+			spl_mx6s_dram_init(DDR_32BIT_512MB, true);
+			return SZ_512M;
+		}
+
+		spl_mx6s_dram_init(DDR_16BIT_256MB, true);
+		bank1_size = get_ram_size((long int *)0x10000000, 0x80000000);
+		if (bank1_size == 0x10000000)
+			return SZ_256M;
+	} else if (cpu_type == IMX6_CPUTYPE_IMX6D || cpu_type == IMX6_CPUTYPE_IMX6Q) {
+		mx6dq_dram_iocfg(64, &ddr_iomux_q, &grp_iomux_q);
+
+		spl_mx6q_dram_init(DDR_64BIT_4GB, false);
+		bank1_size = get_ram_size((long int *)0x10000000, 0x80000000);
+		if (bank1_size == 0x80000000)
+			return SZ_2G;
+
+		if (bank1_size == 0x40000000) {
+			bank2_size = get_ram_size((long int *)0x80000000,
+								0x80000000);
+			if (bank2_size == 0x40000000) {
+				/* Don't do a full reset here */
+				spl_mx6q_dram_init(DDR_64BIT_2GB, false);
+				return SZ_2G;
+			} else {
+				spl_mx6q_dram_init(DDR_64BIT_1GB, true);
+				return SZ_1G;
+			}
+		}
+
+		spl_mx6q_dram_init(DDR_32BIT_512MB, true);
+		bank1_size = get_ram_size((long int *)0x10000000, 0x80000000);
+		if (bank1_size == 0x20000000)
+			return SZ_512M;
+
+		spl_mx6q_dram_init(DDR_16BIT_256MB, true);
+		bank1_size = get_ram_size((long int *)0x10000000, 0x80000000);
+		if (bank1_size == 0x10000000)
+			return SZ_256M;
+	}
+
+	return 0;
+}
+
+static inline void setup_uart(void)
+{
+	void __iomem *iomuxbase = (void *)MX6_IOMUXC_BASE_ADDR;
+
+	writel(0x4, iomuxbase + 0x01f8);
+
+	imx6_ungate_all_peripherals();
+	imx6_uart_setup_ll();
+
+	putc_ll('>');
+}
+
+static void cm_fx6_sdram_init(void)
+{
+	unsigned long sdram_size;
+
+	if (get_pc() > 0x10000000)
+		return;
+
+	sdram_size = cm_fx6_spl_dram_init();
+
+	pr_debug("SDRAM init finished. SDRAM size 0x%08lx\n", sdram_size);
+
+	imx6_spi_start_image(0);
+}
+
+extern char __dtb_imx6q_cm_fx6_start[];
+extern char __dtb_imx6dl_cm_fx6_start[];
+
+static noinline void cm_fx6_start(void)
+{
+	int cpu_type = __imx6_cpu_type();
+
+	cm_fx6_sdram_init();
+
+	if (cpu_type == IMX6_CPUTYPE_IMX6S)
+		imx6q_barebox_entry(__dtb_imx6dl_cm_fx6_start);
+	else
+		imx6q_barebox_entry(__dtb_imx6q_cm_fx6_start);
+}
+
+ENTRY_FUNCTION(start_imx6_cm_fx6, r0, r1, r2)
+{
+	arm_cpu_lowlevel_init();
+
+	setup_uart();
+	relocate_to_current_adr();
+	setup_c();
+	barrier();
+
+	cm_fx6_start();
+}
+
+extern char __dtb_imx6q_utilite_start[];
+extern char __dtb_imx6dl_utilite_value_start[];
+
+static noinline void utilite_start(void)
+{
+	int cpu_type = __imx6_cpu_type();
+
+	cm_fx6_sdram_init();
+
+	if (cpu_type == IMX6_CPUTYPE_IMX6S)
+		/* FIXME: This needs a specialized utilite value dts */
+		imx6q_barebox_entry(__dtb_imx6dl_cm_fx6_start);
+	else
+		imx6q_barebox_entry(__dtb_imx6q_utilite_start);
+}
+
+ENTRY_FUNCTION(start_imx6_utilite, r0, r1, r2)
+{
+	arm_cpu_lowlevel_init();
+
+	setup_uart();
+	relocate_to_current_adr();
+	setup_c();
+	barrier();
+
+	utilite_start();
+}
diff --git a/arch/arm/configs/imx_v7_defconfig b/arch/arm/configs/imx_v7_defconfig
index 7dd6e6f..ec91460 100644
--- a/arch/arm/configs/imx_v7_defconfig
+++ b/arch/arm/configs/imx_v7_defconfig
@@ -24,6 +24,7 @@ CONFIG_MACH_EMBEST_RIOTBOARD=y
 CONFIG_MACH_UDOO=y
 CONFIG_MACH_VARISCITE_MX6=y
 CONFIG_MACH_GW_VENTANA=y
+CONFIG_MACH_CM_FX6=y
 CONFIG_IMX_IIM=y
 CONFIG_IMX_IIM_FUSE_BLOW=y
 CONFIG_IMX_OCOTP=y
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 06c29c8..c072616 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -9,6 +9,7 @@ obj- += dummy.o
 
 pbl-dtb-$(CONFIG_MACH_AFI_GF) += am335x-afi-gf.dtb.o
 pbl-dtb-$(CONFIG_MACH_BEAGLEBONE) += am335x-bone.dtb.o am335x-boneblack.dtb.o am335x-bone-common.dtb.o
+pbl-dtb-$(CONFIG_MACH_CM_FX6) += imx6dl-cm-fx6.dtb.o imx6q-cm-fx6.dtb.o imx6q-utilite.dtb.o
 pbl-dtb-$(CONFIG_MACH_DFI_FS700_M60) += imx6q-dfi-fs700-m60-6q.dtb.o imx6dl-dfi-fs700-m60-6s.dtb.o
 pbl-dtb-$(CONFIG_MACH_DUCKBILL) += imx28-duckbill.dtb.o
 pbl-dtb-$(CONFIG_MACH_EFIKA_MX_SMARTBOOK) += imx51-genesi-efika-sb.dtb.o
diff --git a/arch/arm/dts/imx6q-cm-fx6.dts b/arch/arm/dts/imx6q-cm-fx6.dts
new file mode 100644
index 0000000..5f01e34
--- /dev/null
+++ b/arch/arm/dts/imx6q-cm-fx6.dts
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2014 CompuLab Ltd.
+ *
+ * Author: Valentin Raevsky <valentin@compulab.co.il>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include <arm/imx6q.dtsi>
+#include "imx6q-cm-fx6.dtsi"
+
+/ {
+	model = "CompuLab CM-FX6";
+	compatible = "compulab,cm-fx6", "fsl,imx6q";
+
+	chosen {
+		stdout-path = &uart4;
+	};
+};
+
+&sata {
+	status = "okay";
+};
diff --git a/arch/arm/dts/imx6q-cm-fx6.dtsi b/arch/arm/dts/imx6q-cm-fx6.dtsi
new file mode 100644
index 0000000..b53efdd
--- /dev/null
+++ b/arch/arm/dts/imx6q-cm-fx6.dtsi
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2014 CompuLab Ltd.
+ *
+ * Author: Valentin Raevsky <valentin@compulab.co.il>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include "imx6qdl-cm-fx6.dtsi"
+
+/ {
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_sata_ldo_en: sata_ldo_en {
+			compatible = "regulator-fixed";
+			regulator-name = "cm_fx6_sata_ldo_en";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio2 16 0>;
+			startup-delay-us = <100>;
+			regulator-boot-on;
+			enable-active-high;
+		};
+
+		reg_sata_phy_slp: sata_phy_slp {
+			compatible = "regulator-fixed";
+			regulator-name = "cm_fx6_sata_phy_slp";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio3 23 0>;
+			startup-delay-us = <100>;
+			enable-active-high;
+			regulator-boot-on;
+			vin-supply = <&reg_sata_ldo_en>;
+		};
+
+		reg_sata_nrstdly: sata_nrstdly {
+			compatible = "regulator-fixed";
+			regulator-name = "cm_fx6_sata_nrstdly";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio6 6 0>;
+			startup-delay-us = <100>;
+			enable-active-high;
+			regulator-boot-on;
+			vin-supply = <&reg_sata_phy_slp>;
+		};
+
+		reg_sata_pwren: sata_pwren {
+			compatible = "regulator-fixed";
+			regulator-name = "cm_fx6_sata_pwren";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio1 28 0>;
+			startup-delay-us = <100>;
+			enable-active-high;
+			regulator-boot-on;
+			vin-supply = <&reg_sata_nrstdly>;
+		};
+
+		reg_sata_nstandby1: sata_nstandby1 {
+			compatible = "regulator-fixed";
+			regulator-name = "cm_fx6_sata_nstandby1";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio3 20 0>;
+			startup-delay-us = <100>;
+			enable-active-high;
+			regulator-boot-on;
+			vin-supply = <&reg_sata_pwren>;
+		};
+
+		reg_sata_nstandby2: sata_nstandby2 {
+			compatible = "regulator-fixed";
+			regulator-name = "cm_fx6_sata_nstandby2";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio5 2 0>;
+			startup-delay-us = <100>;
+			enable-active-high;
+			regulator-boot-on;
+			vin-supply = <&reg_sata_nstandby1>;
+		};
+
+	};
+};
+
+/* sata */
+&sata {
+	status = "okay";
+};
diff --git a/arch/arm/dts/imx6q-utilite.dts b/arch/arm/dts/imx6q-utilite.dts
new file mode 100644
index 0000000..f7ee57c
--- /dev/null
+++ b/arch/arm/dts/imx6q-utilite.dts
@@ -0,0 +1,42 @@
+/dts-v1/;
+#include <arm/imx6q.dtsi>
+#include "imx6q-cm-fx6.dtsi"
+
+/ {
+	model = "CompuLab Utilite";
+	compatible = "compulab,utilite", "compulab,cm-fx6", "fsl,imx6q";
+
+	chosen {
+		stdout-path = &uart4;
+	};
+};
+
+&iomuxc {
+	pinctrl_usdhc3: usdhc3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD             0x17059
+			MX6QDL_PAD_SD3_CLK__SD3_CLK             0x10059
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0          0x17059
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1          0x17059
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2          0x17059
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3          0x17059
+		>;
+	};
+};
+
+&usdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	status = "okay";
+};
+
+&hdmi {
+	status = "okay";
+	ddc-i2c-bus = <&i2c2>;
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+};
diff --git a/arch/arm/dts/imx6qdl-cm-fx6.dtsi b/arch/arm/dts/imx6qdl-cm-fx6.dtsi
new file mode 100644
index 0000000..5b9b2c3
--- /dev/null
+++ b/arch/arm/dts/imx6qdl-cm-fx6.dtsi
@@ -0,0 +1,463 @@
+/*
+ * Copyright 2014 CompuLab Ltd.
+ *
+ * Author: Valentin Raevsky <valentin@compulab.co.il>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/ {
+	barebox_environment {
+		compatible = "barebox,environment";
+		device-path = &barebox_env;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		heartbeat-led {
+			label = "Heartbeat";
+			gpios = <&gpio2 31 0>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+	/* regulator for usb otg */
+	reg_usb_otg_vbus: usb_otg_vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_otg_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpio3 22 0>;
+		enable-active-high;
+	};
+
+	/* regulator1 for pcie power-on-gpio */
+	pcie_power_on_gpio: regulator-pcie-power-on-gpio {
+		compatible = "regulator-fixed";
+		regulator-name = "regulator-pcie-power-on-gpio";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&gpio2 24 0>;
+		enable-active-high;
+	};
+
+	/* regulator for usb hub1 */
+	reg_usb_h1_vbus: usb_h1_vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_h1_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpio7 8 0>;
+		enable-active-high;
+	};
+
+	/* regulator1 for wifi/bt */
+	awnh387_npoweron: regulator-awnh387-npoweron {
+		compatible = "regulator-fixed";
+		regulator-name = "regulator-awnh387-npoweron";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&gpio7 12 0>;
+		enable-active-high;
+	};
+
+	/* regulator2 for wifi/bt */
+	awnh387_wifi_nreset: regulator-awnh387-wifi-nreset {
+		compatible = "regulator-fixed";
+		regulator-name = "regulator-awnh387-wifi-nreset";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&gpio6 16 0>;
+		startup-delay-us = <10000>;
+	};
+
+	tsc2046reg: tsc2046-reg {
+		compatible = "regulator-fixed";
+		regulator-name = "tsc2046-reg";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	hog {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				/* SATA PWR */
+				MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x80000000
+				MX6QDL_PAD_EIM_A22__GPIO2_IO16 0x80000000
+				MX6QDL_PAD_EIM_D20__GPIO3_IO20 0x80000000
+				MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x80000000
+				/* SATA CTRL */
+				MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x80000000
+				MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x80000000
+				MX6QDL_PAD_EIM_A23__GPIO6_IO06 0x80000000
+				MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x80000000
+				/* POWER_BUTTON */
+				MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000
+			>;
+		};
+	};
+
+	imx6q-cm-fx6 {
+		/* pins for eth0 */
+		pinctrl_enet: enetgrp {
+			fsl,pins = <
+				MX6QDL_PAD_RGMII_RXC__RGMII_RXC      0x1b0b0
+				MX6QDL_PAD_RGMII_RD0__RGMII_RD0      0x1b0b0
+				MX6QDL_PAD_RGMII_RD1__RGMII_RD1      0x1b0b0
+				MX6QDL_PAD_RGMII_RD2__RGMII_RD2      0x1b0b0
+				MX6QDL_PAD_RGMII_RD3__RGMII_RD3      0x1b0b0
+				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL   0x1b0b0
+				MX6QDL_PAD_RGMII_TXC__RGMII_TXC      0x1b0b0
+				MX6QDL_PAD_RGMII_TD0__RGMII_TD0      0x1b0b0
+				MX6QDL_PAD_RGMII_TD1__RGMII_TD1      0x1b0b0
+				MX6QDL_PAD_RGMII_TD2__RGMII_TD2      0x1b0b0
+				MX6QDL_PAD_RGMII_TD3__RGMII_TD3      0x1b0b0
+				MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL   0x1b0b0
+				MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK   0x1b0b0
+				MX6QDL_PAD_ENET_MDIO__ENET_MDIO      0x1b0b0
+				MX6QDL_PAD_ENET_MDC__ENET_MDC      0x1b0b0
+			>;
+		};
+
+		pinctrl_ipu1_lcd: ipu1grp-lcd {
+			fsl,pins = <
+				MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x38
+				MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15       0x38
+				MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02        0x38
+				MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03        0x38
+				MX6QDL_PAD_DI0_PIN4__IPU1_DI0_PIN04        0x80000028
+				MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00   0x38
+				MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01   0x38
+				MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02   0x38
+				MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03   0x38
+				MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04   0x38
+				MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05   0x38
+				MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06   0x38
+				MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07   0x38
+				MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08   0x38
+				MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09   0x38
+				MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10  0x38
+				MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11  0x38
+				MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12  0x38
+				MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13  0x38
+				MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14  0x38
+				MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15  0x38
+				MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16  0x38
+				MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17  0x38
+				MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18  0x38
+				MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19  0x38
+				MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20  0x38
+				MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21  0x38
+				MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22  0x38
+				MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23  0x38
+			>;
+		};
+
+		/* pins for spi */
+		pinctrl_ecspi1: ecspi1grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D16__ECSPI1_SCLK      0x100b1
+				MX6QDL_PAD_EIM_D17__ECSPI1_MISO      0x100b1
+				MX6QDL_PAD_EIM_D18__ECSPI1_MOSI      0x100b1
+				MX6QDL_PAD_EIM_EB2__GPIO2_IO30      0x100b1
+				MX6QDL_PAD_EIM_D19__GPIO3_IO19      0x100b1
+			>;
+		};
+
+		/* pins for nand */
+		pinctrl_gpmi_nand: gpminandgrp {
+			fsl,pins = <
+				MX6QDL_PAD_NANDF_CLE__NAND_CLE      0xb0b1
+				MX6QDL_PAD_NANDF_ALE__NAND_ALE      0xb0b1
+				MX6QDL_PAD_NANDF_WP_B__NAND_WP_B   0xb0b1
+				MX6QDL_PAD_NANDF_RB0__NAND_READY_B   0xb000
+				MX6QDL_PAD_NANDF_CS0__NAND_CE0_B   0xb0b1
+				MX6QDL_PAD_NANDF_CS1__NAND_CE1_B   0xb0b1
+				MX6QDL_PAD_SD4_CMD__NAND_RE_B      0xb0b1
+				MX6QDL_PAD_SD4_CLK__NAND_WE_B      0xb0b1
+				MX6QDL_PAD_NANDF_D0__NAND_DATA00   0xb0b1
+				MX6QDL_PAD_NANDF_D1__NAND_DATA01   0xb0b1
+				MX6QDL_PAD_NANDF_D2__NAND_DATA02   0xb0b1
+				MX6QDL_PAD_NANDF_D3__NAND_DATA03   0xb0b1
+				MX6QDL_PAD_NANDF_D4__NAND_DATA04   0xb0b1
+				MX6QDL_PAD_NANDF_D5__NAND_DATA05   0xb0b1
+				MX6QDL_PAD_NANDF_D6__NAND_DATA06   0xb0b1
+				MX6QDL_PAD_NANDF_D7__NAND_DATA07   0xb0b1
+				MX6QDL_PAD_SD4_DAT0__NAND_DQS      0x00b1
+			>;
+		};
+
+		/* pins for i2c2 */
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+				MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+			>;
+		};
+
+		/* pins for i2c3 */
+		pinctrl_i2c3: i2c3grp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
+				MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
+			>;
+		};
+
+		/* pins for console */
+		pinctrl_uart4: uart4grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL0__UART4_TX_DATA   0x1b0b1
+				MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA   0x1b0b1
+			>;
+		};
+
+		/* pins for usb hub1 */
+		pinctrl_usbh1: usbh1grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_RST__GPIO7_IO08 0x80000000
+			>;
+		};
+
+		/* pins for usb otg */
+		pinctrl_usbotg: usbotggrp {
+			fsl,pins = <
+				MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
+				MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000
+			>;
+		};
+
+		/* pins for wifi/bt */
+		pinctrl_usdhc1: usdhc1grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD1_CMD__SD1_CMD    0x17071
+				MX6QDL_PAD_SD1_CLK__SD1_CLK    0x10071
+				MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17071
+				MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17071
+				MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17071
+				MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17071
+			>;
+		};
+
+		/* pins for wifi/bt */
+		pinctrl_mrvl1: mrvl1grp {
+			fsl,pins = <
+				/* WIFI_PWR_RST */
+				MX6QDL_PAD_GPIO_17__GPIO7_IO12	0x80000000
+				MX6QDL_PAD_NANDF_CS3__GPIO6_IO16 0x80000000
+			>;
+		};
+
+		/* pins for tsc2046 pendown */
+		pinctrl_tsc2046: tsc2046grp {
+			fsl,pins = <
+				 /* tsc2046 PENDOWN */
+				MX6QDL_PAD_SD4_DAT7__GPIO2_IO15 0x80000000
+			>;
+		};
+
+		/* pins for pcie */
+		pinctrl_pcie: pciegrp {
+			fsl,pins = <
+				MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x80000000
+				MX6QDL_PAD_EIM_CS1__GPIO2_IO24 0x80000000
+			>;
+		};
+
+		/* pins for spdif */
+		pinctrl_spdif: spdifgrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_16__SPDIF_IN  0x1b0b0
+				MX6QDL_PAD_GPIO_19__SPDIF_OUT 0x1b0b0
+			>;
+		};
+
+		/* pins for audmux */
+		pinctrl_audmux: audmuxgrp {
+			fsl,pins = <
+				MX6QDL_PAD_SD2_CMD__AUD4_RXC   0x17059
+				MX6QDL_PAD_SD2_DAT0__AUD4_RXD  0x17059
+				MX6QDL_PAD_SD2_DAT3__AUD4_TXC  0x17059
+				MX6QDL_PAD_SD2_DAT2__AUD4_TXD  0x17059
+				MX6QDL_PAD_SD2_DAT1__AUD4_TXFS 0x17059
+				/* master mode pin */
+				MX6QDL_PAD_GPIO_5__CCM_CLKO1	0x17059
+			>;
+		};
+	};
+};
+
+/* spi */
+&ecspi1 {
+	fsl,spi-num-chipselects = <2>;
+	cs-gpios = <&gpio2 30 0>, <&gpio3 19 0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi1>;
+	status = "okay";
+
+	flash: m25p80@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "st,m25px16", "st,m25p";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+
+		partition@0 {
+			label = "barebox";
+			reg = <0x0 0x100000>;
+		};
+
+		barebox_env: partition@100000 {
+			label = "barebox-environment";
+			reg = <0x100000 0x40000>;
+		};
+
+		partition@140000 {
+			label = "reserved";
+			reg = <0x140000 0x0>;
+		};
+	};
+
+	/* touch controller */
+	touch:	tsc2046@1 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_tsc2046>;
+
+		compatible = "ti,tsc2046";
+		vcc-supply = <&tsc2046reg>;
+
+		reg = <1>;	/* CS1 */
+		spi-max-frequency = <1500000>;
+
+		interrupt-parent = <&gpio2>;
+		interrupts = <15 0>;
+		pendown-gpio = <&gpio2 15 0>;
+
+		ti,x-min = /bits/ 16 <0x0>;
+		ti,x-max = /bits/ 16 <0x0fff>;
+		ti,y-min = /bits/ 16 <0x0>;
+		ti,y-max = /bits/ 16 <0x0fff>;
+
+		ti,x-plate-ohms = /bits/ 16 <180>;
+		ti,pressure-max = /bits/ 16 <255>;
+
+		ti,debounce-max = /bits/ 16 <30>;
+		ti,debounce-tol = /bits/ 16 <10>;
+		ti,debounce-rep = /bits/ 16 <1>;
+
+		linux,wakeup;
+	};
+};
+
+/* eth0 */
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii";
+	status = "okay";
+};
+
+/* nand */
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
+	status = "okay";
+
+	partition@0 {
+		label = "linux";
+		reg = <0x0 0x800000>;
+	};
+
+	partition@800000 {
+		label = "rootfs";
+		reg = < 0x800000 0x0>;
+	};
+};
+
+/* i2c3 */
+&i2c3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	eeprom@50 {
+		compatible = "at24,24c02";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+
+	codec: wm8731@1a {
+		compatible = "wlf,wm8731";
+		reg = <0x1a>;
+		clocks = <&clks 173>, <&clks 158>, <&clks 201>, <&clks 200>;
+		clock-names = "pll4", "imx-ssi.1", "cko", "cko2";
+	};
+};
+
+&pcie {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pcie>;
+	reset-gpio = <&gpio1 26 0>;
+	vdd-supply = <&pcie_power_on_gpio>;
+	status = "okay";
+};
+
+/* console */
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart4>;
+	status = "okay";
+};
+
+/* usb otg */
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	dr_mode = "otg";
+	status = "okay";
+};
+
+/* usb hub1 */
+&usbh1 {
+	vbus-supply = <&reg_usb_h1_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbh1>;
+	status = "okay";
+};
+
+/* wifi/bt */
+&usdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc1>, <&pinctrl_mrvl1>;
+	non-removable;
+	vmmc-supply = <&awnh387_npoweron>;
+	vmmc_aux-supply = <&awnh387_wifi_nreset>;
+	status = "okay";
+};
+
+&ssi2 {
+	fsl,mode = "i2s-master";
+	status = "okay";
+};
+
+&spdif {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_spdif>;
+	status = "okay";
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux>;
+	status = "okay";
+};
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index f8f6004..f643948 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -344,6 +344,10 @@ config MACH_GW_VENTANA
 	select I2C
 	select I2C_IMX
 
+config MACH_CM_FX6
+	bool "CM FX6"
+	select ARCH_IMX6
+
 endif
 
 # ----------------------------------------------------------
diff --git a/images/Makefile.imx b/images/Makefile.imx
index cdbae8c..78895f9 100644
--- a/images/Makefile.imx
+++ b/images/Makefile.imx
@@ -227,6 +227,16 @@ CFG_start_imx6_udoo.pblx.imximg = $(board)/udoo/flash-header-mx6-udoo.imxcfg
 FILE_barebox-udoo-imx6q.img = start_imx6_udoo.pblx.imximg
 image-$(CONFIG_MACH_UDOO) += barebox-udoo-imx6q.img
 
+pblx-$(CONFIG_MACH_CM_FX6) += start_imx6_cm_fx6
+CFG_start_imx6_cm_fx6.imx-sram-img = $(board)/cm-fx6/flash-header-mx6-cm-fx6.imxcfg
+FILE_barebox-cm-fx6.img = start_imx6_cm_fx6.imx-sram-img
+image-$(CONFIG_MACH_CM_FX6) += barebox-cm-fx6.img
+
+pblx-$(CONFIG_MACH_CM_FX6) += start_imx6_utilite
+CFG_start_imx6_utilite.imx-sram-img = $(board)/cm-fx6/flash-header-mx6-cm-fx6.imxcfg
+FILE_barebox-utilite.img = start_imx6_utilite.imx-sram-img
+image-$(CONFIG_MACH_CM_FX6) += barebox-utilite.img
+
 pblx-$(CONFIG_MACH_VARISCITE_MX6) += start_variscite_custom
 CFG_start_variscite_custom.pblx.imximg = $(board)/variscite-mx6/flash-header-variscite.imxcfg
 FILE_barebox-variscite-custom.img = start_variscite_custom.pblx.imximg
-- 
2.1.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2015-07-16  8:51 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-16  8:50 [PATCH] i.MX6 xload and Utilite support Sascha Hauer
2015-07-16  8:50 ` [PATCH 01/11] ARM: i.MX6: Add i.MX6 entry function Sascha Hauer
2015-07-16  8:50 ` [PATCH 02/11] ARM: i.MX6: remove unnecessary includes Sascha Hauer
2015-07-16  8:50 ` [PATCH 03/11] ARM: i.MX6: add function to get bootsource in pbl Sascha Hauer
2015-07-16  8:50 ` [PATCH 04/11] memsize: Compile for PBL aswell Sascha Hauer
2015-07-16  8:50 ` [PATCH 05/11] ARM: i.MX: compile boot.c for pbl aswell Sascha Hauer
2015-07-16  8:50 ` [PATCH 06/11] ARM: i.MX6: create cpu_is() functions for use in PBL Sascha Hauer
2015-07-16  8:50 ` [PATCH 07/11] images: i.MX: Create target for SRAM images Sascha Hauer
2015-07-16  8:50 ` [PATCH 08/11] spi: i.MX: move register defines to include/ Sascha Hauer
2015-07-16  8:50 ` [PATCH 09/11] ARM: i.MX: Add SPI xload code Sascha Hauer
2015-07-16  8:50 ` [PATCH 10/11] ARM: i.MX6: Add DDR setup code from U-Boot Sascha Hauer
2015-07-16  8:50 ` [PATCH 11/11] ARM: initial cm-fx6 support Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox