All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 00/15 V2] Support for the DENX M28 SoM
@ 2011-09-12  4:06 Marek Vasut
  2011-09-12  4:06 ` [U-Boot] [PATCH 01/15] iMX28: Initial support for iMX28 CPU Marek Vasut
                   ` (15 more replies)
  0 siblings, 16 replies; 116+ messages in thread
From: Marek Vasut @ 2011-09-12  4:06 UTC (permalink / raw)
  To: u-boot

This series adds support for DENX M28 SoM and M28EVK kit.

This series depends on previous series:
* Support for both FEC interfaces on i.MX28
* Random NAND fixes and improvements
* SPL modifications

V2: * Convert to SPL framework
    * Squash patches together
    * Fix pointed out issues

Marek Vasut (15):
  iMX28: Initial support for iMX28 CPU
  iMX28: Add SSP MMC driver
  FEC: Add support for iMX28 quirks
  iMX28: Add PINMUX control
  iMX28: Add I2C bus driver
  iMX28: Add GPIO control
  iMX28: Add SPI driver
  iMX28: Add APBH DMA driver
  iMX28: Add GPMI NAND driver
  iMX28: Add driver for internal RTC
  iMX28: Add image header generator tool
  iMX28: Add u-boot.sb target to Makefile
  iMX28: Add support for DENX M28EVK board
  M28: Add MMC SPL
  M28: Add doc/README.m28 documentation

 MAINTAINERS                                   |    1 +
 Makefile                                      |    5 +
 arch/arm/cpu/arm926ejs/mx28/Makefile          |   46 +
 arch/arm/cpu/arm926ejs/mx28/clock.c           |  355 +++++++
 arch/arm/cpu/arm926ejs/mx28/iomux.c           |  109 +++
 arch/arm/cpu/arm926ejs/mx28/mx28.c            |  200 ++++
 arch/arm/cpu/arm926ejs/mx28/timer.c           |  141 +++
 arch/arm/include/asm/arch-mx28/clock.h        |   61 ++
 arch/arm/include/asm/arch-mx28/dma.h          |  170 ++++
 arch/arm/include/asm/arch-mx28/gpio.h         |   32 +
 arch/arm/include/asm/arch-mx28/imx-regs.h     |   39 +
 arch/arm/include/asm/arch-mx28/iomux-mx28.h   |  537 +++++++++++
 arch/arm/include/asm/arch-mx28/iomux.h        |  168 ++++
 arch/arm/include/asm/arch-mx28/regs-apbh.h    |  466 +++++++++
 arch/arm/include/asm/arch-mx28/regs-base.h    |   88 ++
 arch/arm/include/asm/arch-mx28/regs-bch.h     |  230 +++++
 arch/arm/include/asm/arch-mx28/regs-clkctrl.h |  312 ++++++
 arch/arm/include/asm/arch-mx28/regs-common.h  |   66 ++
 arch/arm/include/asm/arch-mx28/regs-gpmi.h    |  222 +++++
 arch/arm/include/asm/arch-mx28/regs-i2c.h     |  207 ++++
 arch/arm/include/asm/arch-mx28/regs-ocotp.h   |  173 ++++
 arch/arm/include/asm/arch-mx28/regs-pinctrl.h | 1284 +++++++++++++++++++++++++
 arch/arm/include/asm/arch-mx28/regs-power.h   |  413 ++++++++
 arch/arm/include/asm/arch-mx28/regs-rtc.h     |  147 +++
 arch/arm/include/asm/arch-mx28/regs-ssp.h     |  349 +++++++
 arch/arm/include/asm/arch-mx28/regs-timrot.h  |  171 ++++
 arch/arm/include/asm/arch-mx28/sys_proto.h    |   32 +
 board/denx/m28evk/Makefile                    |   57 ++
 board/denx/m28evk/m28_init.h                  |   36 +
 board/denx/m28evk/m28evk.c                    |  195 ++++
 board/denx/m28evk/mem_init.c                  |  213 ++++
 board/denx/m28evk/mmc_boot.c                  |  273 ++++++
 board/denx/m28evk/power_init.c                |  911 ++++++++++++++++++
 board/denx/m28evk/start.S                     |  396 ++++++++
 board/denx/m28evk/u-boot-spl.lds              |   87 ++
 board/denx/m28evk/u-boot.bd                   |   14 +
 boards.cfg                                    |    1 +
 doc/README.m28                                |  223 +++++
 drivers/dma/Makefile                          |    1 +
 drivers/dma/apbh_dma.c                        |  691 +++++++++++++
 drivers/gpio/Makefile                         |    1 +
 drivers/gpio/mxs_gpio.c                       |  136 +++
 drivers/i2c/Makefile                          |    1 +
 drivers/i2c/mxs_i2c.c                         |  240 +++++
 drivers/mmc/Makefile                          |    1 +
 drivers/mmc/mxsmmc.c                          |  351 +++++++
 drivers/mtd/nand/Makefile                     |    1 +
 drivers/mtd/nand/mxs_nand.c                   | 1159 ++++++++++++++++++++++
 drivers/net/fec_mxc.c                         |   44 +-
 drivers/rtc/Makefile                          |    1 +
 drivers/rtc/mxsrtc.c                          |   86 ++
 drivers/spi/Makefile                          |    1 +
 drivers/spi/mxs_spi.c                         |  172 ++++
 include/configs/m28evk.h                      |  289 ++++++
 tools/Makefile                                |    6 +
 tools/mxsboot.c                               |  687 +++++++++++++
 56 files changed, 12296 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/Makefile
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/clock.c
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/iomux.c
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/mx28.c
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/timer.c
 create mode 100644 arch/arm/include/asm/arch-mx28/clock.h
 create mode 100644 arch/arm/include/asm/arch-mx28/dma.h
 create mode 100644 arch/arm/include/asm/arch-mx28/gpio.h
 create mode 100644 arch/arm/include/asm/arch-mx28/imx-regs.h
 create mode 100644 arch/arm/include/asm/arch-mx28/iomux-mx28.h
 create mode 100644 arch/arm/include/asm/arch-mx28/iomux.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-apbh.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-base.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-bch.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-clkctrl.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-common.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-gpmi.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-i2c.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-ocotp.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-pinctrl.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-power.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-rtc.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-ssp.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-timrot.h
 create mode 100644 arch/arm/include/asm/arch-mx28/sys_proto.h
 create mode 100644 board/denx/m28evk/Makefile
 create mode 100644 board/denx/m28evk/m28_init.h
 create mode 100644 board/denx/m28evk/m28evk.c
 create mode 100644 board/denx/m28evk/mem_init.c
 create mode 100644 board/denx/m28evk/mmc_boot.c
 create mode 100644 board/denx/m28evk/power_init.c
 create mode 100644 board/denx/m28evk/start.S
 create mode 100644 board/denx/m28evk/u-boot-spl.lds
 create mode 100644 board/denx/m28evk/u-boot.bd
 create mode 100644 doc/README.m28
 create mode 100644 drivers/dma/apbh_dma.c
 create mode 100644 drivers/gpio/mxs_gpio.c
 create mode 100644 drivers/i2c/mxs_i2c.c
 create mode 100644 drivers/mmc/mxsmmc.c
 create mode 100644 drivers/mtd/nand/mxs_nand.c
 create mode 100644 drivers/rtc/mxsrtc.c
 create mode 100644 drivers/spi/mxs_spi.c
 create mode 100644 include/configs/m28evk.h
 create mode 100644 tools/mxsboot.c

-- 
1.7.5.4

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

* [U-Boot] [PATCH 01/15] iMX28: Initial support for iMX28 CPU
  2011-09-12  4:06 [U-Boot] [PATCH 00/15 V2] Support for the DENX M28 SoM Marek Vasut
@ 2011-09-12  4:06 ` Marek Vasut
  2011-09-14  7:10   ` Stefano Babic
  2011-09-27 13:45   ` [U-Boot] [PATCH 01/15 V2] " Marek Vasut
  2011-09-12  4:06 ` [U-Boot] [PATCH 02/15] iMX28: Add SSP MMC driver Marek Vasut
                   ` (14 subsequent siblings)
  15 siblings, 2 replies; 116+ messages in thread
From: Marek Vasut @ 2011-09-12  4:06 UTC (permalink / raw)
  To: u-boot

This patch supports:
- Timers
- Debug UART
- Clock

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 arch/arm/cpu/arm926ejs/mx28/Makefile          |   46 +
 arch/arm/cpu/arm926ejs/mx28/clock.c           |  355 +++++++
 arch/arm/cpu/arm926ejs/mx28/mx28.c            |  194 ++++
 arch/arm/cpu/arm926ejs/mx28/timer.c           |  141 +++
 arch/arm/include/asm/arch-mx28/clock.h        |   61 ++
 arch/arm/include/asm/arch-mx28/imx-regs.h     |   38 +
 arch/arm/include/asm/arch-mx28/regs-base.h    |   88 ++
 arch/arm/include/asm/arch-mx28/regs-bch.h     |  230 +++++
 arch/arm/include/asm/arch-mx28/regs-clkctrl.h |  312 ++++++
 arch/arm/include/asm/arch-mx28/regs-common.h  |   66 ++
 arch/arm/include/asm/arch-mx28/regs-gpmi.h    |  222 +++++
 arch/arm/include/asm/arch-mx28/regs-i2c.h     |  207 ++++
 arch/arm/include/asm/arch-mx28/regs-ocotp.h   |  173 ++++
 arch/arm/include/asm/arch-mx28/regs-pinctrl.h | 1284 +++++++++++++++++++++++++
 arch/arm/include/asm/arch-mx28/regs-power.h   |  413 ++++++++
 arch/arm/include/asm/arch-mx28/regs-rtc.h     |  147 +++
 arch/arm/include/asm/arch-mx28/regs-ssp.h     |  349 +++++++
 arch/arm/include/asm/arch-mx28/regs-timrot.h  |  171 ++++
 arch/arm/include/asm/arch-mx28/sys_proto.h    |   30 +
 19 files changed, 4527 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/Makefile
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/clock.c
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/mx28.c
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/timer.c
 create mode 100644 arch/arm/include/asm/arch-mx28/clock.h
 create mode 100644 arch/arm/include/asm/arch-mx28/imx-regs.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-base.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-bch.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-clkctrl.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-common.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-gpmi.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-i2c.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-ocotp.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-pinctrl.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-power.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-rtc.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-ssp.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-timrot.h
 create mode 100644 arch/arm/include/asm/arch-mx28/sys_proto.h

diff --git a/arch/arm/cpu/arm926ejs/mx28/Makefile b/arch/arm/cpu/arm926ejs/mx28/Makefile
new file mode 100644
index 0000000..98504f9
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/Makefile
@@ -0,0 +1,46 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(SOC).o
+
+COBJS	= clock.o mx28.o timer.o
+
+SRCS	:= $(START:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+START	:= $(addprefix $(obj),$(START))
+
+all:	$(obj).depend $(LIB)
+
+$(LIB):	$(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/arm/cpu/arm926ejs/mx28/clock.c b/arch/arm/cpu/arm926ejs/mx28/clock.c
new file mode 100644
index 0000000..f698506
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/clock.c
@@ -0,0 +1,355 @@
+/*
+ * Freescale i.MX28 clock setup code
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+
+/* The PLL frequency is always 480MHz, see section 10.2 in iMX28 datasheet. */
+#define	PLL_FREQ_KHZ	480000
+#define	PLL_FREQ_COEF	18
+/* The XTAL frequency is always 24MHz, see section 10.2 in iMX28 datasheet. */
+#define	XTAL_FREQ_KHZ	24000
+
+#define	PLL_FREQ_MHZ	(PLL_FREQ_KHZ / 1000)
+#define	XTAL_FREQ_MHZ	(XTAL_FREQ_KHZ / 1000)
+
+static uint32_t mx28_get_pclk(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	uint32_t clkctrl, clkseq, clkfrac;
+	uint32_t frac, div;
+
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_cpu);
+
+	/* No support of fractional divider calculation */
+	if (clkctrl &
+		(CLKCTRL_CPU_DIV_XTAL_FRAC_EN | CLKCTRL_CPU_DIV_CPU_FRAC_EN)) {
+		return 0;
+	}
+
+	clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+
+	/* XTAL Path */
+	if (clkseq & CLKCTRL_CLKSEQ_BYPASS_CPU) {
+		div = (clkctrl & CLKCTRL_CPU_DIV_XTAL_MASK) >>
+			CLKCTRL_CPU_DIV_XTAL_OFFSET;
+		return XTAL_FREQ_MHZ / div;
+	}
+
+	/* REF Path */
+	clkfrac = readl(&clkctrl_regs->hw_clkctrl_frac0);
+	frac = clkfrac & CLKCTRL_FRAC0_CPUFRAC_MASK;
+	div = clkctrl & CLKCTRL_CPU_DIV_CPU_MASK;
+	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
+}
+
+static uint32_t mx28_get_hclk(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	uint32_t div;
+	uint32_t clkctrl;
+
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_hbus);
+
+	/* No support of fractional divider calculation */
+	if (clkctrl & CLKCTRL_HBUS_DIV_FRAC_EN)
+		return 0;
+
+	div = clkctrl & CLKCTRL_HBUS_DIV_MASK;
+	return mx28_get_pclk() / div;
+}
+
+static uint32_t mx28_get_emiclk(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	uint32_t frac, div;
+	uint32_t clkctrl, clkseq, clkfrac;
+
+	clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_emi);
+
+	/* XTAL Path */
+	if (clkseq & CLKCTRL_CLKSEQ_BYPASS_EMI) {
+		div = (clkctrl & CLKCTRL_EMI_DIV_XTAL_MASK) >>
+			CLKCTRL_EMI_DIV_XTAL_OFFSET;
+		return XTAL_FREQ_MHZ / div;
+	}
+
+	clkfrac = readl(&clkctrl_regs->hw_clkctrl_frac0);
+
+	/* REF Path */
+	frac = (clkfrac & CLKCTRL_FRAC0_EMIFRAC_MASK) >>
+		CLKCTRL_FRAC0_EMIFRAC_OFFSET;
+	div = clkctrl & CLKCTRL_EMI_DIV_EMI_MASK;
+	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
+}
+
+static uint32_t mx28_get_gpmiclk(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	uint32_t frac, div;
+	uint32_t clkctrl, clkseq, clkfrac;
+
+	clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_gpmi);
+
+	/* XTAL Path */
+	if (clkseq & CLKCTRL_CLKSEQ_BYPASS_GPMI) {
+		div = clkctrl & CLKCTRL_GPMI_DIV_MASK;
+		return XTAL_FREQ_MHZ / div;
+	}
+
+	clkfrac = readl(&clkctrl_regs->hw_clkctrl_frac1);
+
+	/* REF Path */
+	frac = (clkfrac & CLKCTRL_FRAC1_GPMIFRAC_MASK) >>
+		CLKCTRL_FRAC1_GPMIFRAC_OFFSET;
+	div = clkctrl & CLKCTRL_GPMI_DIV_MASK;
+	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
+}
+
+/*
+ * Set IO clock frequency, in kHz
+ */
+void mx28_set_ioclk(enum mxs_ioclock io, uint32_t freq)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t div;
+
+	if (freq == 0)
+		return;
+
+	if (io > MXC_IOCLK1)
+		return;
+
+	div = (PLL_FREQ_KHZ * PLL_FREQ_COEF) / freq;
+
+	if (div < 18)
+		div = 18;
+
+	if (div > 35)
+		div = 35;
+
+	if (io == MXC_IOCLK0) {
+		writel(CLKCTRL_FRAC0_CLKGATEIO0,
+			&clkctrl_regs->hw_clkctrl_frac0_set);
+		clrsetbits_le32(&clkctrl_regs->hw_clkctrl_frac0,
+				CLKCTRL_FRAC0_IO0FRAC_MASK,
+				div << CLKCTRL_FRAC0_IO0FRAC_OFFSET);
+		writel(CLKCTRL_FRAC0_CLKGATEIO0,
+			&clkctrl_regs->hw_clkctrl_frac0_clr);
+	} else {
+		writel(CLKCTRL_FRAC0_CLKGATEIO1,
+			&clkctrl_regs->hw_clkctrl_frac0_set);
+		clrsetbits_le32(&clkctrl_regs->hw_clkctrl_frac0,
+				CLKCTRL_FRAC0_IO1FRAC_MASK,
+				div << CLKCTRL_FRAC0_IO1FRAC_OFFSET);
+		writel(CLKCTRL_FRAC0_CLKGATEIO1,
+			&clkctrl_regs->hw_clkctrl_frac0_clr);
+	}
+}
+
+/*
+ * Get IO clock, returns IO clock in kHz
+ */
+static uint32_t mx28_get_ioclk(enum mxs_ioclock io)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t tmp, ret;
+
+	if (io > MXC_IOCLK1)
+		return 0;
+
+	tmp = readl(&clkctrl_regs->hw_clkctrl_frac0);
+
+	if (io == MXC_IOCLK0)
+		ret = (tmp & CLKCTRL_FRAC0_IO0FRAC_MASK) >>
+			CLKCTRL_FRAC0_IO0FRAC_OFFSET;
+	else
+		ret = (tmp & CLKCTRL_FRAC0_IO1FRAC_MASK) >>
+			CLKCTRL_FRAC0_IO1FRAC_OFFSET;
+
+	return (PLL_FREQ_KHZ * PLL_FREQ_COEF) / ret;
+}
+
+/*
+ * Configure SSP clock frequency, in kHz
+ */
+void mx28_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t clk, clkreg;
+
+	if (ssp > MXC_SSPCLK3)
+		return;
+
+	clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) +
+			(ssp * sizeof(struct mx28_register));
+
+	clrbits_le32(clkreg, CLKCTRL_SSP_CLKGATE);
+	while (readl(clkreg) & CLKCTRL_SSP_CLKGATE)
+		;
+
+	if (xtal)
+		clk = XTAL_FREQ_KHZ;
+	else
+		clk = mx28_get_ioclk(ssp >> 1);
+
+	if (freq > clk)
+		return;
+
+	/* Calculate the divider and cap it if necessary */
+	clk /= freq;
+	if (clk > CLKCTRL_SSP_DIV_MASK)
+		clk = CLKCTRL_SSP_DIV_MASK;
+
+	clrsetbits_le32(clkreg, CLKCTRL_SSP_DIV_MASK, clk);
+	while (readl(clkreg) & CLKCTRL_SSP_BUSY)
+		;
+
+	if (xtal)
+		writel(CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp,
+			&clkctrl_regs->hw_clkctrl_clkseq_set);
+	else
+		writel(CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp,
+			&clkctrl_regs->hw_clkctrl_clkseq_clr);
+}
+
+/*
+ * Return SSP frequency, in kHz
+ */
+static uint32_t mx28_get_sspclk(enum mxs_sspclock ssp)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t clkreg;
+	uint32_t clk, tmp;
+
+	if (ssp > MXC_SSPCLK3)
+		return 0;
+
+	tmp = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+	if (tmp & (CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp))
+		return XTAL_FREQ_KHZ;
+
+	clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) +
+			(ssp * sizeof(struct mx28_register));
+
+	tmp = readl(clkreg) & CLKCTRL_SSP_DIV_MASK;
+
+	if (tmp == 0)
+		return 0;
+
+	clk = mx28_get_ioclk(ssp >> 1);
+
+	return clk / tmp;
+}
+
+/*
+ * Set SSP/MMC bus frequency, in kHz)
+ */
+void mx28_set_ssp_busclock(unsigned int bus, uint32_t freq)
+{
+	struct mx28_ssp_regs *ssp_regs;
+	const uint32_t sspclk = mx28_get_sspclk(bus);
+	uint32_t reg;
+	uint32_t divide, rate, tgtclk;
+
+	ssp_regs = (struct mx28_ssp_regs *)(MXS_SSP0_BASE + (bus * 0x2000));
+
+	/*
+	 * SSP bit rate = SSPCLK / (CLOCK_DIVIDE * (1 + CLOCK_RATE)),
+	 * CLOCK_DIVIDE has to be an even value from 2 to 254, and
+	 * CLOCK_RATE could be any integer from 0 to 255.
+	 */
+	for (divide = 2; divide < 254; divide += 2) {
+		rate = sspclk / freq / divide;
+		if (rate <= 256)
+			break;
+	}
+
+	tgtclk = sspclk / divide / rate;
+	while (tgtclk > freq) {
+		rate++;
+		tgtclk = sspclk / divide / rate;
+	}
+	if (rate > 256)
+		rate = 256;
+
+	/* Always set timeout the maximum */
+	reg = SSP_TIMING_TIMEOUT_MASK |
+		(divide << SSP_TIMING_CLOCK_DIVIDE_OFFSET) |
+		((rate - 1) << SSP_TIMING_CLOCK_RATE_OFFSET);
+	writel(reg, &ssp_regs->hw_ssp_timing);
+
+	debug("SPI%d: Set freq rate to %d KHz (requested %d KHz)\n",
+		bus, tgtclk, freq);
+}
+
+uint32_t mxc_get_clock(enum mxc_clock clk)
+{
+	switch (clk) {
+	case MXC_ARM_CLK:
+		return mx28_get_pclk() * 1000000;
+	case MXC_GPMI_CLK:
+		return mx28_get_gpmiclk() * 1000000;
+	case MXC_AHB_CLK:
+	case MXC_IPG_CLK:
+		return mx28_get_hclk() * 1000000;
+	case MXC_EMI_CLK:
+		return mx28_get_emiclk();
+	case MXC_IO0_CLK:
+		return mx28_get_ioclk(MXC_IOCLK0);
+	case MXC_IO1_CLK:
+		return mx28_get_ioclk(MXC_IOCLK1);
+	case MXC_SSP0_CLK:
+		return mx28_get_sspclk(MXC_SSPCLK0);
+	case MXC_SSP1_CLK:
+		return mx28_get_sspclk(MXC_SSPCLK1);
+	case MXC_SSP2_CLK:
+		return mx28_get_sspclk(MXC_SSPCLK2);
+	case MXC_SSP3_CLK:
+		return mx28_get_sspclk(MXC_SSPCLK3);
+	}
+
+	return 0;
+}
diff --git a/arch/arm/cpu/arm926ejs/mx28/mx28.c b/arch/arm/cpu/arm926ejs/mx28/mx28.c
new file mode 100644
index 0000000..58ac9ae
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/mx28.c
@@ -0,0 +1,194 @@
+/*
+ * Freescale i.MX28 common code
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+
+/* 1 second delay should be plenty of time for block reset. */
+#define	RESET_MAX_TIMEOUT	1000000
+
+#define	MX28_BLOCK_SFTRST	(1 << 31)
+#define	MX28_BLOCK_CLKGATE	(1 << 30)
+
+/* Lowlevel init isn't used on i.MX28, so just have a dummy here */
+inline void lowlevel_init(void) {}
+
+void reset_cpu(ulong ignored) __attribute__((noreturn));
+
+void reset_cpu(ulong ignored)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	writel(0, &power_regs->hw_power_charge);
+	writel(0, &power_regs->hw_power_minpwr);
+	writel(CLKCTRL_RESET_DIG, &clkctrl_regs->hw_clkctrl_reset);
+
+	/* Endless loop, reset will exit from here */
+	for (;;)
+		;
+}
+
+int mx28_wait_mask_set(struct mx28_register *reg, uint32_t mask, int timeout)
+{
+	while (--timeout) {
+		if ((readl(&reg->reg) & mask) == mask)
+			break;
+		udelay(1);
+	}
+
+	return !timeout;
+}
+
+int mx28_wait_mask_clr(struct mx28_register *reg, uint32_t mask, int timeout)
+{
+	while (--timeout) {
+		if ((readl(&reg->reg) & mask) == 0)
+			break;
+		udelay(1);
+	}
+
+	return !timeout;
+}
+
+int mx28_reset_block(struct mx28_register *reg)
+{
+	/* Clear SFTRST */
+	writel(MX28_BLOCK_SFTRST, &reg->reg_clr);
+
+	if (mx28_wait_mask_clr(reg, MX28_BLOCK_SFTRST, RESET_MAX_TIMEOUT))
+		return 1;
+
+	/* Clear CLKGATE */
+	writel(MX28_BLOCK_CLKGATE, &reg->reg_clr);
+
+	/* Set SFTRST */
+	writel(MX28_BLOCK_SFTRST, &reg->reg_set);
+
+	/* Wait for CLKGATE being set */
+	if (mx28_wait_mask_set(reg, MX28_BLOCK_CLKGATE, RESET_MAX_TIMEOUT))
+		return 1;
+
+	/* Clear SFTRST */
+	writel(MX28_BLOCK_SFTRST, &reg->reg_clr);
+
+	if (mx28_wait_mask_clr(reg, MX28_BLOCK_SFTRST, RESET_MAX_TIMEOUT))
+		return 1;
+
+	/* Clear CLKGATE */
+	writel(MX28_BLOCK_CLKGATE, &reg->reg_clr);
+
+	if (mx28_wait_mask_clr(reg, MX28_BLOCK_CLKGATE, RESET_MAX_TIMEOUT))
+		return 1;
+
+	return 0;
+}
+
+#ifdef	CONFIG_ARCH_CPU_INIT
+int arch_cpu_init(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/*
+	 * Enable NAND clock
+	 */
+	/* Clear bypass bit */
+	writel(CLKCTRL_CLKSEQ_BYPASS_GPMI,
+		&clkctrl_regs->hw_clkctrl_clkseq_set);
+
+	/* Set GPMI clock to ref_gpmi / 12 */
+	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_gpmi,
+		CLKCTRL_GPMI_CLKGATE | CLKCTRL_GPMI_DIV_MASK, 1);
+
+	udelay(1000);
+
+	return 0;
+}
+#endif
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+int print_cpuinfo(void)
+{
+	printf("Freescale i.MX28 family\n");
+	return 0;
+}
+#endif
+
+int do_mx28_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	printf("CPU:   %3d MHz\n", mxc_get_clock(MXC_ARM_CLK) / 1000000);
+	printf("BUS:   %3d MHz\n", mxc_get_clock(MXC_AHB_CLK) / 1000000);
+	printf("EMI:   %3d MHz\n", mxc_get_clock(MXC_EMI_CLK));
+	printf("GPMI:  %3d MHz\n", mxc_get_clock(MXC_GPMI_CLK) / 1000000);
+	return 0;
+}
+
+/*
+ * Initializes on-chip ethernet controllers.
+ */
+#ifdef	CONFIG_CMD_NET
+int cpu_eth_init(bd_t *bis)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/* Turn on ENET clocks */
+	clrbits_le32(&clkctrl_regs->hw_clkctrl_enet,
+		CLKCTRL_ENET_SLEEP | CLKCTRL_ENET_DISABLE);
+
+	/* Set up ENET PLL for 50 MHz */
+	/* Power on ENET PLL */
+	writel(CLKCTRL_PLL2CTRL0_POWER,
+		&clkctrl_regs->hw_clkctrl_pll2ctrl0_set);
+
+	udelay(10);
+
+	/* Gate on ENET PLL */
+	writel(CLKCTRL_PLL2CTRL0_CLKGATE,
+		&clkctrl_regs->hw_clkctrl_pll2ctrl0_clr);
+
+	/* Enable pad output */
+	setbits_le32(&clkctrl_regs->hw_clkctrl_enet, CLKCTRL_ENET_CLK_OUT_EN);
+
+	return 0;
+}
+#endif
+
+U_BOOT_CMD(
+	clocks,	CONFIG_SYS_MAXARGS, 1, do_mx28_showclocks,
+	"display clocks",
+	""
+);
diff --git a/arch/arm/cpu/arm926ejs/mx28/timer.c b/arch/arm/cpu/arm926ejs/mx28/timer.c
new file mode 100644
index 0000000..dbc904d
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/timer.c
@@ -0,0 +1,141 @@
+/*
+ * Freescale i.MX28 timer driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * (C) Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+
+/* Maximum fixed count */
+#define TIMER_LOAD_VAL	0xffffffff
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define timestamp (gd->tbl)
+#define lastdec (gd->lastinc)
+
+/*
+ * This driver uses 1kHz clock source.
+ */
+#define	MX28_INCREMENTER_HZ		1000
+
+static inline unsigned long tick_to_time(unsigned long tick)
+{
+	return tick / (MX28_INCREMENTER_HZ / CONFIG_SYS_HZ);
+}
+
+static inline unsigned long time_to_tick(unsigned long time)
+{
+	return time * (MX28_INCREMENTER_HZ / CONFIG_SYS_HZ);
+}
+
+/* Calculate how many ticks happen in "us" microseconds */
+static inline unsigned long us_to_tick(unsigned long us)
+{
+	return (us * MX28_INCREMENTER_HZ) / 1000000;
+}
+
+int timer_init(void)
+{
+	struct mx28_timrot_regs *timrot_regs =
+		(struct mx28_timrot_regs *)MXS_TIMROT_BASE;
+
+	/* Reset Timers and Rotary Encoder module */
+	mx28_reset_block(&timrot_regs->hw_timrot_rotctrl_reg);
+
+	/* Set fixed_count to 0 */
+	writel(0, &timrot_regs->hw_timrot_fixed_count0);
+
+	/* Set UPDATE bit and 1Khz frequency */
+	writel(TIMROT_TIMCTRLn_UPDATE | TIMROT_TIMCTRLn_RELOAD |
+		TIMROT_TIMCTRLn_SELECT_1KHZ_XTAL,
+		&timrot_regs->hw_timrot_timctrl0);
+
+	/* Set fixed_count to maximal value */
+	writel(TIMER_LOAD_VAL, &timrot_regs->hw_timrot_fixed_count0);
+
+	return 0;
+}
+
+ulong get_timer(ulong base)
+{
+	struct mx28_timrot_regs *timrot_regs =
+		(struct mx28_timrot_regs *)MXS_TIMROT_BASE;
+
+	/* Current tick value */
+	uint32_t now = readl(&timrot_regs->hw_timrot_running_count0);
+
+	if (lastdec >= now) {
+		/*
+		 * normal mode (non roll)
+		 * move stamp forward with absolut diff ticks
+		 */
+		timestamp += (lastdec - now);
+	} else {
+		/* we have rollover of decrementer */
+		timestamp += (TIMER_LOAD_VAL - now) + lastdec;
+
+	}
+	lastdec = now;
+
+	return tick_to_time(timestamp) - base;
+}
+
+/* We use the HW_DIGCTL_MICROSECONDS register for sub-millisecond timer. */
+#define	MX28_HW_DIGCTL_MICROSECONDS	0x8001c0c0
+
+void __udelay(unsigned long usec)
+{
+	uint32_t old, new, incr;
+	uint32_t counter = 0;
+
+	old = readl(MX28_HW_DIGCTL_MICROSECONDS);
+
+	while (counter < usec) {
+		new = readl(MX28_HW_DIGCTL_MICROSECONDS);
+
+		/* Check if the timer wrapped. */
+		if (new < old) {
+			incr = 0xffffffff - old;
+			incr += new;
+		} else {
+			incr = new - old;
+		}
+
+		/*
+		 * Check if we are close to the maximum time and the counter
+		 * would wrap if incremented. If that's the case, break out
+		 * from the loop as the requested delay time passed.
+		 */
+		if (counter + incr < counter)
+			break;
+
+		counter += incr;
+		old = new;
+	}
+}
diff --git a/arch/arm/include/asm/arch-mx28/clock.h b/arch/arm/include/asm/arch-mx28/clock.h
new file mode 100644
index 0000000..1700fe3
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/clock.h
@@ -0,0 +1,61 @@
+/*
+ * Freescale i.MX28 Clock
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __CLOCK_H__
+#define __CLOCK_H__
+
+enum mxc_clock {
+	MXC_ARM_CLK = 0,
+	MXC_AHB_CLK,
+	MXC_IPG_CLK,
+	MXC_EMI_CLK,
+	MXC_GPMI_CLK,
+	MXC_IO0_CLK,
+	MXC_IO1_CLK,
+	MXC_SSP0_CLK,
+	MXC_SSP1_CLK,
+	MXC_SSP2_CLK,
+	MXC_SSP3_CLK,
+};
+
+enum mxs_ioclock {
+	MXC_IOCLK0 = 0,
+	MXC_IOCLK1,
+};
+
+enum mxs_sspclock {
+	MXC_SSPCLK0 = 0,
+	MXC_SSPCLK1,
+	MXC_SSPCLK2,
+	MXC_SSPCLK3,
+};
+
+uint32_t mxc_get_clock(enum mxc_clock clk);
+
+void mx28_set_ioclk(enum mxs_ioclock io, uint32_t freq);
+void mx28_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal);
+void mx28_set_ssp_busclock(unsigned int bus, uint32_t freq);
+
+/* Compatibility with the FEC Ethernet driver */
+#define	imx_get_fecclk()	mxc_get_clock(MXC_AHB_CLK)
+
+#endif	/* __CLOCK_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/imx-regs.h b/arch/arm/include/asm/arch-mx28/imx-regs.h
new file mode 100644
index 0000000..32bfd7e
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/imx-regs.h
@@ -0,0 +1,38 @@
+/*
+ * Freescale i.MX28 Registers
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __IMX_REGS_H__
+#define __IMX_REGS_H__
+
+#include <asm/arch/regs-base.h>
+#include <asm/arch/regs-bch.h>
+#include <asm/arch/regs-clkctrl.h>
+#include <asm/arch/regs-gpmi.h>
+#include <asm/arch/regs-i2c.h>
+#include <asm/arch/regs-ocotp.h>
+#include <asm/arch/regs-pinctrl.h>
+#include <asm/arch/regs-power.h>
+#include <asm/arch/regs-rtc.h>
+#include <asm/arch/regs-ssp.h>
+#include <asm/arch/regs-timrot.h>
+
+#endif	/* __IMX_REGS_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-base.h b/arch/arm/include/asm/arch-mx28/regs-base.h
new file mode 100644
index 0000000..dbdcc2b
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-base.h
@@ -0,0 +1,88 @@
+/*
+ * Freescale i.MX28 Peripheral Base Addresses
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright (C) 2008 Embedded Alley Solutions Inc.
+ *
+ * (C) Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __MX28_REGS_BASE_H__
+#define __MX28_REGS_BASE_H__
+
+/*
+ * Register base address
+ */
+#define	MXS_ICOL_BASE		0x80000000
+#define	MXS_HSADC_BASE		0x80002000
+#define	MXS_APBH_BASE		0x80004000
+#define	MXS_PERFMON_BASE	0x80006000
+#define	MXS_BCH_BASE		0x8000A000
+#define	MXS_GPMI_BASE		0x8000C000
+#define	MXS_SSP0_BASE		0x80010000
+#define	MXS_SSP1_BASE		0x80012000
+#define	MXS_SSP2_BASE		0x80014000
+#define	MXS_SSP3_BASE		0x80016000
+#define	MXS_PINCTRL_BASE	0x80018000
+#define	MXS_DIGCTL_BASE		0x8001C000
+#define	MXS_ETM_BASE		0x80022000
+#define	MXS_APBX_BASE		0x80024000
+#define	MXS_DCP_BASE		0x80028000
+#define	MXS_PXP_BASE		0x8002A000
+#define	MXS_OCOTP_BASE		0x8002C000
+#define	MXS_AXI_AHB0_BASE	0x8002E000
+#define	MXS_LCDIF_BASE		0x80030000
+#define	MXS_CAN0_BASE		0x80032000
+#define	MXS_CAN1_BASE		0x80034000
+#define	MXS_SIMDBG_BASE		0x8003C000
+#define	MXS_SIMGPMISEL_BASE	0x8003C200
+#define	MXS_SIMSSPSEL_BASE	0x8003C300
+#define	MXS_SIMMEMSEL_BASE	0x8003C400
+#define	MXS_GPIOMON_BASE	0x8003C500
+#define	MXS_SIMENET_BASE	0x8003C700
+#define	MXS_ARMJTAG_BASE	0x8003C800
+#define	MXS_CLKCTRL_BASE	0x80040000
+#define	MXS_SAIF0_BASE		0x80042000
+#define	MXS_POWER_BASE		0x80044000
+#define	MXS_SAIF1_BASE		0x80046000
+#define	MXS_LRADC_BASE		0x80050000
+#define	MXS_SPDIF_BASE		0x80054000
+#define	MXS_RTC_BASE		0x80056000
+#define	MXS_I2C0_BASE		0x80058000
+#define	MXS_I2C1_BASE		0x8005A000
+#define	MXS_PWM_BASE		0x80064000
+#define	MXS_TIMROT_BASE		0x80068000
+#define	MXS_UARTAPP0_BASE	0x8006A000
+#define	MXS_UARTAPP1_BASE	0x8006C000
+#define	MXS_UARTAPP2_BASE	0x8006E000
+#define	MXS_UARTAPP3_BASE	0x80070000
+#define	MXS_UARTAPP4_BASE	0x80072000
+#define	MXS_UARTDBG_BASE	0x80074000
+#define	MXS_USBPHY0_BASE	0x8007C000
+#define	MXS_USBPHY1_BASE	0x8007E000
+#define	MXS_USBCTRL0_BASE	0x80080000
+#define	MXS_USBCTRL1_BASE	0x80090000
+#define	MXS_DFLPT_BASE		0x800C0000
+#define	MXS_DRAM_BASE		0x800E0000
+#define	MXS_ENET0_BASE		0x800F0000
+#define	MXS_ENET1_BASE		0x800F4000
+
+#endif /* __MX28_REGS_BASE_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-bch.h b/arch/arm/include/asm/arch-mx28/regs-bch.h
new file mode 100644
index 0000000..cac0470
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-bch.h
@@ -0,0 +1,230 @@
+/*
+ * Freescale i.MX28 BCH Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_BCH_H__
+#define __MX28_REGS_BCH_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_bch_regs {
+	mx28_reg(hw_bch_ctrl)
+	mx28_reg(hw_bch_status0)
+	mx28_reg(hw_bch_mode)
+	mx28_reg(hw_bch_encodeptr)
+	mx28_reg(hw_bch_dataptr)
+	mx28_reg(hw_bch_metaptr)
+
+	uint32_t	reserved[4];
+
+	mx28_reg(hw_bch_layoutselect)
+	mx28_reg(hw_bch_flash0layout0)
+	mx28_reg(hw_bch_flash0layout1)
+	mx28_reg(hw_bch_flash1layout0)
+	mx28_reg(hw_bch_flash1layout1)
+	mx28_reg(hw_bch_flash2layout0)
+	mx28_reg(hw_bch_flash2layout1)
+	mx28_reg(hw_bch_flash3layout0)
+	mx28_reg(hw_bch_flash3layout1)
+	mx28_reg(hw_bch_dbgkesread)
+	mx28_reg(hw_bch_dbgcsferead)
+	mx28_reg(hw_bch_dbgsyndegread)
+	mx28_reg(hw_bch_dbgahbmread)
+	mx28_reg(hw_bch_blockname)
+	mx28_reg(hw_bch_version)
+};
+#endif
+
+#define	BCH_CTRL_SFTRST					(1 << 31)
+#define	BCH_CTRL_CLKGATE				(1 << 30)
+#define	BCH_CTRL_DEBUGSYNDROME				(1 << 22)
+#define	BCH_CTRL_M2M_LAYOUT_MASK			(0x3 << 18)
+#define	BCH_CTRL_M2M_LAYOUT_OFFSET			18
+#define	BCH_CTRL_M2M_ENCODE				(1 << 17)
+#define	BCH_CTRL_M2M_ENABLE				(1 << 16)
+#define	BCH_CTRL_DEBUG_STALL_IRQ_EN			(1 << 10)
+#define	BCH_CTRL_COMPLETE_IRQ_EN			(1 << 8)
+#define	BCH_CTRL_BM_ERROR_IRQ				(1 << 3)
+#define	BCH_CTRL_DEBUG_STALL_IRQ			(1 << 2)
+#define	BCH_CTRL_COMPLETE_IRQ				(1 << 0)
+
+#define	BCH_STATUS0_HANDLE_MASK				(0xfff << 20)
+#define	BCH_STATUS0_HANDLE_OFFSET			20
+#define	BCH_STATUS0_COMPLETED_CE_MASK			(0xf << 16)
+#define	BCH_STATUS0_COMPLETED_CE_OFFSET			16
+#define	BCH_STATUS0_STATUS_BLK0_MASK			(0xff << 8)
+#define	BCH_STATUS0_STATUS_BLK0_OFFSET			8
+#define	BCH_STATUS0_STATUS_BLK0_ZERO			(0x00 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERROR1			(0x01 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERROR2			(0x02 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERROR3			(0x03 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERROR4			(0x04 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_UNCORRECTABLE		(0xfe << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERASED			(0xff << 8)
+#define	BCH_STATUS0_ALLONES				(1 << 4)
+#define	BCH_STATUS0_CORRECTED				(1 << 3)
+#define	BCH_STATUS0_UNCORRECTABLE			(1 << 2)
+
+#define	BCH_MODE_ERASE_THRESHOLD_MASK			0xff
+#define	BCH_MODE_ERASE_THRESHOLD_OFFSET			0
+
+#define	BCH_ENCODEPTR_ADDR_MASK				0xffffffff
+#define	BCH_ENCODEPTR_ADDR_OFFSET			0
+
+#define	BCH_DATAPTR_ADDR_MASK				0xffffffff
+#define	BCH_DATAPTR_ADDR_OFFSET				0
+
+#define	BCH_METAPTR_ADDR_MASK				0xffffffff
+#define	BCH_METAPTR_ADDR_OFFSET				0
+
+#define	BCH_LAYOUTSELECT_CS15_SELECT_MASK		(0x3 << 30)
+#define	BCH_LAYOUTSELECT_CS15_SELECT_OFFSET		30
+#define	BCH_LAYOUTSELECT_CS14_SELECT_MASK		(0x3 << 28)
+#define	BCH_LAYOUTSELECT_CS14_SELECT_OFFSET		28
+#define	BCH_LAYOUTSELECT_CS13_SELECT_MASK		(0x3 << 26)
+#define	BCH_LAYOUTSELECT_CS13_SELECT_OFFSET		26
+#define	BCH_LAYOUTSELECT_CS12_SELECT_MASK		(0x3 << 24)
+#define	BCH_LAYOUTSELECT_CS12_SELECT_OFFSET		24
+#define	BCH_LAYOUTSELECT_CS11_SELECT_MASK		(0x3 << 22)
+#define	BCH_LAYOUTSELECT_CS11_SELECT_OFFSET		22
+#define	BCH_LAYOUTSELECT_CS10_SELECT_MASK		(0x3 << 20)
+#define	BCH_LAYOUTSELECT_CS10_SELECT_OFFSET		20
+#define	BCH_LAYOUTSELECT_CS9_SELECT_MASK		(0x3 << 18)
+#define	BCH_LAYOUTSELECT_CS9_SELECT_OFFSET		18
+#define	BCH_LAYOUTSELECT_CS8_SELECT_MASK		(0x3 << 16)
+#define	BCH_LAYOUTSELECT_CS8_SELECT_OFFSET		16
+#define	BCH_LAYOUTSELECT_CS7_SELECT_MASK		(0x3 << 14)
+#define	BCH_LAYOUTSELECT_CS7_SELECT_OFFSET		14
+#define	BCH_LAYOUTSELECT_CS6_SELECT_MASK		(0x3 << 12)
+#define	BCH_LAYOUTSELECT_CS6_SELECT_OFFSET		12
+#define	BCH_LAYOUTSELECT_CS5_SELECT_MASK		(0x3 << 10)
+#define	BCH_LAYOUTSELECT_CS5_SELECT_OFFSET		10
+#define	BCH_LAYOUTSELECT_CS4_SELECT_MASK		(0x3 << 8)
+#define	BCH_LAYOUTSELECT_CS4_SELECT_OFFSET		8
+#define	BCH_LAYOUTSELECT_CS3_SELECT_MASK		(0x3 << 6)
+#define	BCH_LAYOUTSELECT_CS3_SELECT_OFFSET		6
+#define	BCH_LAYOUTSELECT_CS2_SELECT_MASK		(0x3 << 4)
+#define	BCH_LAYOUTSELECT_CS2_SELECT_OFFSET		4
+#define	BCH_LAYOUTSELECT_CS1_SELECT_MASK		(0x3 << 2)
+#define	BCH_LAYOUTSELECT_CS1_SELECT_OFFSET		2
+#define	BCH_LAYOUTSELECT_CS0_SELECT_MASK		(0x3 << 0)
+#define	BCH_LAYOUTSELECT_CS0_SELECT_OFFSET		0
+
+#define	BCH_FLASHLAYOUT0_NBLOCKS_MASK			(0xff << 24)
+#define	BCH_FLASHLAYOUT0_NBLOCKS_OFFSET			24
+#define	BCH_FLASHLAYOUT0_META_SIZE_MASK			(0xff << 16)
+#define	BCH_FLASHLAYOUT0_META_SIZE_OFFSET		16
+#define	BCH_FLASHLAYOUT0_ECC0_MASK			(0xf << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_OFFSET			12
+#define	BCH_FLASHLAYOUT0_ECC0_NONE			(0x0 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC2			(0x1 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC4			(0x2 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC6			(0x3 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC8			(0x4 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC10			(0x5 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC12			(0x6 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC14			(0x7 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC16			(0x8 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC18			(0x9 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC20			(0xa << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC22			(0xb << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC24			(0xc << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC26			(0xd << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC28			(0xe << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC30			(0xf << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC32			(0x10 << 12)
+#define	BCH_FLASHLAYOUT0_GF13_0_GF14_1			(1 << 10)
+#define	BCH_FLASHLAYOUT0_DATA0_SIZE_MASK		0xfff
+#define	BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET		0
+
+#define	BCH_FLASHLAYOUT1_PAGE_SIZE_MASK			(0xffff << 16)
+#define	BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET		16
+#define	BCH_FLASHLAYOUT1_ECCN_MASK			(0xf << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_OFFSET			12
+#define	BCH_FLASHLAYOUT1_ECCN_NONE			(0x0 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC2			(0x1 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC4			(0x2 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC6			(0x3 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC8			(0x4 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC10			(0x5 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC12			(0x6 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC14			(0x7 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC16			(0x8 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC18			(0x9 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC20			(0xa << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC22			(0xb << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC24			(0xc << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC26			(0xd << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC28			(0xe << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC30			(0xf << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC32			(0x10 << 12)
+#define	BCH_FLASHLAYOUT1_GF13_0_GF14_1			(1 << 10)
+#define	BCH_FLASHLAYOUT1_DATAN_SIZE_MASK		0xfff
+#define	BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET		0
+
+#define	BCH_DEBUG0_RSVD1_MASK				(0x1f << 27)
+#define	BCH_DEBUG0_RSVD1_OFFSET				27
+#define	BCH_DEBUG0_ROM_BIST_ENABLE			(1 << 26)
+#define	BCH_DEBUG0_ROM_BIST_COMPLETE			(1 << 25)
+#define	BCH_DEBUG0_KES_DEBUG_SYNDROME_SYMBOL_MASK	(0x1ff << 16)
+#define	BCH_DEBUG0_KES_DEBUG_SYNDROME_SYMBOL_OFFSET	16
+#define	BCH_DEBUG0_KES_DEBUG_SYNDROME_SYMBOL_NORMAL	(0x0 << 16)
+#define	BCH_DEBUG0_KES_DEBUG_SYNDROME_SYMBOL_TEST_MODE	(0x1 << 16)
+#define	BCH_DEBUG0_KES_DEBUG_SHIFT_SYND			(1 << 15)
+#define	BCH_DEBUG0_KES_DEBUG_PAYLOAD_FLAG		(1 << 14)
+#define	BCH_DEBUG0_KES_DEBUG_MODE4K			(1 << 13)
+#define	BCH_DEBUG0_KES_DEBUG_KICK			(1 << 12)
+#define	BCH_DEBUG0_KES_STANDALONE			(1 << 11)
+#define	BCH_DEBUG0_KES_DEBUG_STEP			(1 << 10)
+#define	BCH_DEBUG0_KES_DEBUG_STALL			(1 << 9)
+#define	BCH_DEBUG0_BM_KES_TEST_BYPASS			(1 << 8)
+#define	BCH_DEBUG0_RSVD0_MASK				(0x3 << 6)
+#define	BCH_DEBUG0_RSVD0_OFFSET				6
+#define	BCH_DEBUG0_DEBUG_REG_SELECT_MASK		0x3f
+#define	BCH_DEBUG0_DEBUG_REG_SELECT_OFFSET		0
+
+#define	BCH_DBGKESREAD_VALUES_MASK			0xffffffff
+#define	BCH_DBGKESREAD_VALUES_OFFSET			0
+
+#define	BCH_DBGCSFEREAD_VALUES_MASK			0xffffffff
+#define	BCH_DBGCSFEREAD_VALUES_OFFSET			0
+
+#define	BCH_DBGSYNDGENREAD_VALUES_MASK			0xffffffff
+#define	BCH_DBGSYNDGENREAD_VALUES_OFFSET		0
+
+#define	BCH_DBGAHBMREAD_VALUES_MASK			0xffffffff
+#define	BCH_DBGAHBMREAD_VALUES_OFFSET			0
+
+#define	BCH_BLOCKNAME_NAME_MASK				0xffffffff
+#define	BCH_BLOCKNAME_NAME_OFFSET			0
+
+#define	BCH_VERSION_MAJOR_MASK				(0xff << 24)
+#define	BCH_VERSION_MAJOR_OFFSET			24
+#define	BCH_VERSION_MINOR_MASK				(0xff << 16)
+#define	BCH_VERSION_MINOR_OFFSET			16
+#define	BCH_VERSION_STEP_MASK				0xffff
+#define	BCH_VERSION_STEP_OFFSET				0
+
+#endif	/* __MX28_REGS_BCH_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-clkctrl.h b/arch/arm/include/asm/arch-mx28/regs-clkctrl.h
new file mode 100644
index 0000000..93d0397
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-clkctrl.h
@@ -0,0 +1,312 @@
+/*
+ * Freescale i.MX28 CLKCTRL Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_CLKCTRL_H__
+#define __MX28_REGS_CLKCTRL_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_clkctrl_regs {
+	mx28_reg(hw_clkctrl_pll0ctrl0)		/* 0x00 */
+	mx28_reg(hw_clkctrl_pll0ctrl1)		/* 0x10 */
+	mx28_reg(hw_clkctrl_pll1ctrl0)		/* 0x20 */
+	mx28_reg(hw_clkctrl_pll1ctrl1)		/* 0x30 */
+	mx28_reg(hw_clkctrl_pll2ctrl0)		/* 0x40 */
+	mx28_reg(hw_clkctrl_cpu)		/* 0x50 */
+	mx28_reg(hw_clkctrl_hbus)		/* 0x60 */
+	mx28_reg(hw_clkctrl_xbus)		/* 0x70 */
+	mx28_reg(hw_clkctrl_xtal)		/* 0x80 */
+	mx28_reg(hw_clkctrl_ssp0)		/* 0x90 */
+	mx28_reg(hw_clkctrl_ssp1)		/* 0xa0 */
+	mx28_reg(hw_clkctrl_ssp2)		/* 0xb0 */
+	mx28_reg(hw_clkctrl_ssp3)		/* 0xc0 */
+	mx28_reg(hw_clkctrl_gpmi)		/* 0xd0 */
+	mx28_reg(hw_clkctrl_spdif)		/* 0xe0 */
+	mx28_reg(hw_clkctrl_emi)		/* 0xf0 */
+	mx28_reg(hw_clkctrl_saif0)		/* 0x100 */
+	mx28_reg(hw_clkctrl_saif1)		/* 0x110 */
+	mx28_reg(hw_clkctrl_lcdif)		/* 0x120 */
+	mx28_reg(hw_clkctrl_etm)		/* 0x130 */
+	mx28_reg(hw_clkctrl_enet)		/* 0x140 */
+	mx28_reg(hw_clkctrl_hsadc)		/* 0x150 */
+	mx28_reg(hw_clkctrl_flexcan)		/* 0x160 */
+
+	uint32_t	reserved[16];
+
+	mx28_reg(hw_clkctrl_frac0)		/* 0x1b0 */
+	mx28_reg(hw_clkctrl_frac1)		/* 0x1c0 */
+	mx28_reg(hw_clkctrl_clkseq)		/* 0x1d0 */
+	mx28_reg(hw_clkctrl_reset)		/* 0x1e0 */
+	mx28_reg(hw_clkctrl_status)		/* 0x1f0 */
+	mx28_reg(hw_clkctrl_version)		/* 0x200 */
+};
+#endif
+
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_MASK		(0x3 << 28)
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_OFFSET	28
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_DEFAULT	(0x0 << 28)
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_TIMES_2	(0x1 << 28)
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_TIMES_05	(0x2 << 28)
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_UNDEFINED	(0x3 << 28)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_MASK		(0x3 << 24)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_OFFSET		24
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_DEFAULT	(0x0 << 24)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_TIMES_2	(0x1 << 24)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_TIMES_05	(0x2 << 24)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_UNDEFINED	(0x3 << 24)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_MASK		(0x3 << 20)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_OFFSET	20
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_DEFAULT	(0x0 << 20)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_LOWER		(0x1 << 20)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_LOWEST	(0x2 << 20)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_UNDEFINED	(0x3 << 20)
+#define	CLKCTRL_PLL0CTRL0_EN_USB_CLKS		(1 << 18)
+#define	CLKCTRL_PLL0CTRL0_POWER			(1 << 17)
+
+#define	CLKCTRL_PLL0CTRL1_LOCK			(1 << 31)
+#define	CLKCTRL_PLL0CTRL1_FORCE_LOCK		(1 << 30)
+#define	CLKCTRL_PLL0CTRL1_LOCK_COUNT_MASK	0xffff
+#define	CLKCTRL_PLL0CTRL1_LOCK_COUNT_OFFSET	0
+
+#define	CLKCTRL_PLL1CTRL0_CLKGATEEMI		(1 << 31)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_MASK		(0x3 << 28)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_OFFSET	28
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_DEFAULT	(0x0 << 28)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_TIMES_2	(0x1 << 28)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_TIMES_05	(0x2 << 28)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_UNDEFINED	(0x3 << 28)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_MASK		(0x3 << 24)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_OFFSET		24
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_DEFAULT	(0x0 << 24)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_TIMES_2	(0x1 << 24)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_TIMES_05	(0x2 << 24)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_UNDEFINED	(0x3 << 24)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_MASK		(0x3 << 20)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_OFFSET	20
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_DEFAULT	(0x0 << 20)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_LOWER		(0x1 << 20)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_LOWEST	(0x2 << 20)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_UNDEFINED	(0x3 << 20)
+#define	CLKCTRL_PLL1CTRL0_EN_USB_CLKS		(1 << 18)
+#define	CLKCTRL_PLL1CTRL0_POWER			(1 << 17)
+
+#define	CLKCTRL_PLL1CTRL1_LOCK			(1 << 31)
+#define	CLKCTRL_PLL1CTRL1_FORCE_LOCK		(1 << 30)
+#define	CLKCTRL_PLL1CTRL1_LOCK_COUNT_MASK	0xffff
+#define	CLKCTRL_PLL1CTRL1_LOCK_COUNT_OFFSET	0
+
+#define	CLKCTRL_PLL2CTRL0_CLKGATE		(1 << 31)
+#define	CLKCTRL_PLL2CTRL0_LFR_SEL_MASK		(0x3 << 28)
+#define	CLKCTRL_PLL2CTRL0_LFR_SEL_OFFSET	28
+#define	CLKCTRL_PLL2CTRL0_HOLD_RING_OFF_B	(1 << 26)
+#define	CLKCTRL_PLL2CTRL0_CP_SEL_MASK		(0x3 << 24)
+#define	CLKCTRL_PLL2CTRL0_CP_SEL_OFFSET		24
+#define	CLKCTRL_PLL2CTRL0_POWER			(1 << 23)
+
+#define	CLKCTRL_CPU_BUSY_REF_XTAL		(1 << 29)
+#define	CLKCTRL_CPU_BUSY_REF_CPU		(1 << 28)
+#define	CLKCTRL_CPU_DIV_XTAL_FRAC_EN		(1 << 26)
+#define	CLKCTRL_CPU_DIV_XTAL_MASK		(0x3ff << 16)
+#define	CLKCTRL_CPU_DIV_XTAL_OFFSET		16
+#define	CLKCTRL_CPU_INTERRUPT_WAIT		(1 << 12)
+#define	CLKCTRL_CPU_DIV_CPU_FRAC_EN		(1 << 10)
+#define	CLKCTRL_CPU_DIV_CPU_MASK		0x3f
+#define	CLKCTRL_CPU_DIV_CPU_OFFSET		0
+
+#define	CLKCTRL_HBUS_ASM_BUSY			(1 << 31)
+#define	CLKCTRL_HBUS_DCP_AS_ENABLE		(1 << 30)
+#define	CLKCTRL_HBUS_PXP_AS_ENABLE		(1 << 29)
+#define	CLKCTRL_HBUS_ASM_EMIPORT_AS_ENABLE	(1 << 27)
+#define	CLKCTRL_HBUS_APBHDMA_AS_ENABLE		(1 << 26)
+#define	CLKCTRL_HBUS_APBXDMA_AS_ENABLE		(1 << 25)
+#define	CLKCTRL_HBUS_TRAFFIC_JAM_AS_ENABLE	(1 << 24)
+#define	CLKCTRL_HBUS_TRAFFIC_AS_ENABLE		(1 << 23)
+#define	CLKCTRL_HBUS_CPU_DATA_AS_ENABLE		(1 << 22)
+#define	CLKCTRL_HBUS_CPU_INSTR_AS_ENABLE	(1 << 21)
+#define	CLKCTRL_HBUS_ASM_ENABLE			(1 << 20)
+#define	CLKCTRL_HBUS_AUTO_CLEAR_DIV_ENABLE	(1 << 19)
+#define	CLKCTRL_HBUS_SLOW_DIV_MASK		(0x7 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_OFFSET		16
+#define	CLKCTRL_HBUS_SLOW_DIV_BY1		(0x0 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY2		(0x1 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY4		(0x2 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY8		(0x3 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY16		(0x4 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY32		(0x5 << 16)
+#define	CLKCTRL_HBUS_DIV_FRAC_EN		(1 << 5)
+#define	CLKCTRL_HBUS_DIV_MASK			0x1f
+#define	CLKCTRL_HBUS_DIV_OFFSET			0
+
+#define	CLKCTRL_XBUS_BUSY			(1 << 31)
+#define	CLKCTRL_XBUS_AUTO_CLEAR_DIV_ENABLE	(1 << 11)
+#define	CLKCTRL_XBUS_DIV_FRAC_EN		(1 << 10)
+#define	CLKCTRL_XBUS_DIV_MASK			0x3ff
+#define	CLKCTRL_XBUS_DIV_OFFSET			0
+
+#define	CLKCTRL_XTAL_UART_CLK_GATE		(1 << 31)
+#define	CLKCTRL_XTAL_PWM_CLK24M_GATE		(1 << 29)
+#define	CLKCTRL_XTAL_TIMROT_CLK32K_GATE		(1 << 26)
+#define	CLKCTRL_XTAL_DIV_UART_MASK		0x3
+#define	CLKCTRL_XTAL_DIV_UART_OFFSET		0
+
+#define	CLKCTRL_SSP_CLKGATE			(1 << 31)
+#define	CLKCTRL_SSP_BUSY			(1 << 29)
+#define	CLKCTRL_SSP_DIV_FRAC_EN			(1 << 9)
+#define	CLKCTRL_SSP_DIV_MASK			0x1ff
+#define	CLKCTRL_SSP_DIV_OFFSET			0
+
+#define	CLKCTRL_GPMI_CLKGATE			(1 << 31)
+#define	CLKCTRL_GPMI_BUSY			(1 << 29)
+#define	CLKCTRL_GPMI_DIV_FRAC_EN		(1 << 10)
+#define	CLKCTRL_GPMI_DIV_MASK			0x3ff
+#define	CLKCTRL_GPMI_DIV_OFFSET			0
+
+#define	CLKCTRL_SPDIF_CLKGATE			(1 << 31)
+
+#define	CLKCTRL_EMI_CLKGATE			(1 << 31)
+#define	CLKCTRL_EMI_SYNC_MODE_EN		(1 << 30)
+#define	CLKCTRL_EMI_BUSY_REF_XTAL		(1 << 29)
+#define	CLKCTRL_EMI_BUSY_REF_EMI		(1 << 28)
+#define	CLKCTRL_EMI_BUSY_REF_CPU		(1 << 27)
+#define	CLKCTRL_EMI_BUSY_SYNC_MODE		(1 << 26)
+#define	CLKCTRL_EMI_BUSY_DCC_RESYNC		(1 << 17)
+#define	CLKCTRL_EMI_DCC_RESYNC_ENABLE		(1 << 16)
+#define	CLKCTRL_EMI_DIV_XTAL_MASK		(0xf << 8)
+#define	CLKCTRL_EMI_DIV_XTAL_OFFSET		8
+#define	CLKCTRL_EMI_DIV_EMI_MASK		0x3f
+#define	CLKCTRL_EMI_DIV_EMI_OFFSET		0
+
+#define	CLKCTRL_SAIF0_CLKGATE			(1 << 31)
+#define	CLKCTRL_SAIF0_BUSY			(1 << 29)
+#define	CLKCTRL_SAIF0_DIV_FRAC_EN		(1 << 16)
+#define	CLKCTRL_SAIF0_DIV_MASK			0xffff
+#define	CLKCTRL_SAIF0_DIV_OFFSET		0
+
+#define	CLKCTRL_SAIF1_CLKGATE			(1 << 31)
+#define	CLKCTRL_SAIF1_BUSY			(1 << 29)
+#define	CLKCTRL_SAIF1_DIV_FRAC_EN		(1 << 16)
+#define	CLKCTRL_SAIF1_DIV_MASK			0xffff
+#define	CLKCTRL_SAIF1_DIV_OFFSET		0
+
+#define	CLKCTRL_DIS_LCDIF_CLKGATE		(1 << 31)
+#define	CLKCTRL_DIS_LCDIF_BUSY			(1 << 29)
+#define	CLKCTRL_DIS_LCDIF_DIV_FRAC_EN		(1 << 13)
+#define	CLKCTRL_DIS_LCDIF_DIV_MASK		0x1fff
+#define	CLKCTRL_DIS_LCDIF_DIV_OFFSET		0
+
+#define	CLKCTRL_ETM_CLKGATE			(1 << 31)
+#define	CLKCTRL_ETM_BUSY			(1 << 29)
+#define	CLKCTRL_ETM_DIV_FRAC_EN			(1 << 7)
+#define	CLKCTRL_ETM_DIV_MASK			0x7f
+#define	CLKCTRL_ETM_DIV_OFFSET			0
+
+#define	CLKCTRL_ENET_SLEEP			(1 << 31)
+#define	CLKCTRL_ENET_DISABLE			(1 << 30)
+#define	CLKCTRL_ENET_STATUS			(1 << 29)
+#define	CLKCTRL_ENET_BUSY_TIME			(1 << 27)
+#define	CLKCTRL_ENET_DIV_TIME_MASK		(0x3f << 21)
+#define	CLKCTRL_ENET_DIV_TIME_OFFSET		21
+#define	CLKCTRL_ENET_TIME_SEL_MASK		(0x3 << 19)
+#define	CLKCTRL_ENET_TIME_SEL_OFFSET		19
+#define	CLKCTRL_ENET_TIME_SEL_XTAL		(0x0 << 19)
+#define	CLKCTRL_ENET_TIME_SEL_PLL		(0x1 << 19)
+#define	CLKCTRL_ENET_TIME_SEL_RMII_CLK		(0x2 << 19)
+#define	CLKCTRL_ENET_TIME_SEL_UNDEFINED		(0x3 << 19)
+#define	CLKCTRL_ENET_CLK_OUT_EN			(1 << 18)
+#define	CLKCTRL_ENET_RESET_BY_SW_CHIP		(1 << 17)
+#define	CLKCTRL_ENET_RESET_BY_SW		(1 << 16)
+
+#define	CLKCTRL_HSADC_RESETB			(1 << 30)
+#define	CLKCTRL_HSADC_FREQDIV_MASK		(0x3 << 28)
+#define	CLKCTRL_HSADC_FREQDIV_OFFSET		28
+
+#define	CLKCTRL_FLEXCAN_STOP_CAN0		(1 << 30)
+#define	CLKCTRL_FLEXCAN_CAN0_STATUS		(1 << 29)
+#define	CLKCTRL_FLEXCAN_STOP_CAN1		(1 << 28)
+#define	CLKCTRL_FLEXCAN_CAN1_STATUS		(1 << 27)
+
+#define	CLKCTRL_FRAC0_CLKGATEIO0		(1 << 31)
+#define	CLKCTRL_FRAC0_IO0_STABLE		(1 << 30)
+#define	CLKCTRL_FRAC0_IO0FRAC_MASK		(0x3f << 24)
+#define	CLKCTRL_FRAC0_IO0FRAC_OFFSET		24
+#define	CLKCTRL_FRAC0_CLKGATEIO1		(1 << 23)
+#define	CLKCTRL_FRAC0_IO1_STABLE		(1 << 22)
+#define	CLKCTRL_FRAC0_IO1FRAC_MASK		(0x3f << 16)
+#define	CLKCTRL_FRAC0_IO1FRAC_OFFSET		16
+#define	CLKCTRL_FRAC0_CLKGATEEMI		(1 << 15)
+#define	CLKCTRL_FRAC0_EMI_STABLE		(1 << 14)
+#define	CLKCTRL_FRAC0_EMIFRAC_MASK		(0x3f << 8)
+#define	CLKCTRL_FRAC0_EMIFRAC_OFFSET		8
+#define	CLKCTRL_FRAC0_CLKGATECPU		(1 << 7)
+#define	CLKCTRL_FRAC0_CPU_STABLE		(1 << 6)
+#define	CLKCTRL_FRAC0_CPUFRAC_MASK		0x3f
+#define	CLKCTRL_FRAC0_CPUFRAC_OFFSET		0
+
+#define	CLKCTRL_FRAC1_CLKGATEGPMI		(1 << 23)
+#define	CLKCTRL_FRAC1_GPMI_STABLE		(1 << 22)
+#define	CLKCTRL_FRAC1_GPMIFRAC_MASK		(0x3f << 16)
+#define	CLKCTRL_FRAC1_GPMIFRAC_OFFSET		16
+#define	CLKCTRL_FRAC1_CLKGATEHSADC		(1 << 15)
+#define	CLKCTRL_FRAC1_HSADC_STABLE		(1 << 14)
+#define	CLKCTRL_FRAC1_HSADCFRAC_MASK		(0x3f << 8)
+#define	CLKCTRL_FRAC1_HSADCFRAC_OFFSET		8
+#define	CLKCTRL_FRAC1_CLKGATEPIX		(1 << 7)
+#define	CLKCTRL_FRAC1_PIX_STABLE		(1 << 6)
+#define	CLKCTRL_FRAC1_PIXFRAC_MASK		0x3f
+#define	CLKCTRL_FRAC1_PIXFRAC_OFFSET		0
+
+#define	CLKCTRL_CLKSEQ_BYPASS_CPU		(1 << 18)
+#define	CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF		(1 << 14)
+#define	CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF_BYPASS	(0x1 << 14)
+#define	CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF_PFD	(0x0 << 14)
+#define	CLKCTRL_CLKSEQ_BYPASS_ETM		(1 << 8)
+#define	CLKCTRL_CLKSEQ_BYPASS_EMI		(1 << 7)
+#define	CLKCTRL_CLKSEQ_BYPASS_SSP3		(1 << 6)
+#define	CLKCTRL_CLKSEQ_BYPASS_SSP2		(1 << 5)
+#define	CLKCTRL_CLKSEQ_BYPASS_SSP1		(1 << 4)
+#define	CLKCTRL_CLKSEQ_BYPASS_SSP0		(1 << 3)
+#define	CLKCTRL_CLKSEQ_BYPASS_GPMI		(1 << 2)
+#define	CLKCTRL_CLKSEQ_BYPASS_SAIF1		(1 << 1)
+#define	CLKCTRL_CLKSEQ_BYPASS_SAIF0		(1 << 0)
+
+#define	CLKCTRL_RESET_WDOG_POR_DISABLE		(1 << 5)
+#define	CLKCTRL_RESET_EXTERNAL_RESET_ENABLE	(1 << 4)
+#define	CLKCTRL_RESET_THERMAL_RESET_ENABLE	(1 << 3)
+#define	CLKCTRL_RESET_THERMAL_RESET_DEFAULT	(1 << 2)
+#define	CLKCTRL_RESET_CHIP			(1 << 1)
+#define	CLKCTRL_RESET_DIG			(1 << 0)
+
+#define	CLKCTRL_STATUS_CPU_LIMIT_MASK		(0x3 << 30)
+#define	CLKCTRL_STATUS_CPU_LIMIT_OFFSET		30
+
+#define	CLKCTRL_VERSION_MAJOR_MASK		(0xff << 24)
+#define	CLKCTRL_VERSION_MAJOR_OFFSET		24
+#define	CLKCTRL_VERSION_MINOR_MASK		(0xff << 16)
+#define	CLKCTRL_VERSION_MINOR_OFFSET		16
+#define	CLKCTRL_VERSION_STEP_MASK		0xffff
+#define	CLKCTRL_VERSION_STEP_OFFSET		0
+
+#endif /* __MX28_REGS_CLKCTRL_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-common.h b/arch/arm/include/asm/arch-mx28/regs-common.h
new file mode 100644
index 0000000..efe975b
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-common.h
@@ -0,0 +1,66 @@
+/*
+ * Freescale i.MX28 Register Accessors
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_COMMON_H__
+#define __MX28_REGS_COMMON_H__
+
+/*
+ * The i.MX28 has interesting feature when it comes to register access. There
+ * are four kinds of access to one particular register. Those are:
+ *
+ * 1) Common read/write access. To use this mode, just write to the address of
+ *    the register.
+ * 2) Set bits only access. To set bits, write which bits you want to set to the
+ *    address of the register + 0x4.
+ * 3) Clear bits only access. To clear bits, write which bits you want to clear
+ *    to the address of the register + 0x8.
+ * 4) Toggle bits only access. To toggle bits, write which bits you want to
+ *    toggle to the address of the register + 0xc.
+ *
+ * IMPORTANT NOTE: Not all registers support accesses 2-4! Also, not all bits
+ * can be set/cleared by pure write as in access type 1, some need to be
+ * explicitly set/cleared by using access type 2-3.
+ *
+ * The following macros and structures allow the user to either access the
+ * register in all aforementioned modes (by accessing reg_name, reg_name_set,
+ * reg_name_clr, reg_name_tog) or pass the register structure further into
+ * various functions with correct type information (by accessing reg_name_reg).
+ *
+ */
+
+#define	__mx28_reg(name)		\
+	uint32_t name;			\
+	uint32_t name##_set;		\
+	uint32_t name##_clr;		\
+	uint32_t name##_tog;
+
+struct mx28_register {
+	__mx28_reg(reg)
+};
+
+#define	mx28_reg(name)					\
+	union {						\
+		struct { __mx28_reg(name) };		\
+		struct mx28_register name##_reg;	\
+	};
+
+#endif	/* __MX28_REGS_COMMON_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-gpmi.h b/arch/arm/include/asm/arch-mx28/regs-gpmi.h
new file mode 100644
index 0000000..0096793
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-gpmi.h
@@ -0,0 +1,222 @@
+/*
+ * Freescale i.MX28 GPMI Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_GPMI_H__
+#define __MX28_REGS_GPMI_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_gpmi_regs {
+	mx28_reg(hw_gpmi_ctrl0)
+	mx28_reg(hw_gpmi_compare)
+	mx28_reg(hw_gpmi_eccctrl)
+	mx28_reg(hw_gpmi_ecccount)
+	mx28_reg(hw_gpmi_payload)
+	mx28_reg(hw_gpmi_auxiliary)
+	mx28_reg(hw_gpmi_ctrl1)
+	mx28_reg(hw_gpmi_timing0)
+	mx28_reg(hw_gpmi_timing1)
+
+	uint32_t	reserved[4];
+
+	mx28_reg(hw_gpmi_data)
+	mx28_reg(hw_gpmi_stat)
+	mx28_reg(hw_gpmi_debug)
+	mx28_reg(hw_gpmi_version)
+};
+#endif
+
+#define	GPMI_CTRL0_SFTRST				(1 << 31)
+#define	GPMI_CTRL0_CLKGATE				(1 << 30)
+#define	GPMI_CTRL0_RUN					(1 << 29)
+#define	GPMI_CTRL0_DEV_IRQ_EN				(1 << 28)
+#define	GPMI_CTRL0_LOCK_CS				(1 << 27)
+#define	GPMI_CTRL0_UDMA					(1 << 26)
+#define	GPMI_CTRL0_COMMAND_MODE_MASK			(0x3 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_OFFSET			24
+#define	GPMI_CTRL0_COMMAND_MODE_WRITE			(0x0 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_READ			(0x1 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_READ_AND_COMPARE	(0x2 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY		(0x3 << 24)
+#define	GPMI_CTRL0_WORD_LENGTH				(1 << 23)
+#define	GPMI_CTRL0_CS_MASK				(0x7 << 20)
+#define	GPMI_CTRL0_CS_OFFSET				20
+#define	GPMI_CTRL0_ADDRESS_MASK				(0x7 << 17)
+#define	GPMI_CTRL0_ADDRESS_OFFSET			17
+#define	GPMI_CTRL0_ADDRESS_NAND_DATA			(0x0 << 17)
+#define	GPMI_CTRL0_ADDRESS_NAND_CLE			(0x1 << 17)
+#define	GPMI_CTRL0_ADDRESS_NAND_ALE			(0x2 << 17)
+#define	GPMI_CTRL0_ADDRESS_INCREMENT			(1 << 16)
+#define	GPMI_CTRL0_XFER_COUNT_MASK			0xffff
+#define	GPMI_CTRL0_XFER_COUNT_OFFSET			0
+
+#define	GPMI_COMPARE_MASK_MASK				(0xffff << 16)
+#define	GPMI_COMPARE_MASK_OFFSET			16
+#define	GPMI_COMPARE_REFERENCE_MASK			0xffff
+#define	GPMI_COMPARE_REFERENCE_OFFSET			0
+
+#define	GPMI_ECCCTRL_HANDLE_MASK			(0xffff << 16)
+#define	GPMI_ECCCTRL_HANDLE_OFFSET			16
+#define	GPMI_ECCCTRL_ECC_CMD_MASK			(0x3 << 13)
+#define	GPMI_ECCCTRL_ECC_CMD_OFFSET			13
+#define	GPMI_ECCCTRL_ECC_CMD_DECODE			(0x0 << 13)
+#define	GPMI_ECCCTRL_ECC_CMD_ENCODE			(0x1 << 13)
+#define	GPMI_ECCCTRL_ENABLE_ECC				(1 << 12)
+#define	GPMI_ECCCTRL_BUFFER_MASK_MASK			0x1ff
+#define	GPMI_ECCCTRL_BUFFER_MASK_OFFSET			0
+#define	GPMI_ECCCTRL_BUFFER_MASK_BCH_AUXONLY		0x100
+#define	GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE		0x1ff
+
+#define	GPMI_ECCCOUNT_COUNT_MASK			0xffff
+#define	GPMI_ECCCOUNT_COUNT_OFFSET			0
+
+#define	GPMI_PAYLOAD_ADDRESS_MASK			(0x3fffffff << 2)
+#define	GPMI_PAYLOAD_ADDRESS_OFFSET			2
+
+#define	GPMI_AUXILIARY_ADDRESS_MASK			(0x3fffffff << 2)
+#define	GPMI_AUXILIARY_ADDRESS_OFFSET			2
+
+#define	GPMI_CTRL1_DECOUPLE_CS				(1 << 24)
+#define	GPMI_CTRL1_WRN_DLY_SEL_MASK			(0x3 << 22)
+#define	GPMI_CTRL1_WRN_DLY_SEL_OFFSET			22
+#define	GPMI_CTRL1_TIMEOUT_IRQ_EN			(1 << 20)
+#define	GPMI_CTRL1_GANGED_RDYBUSY			(1 << 19)
+#define	GPMI_CTRL1_BCH_MODE				(1 << 18)
+#define	GPMI_CTRL1_DLL_ENABLE				(1 << 17)
+#define	GPMI_CTRL1_HALF_PERIOD				(1 << 16)
+#define	GPMI_CTRL1_RDN_DELAY_MASK			(0xf << 12)
+#define	GPMI_CTRL1_RDN_DELAY_OFFSET			12
+#define	GPMI_CTRL1_DMA2ECC_MODE				(1 << 11)
+#define	GPMI_CTRL1_DEV_IRQ				(1 << 10)
+#define	GPMI_CTRL1_TIMEOUT_IRQ				(1 << 9)
+#define	GPMI_CTRL1_BURST_EN				(1 << 8)
+#define	GPMI_CTRL1_ABORT_WAIT_REQUEST			(1 << 7)
+#define	GPMI_CTRL1_ABORT_WAIT_FOR_READY_CHANNEL_MASK	(0x7 << 4)
+#define	GPMI_CTRL1_ABORT_WAIT_FOR_READY_CHANNEL_OFFSET	4
+#define	GPMI_CTRL1_DEV_RESET				(1 << 3)
+#define	GPMI_CTRL1_ATA_IRQRDY_POLARITY			(1 << 2)
+#define	GPMI_CTRL1_CAMERA_MODE				(1 << 1)
+#define	GPMI_CTRL1_GPMI_MODE				(1 << 0)
+
+#define	GPMI_TIMING0_ADDRESS_SETUP_MASK			(0xff << 16)
+#define	GPMI_TIMING0_ADDRESS_SETUP_OFFSET		16
+#define	GPMI_TIMING0_DATA_HOLD_MASK			(0xff << 8)
+#define	GPMI_TIMING0_DATA_HOLD_OFFSET			8
+#define	GPMI_TIMING0_DATA_SETUP_MASK			0xff
+#define	GPMI_TIMING0_DATA_SETUP_OFFSET			0
+
+#define	GPMI_TIMING1_DEVICE_BUSY_TIMEOUT_MASK		(0xffff << 16)
+#define	GPMI_TIMING1_DEVICE_BUSY_TIMEOUT_OFFSET		16
+
+#define	GPMI_TIMING2_UDMA_TRP_MASK			(0xff << 24)
+#define	GPMI_TIMING2_UDMA_TRP_OFFSET			24
+#define	GPMI_TIMING2_UDMA_ENV_MASK			(0xff << 16)
+#define	GPMI_TIMING2_UDMA_ENV_OFFSET			16
+#define	GPMI_TIMING2_UDMA_HOLD_MASK			(0xff << 8)
+#define	GPMI_TIMING2_UDMA_HOLD_OFFSET			8
+#define	GPMI_TIMING2_UDMA_SETUP_MASK			0xff
+#define	GPMI_TIMING2_UDMA_SETUP_OFFSET			0
+
+#define	GPMI_DATA_DATA_MASK				0xffffffff
+#define	GPMI_DATA_DATA_OFFSET				0
+
+#define	GPMI_STAT_READY_BUSY_MASK			(0xff << 24)
+#define	GPMI_STAT_READY_BUSY_OFFSET			24
+#define	GPMI_STAT_RDY_TIMEOUT_MASK			(0xff << 16)
+#define	GPMI_STAT_RDY_TIMEOUT_OFFSET			16
+#define	GPMI_STAT_DEV7_ERROR				(1 << 15)
+#define	GPMI_STAT_DEV6_ERROR				(1 << 14)
+#define	GPMI_STAT_DEV5_ERROR				(1 << 13)
+#define	GPMI_STAT_DEV4_ERROR				(1 << 12)
+#define	GPMI_STAT_DEV3_ERROR				(1 << 11)
+#define	GPMI_STAT_DEV2_ERROR				(1 << 10)
+#define	GPMI_STAT_DEV1_ERROR				(1 << 9)
+#define	GPMI_STAT_DEV0_ERROR				(1 << 8)
+#define	GPMI_STAT_ATA_IRQ				(1 << 4)
+#define	GPMI_STAT_INVALID_BUFFER_MASK			(1 << 3)
+#define	GPMI_STAT_FIFO_EMPTY				(1 << 2)
+#define	GPMI_STAT_FIFO_FULL				(1 << 1)
+#define	GPMI_STAT_PRESENT				(1 << 0)
+
+#define	GPMI_DEBUG_WAIT_FOR_READY_END_MASK		(0xff << 24)
+#define	GPMI_DEBUG_WAIT_FOR_READY_END_OFFSET		24
+#define	GPMI_DEBUG_DMA_SENSE_MASK			(0xff << 16)
+#define	GPMI_DEBUG_DMA_SENSE_OFFSET			16
+#define	GPMI_DEBUG_DMAREQ_MASK				(0xff << 8)
+#define	GPMI_DEBUG_DMAREQ_OFFSET			8
+#define	GPMI_DEBUG_CMD_END_MASK				0xff
+#define	GPMI_DEBUG_CMD_END_OFFSET			0
+
+#define	GPMI_VERSION_MAJOR_MASK				(0xff << 24)
+#define	GPMI_VERSION_MAJOR_OFFSET			24
+#define	GPMI_VERSION_MINOR_MASK				(0xff << 16)
+#define	GPMI_VERSION_MINOR_OFFSET			16
+#define	GPMI_VERSION_STEP_MASK				0xffff
+#define	GPMI_VERSION_STEP_OFFSET			0
+
+#define	GPMI_DEBUG2_UDMA_STATE_MASK			(0xf << 24)
+#define	GPMI_DEBUG2_UDMA_STATE_OFFSET			24
+#define	GPMI_DEBUG2_BUSY				(1 << 23)
+#define	GPMI_DEBUG2_PIN_STATE_MASK			(0x7 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_OFFSET			20
+#define	GPMI_DEBUG2_PIN_STATE_PSM_IDLE			(0x0 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_BYTCNT		(0x1 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_ADDR			(0x2 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_STALL			(0x3 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_STROBE		(0x4 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_ATARDY		(0x5 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_DHOLD			(0x6 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_DONE			(0x7 << 20)
+#define	GPMI_DEBUG2_MAIN_STATE_MASK			(0xf << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_OFFSET			16
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_IDLE			(0x0 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_BYTCNT		(0x1 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_WAITFE		(0x2 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_WAITFR		(0x3 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_DMAREQ		(0x4 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_DMAACK		(0x5 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_WAITFF		(0x6 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_LDFIFO		(0x7 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_LDDMAR		(0x8 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_RDCMP		(0x9 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_DONE			(0xa << 16)
+#define	GPMI_DEBUG2_SYND2GPMI_BE_MASK			(0xf << 12)
+#define	GPMI_DEBUG2_SYND2GPMI_BE_OFFSET			12
+#define	GPMI_DEBUG2_GPMI2SYND_VALID			(1 << 11)
+#define	GPMI_DEBUG2_GPMI2SYND_READY			(1 << 10)
+#define	GPMI_DEBUG2_SYND2GPMI_VALID			(1 << 9)
+#define	GPMI_DEBUG2_SYND2GPMI_READY			(1 << 8)
+#define	GPMI_DEBUG2_VIEW_DELAYED_RDN			(1 << 7)
+#define	GPMI_DEBUG2_UPDATE_WINDOW			(1 << 6)
+#define	GPMI_DEBUG2_RDN_TAP_MASK			0x3f
+#define	GPMI_DEBUG2_RDN_TAP_OFFSET			0
+
+#define	GPMI_DEBUG3_APB_WORD_CNTR_MASK			(0xffff << 16)
+#define	GPMI_DEBUG3_APB_WORD_CNTR_OFFSET		16
+#define	GPMI_DEBUG3_DEV_WORD_CNTR_MASK			0xffff
+#define	GPMI_DEBUG3_DEV_WORD_CNTR_OFFSET		0
+
+#endif	/* __MX28_REGS_GPMI_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-i2c.h b/arch/arm/include/asm/arch-mx28/regs-i2c.h
new file mode 100644
index 0000000..30e0ed7
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-i2c.h
@@ -0,0 +1,207 @@
+/*
+ * Freescale i.MX28 I2C Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_I2C_H__
+#define __MX28_REGS_I2C_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_i2c_regs {
+	mx28_reg(hw_i2c_ctrl0)
+	mx28_reg(hw_i2c_timing0)
+	mx28_reg(hw_i2c_timing1)
+	mx28_reg(hw_i2c_timing2)
+	mx28_reg(hw_i2c_ctrl1)
+	mx28_reg(hw_i2c_stat)
+	mx28_reg(hw_i2c_queuectrl)
+	mx28_reg(hw_i2c_queuestat)
+	mx28_reg(hw_i2c_queuecmd)
+	mx28_reg(hw_i2c_queuedata)
+	mx28_reg(hw_i2c_data)
+	mx28_reg(hw_i2c_debug0)
+	mx28_reg(hw_i2c_debug1)
+	mx28_reg(hw_i2c_version)
+};
+#endif
+
+#define	I2C_CTRL_SFTRST				(1 << 31)
+#define	I2C_CTRL_CLKGATE			(1 << 30)
+#define	I2C_CTRL_RUN				(1 << 29)
+#define	I2C_CTRL_PREACK				(1 << 27)
+#define	I2C_CTRL_ACKNOWLEDGE			(1 << 26)
+#define	I2C_CTRL_SEND_NAK_ON_LAST		(1 << 25)
+#define	I2C_CTRL_MULTI_MASTER			(1 << 23)
+#define	I2C_CTRL_CLOCK_HELD			(1 << 22)
+#define	I2C_CTRL_RETAIN_CLOCK			(1 << 21)
+#define	I2C_CTRL_POST_SEND_STOP			(1 << 20)
+#define	I2C_CTRL_PRE_SEND_START			(1 << 19)
+#define	I2C_CTRL_SLAVE_ADDRESS_ENABLE		(1 << 18)
+#define	I2C_CTRL_MASTER_MODE			(1 << 17)
+#define	I2C_CTRL_DIRECTION			(1 << 16)
+#define	I2C_CTRL_XFER_COUNT_MASK		0xffff
+#define	I2C_CTRL_XFER_COUNT_OFFSET		0
+
+#define	I2C_TIMING0_HIGH_COUNT_MASK		(0x3ff << 16)
+#define	I2C_TIMING0_HIGH_COUNT_OFFSET		16
+#define	I2C_TIMING0_RCV_COUNT_MASK		0x3ff
+#define	I2C_TIMING0_RCV_COUNT_OFFSET		0
+
+#define	I2C_TIMING1_LOW_COUNT_MASK		(0x3ff << 16)
+#define	I2C_TIMING1_LOW_COUNT_OFFSET		16
+#define	I2C_TIMING1_XMIT_COUNT_MASK		0x3ff
+#define	I2C_TIMING1_XMIT_COUNT_OFFSET		0
+
+#define	I2C_TIMING2_BUS_FREE_MASK		(0x3ff << 16)
+#define	I2C_TIMING2_BUS_FREE_OFFSET		16
+#define	I2C_TIMING2_LEADIN_COUNT_MASK		0x3ff
+#define	I2C_TIMING2_LEADIN_COUNT_OFFSET		0
+
+#define	I2C_CTRL1_RD_QUEUE_IRQ			(1 << 30)
+#define	I2C_CTRL1_WR_QUEUE_IRQ			(1 << 29)
+#define	I2C_CTRL1_CLR_GOT_A_NAK			(1 << 28)
+#define	I2C_CTRL1_ACK_MODE			(1 << 27)
+#define	I2C_CTRL1_FORCE_DATA_IDLE		(1 << 26)
+#define	I2C_CTRL1_FORCE_CLK_IDLE		(1 << 25)
+#define	I2C_CTRL1_BCAST_SLAVE_EN		(1 << 24)
+#define	I2C_CTRL1_SLAVE_ADDRESS_BYTE_MASK	(0xff << 16)
+#define	I2C_CTRL1_SLAVE_ADDRESS_BYTE_OFFSET	16
+#define	I2C_CTRL1_BUS_FREE_IRQ_EN		(1 << 15)
+#define	I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ_EN	(1 << 14)
+#define	I2C_CTRL1_NO_SLAVE_ACK_IRQ_EN		(1 << 13)
+#define	I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ_EN	(1 << 12)
+#define	I2C_CTRL1_EARLY_TERM_IRQ_EN		(1 << 11)
+#define	I2C_CTRL1_MASTER_LOSS_IRQ_EN		(1 << 10)
+#define	I2C_CTRL1_SLAVE_STOP_IRQ_EN		(1 << 9)
+#define	I2C_CTRL1_SLAVE_IRQ_EN			(1 << 8)
+#define	I2C_CTRL1_BUS_FREE_IRQ			(1 << 7)
+#define	I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ		(1 << 6)
+#define	I2C_CTRL1_NO_SLAVE_ACK_IRQ		(1 << 5)
+#define	I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ	(1 << 4)
+#define	I2C_CTRL1_EARLY_TERM_IRQ		(1 << 3)
+#define	I2C_CTRL1_MASTER_LOSS_IRQ		(1 << 2)
+#define	I2C_CTRL1_SLAVE_STOP_IRQ		(1 << 1)
+#define	I2C_CTRL1_SLAVE_IRQ			(1 << 0)
+
+#define	I2C_STAT_MASTER_PRESENT			(1 << 31)
+#define	I2C_STAT_SLAVE_PRESENT			(1 << 30)
+#define	I2C_STAT_ANY_ENABLED_IRQ		(1 << 29)
+#define	I2C_STAT_GOT_A_NAK			(1 << 28)
+#define	I2C_STAT_RCVD_SLAVE_ADDR_MASK		(0xff << 16)
+#define	I2C_STAT_RCVD_SLAVE_ADDR_OFFSET		16
+#define	I2C_STAT_SLAVE_ADDR_EQ_ZERO		(1 << 15)
+#define	I2C_STAT_SLAVE_FOUND			(1 << 14)
+#define	I2C_STAT_SLAVE_SEARCHING		(1 << 13)
+#define	I2C_STAT_DATA_ENGING_DMA_WAIT		(1 << 12)
+#define	I2C_STAT_BUS_BUSY			(1 << 11)
+#define	I2C_STAT_CLK_GEN_BUSY			(1 << 10)
+#define	I2C_STAT_DATA_ENGINE_BUSY		(1 << 9)
+#define	I2C_STAT_SLAVE_BUSY			(1 << 8)
+#define	I2C_STAT_BUS_FREE_IRQ_SUMMARY		(1 << 7)
+#define	I2C_STAT_DATA_ENGINE_CMPLT_IRQ_SUMMARY	(1 << 6)
+#define	I2C_STAT_NO_SLAVE_ACK_IRQ_SUMMARY	(1 << 5)
+#define	I2C_STAT_OVERSIZE_XFER_TERM_IRQ_SUMMARY	(1 << 4)
+#define	I2C_STAT_EARLY_TERM_IRQ_SUMMARY		(1 << 3)
+#define	I2C_STAT_MASTER_LOSS_IRQ_SUMMARY	(1 << 2)
+#define	I2C_STAT_SLAVE_STOP_IRQ_SUMMARY		(1 << 1)
+#define	I2C_STAT_SLAVE_IRQ_SUMMARY		(1 << 0)
+
+#define	I2C_QUEUECTRL_RD_THRESH_MASK		(0x1f << 16)
+#define	I2C_QUEUECTRL_RD_THRESH_OFFSET		16
+#define	I2C_QUEUECTRL_WR_THRESH_MASK		(0x1f << 8)
+#define	I2C_QUEUECTRL_WR_THRESH_OFFSET		8
+#define	I2C_QUEUECTRL_QUEUE_RUN			(1 << 5)
+#define	I2C_QUEUECTRL_RD_CLEAR			(1 << 4)
+#define	I2C_QUEUECTRL_WR_CLEAR			(1 << 3)
+#define	I2C_QUEUECTRL_PIO_QUEUE_MODE		(1 << 2)
+#define	I2C_QUEUECTRL_RD_QUEUE_IRQ_EN		(1 << 1)
+#define	I2C_QUEUECTRL_WR_QUEUE_IRQ_EN		(1 << 0)
+
+#define	I2C_QUEUESTAT_RD_QUEUE_FULL		(1 << 14)
+#define	I2C_QUEUESTAT_RD_QUEUE_EMPTY		(1 << 13)
+#define	I2C_QUEUESTAT_RD_QUEUE_CNT_MASK		(0x1f << 8)
+#define	I2C_QUEUESTAT_RD_QUEUE_CNT_OFFSET	8
+#define	I2C_QUEUESTAT_WR_QUEUE_FULL		(1 << 6)
+#define	I2C_QUEUESTAT_WR_QUEUE_EMPTY		(1 << 5)
+#define	I2C_QUEUESTAT_WR_QUEUE_CNT_MASK		0x1f
+#define	I2C_QUEUESTAT_WR_QUEUE_CNT_OFFSET	0
+
+#define	I2C_QUEUECMD_PREACK			(1 << 27)
+#define	I2C_QUEUECMD_ACKNOWLEDGE		(1 << 26)
+#define	I2C_QUEUECMD_SEND_NAK_ON_LAST		(1 << 25)
+#define	I2C_QUEUECMD_MULTI_MASTER		(1 << 23)
+#define	I2C_QUEUECMD_CLOCK_HELD			(1 << 22)
+#define	I2C_QUEUECMD_RETAIN_CLOCK		(1 << 21)
+#define	I2C_QUEUECMD_POST_SEND_STOP		(1 << 20)
+#define	I2C_QUEUECMD_PRE_SEND_START		(1 << 19)
+#define	I2C_QUEUECMD_SLAVE_ADDRESS_ENABLE	(1 << 18)
+#define	I2C_QUEUECMD_MASTER_MODE		(1 << 17)
+#define	I2C_QUEUECMD_DIRECTION			(1 << 16)
+#define	I2C_QUEUECMD_XFER_COUNT_MASK		0xffff
+#define	I2C_QUEUECMD_XFER_COUNT_OFFSET		0
+
+#define	I2C_QUEUEDATA_DATA_MASK			0xffffffff
+#define	I2C_QUEUEDATA_DATA_OFFSET		0
+
+#define	I2C_DATA_DATA_MASK			0xffffffff
+#define	I2C_DATA_DATA_OFFSET			0
+
+#define	I2C_DEBUG0_DMAREQ			(1 << 31)
+#define	I2C_DEBUG0_DMAENDCMD			(1 << 30)
+#define	I2C_DEBUG0_DMAKICK			(1 << 29)
+#define	I2C_DEBUG0_DMATERMINATE			(1 << 28)
+#define	I2C_DEBUG0_STATE_VALUE_MASK		(0x3 << 26)
+#define	I2C_DEBUG0_STATE_VALUE_OFFSET		26
+#define	I2C_DEBUG0_DMA_STATE_MASK		(0x3ff << 16)
+#define	I2C_DEBUG0_DMA_STATE_OFFSET		16
+#define	I2C_DEBUG0_START_TOGGLE			(1 << 15)
+#define	I2C_DEBUG0_STOP_TOGGLE			(1 << 14)
+#define	I2C_DEBUG0_GRAB_TOGGLE			(1 << 13)
+#define	I2C_DEBUG0_CHANGE_TOGGLE		(1 << 12)
+#define	I2C_DEBUG0_STATE_LATCH			(1 << 11)
+#define	I2C_DEBUG0_SLAVE_HOLD_CLK		(1 << 10)
+#define	I2C_DEBUG0_STATE_STATE_MASK		0x3ff
+#define	I2C_DEBUG0_STATE_STATE_OFFSET		0
+
+#define	I2C_DEBUG1_I2C_CLK_IN			(1 << 31)
+#define	I2C_DEBUG1_I2C_DATA_IN			(1 << 30)
+#define	I2C_DEBUG1_DMA_BYTE_ENABLES_MASK	(0xf << 24)
+#define	I2C_DEBUG1_DMA_BYTE_ENABLES_OFFSET	24
+#define	I2C_DEBUG1_CLK_GEN_STATE_MASK		(0xff << 16)
+#define	I2C_DEBUG1_CLK_GEN_STATE_OFFSET		16
+#define	I2C_DEBUG1_LST_MODE_MASK		(0x3 << 9)
+#define	I2C_DEBUG1_LST_MODE_OFFSET		9
+#define	I2C_DEBUG1_LOCAL_SLAVE_TEST		(1 << 8)
+#define	I2C_DEBUG1_FORCE_CLK_ON			(1 << 4)
+#define	I2C_DEBUG1_FORCE_ABR_LOSS		(1 << 3)
+#define	I2C_DEBUG1_FORCE_RCV_ACK		(1 << 2)
+#define	I2C_DEBUG1_FORCE_I2C_DATA_OE		(1 << 1)
+#define	I2C_DEBUG1_FORCE_I2C_CLK_OE		(1 << 0)
+
+#define	I2C_VERSION_MAJOR_MASK			(0xff << 24)
+#define	I2C_VERSION_MAJOR_OFFSET		24
+#define	I2C_VERSION_MINOR_MASK			(0xff << 16)
+#define	I2C_VERSION_MINOR_OFFSET		16
+#define	I2C_VERSION_STEP_MASK			0xffff
+#define	I2C_VERSION_STEP_OFFSET			0
+
+#endif	/* __MX28_REGS_I2C_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-ocotp.h b/arch/arm/include/asm/arch-mx28/regs-ocotp.h
new file mode 100644
index 0000000..ea2fd7b
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-ocotp.h
@@ -0,0 +1,173 @@
+/*
+ * Freescale i.MX28 OCOTP Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_OCOTP_H__
+#define __MX28_REGS_OCOTP_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_ocotp_regs {
+	mx28_reg(hw_ocotp_ctrl)		/* 0x0 */
+	mx28_reg(hw_ocotp_data)		/* 0x10 */
+	mx28_reg(hw_ocotp_cust0)	/* 0x20 */
+	mx28_reg(hw_ocotp_cust1)	/* 0x30 */
+	mx28_reg(hw_ocotp_cust2)	/* 0x40 */
+	mx28_reg(hw_ocotp_cust3)	/* 0x50 */
+	mx28_reg(hw_ocotp_crypto0)	/* 0x60 */
+	mx28_reg(hw_ocotp_crypto1)	/* 0x70 */
+	mx28_reg(hw_ocotp_crypto2)	/* 0x80 */
+	mx28_reg(hw_ocotp_crypto3)	/* 0x90 */
+	mx28_reg(hw_ocotp_hwcap0)	/* 0xa0 */
+	mx28_reg(hw_ocotp_hwcap1)	/* 0xb0 */
+	mx28_reg(hw_ocotp_hwcap2)	/* 0xc0 */
+	mx28_reg(hw_ocotp_hwcap3)	/* 0xd0 */
+	mx28_reg(hw_ocotp_hwcap4)	/* 0xe0 */
+	mx28_reg(hw_ocotp_hwcap5)	/* 0xf0 */
+	mx28_reg(hw_ocotp_swcap)	/* 0x100 */
+	mx28_reg(hw_ocotp_custcap)	/* 0x110 */
+	mx28_reg(hw_ocotp_lock)		/* 0x120 */
+	mx28_reg(hw_ocotp_ops0)		/* 0x130 */
+	mx28_reg(hw_ocotp_ops1)		/* 0x140 */
+	mx28_reg(hw_ocotp_ops2)		/* 0x150 */
+	mx28_reg(hw_ocotp_ops3)		/* 0x160 */
+	mx28_reg(hw_ocotp_un0)		/* 0x170 */
+	mx28_reg(hw_ocotp_un1)		/* 0x180 */
+	mx28_reg(hw_ocotp_un2)		/* 0x190 */
+	mx28_reg(hw_ocotp_rom0)		/* 0x1a0 */
+	mx28_reg(hw_ocotp_rom1)		/* 0x1b0 */
+	mx28_reg(hw_ocotp_rom2)		/* 0x1c0 */
+	mx28_reg(hw_ocotp_rom3)		/* 0x1d0 */
+	mx28_reg(hw_ocotp_rom4)		/* 0x1e0 */
+	mx28_reg(hw_ocotp_rom5)		/* 0x1f0 */
+	mx28_reg(hw_ocotp_rom6)		/* 0x200 */
+	mx28_reg(hw_ocotp_rom7)		/* 0x210 */
+	mx28_reg(hw_ocotp_srk0)		/* 0x220 */
+	mx28_reg(hw_ocotp_srk1)		/* 0x230 */
+	mx28_reg(hw_ocotp_srk2)		/* 0x240 */
+	mx28_reg(hw_ocotp_srk3)		/* 0x250 */
+	mx28_reg(hw_ocotp_srk4)		/* 0x260 */
+	mx28_reg(hw_ocotp_srk5)		/* 0x270 */
+	mx28_reg(hw_ocotp_srk6)		/* 0x280 */
+	mx28_reg(hw_ocotp_srk7)		/* 0x290 */
+	mx28_reg(hw_ocotp_version)	/* 0x2a0 */
+};
+#endif
+
+#define	OCOTP_CTRL_WR_UNLOCK_MASK		(0xffff << 16)
+#define	OCOTP_CTRL_WR_UNLOCK_OFFSET		16
+#define	OCOTP_CTRL_WR_UNLOCK_KEY		(0x3e77 << 16)
+#define	OCOTP_CTRL_RELOAD_SHADOWS		(1 << 13)
+#define	OCOTP_CTRL_RD_BANK_OPEN			(1 << 12)
+#define	OCOTP_CTRL_ERROR			(1 << 9)
+#define	OCOTP_CTRL_BUSY				(1 << 8)
+#define	OCOTP_CTRL_ADDR_MASK			0x3f
+#define	OCOTP_CTRL_ADDR_OFFSET			0
+
+#define	OCOTP_DATA_DATA_MASK			0xffffffff
+#define	OCOTP_DATA_DATA_OFFSET			0
+
+#define	OCOTP_CUST_BITS_MASK			0xffffffff
+#define	OCOTP_CUST_BITS_OFFSET			0
+
+#define	OCOTP_CRYPTO_BITS_MASK			0xffffffff
+#define	OCOTP_CRYPTO_BITS_OFFSET		0
+
+#define	OCOTP_HWCAP_BITS_MASK			0xffffffff
+#define	OCOTP_HWCAP_BITS_OFFSET			0
+
+#define	OCOTP_SWCAP_BITS_MASK			0xffffffff
+#define	OCOTP_SWCAP_BITS_OFFSET			0
+
+#define	OCOTP_CUSTCAP_RTC_XTAL_32768_PRESENT	(1 << 2)
+#define	OCOTP_CUSTCAP_RTC_XTAL_32000_PRESENT	(1 << 1)
+
+#define	OCOTP_LOCK_ROM7				(1 << 31)
+#define	OCOTP_LOCK_ROM6				(1 << 30)
+#define	OCOTP_LOCK_ROM5				(1 << 29)
+#define	OCOTP_LOCK_ROM4				(1 << 28)
+#define	OCOTP_LOCK_ROM3				(1 << 27)
+#define	OCOTP_LOCK_ROM2				(1 << 26)
+#define	OCOTP_LOCK_ROM1				(1 << 25)
+#define	OCOTP_LOCK_ROM0				(1 << 24)
+#define	OCOTP_LOCK_HWSW_SHADOW_ALT		(1 << 23)
+#define	OCOTP_LOCK_CRYPTODCP_ALT		(1 << 22)
+#define	OCOTP_LOCK_CRYPTOKEY_ALT		(1 << 21)
+#define	OCOTP_LOCK_PIN				(1 << 20)
+#define	OCOTP_LOCK_OPS				(1 << 19)
+#define	OCOTP_LOCK_UN2				(1 << 18)
+#define	OCOTP_LOCK_UN1				(1 << 17)
+#define	OCOTP_LOCK_UN0				(1 << 16)
+#define	OCOTP_LOCK_SRK				(1 << 15)
+#define	OCOTP_LOCK_UNALLOCATED_MASK		(0x7 << 12)
+#define	OCOTP_LOCK_UNALLOCATED_OFFSET		12
+#define	OCOTP_LOCK_SRK_SHADOW			(1 << 11)
+#define	OCOTP_LOCK_ROM_SHADOW			(1 << 10)
+#define	OCOTP_LOCK_CUSTCAP			(1 << 9)
+#define	OCOTP_LOCK_HWSW				(1 << 8)
+#define	OCOTP_LOCK_CUSTCAP_SHADOW		(1 << 7)
+#define	OCOTP_LOCK_HWSW_SHADOW			(1 << 6)
+#define	OCOTP_LOCK_CRYPTODCP			(1 << 5)
+#define	OCOTP_LOCK_CRYPTOKEY			(1 << 4)
+#define	OCOTP_LOCK_CUST3			(1 << 3)
+#define	OCOTP_LOCK_CUST2			(1 << 2)
+#define	OCOTP_LOCK_CUST1			(1 << 1)
+#define	OCOTP_LOCK_CUST0			(1 << 0)
+
+#define	OCOTP_OPS_BITS_MASK			0xffffffff
+#define	OCOTP_OPS_BITS_OFFSET			0
+
+#define	OCOTP_UN_BITS_MASK			0xffffffff
+#define	OCOTP_UN_BITS_OFFSET			0
+
+#define	OCOTP_ROM_BOOT_MODE_MASK		(0xff << 24)
+#define	OCOTP_ROM_BOOT_MODE_OFFSET		24
+#define	OCOTP_ROM_SD_MMC_MODE_MASK		(0x3 << 22)
+#define	OCOTP_ROM_SD_MMC_MODE_OFFSET		22
+#define	OCOTP_ROM_SD_POWER_GATE_GPIO_MASK	(0x3 << 20)
+#define	OCOTP_ROM_SD_POWER_GATE_GPIO_OFFSET	20
+#define	OCOTP_ROM_SD_POWER_UP_DELAY_MASK	(0x3f << 14)
+#define	OCOTP_ROM_SD_POWER_UP_DELAY_OFFSET	14
+#define	OCOTP_ROM_SD_BUS_WIDTH_MASK		(0x3 << 12)
+#define	OCOTP_ROM_SD_BUS_WIDTH_OFFSET		12
+#define	OCOTP_ROM_SSP_SCK_INDEX_MASK		(0xf << 8)
+#define	OCOTP_ROM_SSP_SCK_INDEX_OFFSET		8
+#define	OCOTP_ROM_EMMC_USE_DDR			(1 << 7)
+#define	OCOTP_ROM_DISABLE_SPI_NOR_FAST_READ	(1 << 6)
+#define	OCOTP_ROM_ENABLE_USB_BOOT_SERIAL_NUM	(1 << 5)
+#define	OCOTP_ROM_ENABLE_UNENCRYPTED_BOOT	(1 << 4)
+#define	OCOTP_ROM_SD_MBR_BOOT			(1 << 3)
+
+#define	OCOTP_SRK_BITS_MASK			0xffffffff
+#define	OCOTP_SRK_BITS_OFFSET			0
+
+#define	OCOTP_VERSION_MAJOR_MASK		(0xff << 24)
+#define	OCOTP_VERSION_MAJOR_OFFSET		24
+#define	OCOTP_VERSION_MINOR_MASK		(0xff << 16)
+#define	OCOTP_VERSION_MINOR_OFFSET		16
+#define	OCOTP_VERSION_STEP_MASK			0xffff
+#define	OCOTP_VERSION_STEP_OFFSET		0
+
+#endif /* __MX28_REGS_OCOTP_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-pinctrl.h b/arch/arm/include/asm/arch-mx28/regs-pinctrl.h
new file mode 100644
index 0000000..73739ca
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-pinctrl.h
@@ -0,0 +1,1284 @@
+/*
+ * Freescale i.MX28 PINCTRL Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_PINCTRL_H__
+#define __MX28_REGS_PINCTRL_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_pinctrl_regs {
+	mx28_reg(hw_pinctrl_ctrl)		/* 0x0 */
+
+	uint32_t	reserved1[60];
+
+	mx28_reg(hw_pinctrl_muxsel0)		/* 0x100 */
+	mx28_reg(hw_pinctrl_muxsel1)		/* 0x110 */
+	mx28_reg(hw_pinctrl_muxsel2)		/* 0x120 */
+	mx28_reg(hw_pinctrl_muxsel3)		/* 0x130 */
+	mx28_reg(hw_pinctrl_muxsel4)		/* 0x140 */
+	mx28_reg(hw_pinctrl_muxsel5)		/* 0x150 */
+	mx28_reg(hw_pinctrl_muxsel6)		/* 0x160 */
+	mx28_reg(hw_pinctrl_muxsel7)		/* 0x170 */
+	mx28_reg(hw_pinctrl_muxsel8)		/* 0x180 */
+	mx28_reg(hw_pinctrl_muxsel9)		/* 0x190 */
+	mx28_reg(hw_pinctrl_muxsel10)		/* 0x1a0 */
+	mx28_reg(hw_pinctrl_muxsel11)		/* 0x1b0 */
+	mx28_reg(hw_pinctrl_muxsel12)		/* 0x1c0 */
+	mx28_reg(hw_pinctrl_muxsel13)		/* 0x1d0 */
+
+	uint32_t	reserved2[72];
+
+	mx28_reg(hw_pinctrl_drive0)		/* 0x300 */
+	mx28_reg(hw_pinctrl_drive1)		/* 0x310 */
+	mx28_reg(hw_pinctrl_drive2)		/* 0x320 */
+	mx28_reg(hw_pinctrl_drive3)		/* 0x330 */
+	mx28_reg(hw_pinctrl_drive4)		/* 0x340 */
+	mx28_reg(hw_pinctrl_drive5)		/* 0x350 */
+	mx28_reg(hw_pinctrl_drive6)		/* 0x360 */
+	mx28_reg(hw_pinctrl_drive7)		/* 0x370 */
+	mx28_reg(hw_pinctrl_drive8)		/* 0x380 */
+	mx28_reg(hw_pinctrl_drive9)		/* 0x390 */
+	mx28_reg(hw_pinctrl_drive10)		/* 0x3a0 */
+	mx28_reg(hw_pinctrl_drive11)		/* 0x3b0 */
+	mx28_reg(hw_pinctrl_drive12)		/* 0x3c0 */
+	mx28_reg(hw_pinctrl_drive13)		/* 0x3d0 */
+	mx28_reg(hw_pinctrl_drive14)		/* 0x3e0 */
+	mx28_reg(hw_pinctrl_drive15)		/* 0x3f0 */
+	mx28_reg(hw_pinctrl_drive16)		/* 0x400 */
+	mx28_reg(hw_pinctrl_drive17)		/* 0x410 */
+	mx28_reg(hw_pinctrl_drive18)		/* 0x420 */
+	mx28_reg(hw_pinctrl_drive19)		/* 0x430 */
+
+	uint32_t	reserved3[112];
+
+	mx28_reg(hw_pinctrl_pull0)		/* 0x600 */
+	mx28_reg(hw_pinctrl_pull1)		/* 0x610 */
+	mx28_reg(hw_pinctrl_pull2)		/* 0x620 */
+	mx28_reg(hw_pinctrl_pull3)		/* 0x630 */
+	mx28_reg(hw_pinctrl_pull4)		/* 0x640 */
+	mx28_reg(hw_pinctrl_pull5)		/* 0x650 */
+	mx28_reg(hw_pinctrl_pull6)		/* 0x660 */
+
+	uint32_t	reserved4[36];
+
+	mx28_reg(hw_pinctrl_dout0)		/* 0x700 */
+	mx28_reg(hw_pinctrl_dout1)		/* 0x710 */
+	mx28_reg(hw_pinctrl_dout2)		/* 0x720 */
+	mx28_reg(hw_pinctrl_dout3)		/* 0x730 */
+	mx28_reg(hw_pinctrl_dout4)		/* 0x740 */
+
+	uint32_t	reserved5[108];
+
+	mx28_reg(hw_pinctrl_din0)		/* 0x900 */
+	mx28_reg(hw_pinctrl_din1)		/* 0x910 */
+	mx28_reg(hw_pinctrl_din2)		/* 0x920 */
+	mx28_reg(hw_pinctrl_din3)		/* 0x930 */
+	mx28_reg(hw_pinctrl_din4)		/* 0x940 */
+
+	uint32_t	reserved6[108];
+
+	mx28_reg(hw_pinctrl_doe0)		/* 0xb00 */
+	mx28_reg(hw_pinctrl_doe1)		/* 0xb10 */
+	mx28_reg(hw_pinctrl_doe2)		/* 0xb20 */
+	mx28_reg(hw_pinctrl_doe3)		/* 0xb30 */
+	mx28_reg(hw_pinctrl_doe4)		/* 0xb40 */
+
+	uint32_t	reserved7[300];
+
+	mx28_reg(hw_pinctrl_pin2irq0)		/* 0x1000 */
+	mx28_reg(hw_pinctrl_pin2irq1)		/* 0x1010 */
+	mx28_reg(hw_pinctrl_pin2irq2)		/* 0x1020 */
+	mx28_reg(hw_pinctrl_pin2irq3)		/* 0x1030 */
+	mx28_reg(hw_pinctrl_pin2irq4)		/* 0x1040 */
+
+	uint32_t	reserved8[44];
+
+	mx28_reg(hw_pinctrl_irqen0)		/* 0x1100 */
+	mx28_reg(hw_pinctrl_irqen1)		/* 0x1110 */
+	mx28_reg(hw_pinctrl_irqen2)		/* 0x1120 */
+	mx28_reg(hw_pinctrl_irqen3)		/* 0x1130 */
+	mx28_reg(hw_pinctrl_irqen4)		/* 0x1140 */
+
+	uint32_t	reserved9[44];
+
+	mx28_reg(hw_pinctrl_irqlevel0)		/* 0x1200 */
+	mx28_reg(hw_pinctrl_irqlevel1)		/* 0x1210 */
+	mx28_reg(hw_pinctrl_irqlevel2)		/* 0x1220 */
+	mx28_reg(hw_pinctrl_irqlevel3)		/* 0x1230 */
+	mx28_reg(hw_pinctrl_irqlevel4)		/* 0x1240 */
+
+	uint32_t	reserved10[44];
+
+	mx28_reg(hw_pinctrl_irqpol0)		/* 0x1300 */
+	mx28_reg(hw_pinctrl_irqpol1)		/* 0x1310 */
+	mx28_reg(hw_pinctrl_irqpol2)		/* 0x1320 */
+	mx28_reg(hw_pinctrl_irqpol3)		/* 0x1330 */
+	mx28_reg(hw_pinctrl_irqpol4)		/* 0x1340 */
+
+	uint32_t	reserved11[44];
+
+	mx28_reg(hw_pinctrl_irqstat0)		/* 0x1400 */
+	mx28_reg(hw_pinctrl_irqstat1)		/* 0x1410 */
+	mx28_reg(hw_pinctrl_irqstat2)		/* 0x1420 */
+	mx28_reg(hw_pinctrl_irqstat3)		/* 0x1430 */
+	mx28_reg(hw_pinctrl_irqstat4)		/* 0x1440 */
+
+	uint32_t	reserved12[380];
+
+	mx28_reg(hw_pinctrl_emi_odt_ctrl)	/* 0x1a40 */
+
+	uint32_t	reserved13[76];
+
+	mx28_reg(hw_pinctrl_emi_ds_ctrl)	/* 0x1b80 */
+};
+#endif
+
+#define	PINCTRL_CTRL_SFTRST				(1 << 31)
+#define	PINCTRL_CTRL_CLKGATE				(1 << 30)
+#define	PINCTRL_CTRL_PRESENT4				(1 << 24)
+#define	PINCTRL_CTRL_PRESENT3				(1 << 23)
+#define	PINCTRL_CTRL_PRESENT2				(1 << 22)
+#define	PINCTRL_CTRL_PRESENT1				(1 << 21)
+#define	PINCTRL_CTRL_PRESENT0				(1 << 20)
+#define	PINCTRL_CTRL_IRQOUT4				(1 << 4)
+#define	PINCTRL_CTRL_IRQOUT3				(1 << 3)
+#define	PINCTRL_CTRL_IRQOUT2				(1 << 2)
+#define	PINCTRL_CTRL_IRQOUT1				(1 << 1)
+#define	PINCTRL_CTRL_IRQOUT0				(1 << 0)
+
+#define	PINCTRL_MUXSEL0_BANK0_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL0_BANK0_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL0_BANK0_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL0_BANK0_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL0_BANK0_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL0_BANK0_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL0_BANK0_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL0_BANK0_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL0_BANK0_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL0_BANK0_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL0_BANK0_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL0_BANK0_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL0_BANK0_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL0_BANK0_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL0_BANK0_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL0_BANK0_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL1_BANK0_PIN28_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL1_BANK0_PIN28_OFFSET		24
+#define	PINCTRL_MUXSEL1_BANK0_PIN27_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL1_BANK0_PIN27_OFFSET		22
+#define	PINCTRL_MUXSEL1_BANK0_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL1_BANK0_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL1_BANK0_PIN25_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL1_BANK0_PIN25_OFFSET		18
+#define	PINCTRL_MUXSEL1_BANK0_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL1_BANK0_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL1_BANK0_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL1_BANK0_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL1_BANK0_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL1_BANK0_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL1_BANK0_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL1_BANK0_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL1_BANK0_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL1_BANK0_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL1_BANK0_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL1_BANK0_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL1_BANK0_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL1_BANK0_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL1_BANK0_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL1_BANK0_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL1_BANK0_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL1_BANK0_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL2_BANK1_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL2_BANK1_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL2_BANK1_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL2_BANK1_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL2_BANK1_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL2_BANK1_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL2_BANK1_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL2_BANK1_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL2_BANK1_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL2_BANK1_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL2_BANK1_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL2_BANK1_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL2_BANK1_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL2_BANK1_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL2_BANK1_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL2_BANK1_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL2_BANK1_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL2_BANK1_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL2_BANK1_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL2_BANK1_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL2_BANK1_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL2_BANK1_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL2_BANK1_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL2_BANK1_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL2_BANK1_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL2_BANK1_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL2_BANK1_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL2_BANK1_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL2_BANK1_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL2_BANK1_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL2_BANK1_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL2_BANK1_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL3_BANK1_PIN31_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL3_BANK1_PIN31_OFFSET		30
+#define	PINCTRL_MUXSEL3_BANK1_PIN30_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL3_BANK1_PIN30_OFFSET		28
+#define	PINCTRL_MUXSEL3_BANK1_PIN29_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL3_BANK1_PIN29_OFFSET		26
+#define	PINCTRL_MUXSEL3_BANK1_PIN28_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL3_BANK1_PIN28_OFFSET		24
+#define	PINCTRL_MUXSEL3_BANK1_PIN27_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL3_BANK1_PIN27_OFFSET		22
+#define	PINCTRL_MUXSEL3_BANK1_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL3_BANK1_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL3_BANK1_PIN25_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL3_BANK1_PIN25_OFFSET		18
+#define	PINCTRL_MUXSEL3_BANK1_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL3_BANK1_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL3_BANK1_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL3_BANK1_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL3_BANK1_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL3_BANK1_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL3_BANK1_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL3_BANK1_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL3_BANK1_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL3_BANK1_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL3_BANK1_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL3_BANK1_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL3_BANK1_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL3_BANK1_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL3_BANK1_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL3_BANK1_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL3_BANK1_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL3_BANK1_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL4_BANK2_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL4_BANK2_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL4_BANK2_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL4_BANK2_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL4_BANK2_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL4_BANK2_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL4_BANK2_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL4_BANK2_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL4_BANK2_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL4_BANK2_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL4_BANK2_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL4_BANK2_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL4_BANK2_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL4_BANK2_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL4_BANK2_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL4_BANK2_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL4_BANK2_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL4_BANK2_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL4_BANK2_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL4_BANK2_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL4_BANK2_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL4_BANK2_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL4_BANK2_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL4_BANK2_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL4_BANK2_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL4_BANK2_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL4_BANK2_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL4_BANK2_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL4_BANK2_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL4_BANK2_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL5_BANK2_PIN27_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL5_BANK2_PIN27_OFFSET		22
+#define	PINCTRL_MUXSEL5_BANK2_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL5_BANK2_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL5_BANK2_PIN25_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL5_BANK2_PIN25_OFFSET		18
+#define	PINCTRL_MUXSEL5_BANK2_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL5_BANK2_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL5_BANK2_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL5_BANK2_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL5_BANK2_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL5_BANK2_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL5_BANK2_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL5_BANK2_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL5_BANK2_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL5_BANK2_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL5_BANK2_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL5_BANK2_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL5_BANK2_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL5_BANK2_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL6_BANK3_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL6_BANK3_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL6_BANK3_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL6_BANK3_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL6_BANK3_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL6_BANK3_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL6_BANK3_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL6_BANK3_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL6_BANK3_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL6_BANK3_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL6_BANK3_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL6_BANK3_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL6_BANK3_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL6_BANK3_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL6_BANK3_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL6_BANK3_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL6_BANK3_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL6_BANK3_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL6_BANK3_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL6_BANK3_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL6_BANK3_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL6_BANK3_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL6_BANK3_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL6_BANK3_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL6_BANK3_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL6_BANK3_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL6_BANK3_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL6_BANK3_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL6_BANK3_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL6_BANK3_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL6_BANK3_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL6_BANK3_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL7_BANK3_PIN30_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL7_BANK3_PIN30_OFFSET		28
+#define	PINCTRL_MUXSEL7_BANK3_PIN29_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL7_BANK3_PIN29_OFFSET		26
+#define	PINCTRL_MUXSEL7_BANK3_PIN28_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL7_BANK3_PIN28_OFFSET		24
+#define	PINCTRL_MUXSEL7_BANK3_PIN27_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL7_BANK3_PIN27_OFFSET		22
+#define	PINCTRL_MUXSEL7_BANK3_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL7_BANK3_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL7_BANK3_PIN25_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL7_BANK3_PIN25_OFFSET		18
+#define	PINCTRL_MUXSEL7_BANK3_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL7_BANK3_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL7_BANK3_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL7_BANK3_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL7_BANK3_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL7_BANK3_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL7_BANK3_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL7_BANK3_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL7_BANK3_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL7_BANK3_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL7_BANK3_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL7_BANK3_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL7_BANK3_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL7_BANK3_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL7_BANK3_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL7_BANK3_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL8_BANK4_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL8_BANK4_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL8_BANK4_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL8_BANK4_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL8_BANK4_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL8_BANK4_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL8_BANK4_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL8_BANK4_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL8_BANK4_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL8_BANK4_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL8_BANK4_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL8_BANK4_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL8_BANK4_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL8_BANK4_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL8_BANK4_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL8_BANK4_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL8_BANK4_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL8_BANK4_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL8_BANK4_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL8_BANK4_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL8_BANK4_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL8_BANK4_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL8_BANK4_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL8_BANK4_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL8_BANK4_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL8_BANK4_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL8_BANK4_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL8_BANK4_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL8_BANK4_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL8_BANK4_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL8_BANK4_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL8_BANK4_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL9_BANK4_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL9_BANK4_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL9_BANK4_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL9_BANK4_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL10_BANK5_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL10_BANK5_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL10_BANK5_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL10_BANK5_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL10_BANK5_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL10_BANK5_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL10_BANK5_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL10_BANK5_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL10_BANK5_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL10_BANK5_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL10_BANK5_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL10_BANK5_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL10_BANK5_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL10_BANK5_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL10_BANK5_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL10_BANK5_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL10_BANK5_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL10_BANK5_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL10_BANK5_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL10_BANK5_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL10_BANK5_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL10_BANK5_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL10_BANK5_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL10_BANK5_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL10_BANK5_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL10_BANK5_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL10_BANK5_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL10_BANK5_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL10_BANK5_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL10_BANK5_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL10_BANK5_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL10_BANK5_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL11_BANK5_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL11_BANK5_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL11_BANK5_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL11_BANK5_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL11_BANK5_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL11_BANK5_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL11_BANK5_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL11_BANK5_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL11_BANK5_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL11_BANK5_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL11_BANK5_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL11_BANK5_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL11_BANK5_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL11_BANK5_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL11_BANK5_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL11_BANK5_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL11_BANK5_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL11_BANK5_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL12_BANK6_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL12_BANK6_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL12_BANK6_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL12_BANK6_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL12_BANK6_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL12_BANK6_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL12_BANK6_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL12_BANK6_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL12_BANK6_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL12_BANK6_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL12_BANK6_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL12_BANK6_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL12_BANK6_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL12_BANK6_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL12_BANK6_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL12_BANK6_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL12_BANK6_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL12_BANK6_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL12_BANK6_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL12_BANK6_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL12_BANK6_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL12_BANK6_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL12_BANK6_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL12_BANK6_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL12_BANK6_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL12_BANK6_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL12_BANK6_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL12_BANK6_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL12_BANK6_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL12_BANK6_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL13_BANK6_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL13_BANK6_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL13_BANK6_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL13_BANK6_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL13_BANK6_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL13_BANK6_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL13_BANK6_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL13_BANK6_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL13_BANK6_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL13_BANK6_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL13_BANK6_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL13_BANK6_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL13_BANK6_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL13_BANK6_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL13_BANK6_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL13_BANK6_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL13_BANK6_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL13_BANK6_PIN16_OFFSET		0
+
+#define	PINCTRL_DRIVE0_BANK0_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE0_BANK0_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE0_BANK0_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE0_BANK0_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE0_BANK0_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE0_BANK0_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE0_BANK0_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE0_BANK0_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE0_BANK0_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE0_BANK0_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE0_BANK0_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE0_BANK0_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE0_BANK0_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE0_BANK0_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE0_BANK0_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE0_BANK0_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE0_BANK0_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE0_BANK0_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE0_BANK0_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE0_BANK0_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE0_BANK0_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE0_BANK0_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE0_BANK0_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE0_BANK0_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE2_BANK0_PIN23_V			(1 << 30)
+#define	PINCTRL_DRIVE2_BANK0_PIN23_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE2_BANK0_PIN23_MA_OFFSET		28
+#define	PINCTRL_DRIVE2_BANK0_PIN22_V			(1 << 26)
+#define	PINCTRL_DRIVE2_BANK0_PIN22_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE2_BANK0_PIN22_MA_OFFSET		24
+#define	PINCTRL_DRIVE2_BANK0_PIN21_V			(1 << 22)
+#define	PINCTRL_DRIVE2_BANK0_PIN21_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE2_BANK0_PIN21_MA_OFFSET		20
+#define	PINCTRL_DRIVE2_BANK0_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE2_BANK0_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE2_BANK0_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE2_BANK0_PIN19_V			(1 << 14)
+#define	PINCTRL_DRIVE2_BANK0_PIN19_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE2_BANK0_PIN19_MA_OFFSET		12
+#define	PINCTRL_DRIVE2_BANK0_PIN18_V			(1 << 10)
+#define	PINCTRL_DRIVE2_BANK0_PIN18_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE2_BANK0_PIN18_MA_OFFSET		8
+#define	PINCTRL_DRIVE2_BANK0_PIN17_V			(1 << 6)
+#define	PINCTRL_DRIVE2_BANK0_PIN17_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE2_BANK0_PIN17_MA_OFFSET		4
+#define	PINCTRL_DRIVE2_BANK0_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE2_BANK0_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE2_BANK0_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE3_BANK0_PIN28_V			(1 << 18)
+#define	PINCTRL_DRIVE3_BANK0_PIN28_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE3_BANK0_PIN28_MA_OFFSET		16
+#define	PINCTRL_DRIVE3_BANK0_PIN27_V			(1 << 14)
+#define	PINCTRL_DRIVE3_BANK0_PIN27_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE3_BANK0_PIN27_MA_OFFSET		12
+#define	PINCTRL_DRIVE3_BANK0_PIN26_V			(1 << 10)
+#define	PINCTRL_DRIVE3_BANK0_PIN26_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE3_BANK0_PIN26_MA_OFFSET		8
+#define	PINCTRL_DRIVE3_BANK0_PIN25_V			(1 << 6)
+#define	PINCTRL_DRIVE3_BANK0_PIN25_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE3_BANK0_PIN25_MA_OFFSET		4
+#define	PINCTRL_DRIVE3_BANK0_PIN24_V			(1 << 2)
+#define	PINCTRL_DRIVE3_BANK0_PIN24_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE3_BANK0_PIN24_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE4_BANK1_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE4_BANK1_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE4_BANK1_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE4_BANK1_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE4_BANK1_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE4_BANK1_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE4_BANK1_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE4_BANK1_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE4_BANK1_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE4_BANK1_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE4_BANK1_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE4_BANK1_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE4_BANK1_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE4_BANK1_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE4_BANK1_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE4_BANK1_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE4_BANK1_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE4_BANK1_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE4_BANK1_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE4_BANK1_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE4_BANK1_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE4_BANK1_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE4_BANK1_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE4_BANK1_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE5_BANK1_PIN15_V			(1 << 30)
+#define	PINCTRL_DRIVE5_BANK1_PIN15_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE5_BANK1_PIN15_MA_OFFSET		28
+#define	PINCTRL_DRIVE5_BANK1_PIN14_V			(1 << 26)
+#define	PINCTRL_DRIVE5_BANK1_PIN14_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE5_BANK1_PIN14_MA_OFFSET		24
+#define	PINCTRL_DRIVE5_BANK1_PIN13_V			(1 << 22)
+#define	PINCTRL_DRIVE5_BANK1_PIN13_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE5_BANK1_PIN13_MA_OFFSET		20
+#define	PINCTRL_DRIVE5_BANK1_PIN12_V			(1 << 18)
+#define	PINCTRL_DRIVE5_BANK1_PIN12_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE5_BANK1_PIN12_MA_OFFSET		16
+#define	PINCTRL_DRIVE5_BANK1_PIN11_V			(1 << 14)
+#define	PINCTRL_DRIVE5_BANK1_PIN11_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE5_BANK1_PIN11_MA_OFFSET		12
+#define	PINCTRL_DRIVE5_BANK1_PIN10_V			(1 << 10)
+#define	PINCTRL_DRIVE5_BANK1_PIN10_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE5_BANK1_PIN10_MA_OFFSET		8
+#define	PINCTRL_DRIVE5_BANK1_PIN09_V			(1 << 6)
+#define	PINCTRL_DRIVE5_BANK1_PIN09_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE5_BANK1_PIN09_MA_OFFSET		4
+#define	PINCTRL_DRIVE5_BANK1_PIN08_V			(1 << 2)
+#define	PINCTRL_DRIVE5_BANK1_PIN08_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE5_BANK1_PIN08_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE6_BANK1_PIN23_V			(1 << 30)
+#define	PINCTRL_DRIVE6_BANK1_PIN23_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE6_BANK1_PIN23_MA_OFFSET		28
+#define	PINCTRL_DRIVE6_BANK1_PIN22_V			(1 << 26)
+#define	PINCTRL_DRIVE6_BANK1_PIN22_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE6_BANK1_PIN22_MA_OFFSET		24
+#define	PINCTRL_DRIVE6_BANK1_PIN21_V			(1 << 22)
+#define	PINCTRL_DRIVE6_BANK1_PIN21_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE6_BANK1_PIN21_MA_OFFSET		20
+#define	PINCTRL_DRIVE6_BANK1_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE6_BANK1_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE6_BANK1_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE6_BANK1_PIN19_V			(1 << 14)
+#define	PINCTRL_DRIVE6_BANK1_PIN19_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE6_BANK1_PIN19_MA_OFFSET		12
+#define	PINCTRL_DRIVE6_BANK1_PIN18_V			(1 << 10)
+#define	PINCTRL_DRIVE6_BANK1_PIN18_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE6_BANK1_PIN18_MA_OFFSET		8
+#define	PINCTRL_DRIVE6_BANK1_PIN17_V			(1 << 6)
+#define	PINCTRL_DRIVE6_BANK1_PIN17_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE6_BANK1_PIN17_MA_OFFSET		4
+#define	PINCTRL_DRIVE6_BANK1_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE6_BANK1_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE6_BANK1_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE7_BANK1_PIN31_V			(1 << 30)
+#define	PINCTRL_DRIVE7_BANK1_PIN31_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE7_BANK1_PIN31_MA_OFFSET		28
+#define	PINCTRL_DRIVE7_BANK1_PIN30_V			(1 << 26)
+#define	PINCTRL_DRIVE7_BANK1_PIN30_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE7_BANK1_PIN30_MA_OFFSET		24
+#define	PINCTRL_DRIVE7_BANK1_PIN29_V			(1 << 22)
+#define	PINCTRL_DRIVE7_BANK1_PIN29_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE7_BANK1_PIN29_MA_OFFSET		20
+#define	PINCTRL_DRIVE7_BANK1_PIN28_V			(1 << 18)
+#define	PINCTRL_DRIVE7_BANK1_PIN28_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE7_BANK1_PIN28_MA_OFFSET		16
+#define	PINCTRL_DRIVE7_BANK1_PIN27_V			(1 << 14)
+#define	PINCTRL_DRIVE7_BANK1_PIN27_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE7_BANK1_PIN27_MA_OFFSET		12
+#define	PINCTRL_DRIVE7_BANK1_PIN26_V			(1 << 10)
+#define	PINCTRL_DRIVE7_BANK1_PIN26_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE7_BANK1_PIN26_MA_OFFSET		8
+#define	PINCTRL_DRIVE7_BANK1_PIN25_V			(1 << 6)
+#define	PINCTRL_DRIVE7_BANK1_PIN25_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE7_BANK1_PIN25_MA_OFFSET		4
+#define	PINCTRL_DRIVE7_BANK1_PIN24_V			(1 << 2)
+#define	PINCTRL_DRIVE7_BANK1_PIN24_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE7_BANK1_PIN24_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE8_BANK2_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE8_BANK2_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE8_BANK2_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE8_BANK2_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE8_BANK2_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE8_BANK2_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE8_BANK2_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE8_BANK2_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE8_BANK2_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE8_BANK2_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE8_BANK2_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE8_BANK2_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE8_BANK2_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE8_BANK2_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE8_BANK2_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE8_BANK2_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE8_BANK2_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE8_BANK2_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE8_BANK2_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE8_BANK2_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE8_BANK2_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE8_BANK2_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE8_BANK2_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE8_BANK2_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE9_BANK2_PIN15_V			(1 << 30)
+#define	PINCTRL_DRIVE9_BANK2_PIN15_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE9_BANK2_PIN15_MA_OFFSET		28
+#define	PINCTRL_DRIVE9_BANK2_PIN14_V			(1 << 26)
+#define	PINCTRL_DRIVE9_BANK2_PIN14_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE9_BANK2_PIN14_MA_OFFSET		24
+#define	PINCTRL_DRIVE9_BANK2_PIN13_V			(1 << 22)
+#define	PINCTRL_DRIVE9_BANK2_PIN13_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE9_BANK2_PIN13_MA_OFFSET		20
+#define	PINCTRL_DRIVE9_BANK2_PIN12_V			(1 << 18)
+#define	PINCTRL_DRIVE9_BANK2_PIN12_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE9_BANK2_PIN12_MA_OFFSET		16
+#define	PINCTRL_DRIVE9_BANK2_PIN10_V			(1 << 10)
+#define	PINCTRL_DRIVE9_BANK2_PIN10_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE9_BANK2_PIN10_MA_OFFSET		8
+#define	PINCTRL_DRIVE9_BANK2_PIN09_V			(1 << 6)
+#define	PINCTRL_DRIVE9_BANK2_PIN09_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE9_BANK2_PIN09_MA_OFFSET		4
+#define	PINCTRL_DRIVE9_BANK2_PIN08_V			(1 << 2)
+#define	PINCTRL_DRIVE9_BANK2_PIN08_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE9_BANK2_PIN08_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE10_BANK2_PIN21_V			(1 << 22)
+#define	PINCTRL_DRIVE10_BANK2_PIN21_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE10_BANK2_PIN21_MA_OFFSET		20
+#define	PINCTRL_DRIVE10_BANK2_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE10_BANK2_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE10_BANK2_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE10_BANK2_PIN19_V			(1 << 14)
+#define	PINCTRL_DRIVE10_BANK2_PIN19_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE10_BANK2_PIN19_MA_OFFSET		12
+#define	PINCTRL_DRIVE10_BANK2_PIN18_V			(1 << 10)
+#define	PINCTRL_DRIVE10_BANK2_PIN18_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE10_BANK2_PIN18_MA_OFFSET		8
+#define	PINCTRL_DRIVE10_BANK2_PIN17_V			(1 << 6)
+#define	PINCTRL_DRIVE10_BANK2_PIN17_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE10_BANK2_PIN17_MA_OFFSET		4
+#define	PINCTRL_DRIVE10_BANK2_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE10_BANK2_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE10_BANK2_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE11_BANK2_PIN27_V			(1 << 14)
+#define	PINCTRL_DRIVE11_BANK2_PIN27_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE11_BANK2_PIN27_MA_OFFSET		12
+#define	PINCTRL_DRIVE11_BANK2_PIN26_V			(1 << 10)
+#define	PINCTRL_DRIVE11_BANK2_PIN26_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE11_BANK2_PIN26_MA_OFFSET		8
+#define	PINCTRL_DRIVE11_BANK2_PIN25_V			(1 << 6)
+#define	PINCTRL_DRIVE11_BANK2_PIN25_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE11_BANK2_PIN25_MA_OFFSET		4
+#define	PINCTRL_DRIVE11_BANK2_PIN24_V			(1 << 2)
+#define	PINCTRL_DRIVE11_BANK2_PIN24_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE11_BANK2_PIN24_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE12_BANK3_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE12_BANK3_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE12_BANK3_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE12_BANK3_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE12_BANK3_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE12_BANK3_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE12_BANK3_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE12_BANK3_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE12_BANK3_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE12_BANK3_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE12_BANK3_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE12_BANK3_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE12_BANK3_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE12_BANK3_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE12_BANK3_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE12_BANK3_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE12_BANK3_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE12_BANK3_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE12_BANK3_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE12_BANK3_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE12_BANK3_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE12_BANK3_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE12_BANK3_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE12_BANK3_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE13_BANK3_PIN15_V			(1 << 30)
+#define	PINCTRL_DRIVE13_BANK3_PIN15_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE13_BANK3_PIN15_MA_OFFSET		28
+#define	PINCTRL_DRIVE13_BANK3_PIN14_V			(1 << 26)
+#define	PINCTRL_DRIVE13_BANK3_PIN14_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE13_BANK3_PIN14_MA_OFFSET		24
+#define	PINCTRL_DRIVE13_BANK3_PIN13_V			(1 << 22)
+#define	PINCTRL_DRIVE13_BANK3_PIN13_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE13_BANK3_PIN13_MA_OFFSET		20
+#define	PINCTRL_DRIVE13_BANK3_PIN12_V			(1 << 18)
+#define	PINCTRL_DRIVE13_BANK3_PIN12_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE13_BANK3_PIN12_MA_OFFSET		16
+#define	PINCTRL_DRIVE13_BANK3_PIN11_V			(1 << 14)
+#define	PINCTRL_DRIVE13_BANK3_PIN11_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE13_BANK3_PIN11_MA_OFFSET		12
+#define	PINCTRL_DRIVE13_BANK3_PIN10_V			(1 << 10)
+#define	PINCTRL_DRIVE13_BANK3_PIN10_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE13_BANK3_PIN10_MA_OFFSET		8
+#define	PINCTRL_DRIVE13_BANK3_PIN09_V			(1 << 6)
+#define	PINCTRL_DRIVE13_BANK3_PIN09_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE13_BANK3_PIN09_MA_OFFSET		4
+#define	PINCTRL_DRIVE13_BANK3_PIN08_V			(1 << 2)
+#define	PINCTRL_DRIVE13_BANK3_PIN08_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE13_BANK3_PIN08_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE14_BANK3_PIN23_V			(1 << 30)
+#define	PINCTRL_DRIVE14_BANK3_PIN23_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE14_BANK3_PIN23_MA_OFFSET		28
+#define	PINCTRL_DRIVE14_BANK3_PIN22_V			(1 << 26)
+#define	PINCTRL_DRIVE14_BANK3_PIN22_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE14_BANK3_PIN22_MA_OFFSET		24
+#define	PINCTRL_DRIVE14_BANK3_PIN21_V			(1 << 22)
+#define	PINCTRL_DRIVE14_BANK3_PIN21_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE14_BANK3_PIN21_MA_OFFSET		20
+#define	PINCTRL_DRIVE14_BANK3_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE14_BANK3_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE14_BANK3_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE14_BANK3_PIN18_V			(1 << 10)
+#define	PINCTRL_DRIVE14_BANK3_PIN18_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE14_BANK3_PIN18_MA_OFFSET		8
+#define	PINCTRL_DRIVE14_BANK3_PIN17_V			(1 << 6)
+#define	PINCTRL_DRIVE14_BANK3_PIN17_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE14_BANK3_PIN17_MA_OFFSET		4
+#define	PINCTRL_DRIVE14_BANK3_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE14_BANK3_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE14_BANK3_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE15_BANK3_PIN30_V			(1 << 26)
+#define	PINCTRL_DRIVE15_BANK3_PIN30_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE15_BANK3_PIN30_MA_OFFSET		24
+#define	PINCTRL_DRIVE15_BANK3_PIN29_V			(1 << 22)
+#define	PINCTRL_DRIVE15_BANK3_PIN29_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE15_BANK3_PIN29_MA_OFFSET		20
+#define	PINCTRL_DRIVE15_BANK3_PIN28_V			(1 << 18)
+#define	PINCTRL_DRIVE15_BANK3_PIN28_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE15_BANK3_PIN28_MA_OFFSET		16
+#define	PINCTRL_DRIVE15_BANK3_PIN27_V			(1 << 14)
+#define	PINCTRL_DRIVE15_BANK3_PIN27_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE15_BANK3_PIN27_MA_OFFSET		12
+#define	PINCTRL_DRIVE15_BANK3_PIN26_V			(1 << 10)
+#define	PINCTRL_DRIVE15_BANK3_PIN26_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE15_BANK3_PIN26_MA_OFFSET		8
+#define	PINCTRL_DRIVE15_BANK3_PIN25_V			(1 << 6)
+#define	PINCTRL_DRIVE15_BANK3_PIN25_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE15_BANK3_PIN25_MA_OFFSET		4
+#define	PINCTRL_DRIVE15_BANK3_PIN24_V			(1 << 2)
+#define	PINCTRL_DRIVE15_BANK3_PIN24_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE15_BANK3_PIN24_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE16_BANK4_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE16_BANK4_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE16_BANK4_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE16_BANK4_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE16_BANK4_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE16_BANK4_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE16_BANK4_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE16_BANK4_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE16_BANK4_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE16_BANK4_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE16_BANK4_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE16_BANK4_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE16_BANK4_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE16_BANK4_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE16_BANK4_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE16_BANK4_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE16_BANK4_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE16_BANK4_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE16_BANK4_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE16_BANK4_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE16_BANK4_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE16_BANK4_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE16_BANK4_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE16_BANK4_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE17_BANK4_PIN15_V			(1 << 30)
+#define	PINCTRL_DRIVE17_BANK4_PIN15_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE17_BANK4_PIN15_MA_OFFSET		28
+#define	PINCTRL_DRIVE17_BANK4_PIN14_V			(1 << 26)
+#define	PINCTRL_DRIVE17_BANK4_PIN14_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE17_BANK4_PIN14_MA_OFFSET		24
+#define	PINCTRL_DRIVE17_BANK4_PIN13_V			(1 << 22)
+#define	PINCTRL_DRIVE17_BANK4_PIN13_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE17_BANK4_PIN13_MA_OFFSET		20
+#define	PINCTRL_DRIVE17_BANK4_PIN12_V			(1 << 18)
+#define	PINCTRL_DRIVE17_BANK4_PIN12_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE17_BANK4_PIN12_MA_OFFSET		16
+#define	PINCTRL_DRIVE17_BANK4_PIN11_V			(1 << 14)
+#define	PINCTRL_DRIVE17_BANK4_PIN11_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE17_BANK4_PIN11_MA_OFFSET		12
+#define	PINCTRL_DRIVE17_BANK4_PIN10_V			(1 << 10)
+#define	PINCTRL_DRIVE17_BANK4_PIN10_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE17_BANK4_PIN10_MA_OFFSET		8
+#define	PINCTRL_DRIVE17_BANK4_PIN09_V			(1 << 6)
+#define	PINCTRL_DRIVE17_BANK4_PIN09_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE17_BANK4_PIN09_MA_OFFSET		4
+#define	PINCTRL_DRIVE17_BANK4_PIN08_V			(1 << 2)
+#define	PINCTRL_DRIVE17_BANK4_PIN08_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE17_BANK4_PIN08_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE18_BANK4_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE18_BANK4_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE18_BANK4_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE18_BANK4_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE18_BANK4_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE18_BANK4_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_PULL0_BANK0_PIN28			(1 << 28)
+#define	PINCTRL_PULL0_BANK0_PIN27			(1 << 27)
+#define	PINCTRL_PULL0_BANK0_PIN26			(1 << 26)
+#define	PINCTRL_PULL0_BANK0_PIN25			(1 << 25)
+#define	PINCTRL_PULL0_BANK0_PIN24			(1 << 24)
+#define	PINCTRL_PULL0_BANK0_PIN23			(1 << 23)
+#define	PINCTRL_PULL0_BANK0_PIN22			(1 << 22)
+#define	PINCTRL_PULL0_BANK0_PIN21			(1 << 21)
+#define	PINCTRL_PULL0_BANK0_PIN20			(1 << 20)
+#define	PINCTRL_PULL0_BANK0_PIN19			(1 << 19)
+#define	PINCTRL_PULL0_BANK0_PIN18			(1 << 18)
+#define	PINCTRL_PULL0_BANK0_PIN17			(1 << 17)
+#define	PINCTRL_PULL0_BANK0_PIN16			(1 << 16)
+#define	PINCTRL_PULL0_BANK0_PIN07			(1 << 7)
+#define	PINCTRL_PULL0_BANK0_PIN06			(1 << 6)
+#define	PINCTRL_PULL0_BANK0_PIN05			(1 << 5)
+#define	PINCTRL_PULL0_BANK0_PIN04			(1 << 4)
+#define	PINCTRL_PULL0_BANK0_PIN03			(1 << 3)
+#define	PINCTRL_PULL0_BANK0_PIN02			(1 << 2)
+#define	PINCTRL_PULL0_BANK0_PIN01			(1 << 1)
+#define	PINCTRL_PULL0_BANK0_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL1_BANK1_PIN31			(1 << 31)
+#define	PINCTRL_PULL1_BANK1_PIN30			(1 << 30)
+#define	PINCTRL_PULL1_BANK1_PIN29			(1 << 29)
+#define	PINCTRL_PULL1_BANK1_PIN28			(1 << 28)
+#define	PINCTRL_PULL1_BANK1_PIN27			(1 << 27)
+#define	PINCTRL_PULL1_BANK1_PIN26			(1 << 26)
+#define	PINCTRL_PULL1_BANK1_PIN25			(1 << 25)
+#define	PINCTRL_PULL1_BANK1_PIN24			(1 << 24)
+#define	PINCTRL_PULL1_BANK1_PIN23			(1 << 23)
+#define	PINCTRL_PULL1_BANK1_PIN22			(1 << 22)
+#define	PINCTRL_PULL1_BANK1_PIN21			(1 << 21)
+#define	PINCTRL_PULL1_BANK1_PIN20			(1 << 20)
+#define	PINCTRL_PULL1_BANK1_PIN19			(1 << 19)
+#define	PINCTRL_PULL1_BANK1_PIN18			(1 << 18)
+#define	PINCTRL_PULL1_BANK1_PIN17			(1 << 17)
+#define	PINCTRL_PULL1_BANK1_PIN16			(1 << 16)
+#define	PINCTRL_PULL1_BANK1_PIN15			(1 << 15)
+#define	PINCTRL_PULL1_BANK1_PIN14			(1 << 14)
+#define	PINCTRL_PULL1_BANK1_PIN13			(1 << 13)
+#define	PINCTRL_PULL1_BANK1_PIN12			(1 << 12)
+#define	PINCTRL_PULL1_BANK1_PIN11			(1 << 11)
+#define	PINCTRL_PULL1_BANK1_PIN10			(1 << 10)
+#define	PINCTRL_PULL1_BANK1_PIN09			(1 << 9)
+#define	PINCTRL_PULL1_BANK1_PIN08			(1 << 8)
+#define	PINCTRL_PULL1_BANK1_PIN07			(1 << 7)
+#define	PINCTRL_PULL1_BANK1_PIN06			(1 << 6)
+#define	PINCTRL_PULL1_BANK1_PIN05			(1 << 5)
+#define	PINCTRL_PULL1_BANK1_PIN04			(1 << 4)
+#define	PINCTRL_PULL1_BANK1_PIN03			(1 << 3)
+#define	PINCTRL_PULL1_BANK1_PIN02			(1 << 2)
+#define	PINCTRL_PULL1_BANK1_PIN01			(1 << 1)
+#define	PINCTRL_PULL1_BANK1_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL2_BANK2_PIN27			(1 << 27)
+#define	PINCTRL_PULL2_BANK2_PIN26			(1 << 26)
+#define	PINCTRL_PULL2_BANK2_PIN25			(1 << 25)
+#define	PINCTRL_PULL2_BANK2_PIN24			(1 << 24)
+#define	PINCTRL_PULL2_BANK2_PIN21			(1 << 21)
+#define	PINCTRL_PULL2_BANK2_PIN20			(1 << 20)
+#define	PINCTRL_PULL2_BANK2_PIN19			(1 << 19)
+#define	PINCTRL_PULL2_BANK2_PIN18			(1 << 18)
+#define	PINCTRL_PULL2_BANK2_PIN17			(1 << 17)
+#define	PINCTRL_PULL2_BANK2_PIN16			(1 << 16)
+#define	PINCTRL_PULL2_BANK2_PIN15			(1 << 15)
+#define	PINCTRL_PULL2_BANK2_PIN14			(1 << 14)
+#define	PINCTRL_PULL2_BANK2_PIN13			(1 << 13)
+#define	PINCTRL_PULL2_BANK2_PIN12			(1 << 12)
+#define	PINCTRL_PULL2_BANK2_PIN10			(1 << 10)
+#define	PINCTRL_PULL2_BANK2_PIN09			(1 << 9)
+#define	PINCTRL_PULL2_BANK2_PIN08			(1 << 8)
+#define	PINCTRL_PULL2_BANK2_PIN07			(1 << 7)
+#define	PINCTRL_PULL2_BANK2_PIN06			(1 << 6)
+#define	PINCTRL_PULL2_BANK2_PIN05			(1 << 5)
+#define	PINCTRL_PULL2_BANK2_PIN04			(1 << 4)
+#define	PINCTRL_PULL2_BANK2_PIN03			(1 << 3)
+#define	PINCTRL_PULL2_BANK2_PIN02			(1 << 2)
+#define	PINCTRL_PULL2_BANK2_PIN01			(1 << 1)
+#define	PINCTRL_PULL2_BANK2_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL3_BANK3_PIN30			(1 << 30)
+#define	PINCTRL_PULL3_BANK3_PIN29			(1 << 29)
+#define	PINCTRL_PULL3_BANK3_PIN28			(1 << 28)
+#define	PINCTRL_PULL3_BANK3_PIN27			(1 << 27)
+#define	PINCTRL_PULL3_BANK3_PIN26			(1 << 26)
+#define	PINCTRL_PULL3_BANK3_PIN25			(1 << 25)
+#define	PINCTRL_PULL3_BANK3_PIN24			(1 << 24)
+#define	PINCTRL_PULL3_BANK3_PIN23			(1 << 23)
+#define	PINCTRL_PULL3_BANK3_PIN22			(1 << 22)
+#define	PINCTRL_PULL3_BANK3_PIN21			(1 << 21)
+#define	PINCTRL_PULL3_BANK3_PIN20			(1 << 20)
+#define	PINCTRL_PULL3_BANK3_PIN18			(1 << 18)
+#define	PINCTRL_PULL3_BANK3_PIN17			(1 << 17)
+#define	PINCTRL_PULL3_BANK3_PIN16			(1 << 16)
+#define	PINCTRL_PULL3_BANK3_PIN15			(1 << 15)
+#define	PINCTRL_PULL3_BANK3_PIN14			(1 << 14)
+#define	PINCTRL_PULL3_BANK3_PIN13			(1 << 13)
+#define	PINCTRL_PULL3_BANK3_PIN12			(1 << 12)
+#define	PINCTRL_PULL3_BANK3_PIN11			(1 << 11)
+#define	PINCTRL_PULL3_BANK3_PIN10			(1 << 10)
+#define	PINCTRL_PULL3_BANK3_PIN09			(1 << 9)
+#define	PINCTRL_PULL3_BANK3_PIN08			(1 << 8)
+#define	PINCTRL_PULL3_BANK3_PIN07			(1 << 7)
+#define	PINCTRL_PULL3_BANK3_PIN06			(1 << 6)
+#define	PINCTRL_PULL3_BANK3_PIN05			(1 << 5)
+#define	PINCTRL_PULL3_BANK3_PIN04			(1 << 4)
+#define	PINCTRL_PULL3_BANK3_PIN03			(1 << 3)
+#define	PINCTRL_PULL3_BANK3_PIN02			(1 << 2)
+#define	PINCTRL_PULL3_BANK3_PIN01			(1 << 1)
+#define	PINCTRL_PULL3_BANK3_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL4_BANK4_PIN20			(1 << 20)
+#define	PINCTRL_PULL4_BANK4_PIN16			(1 << 16)
+#define	PINCTRL_PULL4_BANK4_PIN15			(1 << 15)
+#define	PINCTRL_PULL4_BANK4_PIN14			(1 << 14)
+#define	PINCTRL_PULL4_BANK4_PIN13			(1 << 13)
+#define	PINCTRL_PULL4_BANK4_PIN12			(1 << 12)
+#define	PINCTRL_PULL4_BANK4_PIN11			(1 << 11)
+#define	PINCTRL_PULL4_BANK4_PIN10			(1 << 10)
+#define	PINCTRL_PULL4_BANK4_PIN09			(1 << 9)
+#define	PINCTRL_PULL4_BANK4_PIN08			(1 << 8)
+#define	PINCTRL_PULL4_BANK4_PIN07			(1 << 7)
+#define	PINCTRL_PULL4_BANK4_PIN06			(1 << 6)
+#define	PINCTRL_PULL4_BANK4_PIN05			(1 << 5)
+#define	PINCTRL_PULL4_BANK4_PIN04			(1 << 4)
+#define	PINCTRL_PULL4_BANK4_PIN03			(1 << 3)
+#define	PINCTRL_PULL4_BANK4_PIN02			(1 << 2)
+#define	PINCTRL_PULL4_BANK4_PIN01			(1 << 1)
+#define	PINCTRL_PULL4_BANK4_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL5_BANK5_PIN26			(1 << 26)
+#define	PINCTRL_PULL5_BANK5_PIN23			(1 << 23)
+#define	PINCTRL_PULL5_BANK5_PIN22			(1 << 22)
+#define	PINCTRL_PULL5_BANK5_PIN21			(1 << 21)
+#define	PINCTRL_PULL5_BANK5_PIN20			(1 << 20)
+#define	PINCTRL_PULL5_BANK5_PIN19			(1 << 19)
+#define	PINCTRL_PULL5_BANK5_PIN18			(1 << 18)
+#define	PINCTRL_PULL5_BANK5_PIN17			(1 << 17)
+#define	PINCTRL_PULL5_BANK5_PIN16			(1 << 16)
+#define	PINCTRL_PULL5_BANK5_PIN15			(1 << 15)
+#define	PINCTRL_PULL5_BANK5_PIN14			(1 << 14)
+#define	PINCTRL_PULL5_BANK5_PIN13			(1 << 13)
+#define	PINCTRL_PULL5_BANK5_PIN12			(1 << 12)
+#define	PINCTRL_PULL5_BANK5_PIN11			(1 << 11)
+#define	PINCTRL_PULL5_BANK5_PIN10			(1 << 10)
+#define	PINCTRL_PULL5_BANK5_PIN09			(1 << 9)
+#define	PINCTRL_PULL5_BANK5_PIN08			(1 << 8)
+#define	PINCTRL_PULL5_BANK5_PIN07			(1 << 7)
+#define	PINCTRL_PULL5_BANK5_PIN06			(1 << 6)
+#define	PINCTRL_PULL5_BANK5_PIN05			(1 << 5)
+#define	PINCTRL_PULL5_BANK5_PIN04			(1 << 4)
+#define	PINCTRL_PULL5_BANK5_PIN03			(1 << 3)
+#define	PINCTRL_PULL5_BANK5_PIN02			(1 << 2)
+#define	PINCTRL_PULL5_BANK5_PIN01			(1 << 1)
+#define	PINCTRL_PULL5_BANK5_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL6_BANK6_PIN24			(1 << 24)
+#define	PINCTRL_PULL6_BANK6_PIN23			(1 << 23)
+#define	PINCTRL_PULL6_BANK6_PIN22			(1 << 22)
+#define	PINCTRL_PULL6_BANK6_PIN21			(1 << 21)
+#define	PINCTRL_PULL6_BANK6_PIN20			(1 << 20)
+#define	PINCTRL_PULL6_BANK6_PIN19			(1 << 19)
+#define	PINCTRL_PULL6_BANK6_PIN18			(1 << 18)
+#define	PINCTRL_PULL6_BANK6_PIN17			(1 << 17)
+#define	PINCTRL_PULL6_BANK6_PIN16			(1 << 16)
+#define	PINCTRL_PULL6_BANK6_PIN14			(1 << 14)
+#define	PINCTRL_PULL6_BANK6_PIN13			(1 << 13)
+#define	PINCTRL_PULL6_BANK6_PIN12			(1 << 12)
+#define	PINCTRL_PULL6_BANK6_PIN11			(1 << 11)
+#define	PINCTRL_PULL6_BANK6_PIN10			(1 << 10)
+#define	PINCTRL_PULL6_BANK6_PIN09			(1 << 9)
+#define	PINCTRL_PULL6_BANK6_PIN08			(1 << 8)
+#define	PINCTRL_PULL6_BANK6_PIN07			(1 << 7)
+#define	PINCTRL_PULL6_BANK6_PIN06			(1 << 6)
+#define	PINCTRL_PULL6_BANK6_PIN05			(1 << 5)
+#define	PINCTRL_PULL6_BANK6_PIN04			(1 << 4)
+#define	PINCTRL_PULL6_BANK6_PIN03			(1 << 3)
+#define	PINCTRL_PULL6_BANK6_PIN02			(1 << 2)
+#define	PINCTRL_PULL6_BANK6_PIN01			(1 << 1)
+#define	PINCTRL_PULL6_BANK6_PIN00			(1 << 0)
+
+#define	PINCTRL_DOUT0_DOUT_MASK				0x1fffffff
+#define	PINCTRL_DOUT0_DOUT_OFFSET			0
+
+#define	PINCTRL_DOUT1_DOUT_MASK				0xffffffff
+#define	PINCTRL_DOUT1_DOUT_OFFSET			0
+
+#define	PINCTRL_DOUT2_DOUT_MASK				0xfffffff
+#define	PINCTRL_DOUT2_DOUT_OFFSET			0
+
+#define	PINCTRL_DOUT3_DOUT_MASK				0x7fffffff
+#define	PINCTRL_DOUT3_DOUT_OFFSET			0
+
+#define	PINCTRL_DOUT4_DOUT_MASK				0x1fffff
+#define	PINCTRL_DOUT4_DOUT_OFFSET			0
+
+#define	PINCTRL_DIN0_DIN_MASK				0x1fffffff
+#define	PINCTRL_DIN0_DIN_OFFSET				0
+
+#define	PINCTRL_DIN1_DIN_MASK				0xffffffff
+#define	PINCTRL_DIN1_DIN_OFFSET				0
+
+#define	PINCTRL_DIN2_DIN_MASK				0xfffffff
+#define	PINCTRL_DIN2_DIN_OFFSET				0
+
+#define	PINCTRL_DIN3_DIN_MASK				0x7fffffff
+#define	PINCTRL_DIN3_DIN_OFFSET				0
+
+#define	PINCTRL_DIN4_DIN_MASK				0x1fffff
+#define	PINCTRL_DIN4_DIN_OFFSET				0
+
+#define	PINCTRL_DOE0_DOE_MASK				0x1fffffff
+#define	PINCTRL_DOE0_DOE_OFFSET				0
+
+#define	PINCTRL_DOE1_DOE_MASK				0xffffffff
+#define	PINCTRL_DOE1_DOE_OFFSET				0
+
+#define	PINCTRL_DOE2_DOE_MASK				0xfffffff
+#define	PINCTRL_DOE2_DOE_OFFSET				0
+
+#define	PINCTRL_DOE3_DOE_MASK				0x7fffffff
+#define	PINCTRL_DOE3_DOE_OFFSET				0
+
+#define	PINCTRL_DOE4_DOE_MASK				0x1fffff
+#define	PINCTRL_DOE4_DOE_OFFSET				0
+
+#define	PINCTRL_PIN2IRQ0_PIN2IRQ_MASK			0x1fffffff
+#define	PINCTRL_PIN2IRQ0_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_PIN2IRQ1_PIN2IRQ_MASK			0xffffffff
+#define	PINCTRL_PIN2IRQ1_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_PIN2IRQ2_PIN2IRQ_MASK			0xfffffff
+#define	PINCTRL_PIN2IRQ2_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_PIN2IRQ3_PIN2IRQ_MASK			0x7fffffff
+#define	PINCTRL_PIN2IRQ3_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_PIN2IRQ4_PIN2IRQ_MASK			0x1fffff
+#define	PINCTRL_PIN2IRQ4_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_IRQEN0_IRQEN_MASK			0x1fffffff
+#define	PINCTRL_IRQEN0_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQEN1_IRQEN_MASK			0xffffffff
+#define	PINCTRL_IRQEN1_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQEN2_IRQEN_MASK			0xfffffff
+#define	PINCTRL_IRQEN2_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQEN3_IRQEN_MASK			0x7fffffff
+#define	PINCTRL_IRQEN3_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQEN4_IRQEN_MASK			0x1fffff
+#define	PINCTRL_IRQEN4_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQLEVEL0_IRQLEVEL_MASK			0x1fffffff
+#define	PINCTRL_IRQLEVEL0_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQLEVEL1_IRQLEVEL_MASK			0xffffffff
+#define	PINCTRL_IRQLEVEL1_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQLEVEL2_IRQLEVEL_MASK			0xfffffff
+#define	PINCTRL_IRQLEVEL2_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQLEVEL3_IRQLEVEL_MASK			0x7fffffff
+#define	PINCTRL_IRQLEVEL3_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQLEVEL4_IRQLEVEL_MASK			0x1fffff
+#define	PINCTRL_IRQLEVEL4_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQPOL0_IRQPOL_MASK			0x1fffffff
+#define	PINCTRL_IRQPOL0_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQPOL1_IRQPOL_MASK			0xffffffff
+#define	PINCTRL_IRQPOL1_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQPOL2_IRQPOL_MASK			0xfffffff
+#define	PINCTRL_IRQPOL2_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQPOL3_IRQPOL_MASK			0x7fffffff
+#define	PINCTRL_IRQPOL3_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQPOL4_IRQPOL_MASK			0x1fffff
+#define	PINCTRL_IRQPOL4_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQSTAT0_IRQSTAT_MASK			0x1fffffff
+#define	PINCTRL_IRQSTAT0_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_IRQSTAT1_IRQSTAT_MASK			0xffffffff
+#define	PINCTRL_IRQSTAT1_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_IRQSTAT2_IRQSTAT_MASK			0xfffffff
+#define	PINCTRL_IRQSTAT2_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_IRQSTAT3_IRQSTAT_MASK			0x7fffffff
+#define	PINCTRL_IRQSTAT3_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_IRQSTAT4_IRQSTAT_MASK			0x1fffff
+#define	PINCTRL_IRQSTAT4_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_EMI_ODT_CTRL_ADDRESS_CALIB_MASK		(0x3 << 26)
+#define	PINCTRL_EMI_ODT_CTRL_ADDRESS_CALIB_OFFSET	26
+#define	PINCTRL_EMI_ODT_CTRL_ADDRESS_TLOAD_MASK		(0x3 << 24)
+#define	PINCTRL_EMI_ODT_CTRL_ADDRESS_TLOAD_OFFSET	24
+#define	PINCTRL_EMI_ODT_CTRL_CONTROL_CALIB_MASK		(0x3 << 22)
+#define	PINCTRL_EMI_ODT_CTRL_CONTROL_CALIB_OFFSET	22
+#define	PINCTRL_EMI_ODT_CTRL_CONTROL_TLOAD_MASK		(0x3 << 20)
+#define	PINCTRL_EMI_ODT_CTRL_CONTROL_TLOAD_OFFSET	20
+#define	PINCTRL_EMI_ODT_CTRL_DUALPAD_CALIB_MASK		(0x3 << 18)
+#define	PINCTRL_EMI_ODT_CTRL_DUALPAD_CALIB_OFFSET	18
+#define	PINCTRL_EMI_ODT_CTRL_DUALPAD_TLOAD_MASK		(0x3 << 16)
+#define	PINCTRL_EMI_ODT_CTRL_DUALPAD_TLOAD_OFFSET	16
+#define	PINCTRL_EMI_ODT_CTRL_SLICE3_CALIB_MASK		(0x3 << 14)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE3_CALIB_OFFSET	14
+#define	PINCTRL_EMI_ODT_CTRL_SLICE3_TLOAD_MASK		(0x3 << 12)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE3_TLOAD_OFFSET	12
+#define	PINCTRL_EMI_ODT_CTRL_SLICE2_CALIB_MASK		(0x3 << 10)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE2_CALIB_OFFSET	10
+#define	PINCTRL_EMI_ODT_CTRL_SLICE2_TLOAD_MASK		(0x3 << 8)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE2_TLOAD_OFFSET	8
+#define	PINCTRL_EMI_ODT_CTRL_SLICE1_CALIB_MASK		(0x3 << 6)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE1_CALIB_OFFSET	6
+#define	PINCTRL_EMI_ODT_CTRL_SLICE1_TLOAD_MASK		(0x3 << 4)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE1_TLOAD_OFFSET	4
+#define	PINCTRL_EMI_ODT_CTRL_SLICE0_CALIB_MASK		(0x3 << 2)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE0_CALIB_OFFSET	2
+#define	PINCTRL_EMI_ODT_CTRL_SLICE0_TLOAD_MASK		(0x3 << 0)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE0_TLOAD_OFFSET	0
+
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_MASK		(0x3 << 16)
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_OFFSET		16
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_mDDR		(0x0 << 16)
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_GPIO		(0x1 << 16)
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_LVDDR2		(0x2 << 16)
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2		(0x3 << 16)
+#define	PINCTRL_EMI_DS_CTRL_ADDRESS_MA_MASK		(0x3 << 12)
+#define	PINCTRL_EMI_DS_CTRL_ADDRESS_MA_OFFSET		12
+#define	PINCTRL_EMI_DS_CTRL_CONTROL_MA_MASK		(0x3 << 10)
+#define	PINCTRL_EMI_DS_CTRL_CONTROL_MA_OFFSET		10
+#define	PINCTRL_EMI_DS_CTRL_DUALPAD_MA_MASK		(0x3 << 8)
+#define	PINCTRL_EMI_DS_CTRL_DUALPAD_MA_OFFSET		8
+#define	PINCTRL_EMI_DS_CTRL_SLICE3_MA_MASK		(0x3 << 6)
+#define	PINCTRL_EMI_DS_CTRL_SLICE3_MA_OFFSET		6
+#define	PINCTRL_EMI_DS_CTRL_SLICE2_MA_MASK		(0x3 << 4)
+#define	PINCTRL_EMI_DS_CTRL_SLICE2_MA_OFFSET		4
+#define	PINCTRL_EMI_DS_CTRL_SLICE1_MA_MASK		(0x3 << 2)
+#define	PINCTRL_EMI_DS_CTRL_SLICE1_MA_OFFSET		2
+#define	PINCTRL_EMI_DS_CTRL_SLICE0_MA_MASK		(0x3 << 0)
+#define	PINCTRL_EMI_DS_CTRL_SLICE0_MA_OFFSET		0
+
+#endif /* __MX28_REGS_PINCTRL_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-power.h b/arch/arm/include/asm/arch-mx28/regs-power.h
new file mode 100644
index 0000000..9da63ad
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-power.h
@@ -0,0 +1,413 @@
+/*
+ * Freescale i.MX28 Power Controller Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_POWER_H__
+#define __MX28_REGS_POWER_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_power_regs {
+	mx28_reg(hw_power_ctrl)
+	mx28_reg(hw_power_5vctrl)
+	mx28_reg(hw_power_minpwr)
+	mx28_reg(hw_power_charge)
+	uint32_t	hw_power_vdddctrl;
+	uint32_t	reserved_vddd[3];
+	uint32_t	hw_power_vddactrl;
+	uint32_t	reserved_vdda[3];
+	uint32_t	hw_power_vddioctrl;
+	uint32_t	reserved_vddio[3];
+	uint32_t	hw_power_vddmemctrl;
+	uint32_t	reserved_vddmem[3];
+	uint32_t	hw_power_dcdc4p2;
+	uint32_t	reserved_dcdc4p2[3];
+	uint32_t	hw_power_misc;
+	uint32_t	reserved_misc[3];
+	uint32_t	hw_power_dclimits;
+	uint32_t	reserved_dclimits[3];
+	mx28_reg(hw_power_loopctrl)
+	uint32_t	hw_power_sts;
+	uint32_t	reserved_sts[3];
+	mx28_reg(hw_power_speed)
+	uint32_t	hw_power_battmonitor;
+	uint32_t	reserved_battmonitor[3];
+
+	uint32_t	reserved[4];
+
+	mx28_reg(hw_power_reset)
+	mx28_reg(hw_power_debug)
+	mx28_reg(hw_power_thermal)
+	mx28_reg(hw_power_usb1ctrl)
+	mx28_reg(hw_power_special)
+	mx28_reg(hw_power_version)
+	mx28_reg(hw_power_anaclkctrl)
+	mx28_reg(hw_power_refctrl)
+};
+#endif
+
+#define	POWER_CTRL_PSWITCH_MID_TRAN			(1 << 27)
+#define	POWER_CTRL_DCDC4P2_BO_IRQ			(1 << 24)
+#define	POWER_CTRL_ENIRQ_DCDC4P2_BO			(1 << 23)
+#define	POWER_CTRL_VDD5V_DROOP_IRQ			(1 << 22)
+#define	POWER_CTRL_ENIRQ_VDD5V_DROOP			(1 << 21)
+#define	POWER_CTRL_PSWITCH_IRQ				(1 << 20)
+#define	POWER_CTRL_PSWITCH_IRQ_SRC			(1 << 19)
+#define	POWER_CTRL_POLARITY_PSWITCH			(1 << 18)
+#define	POWER_CTRL_ENIRQ_PSWITCH			(1 << 17)
+#define	POWER_CTRL_POLARITY_DC_OK			(1 << 16)
+#define	POWER_CTRL_DC_OK_IRQ				(1 << 15)
+#define	POWER_CTRL_ENIRQ_DC_OK				(1 << 14)
+#define	POWER_CTRL_BATT_BO_IRQ				(1 << 13)
+#define	POWER_CTRL_ENIRQ_BATT_BO			(1 << 12)
+#define	POWER_CTRL_VDDIO_BO_IRQ				(1 << 11)
+#define	POWER_CTRL_ENIRQ_VDDIO_BO			(1 << 10)
+#define	POWER_CTRL_VDDA_BO_IRQ				(1 << 9)
+#define	POWER_CTRL_ENIRQ_VDDA_BO			(1 << 8)
+#define	POWER_CTRL_VDDD_BO_IRQ				(1 << 7)
+#define	POWER_CTRL_ENIRQ_VDDD_BO			(1 << 6)
+#define	POWER_CTRL_POLARITY_VBUSVALID			(1 << 5)
+#define	POWER_CTRL_VBUS_VALID_IRQ			(1 << 4)
+#define	POWER_CTRL_ENIRQ_VBUS_VALID			(1 << 3)
+#define	POWER_CTRL_POLARITY_VDD5V_GT_VDDIO		(1 << 2)
+#define	POWER_CTRL_VDD5V_GT_VDDIO_IRQ			(1 << 1)
+#define	POWER_CTRL_ENIRQ_VDD5V_GT_VDDIO			(1 << 0)
+
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_MASK		(0x3 << 30)
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_OFFSET		30
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_4V3			(0x0 << 30)
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_4V4			(0x1 << 30)
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_4V5			(0x2 << 30)
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_4V7			(0x3 << 30)
+#define	POWER_5VCTRL_HEADROOM_ADJ_MASK			(0x7 << 24)
+#define	POWER_5VCTRL_HEADROOM_ADJ_OFFSET		24
+#define	POWER_5VCTRL_PWD_CHARGE_4P2_MASK		(0x3 << 20)
+#define	POWER_5VCTRL_PWD_CHARGE_4P2_OFFSET		20
+#define	POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK		(0x3f << 12)
+#define	POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET		12
+#define	POWER_5VCTRL_VBUSVALID_TRSH_MASK		(0x7 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_OFFSET		8
+#define	POWER_5VCTRL_VBUSVALID_TRSH_2V9			(0x0 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V0			(0x1 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V1			(0x2 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V2			(0x3 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V3			(0x4 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V4			(0x5 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V5			(0x6 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V6			(0x7 << 8)
+#define	POWER_5VCTRL_PWDN_5VBRNOUT			(1 << 7)
+#define	POWER_5VCTRL_ENABLE_LINREG_ILIMIT		(1 << 6)
+#define	POWER_5VCTRL_DCDC_XFER				(1 << 5)
+#define	POWER_5VCTRL_VBUSVALID_5VDETECT			(1 << 4)
+#define	POWER_5VCTRL_VBUSVALID_TO_B			(1 << 3)
+#define	POWER_5VCTRL_ILIMIT_EQ_ZERO			(1 << 2)
+#define	POWER_5VCTRL_PWRUP_VBUS_CMPS			(1 << 1)
+#define	POWER_5VCTRL_ENABLE_DCDC			(1 << 0)
+
+#define	POWER_MINPWR_LOWPWR_4P2				(1 << 14)
+#define	POWER_MINPWR_PWD_BO				(1 << 12)
+#define	POWER_MINPWR_USE_VDDXTAL_VBG			(1 << 11)
+#define	POWER_MINPWR_PWD_ANA_CMPS			(1 << 10)
+#define	POWER_MINPWR_ENABLE_OSC				(1 << 9)
+#define	POWER_MINPWR_SELECT_OSC				(1 << 8)
+#define	POWER_MINPWR_FBG_OFF				(1 << 7)
+#define	POWER_MINPWR_DOUBLE_FETS			(1 << 6)
+#define	POWER_MINPWR_HALFFETS				(1 << 5)
+#define	POWER_MINPWR_LESSANA_I				(1 << 4)
+#define	POWER_MINPWR_PWD_XTAL24				(1 << 3)
+#define	POWER_MINPWR_DC_STOPCLK				(1 << 2)
+#define	POWER_MINPWR_EN_DC_PFM				(1 << 1)
+#define	POWER_MINPWR_DC_HALFCLK				(1 << 0)
+
+#define	POWER_CHARGE_ADJ_VOLT_MASK			(0x7 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_OFFSET			24
+#define	POWER_CHARGE_ADJ_VOLT_M025P			(0x1 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_P050P			(0x2 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_M075P			(0x3 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_P025P			(0x4 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_M050P			(0x5 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_P075P			(0x6 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_M100P			(0x7 << 24)
+#define	POWER_CHARGE_ENABLE_LOAD			(1 << 22)
+#define	POWER_CHARGE_ENABLE_FAULT_DETECT		(1 << 20)
+#define	POWER_CHARGE_CHRG_STS_OFF			(1 << 19)
+#define	POWER_CHARGE_LIION_4P1				(1 << 18)
+#define	POWER_CHARGE_PWD_BATTCHRG			(1 << 16)
+#define	POWER_CHARGE_ENABLE_CHARGER_USB1		(1 << 13)
+#define	POWER_CHARGE_ENABLE_CHARGER_USB0		(1 << 12)
+#define	POWER_CHARGE_STOP_ILIMIT_MASK			(0xf << 8)
+#define	POWER_CHARGE_STOP_ILIMIT_OFFSET			8
+#define	POWER_CHARGE_STOP_ILIMIT_10MA			(0x1 << 8)
+#define	POWER_CHARGE_STOP_ILIMIT_20MA			(0x2 << 8)
+#define	POWER_CHARGE_STOP_ILIMIT_50MA			(0x4 << 8)
+#define	POWER_CHARGE_STOP_ILIMIT_100MA			(0x8 << 8)
+#define	POWER_CHARGE_BATTCHRG_I_MASK			0x3f
+#define	POWER_CHARGE_BATTCHRG_I_OFFSET			0
+#define	POWER_CHARGE_BATTCHRG_I_10MA			0x01
+#define	POWER_CHARGE_BATTCHRG_I_20MA			0x02
+#define	POWER_CHARGE_BATTCHRG_I_50MA			0x04
+#define	POWER_CHARGE_BATTCHRG_I_100MA			0x08
+#define	POWER_CHARGE_BATTCHRG_I_200MA			0x10
+#define	POWER_CHARGE_BATTCHRG_I_400MA			0x20
+
+#define	POWER_VDDDCTRL_ADJTN_MASK			(0xf << 28)
+#define	POWER_VDDDCTRL_ADJTN_OFFSET			28
+#define	POWER_VDDDCTRL_PWDN_BRNOUT			(1 << 23)
+#define	POWER_VDDDCTRL_DISABLE_STEPPING			(1 << 22)
+#define	POWER_VDDDCTRL_ENABLE_LINREG			(1 << 21)
+#define	POWER_VDDDCTRL_DISABLE_FET			(1 << 20)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_MASK		(0x3 << 16)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_OFFSET		16
+#define	POWER_VDDDCTRL_LINREG_OFFSET_0STEPS		(0x0 << 16)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_ABOVE	(0x1 << 16)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW	(0x2 << 16)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_2STEPS_BELOW	(0x3 << 16)
+#define	POWER_VDDDCTRL_BO_OFFSET_MASK			(0x7 << 8)
+#define	POWER_VDDDCTRL_BO_OFFSET_OFFSET			8
+#define	POWER_VDDDCTRL_TRG_MASK				0x1f
+#define	POWER_VDDDCTRL_TRG_OFFSET			0
+
+#define	POWER_VDDACTRL_PWDN_BRNOUT			(1 << 19)
+#define	POWER_VDDACTRL_DISABLE_STEPPING			(1 << 18)
+#define	POWER_VDDACTRL_ENABLE_LINREG			(1 << 17)
+#define	POWER_VDDACTRL_DISABLE_FET			(1 << 16)
+#define	POWER_VDDACTRL_LINREG_OFFSET_MASK		(0x3 << 12)
+#define	POWER_VDDACTRL_LINREG_OFFSET_OFFSET		12
+#define	POWER_VDDACTRL_LINREG_OFFSET_0STEPS		(0x0 << 12)
+#define	POWER_VDDACTRL_LINREG_OFFSET_1STEPS_ABOVE	(0x1 << 12)
+#define	POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW	(0x2 << 12)
+#define	POWER_VDDACTRL_LINREG_OFFSET_2STEPS_BELOW	(0x3 << 12)
+#define	POWER_VDDACTRL_BO_OFFSET_MASK			(0x7 << 8)
+#define	POWER_VDDACTRL_BO_OFFSET_OFFSET			8
+#define	POWER_VDDACTRL_TRG_MASK				0x1f
+#define	POWER_VDDACTRL_TRG_OFFSET			0
+
+#define	POWER_VDDIOCTRL_ADJTN_MASK			(0xf << 20)
+#define	POWER_VDDIOCTRL_ADJTN_OFFSET			20
+#define	POWER_VDDIOCTRL_PWDN_BRNOUT			(1 << 18)
+#define	POWER_VDDIOCTRL_DISABLE_STEPPING		(1 << 17)
+#define	POWER_VDDIOCTRL_DISABLE_FET			(1 << 16)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_MASK		(0x3 << 12)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_OFFSET		12
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_0STEPS		(0x0 << 12)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_ABOVE	(0x1 << 12)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW	(0x2 << 12)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_2STEPS_BELOW	(0x3 << 12)
+#define	POWER_VDDIOCTRL_BO_OFFSET_MASK			(0x7 << 8)
+#define	POWER_VDDIOCTRL_BO_OFFSET_OFFSET		8
+#define	POWER_VDDIOCTRL_TRG_MASK			0x1f
+#define	POWER_VDDIOCTRL_TRG_OFFSET			0
+
+#define	POWER_VDDMEMCTRL_PULLDOWN_ACTIVE		(1 << 10)
+#define	POWER_VDDMEMCTRL_ENABLE_ILIMIT			(1 << 9)
+#define	POWER_VDDMEMCTRL_ENABLE_LINREG			(1 << 8)
+#define	POWER_VDDMEMCTRL_BO_OFFSET_MASK			(0x7 << 5)
+#define	POWER_VDDMEMCTRL_BO_OFFSET_OFFSET		5
+#define	POWER_VDDMEMCTRL_TRG_MASK			0x1f
+#define	POWER_VDDMEMCTRL_TRG_OFFSET			0
+
+#define	POWER_DCDC4P2_DROPOUT_CTRL_MASK			(0xf << 28)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_OFFSET		28
+#define	POWER_DCDC4P2_DROPOUT_CTRL_200MV		(0x3 << 30)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_100MV		(0x2 << 30)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_50MV			(0x1 << 30)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_25MV			(0x0 << 30)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_SRC_4P2		(0x0 << 28)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_SRC_4P2_LT_BATT	(0x1 << 28)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL		(0x2 << 28)
+#define	POWER_DCDC4P2_ISTEAL_THRESH_MASK		(0x3 << 24)
+#define	POWER_DCDC4P2_ISTEAL_THRESH_OFFSET		24
+#define	POWER_DCDC4P2_ENABLE_4P2			(1 << 23)
+#define	POWER_DCDC4P2_ENABLE_DCDC			(1 << 22)
+#define	POWER_DCDC4P2_HYST_DIR				(1 << 21)
+#define	POWER_DCDC4P2_HYST_THRESH			(1 << 20)
+#define	POWER_DCDC4P2_TRG_MASK				(0x7 << 16)
+#define	POWER_DCDC4P2_TRG_OFFSET			16
+#define	POWER_DCDC4P2_TRG_4V2				(0x0 << 16)
+#define	POWER_DCDC4P2_TRG_4V1				(0x1 << 16)
+#define	POWER_DCDC4P2_TRG_4V0				(0x2 << 16)
+#define	POWER_DCDC4P2_TRG_3V9				(0x3 << 16)
+#define	POWER_DCDC4P2_TRG_BATT				(0x4 << 16)
+#define	POWER_DCDC4P2_BO_MASK				(0x1f << 8)
+#define	POWER_DCDC4P2_BO_OFFSET				8
+#define	POWER_DCDC4P2_CMPTRIP_MASK			0x1f
+#define	POWER_DCDC4P2_CMPTRIP_OFFSET			0
+
+#define	POWER_MISC_FREQSEL_MASK				(0x7 << 4)
+#define	POWER_MISC_FREQSEL_OFFSET			4
+#define	POWER_MISC_FREQSEL_20MHZ			(0x1 << 4)
+#define	POWER_MISC_FREQSEL_24MHZ			(0x2 << 4)
+#define	POWER_MISC_FREQSEL_19MHZ			(0x3 << 4)
+#define	POWER_MISC_FREQSEL_14MHZ			(0x4 << 4)
+#define	POWER_MISC_FREQSEL_18MHZ			(0x5 << 4)
+#define	POWER_MISC_FREQSEL_21MHZ			(0x6 << 4)
+#define	POWER_MISC_FREQSEL_17MHZ			(0x7 << 4)
+#define	POWER_MISC_DISABLE_FET_BO_LOGIC			(1 << 3)
+#define	POWER_MISC_DELAY_TIMING				(1 << 2)
+#define	POWER_MISC_TEST					(1 << 1)
+#define	POWER_MISC_SEL_PLLCLK				(1 << 0)
+
+#define	POWER_DCLIMITS_POSLIMIT_BUCK_MASK		(0x7f << 8)
+#define	POWER_DCLIMITS_POSLIMIT_BUCK_OFFSET		8
+#define	POWER_DCLIMITS_NEGLIMIT_MASK			0x7f
+#define	POWER_DCLIMITS_NETLIMIT_OFFSET			0
+
+#define	POWER_LOOPCTRL_TOGGLE_DIF			(1 << 20)
+#define	POWER_LOOPCTRL_HYST_SIGN			(1 << 19)
+#define	POWER_LOOPCTRL_EN_CM_HYST			(1 << 18)
+#define	POWER_LOOPCTRL_EN_DF_HYST			(1 << 17)
+#define	POWER_LOOPCTRL_CM_HYST_THRESH			(1 << 16)
+#define	POWER_LOOPCTRL_DF_HYST_THRESH			(1 << 15)
+#define	POWER_LOOPCTRL_RCSCALE_THRESH			(1 << 14)
+#define	POWER_LOOPCTRL_EN_RCSCALE_MASK			(0x3 << 12)
+#define	POWER_LOOPCTRL_EN_RCSCALE_OFFSET		12
+#define	POWER_LOOPCTRL_EN_RCSCALE_DIS			(0x0 << 12)
+#define	POWER_LOOPCTRL_EN_RCSCALE_2X			(0x1 << 12)
+#define	POWER_LOOPCTRL_EN_RCSCALE_4X			(0x2 << 12)
+#define	POWER_LOOPCTRL_EN_RCSCALE_8X			(0x3 << 12)
+#define	POWER_LOOPCTRL_DC_FF_MASK			(0x7 << 8)
+#define	POWER_LOOPCTRL_DC_FF_OFFSET			8
+#define	POWER_LOOPCTRL_DC_R_MASK			(0xf << 4)
+#define	POWER_LOOPCTRL_DC_R_OFFSET			4
+#define	POWER_LOOPCTRL_DC_C_MASK			0x3
+#define	POWER_LOOPCTRL_DC_C_OFFSET			0
+#define	POWER_LOOPCTRL_DC_C_MAX				0x0
+#define	POWER_LOOPCTRL_DC_C_2X				0x1
+#define	POWER_LOOPCTRL_DC_C_4X				0x2
+#define	POWER_LOOPCTRL_DC_C_MIN				0x3
+
+#define	POWER_STS_PWRUP_SOURCE_MASK			(0x3f << 24)
+#define	POWER_STS_PWRUP_SOURCE_OFFSET			24
+#define	POWER_STS_PWRUP_SOURCE_5V			(0x20 << 24)
+#define	POWER_STS_PWRUP_SOURCE_RTC			(0x10 << 24)
+#define	POWER_STS_PWRUP_SOURCE_PSWITCH_HIGH		(0x02 << 24)
+#define	POWER_STS_PWRUP_SOURCE_PSWITCH_MID		(0x01 << 24)
+#define	POWER_STS_PSWITCH_MASK				(0x3 << 20)
+#define	POWER_STS_PSWITCH_OFFSET			20
+#define	POWER_STS_THERMAL_WARNING			(1 << 19)
+#define	POWER_STS_VDDMEM_BO				(1 << 18)
+#define	POWER_STS_AVALID0_STATUS			(1 << 17)
+#define	POWER_STS_BVALID0_STATUS			(1 << 16)
+#define	POWER_STS_VBUSVALID0_STATUS			(1 << 15)
+#define	POWER_STS_SESSEND0_STATUS			(1 << 14)
+#define	POWER_STS_BATT_BO				(1 << 13)
+#define	POWER_STS_VDD5V_FAULT				(1 << 12)
+#define	POWER_STS_CHRGSTS				(1 << 11)
+#define	POWER_STS_DCDC_4P2_BO				(1 << 10)
+#define	POWER_STS_DC_OK					(1 << 9)
+#define	POWER_STS_VDDIO_BO				(1 << 8)
+#define	POWER_STS_VDDA_BO				(1 << 7)
+#define	POWER_STS_VDDD_BO				(1 << 6)
+#define	POWER_STS_VDD5V_GT_VDDIO			(1 << 5)
+#define	POWER_STS_VDD5V_DROOP				(1 << 4)
+#define	POWER_STS_AVALID0				(1 << 3)
+#define	POWER_STS_BVALID0				(1 << 2)
+#define	POWER_STS_VBUSVALID0				(1 << 1)
+#define	POWER_STS_SESSEND0				(1 << 0)
+
+#define	POWER_SPEED_STATUS_MASK				(0xffff << 8)
+#define	POWER_SPEED_STATUS_OFFSET			8
+#define	POWER_SPEED_STATUS_SEL_MASK			(0x3 << 6)
+#define	POWER_SPEED_STATUS_SEL_OFFSET			6
+#define	POWER_SPEED_STATUS_SEL_DCDC_STAT		(0x0 << 6)
+#define	POWER_SPEED_STATUS_SEL_CORE_STAT		(0x1 << 6)
+#define	POWER_SPEED_STATUS_SEL_ARM_STAT			(0x2 << 6)
+#define	POWER_SPEED_CTRL_MASK				0x3
+#define	POWER_SPEED_CTRL_OFFSET				0
+#define	POWER_SPEED_CTRL_SS_OFF				0x0
+#define	POWER_SPEED_CTRL_SS_ON				0x1
+#define	POWER_SPEED_CTRL_SS_ENABLE			0x3
+
+#define	POWER_BATTMONITOR_BATT_VAL_MASK			(0x3ff << 16)
+#define	POWER_BATTMONITOR_BATT_VAL_OFFSET		16
+#define	POWER_BATTMONITOR_PWDN_BATTBRNOUT_5VDETECT_EN	(1 << 11)
+#define	POWER_BATTMONITOR_EN_BATADJ			(1 << 10)
+#define	POWER_BATTMONITOR_PWDN_BATTBRNOUT		(1 << 9)
+#define	POWER_BATTMONITOR_BRWNOUT_PWD			(1 << 8)
+#define	POWER_BATTMONITOR_BRWNOUT_LVL_MASK		0x1f
+#define	POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET		0
+
+#define	POWER_RESET_UNLOCK_MASK				(0xffff << 16)
+#define	POWER_RESET_UNLOCK_OFFSET			16
+#define	POWER_RESET_UNLOCK_KEY				(0x3e77 << 16)
+#define	POWER_RESET_FASTFALL_PSWITCH_OFF		(1 << 2)
+#define	POWER_RESET_PWD_OFF				(1 << 1)
+#define	POWER_RESET_PWD					(1 << 0)
+
+#define	POWER_DEBUG_VBUSVALIDPIOLOCK			(1 << 3)
+#define	POWER_DEBUG_AVALIDPIOLOCK			(1 << 2)
+#define	POWER_DEBUG_BVALIDPIOLOCK			(1 << 1)
+#define	POWER_DEBUG_SESSENDPIOLOCK			(1 << 0)
+
+#define	POWER_THERMAL_TEST				(1 << 8)
+#define	POWER_THERMAL_PWD				(1 << 7)
+#define	POWER_THERMAL_LOW_POWER				(1 << 6)
+#define	POWER_THERMAL_OFFSET_ADJ_MASK			(0x3 << 4)
+#define	POWER_THERMAL_OFFSET_ADJ_OFFSET			4
+#define	POWER_THERMAL_OFFSET_ADJ_ENABLE			(1 << 3)
+#define	POWER_THERMAL_TEMP_THRESHOLD_MASK		0x7
+#define	POWER_THERMAL_TEMP_THRESHOLD_OFFSET		0
+
+#define	POWER_USB1CTRL_AVALID1				(1 << 3)
+#define	POWER_USB1CTRL_BVALID1				(1 << 2)
+#define	POWER_USB1CTRL_VBUSVALID1			(1 << 1)
+#define	POWER_USB1CTRL_SESSEND1				(1 << 0)
+
+#define	POWER_SPECIAL_TEST_MASK				0xffffffff
+#define	POWER_SPECIAL_TEST_OFFSET			0
+
+#define	POWER_VERSION_MAJOR_MASK			(0xff << 24)
+#define	POWER_VERSION_MAJOR_OFFSET			24
+#define	POWER_VERSION_MINOR_MASK			(0xff << 16)
+#define	POWER_VERSION_MINOR_OFFSET			16
+#define	POWER_VERSION_STEP_MASK				0xffff
+#define	POWER_VERSION_STEP_OFFSET			0
+
+#define	POWER_ANACLKCTRL_CLKGATE_0			(1 << 31)
+#define	POWER_ANACLKCTRL_OUTDIV_MASK			(0x7 << 28)
+#define	POWER_ANACLKCTRL_OUTDIV_OFFSET			28
+#define	POWER_ANACLKCTRL_INVERT_OUTCLK			(1 << 27)
+#define	POWER_ANACLKCTRL_CLKGATE_I			(1 << 26)
+#define	POWER_ANACLKCTRL_DITHER_OFF			(1 << 10)
+#define	POWER_ANACLKCTRL_SLOW_DITHER			(1 << 9)
+#define	POWER_ANACLKCTRL_INVERT_INCLK			(1 << 8)
+#define	POWER_ANACLKCTRL_INCLK_SHIFT_MASK		(0x3 << 4)
+#define	POWER_ANACLKCTRL_INCLK_SHIFT_OFFSET		4
+#define	POWER_ANACLKCTRL_INDIV_MASK			0x7
+#define	POWER_ANACLKCTRL_INDIV_OFFSET			0
+
+#define	POWER_REFCTRL_FASTSETTLING			(1 << 26)
+#define	POWER_REFCTRL_RAISE_REF				(1 << 25)
+#define	POWER_REFCTRL_XTAL_BGR_BIAS			(1 << 24)
+#define	POWER_REFCTRL_VBG_ADJ_MASK			(0x7 << 20)
+#define	POWER_REFCTRL_VBG_ADJ_OFFSET			20
+#define	POWER_REFCTRL_LOW_PWR				(1 << 19)
+#define	POWER_REFCTRL_BIAS_CTRL_MASK			(0x3 << 16)
+#define	POWER_REFCTRL_BIAS_CTRL_OFFSET			16
+#define	POWER_REFCTRL_VDDXTAL_TO_VDDD			(1 << 14)
+#define	POWER_REFCTRL_ADJ_ANA				(1 << 13)
+#define	POWER_REFCTRL_ADJ_VAG				(1 << 12)
+#define	POWER_REFCTRL_ANA_REFVAL_MASK			(0xf << 8)
+#define	POWER_REFCTRL_ANA_REFVAL_OFFSET			8
+#define	POWER_REFCTRL_VAG_VAL_MASK			(0xf << 4)
+#define	POWER_REFCTRL_VAG_VAL_OFFSET			4
+
+#endif	/* __MX28_REGS_POWER_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-rtc.h b/arch/arm/include/asm/arch-mx28/regs-rtc.h
new file mode 100644
index 0000000..fe2fda9
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-rtc.h
@@ -0,0 +1,147 @@
+/*
+ * Freescale i.MX28 RTC Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_RTC_H__
+#define __MX28_REGS_RTC_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_rtc_regs {
+	mx28_reg(hw_rtc_ctrl)
+	mx28_reg(hw_rtc_stat)
+	mx28_reg(hw_rtc_milliseconds)
+	mx28_reg(hw_rtc_seconds)
+	mx28_reg(hw_rtc_rtc_alarm)
+	mx28_reg(hw_rtc_watchdog)
+	mx28_reg(hw_rtc_persistent0)
+	mx28_reg(hw_rtc_persistent1)
+	mx28_reg(hw_rtc_persistent2)
+	mx28_reg(hw_rtc_persistent3)
+	mx28_reg(hw_rtc_persistent4)
+	mx28_reg(hw_rtc_persistent5)
+	mx28_reg(hw_rtc_debug)
+	mx28_reg(hw_rtc_version)
+};
+#endif
+
+#define	RTC_CTRL_SFTRST				(1 << 31)
+#define	RTC_CTRL_CLKGATE			(1 << 30)
+#define	RTC_CTRL_SUPPRESS_COPY2ANALOG		(1 << 6)
+#define	RTC_CTRL_FORCE_UPDATE			(1 << 5)
+#define	RTC_CTRL_WATCHDOGEN			(1 << 4)
+#define	RTC_CTRL_ONEMSEC_IRQ			(1 << 3)
+#define	RTC_CTRL_ALARM_IRQ			(1 << 2)
+#define	RTC_CTRL_ONEMSEC_IRQ_EN			(1 << 1)
+#define	RTC_CTRL_ALARM_IRQ_EN			(1 << 0)
+
+#define	RTC_STAT_RTC_PRESENT			(1 << 31)
+#define	RTC_STAT_ALARM_PRESENT			(1 << 30)
+#define	RTC_STAT_WATCHDOG_PRESENT		(1 << 29)
+#define	RTC_STAT_XTAL32000_PRESENT		(1 << 28)
+#define	RTC_STAT_XTAL32768_PRESENT		(1 << 27)
+#define	RTC_STAT_STALE_REGS_MASK		(0xff << 16)
+#define	RTC_STAT_STALE_REGS_OFFSET		16
+#define	RTC_STAT_NEW_REGS_MASK			(0xff << 8)
+#define	RTC_STAT_NEW_REGS_OFFSET		8
+
+#define	RTC_MILLISECONDS_COUNT_MASK		0xffffffff
+#define	RTC_MILLISECONDS_COUNT_OFFSET		0
+
+#define	RTC_SECONDS_COUNT_MASK			0xffffffff
+#define	RTC_SECONDS_COUNT_OFFSET		0
+
+#define	RTC_ALARM_VALUE_MASK			0xffffffff
+#define	RTC_ALARM_VALUE_OFFSET			0
+
+#define	RTC_WATCHDOG_COUNT_MASK			0xffffffff
+#define	RTC_WATCHDOG_COUNT_OFFSET		0
+
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_MASK	(0xf << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_OFFSET	28
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V83	(0x0 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V78	(0x1 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V73	(0x2 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V68	(0x3 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V62	(0x4 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V57	(0x5 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V52	(0x6 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V48	(0x7 << 28)
+#define	RTC_PERSISTENT0_EXTERNAL_RESET		(1 << 21)
+#define	RTC_PERSISTENT0_THERMAL_RESET		(1 << 20)
+#define	RTC_PERSISTENT0_ENABLE_LRADC_PWRUP	(1 << 18)
+#define	RTC_PERSISTENT0_AUTO_RESTART		(1 << 17)
+#define	RTC_PERSISTENT0_DISABLE_PSWITCH		(1 << 16)
+#define	RTC_PERSISTENT0_LOWERBIAS_MASK		(0xf << 14)
+#define	RTC_PERSISTENT0_LOWERBIAS_OFFSET	14
+#define	RTC_PERSISTENT0_LOWERBIAS_NOMINAL	(0x0 << 14)
+#define	RTC_PERSISTENT0_LOWERBIAS_M25P		(0x1 << 14)
+#define	RTC_PERSISTENT0_LOWERBIAS_M50P		(0x3 << 14)
+#define	RTC_PERSISTENT0_DISABLE_XTALOK		(1 << 13)
+#define	RTC_PERSISTENT0_MSEC_RES_MASK		(0x1f << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_OFFSET		8
+#define	RTC_PERSISTENT0_MSEC_RES_1MS		(0x01 << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_2MS		(0x02 << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_4MS		(0x04 << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_8MS		(0x08 << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_16MS		(0x10 << 8)
+#define	RTC_PERSISTENT0_ALARM_WAKE		(1 << 7)
+#define	RTC_PERSISTENT0_XTAL32_FREQ		(1 << 6)
+#define	RTC_PERSISTENT0_XTAL32KHZ_PWRUP		(1 << 5)
+#define	RTC_PERSISTENT0_XTAL24KHZ_PWRUP		(1 << 4)
+#define	RTC_PERSISTENT0_LCK_SECS		(1 << 3)
+#define	RTC_PERSISTENT0_ALARM_EN		(1 << 2)
+#define	RTC_PERSISTENT0_ALARM_WAKE_EN		(1 << 1)
+#define	RTC_PERSISTENT0_CLOCKSOURCE		(1 << 0)
+
+#define	RTC_PERSISTENT1_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT1_GENERAL_OFFSET		0
+#define	RTC_PERSISTENT1_GENERAL_OTG_ALT_ROLE	0x0080
+#define	RTC_PERSISTENT1_GENERAL_OTG_HNP		0x0100
+#define	RTC_PERSISTENT1_GENERAL_USB_LPM		0x0200
+#define	RTC_PERSISTENT1_GENERAL_SKIP_CHECKDISK	0x0400
+#define	RTC_PERSISTENT1_GENERAL_USB_BOOT_PLAYER	0x0800
+#define	RTC_PERSISTENT1_GENERAL_ENUM_500MA_2X	0x1000
+
+#define	RTC_PERSISTENT2_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT2_GENERAL_OFFSET		0
+
+#define	RTC_PERSISTENT3_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT3_GENERAL_OFFSET		0
+
+#define	RTC_PERSISTENT4_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT4_GENERAL_OFFSET		0
+
+#define	RTC_PERSISTENT5_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT5_GENERAL_OFFSET		0
+
+#define	RTC_DEBUG_WATCHDOG_RESET_MASK		(1 << 1)
+#define	RTC_DEBUG_WATCHDOG_RESET		(1 << 0)
+
+#define	RTC_VERSION_MAJOR_MASK			(0xff << 24)
+#define	RTC_VERSION_MAJOR_OFFSET		24
+#define	RTC_VERSION_MINOR_MASK			(0xff << 16)
+#define	RTC_VERSION_MINOR_OFFSET		16
+#define	RTC_VERSION_STEP_MASK			0xffff
+#define	RTC_VERSION_STEP_OFFSET			0
+
+#endif	/* __MX28_REGS_RTC_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-ssp.h b/arch/arm/include/asm/arch-mx28/regs-ssp.h
new file mode 100644
index 0000000..ab3870c
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-ssp.h
@@ -0,0 +1,349 @@
+/*
+ * Freescale i.MX28 SSP Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_SSP_H__
+#define __MX28_REGS_SSP_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_ssp_regs {
+	mx28_reg(hw_ssp_ctrl0)
+	mx28_reg(hw_ssp_cmd0)
+	mx28_reg(hw_ssp_cmd1)
+	mx28_reg(hw_ssp_xfer_size)
+	mx28_reg(hw_ssp_block_size)
+	mx28_reg(hw_ssp_compref)
+	mx28_reg(hw_ssp_compmask)
+	mx28_reg(hw_ssp_timing)
+	mx28_reg(hw_ssp_ctrl1)
+	mx28_reg(hw_ssp_data)
+	mx28_reg(hw_ssp_sdresp0)
+	mx28_reg(hw_ssp_sdresp1)
+	mx28_reg(hw_ssp_sdresp2)
+	mx28_reg(hw_ssp_sdresp3)
+	mx28_reg(hw_ssp_ddr_ctrl)
+	mx28_reg(hw_ssp_dll_ctrl)
+	mx28_reg(hw_ssp_status)
+	mx28_reg(hw_ssp_dll_sts)
+	mx28_reg(hw_ssp_debug)
+	mx28_reg(hw_ssp_version)
+};
+#endif
+
+#define	SSP_CTRL0_SFTRST			(1 << 31)
+#define	SSP_CTRL0_CLKGATE			(1 << 30)
+#define	SSP_CTRL0_RUN				(1 << 29)
+#define	SSP_CTRL0_SDIO_IRQ_CHECK		(1 << 28)
+#define	SSP_CTRL0_LOCK_CS			(1 << 27)
+#define	SSP_CTRL0_IGNORE_CRC			(1 << 26)
+#define	SSP_CTRL0_READ				(1 << 25)
+#define	SSP_CTRL0_DATA_XFER			(1 << 24)
+#define	SSP_CTRL0_BUS_WIDTH_MASK		(0x3 << 22)
+#define	SSP_CTRL0_BUS_WIDTH_OFFSET		22
+#define	SSP_CTRL0_BUS_WIDTH_ONE_BIT		(0x0 << 22)
+#define	SSP_CTRL0_BUS_WIDTH_FOUR_BIT		(0x1 << 22)
+#define	SSP_CTRL0_BUS_WIDTH_EIGHT_BIT		(0x2 << 22)
+#define	SSP_CTRL0_WAIT_FOR_IRQ			(1 << 21)
+#define	SSP_CTRL0_WAIT_FOR_CMD			(1 << 20)
+#define	SSP_CTRL0_LONG_RESP			(1 << 19)
+#define	SSP_CTRL0_CHECK_RESP			(1 << 18)
+#define	SSP_CTRL0_GET_RESP			(1 << 17)
+#define	SSP_CTRL0_ENABLE			(1 << 16)
+
+#define	SSP_CMD0_SOFT_TERMINATE			(1 << 26)
+#define	SSP_CMD0_DBL_DATA_RATE_EN		(1 << 25)
+#define	SSP_CMD0_PRIM_BOOT_OP_EN		(1 << 24)
+#define	SSP_CMD0_BOOT_ACK_EN			(1 << 23)
+#define	SSP_CMD0_SLOW_CLKING_EN			(1 << 22)
+#define	SSP_CMD0_CONT_CLKING_EN			(1 << 21)
+#define	SSP_CMD0_APPEND_8CYC			(1 << 20)
+#define	SSP_CMD0_CMD_MASK			0xff
+#define	SSP_CMD0_CMD_OFFSET			0
+#define	SSP_CMD0_CMD_MMC_GO_IDLE_STATE		0x00
+#define	SSP_CMD0_CMD_MMC_SEND_OP_COND		0x01
+#define	SSP_CMD0_CMD_MMC_ALL_SEND_CID		0x02
+#define	SSP_CMD0_CMD_MMC_SET_RELATIVE_ADDR	0x03
+#define	SSP_CMD0_CMD_MMC_SET_DSR		0x04
+#define	SSP_CMD0_CMD_MMC_RESERVED_5		0x05
+#define	SSP_CMD0_CMD_MMC_SWITCH			0x06
+#define	SSP_CMD0_CMD_MMC_SELECT_DESELECT_CARD	0x07
+#define	SSP_CMD0_CMD_MMC_SEND_EXT_CSD		0x08
+#define	SSP_CMD0_CMD_MMC_SEND_CSD		0x09
+#define	SSP_CMD0_CMD_MMC_SEND_CID		0x0a
+#define	SSP_CMD0_CMD_MMC_READ_DAT_UNTIL_STOP	0x0b
+#define	SSP_CMD0_CMD_MMC_STOP_TRANSMISSION	0x0c
+#define	SSP_CMD0_CMD_MMC_SEND_STATUS		0x0d
+#define	SSP_CMD0_CMD_MMC_BUSTEST_R		0x0e
+#define	SSP_CMD0_CMD_MMC_GO_INACTIVE_STATE	0x0f
+#define	SSP_CMD0_CMD_MMC_SET_BLOCKLEN		0x10
+#define	SSP_CMD0_CMD_MMC_READ_SINGLE_BLOCK	0x11
+#define	SSP_CMD0_CMD_MMC_READ_MULTIPLE_BLOCK	0x12
+#define	SSP_CMD0_CMD_MMC_BUSTEST_W		0x13
+#define	SSP_CMD0_CMD_MMC_WRITE_DAT_UNTIL_STOP	0x14
+#define	SSP_CMD0_CMD_MMC_SET_BLOCK_COUNT	0x17
+#define	SSP_CMD0_CMD_MMC_WRITE_BLOCK		0x18
+#define	SSP_CMD0_CMD_MMC_WRITE_MULTIPLE_BLOCK	0x19
+#define	SSP_CMD0_CMD_MMC_PROGRAM_CID		0x1a
+#define	SSP_CMD0_CMD_MMC_PROGRAM_CSD		0x1b
+#define	SSP_CMD0_CMD_MMC_SET_WRITE_PROT		0x1c
+#define	SSP_CMD0_CMD_MMC_CLR_WRITE_PROT		0x1d
+#define	SSP_CMD0_CMD_MMC_SEND_WRITE_PROT	0x1e
+#define	SSP_CMD0_CMD_MMC_ERASE_GROUP_START	0x23
+#define	SSP_CMD0_CMD_MMC_ERASE_GROUP_END	0x24
+#define	SSP_CMD0_CMD_MMC_ERASE			0x26
+#define	SSP_CMD0_CMD_MMC_FAST_IO		0x27
+#define	SSP_CMD0_CMD_MMC_GO_IRQ_STATE		0x28
+#define	SSP_CMD0_CMD_MMC_LOCK_UNLOCK		0x2a
+#define	SSP_CMD0_CMD_MMC_APP_CMD		0x37
+#define	SSP_CMD0_CMD_MMC_GEN_CMD		0x38
+#define	SSP_CMD0_CMD_SD_GO_IDLE_STATE		0x00
+#define	SSP_CMD0_CMD_SD_ALL_SEND_CID		0x02
+#define	SSP_CMD0_CMD_SD_SEND_RELATIVE_ADDR	0x03
+#define	SSP_CMD0_CMD_SD_SET_DSR			0x04
+#define	SSP_CMD0_CMD_SD_IO_SEND_OP_COND		0x05
+#define	SSP_CMD0_CMD_SD_SELECT_DESELECT_CARD	0x07
+#define	SSP_CMD0_CMD_SD_SEND_CSD		0x09
+#define	SSP_CMD0_CMD_SD_SEND_CID		0x0a
+#define	SSP_CMD0_CMD_SD_STOP_TRANSMISSION	0x0c
+#define	SSP_CMD0_CMD_SD_SEND_STATUS		0x0d
+#define	SSP_CMD0_CMD_SD_GO_INACTIVE_STATE	0x0f
+#define	SSP_CMD0_CMD_SD_SET_BLOCKLEN		0x10
+#define	SSP_CMD0_CMD_SD_READ_SINGLE_BLOCK	0x11
+#define	SSP_CMD0_CMD_SD_READ_MULTIPLE_BLOCK	0x12
+#define	SSP_CMD0_CMD_SD_WRITE_BLOCK		0x18
+#define	SSP_CMD0_CMD_SD_WRITE_MULTIPLE_BLOCK	0x19
+#define	SSP_CMD0_CMD_SD_PROGRAM_CSD		0x1b
+#define	SSP_CMD0_CMD_SD_SET_WRITE_PROT		0x1c
+#define	SSP_CMD0_CMD_SD_CLR_WRITE_PROT		0x1d
+#define	SSP_CMD0_CMD_SD_SEND_WRITE_PROT		0x1e
+#define	SSP_CMD0_CMD_SD_ERASE_WR_BLK_START	0x20
+#define	SSP_CMD0_CMD_SD_ERASE_WR_BLK_END	0x21
+#define	SSP_CMD0_CMD_SD_ERASE_GROUP_START	0x23
+#define	SSP_CMD0_CMD_SD_ERASE_GROUP_END		0x24
+#define	SSP_CMD0_CMD_SD_ERASE			0x26
+#define	SSP_CMD0_CMD_SD_LOCK_UNLOCK		0x2a
+#define	SSP_CMD0_CMD_SD_IO_RW_DIRECT		0x34
+#define	SSP_CMD0_CMD_SD_IO_RW_EXTENDED		0x35
+#define	SSP_CMD0_CMD_SD_APP_CMD			0x37
+#define	SSP_CMD0_CMD_SD_GEN_CMD			0x38
+
+#define	SSP_CMD1_CMD_ARG_MASK			0xffffffff
+#define	SSP_CMD1_CMD_ARG_OFFSET			0
+
+#define	SSP_XFER_SIZE_XFER_COUNT_MASK		0xffffffff
+#define	SSP_XFER_SIZE_XFER_COUNT_OFFSET		0
+
+#define	SSP_BLOCK_SIZE_BLOCK_COUNT_MASK		(0xffffff << 4)
+#define	SSP_BLOCK_SIZE_BLOCK_COUNT_OFFSET	4
+#define	SSP_BLOCK_SIZE_BLOCK_SIZE_MASK		0xf
+#define	SSP_BLOCK_SIZE_BLOCK_SIZE_OFFSET	0
+
+#define	SSP_COMPREF_REFERENCE_MASK		0xffffffff
+#define	SSP_COMPREF_REFERENCE_OFFSET		0
+
+#define	SSP_COMPMASK_MASK_MASK			0xffffffff
+#define	SSP_COMPMASK_MASK_OFFSET		0
+
+#define	SSP_TIMING_TIMEOUT_MASK			(0xffff << 16)
+#define	SSP_TIMING_TIMEOUT_OFFSET		16
+#define	SSP_TIMING_CLOCK_DIVIDE_MASK		(0xff << 8)
+#define	SSP_TIMING_CLOCK_DIVIDE_OFFSET		8
+#define	SSP_TIMING_CLOCK_RATE_MASK		0xff
+#define	SSP_TIMING_CLOCK_RATE_OFFSET		0
+
+#define	SSP_CTRL1_SDIO_IRQ			(1 << 31)
+#define	SSP_CTRL1_SDIO_IRQ_EN			(1 << 30)
+#define	SSP_CTRL1_RESP_ERR_IRQ			(1 << 29)
+#define	SSP_CTRL1_RESP_ERR_IRQ_EN		(1 << 28)
+#define	SSP_CTRL1_RESP_TIMEOUT_IRQ		(1 << 27)
+#define	SSP_CTRL1_RESP_TIMEOUT_IRQ_EN		(1 << 26)
+#define	SSP_CTRL1_DATA_TIMEOUT_IRQ		(1 << 25)
+#define	SSP_CTRL1_DATA_TIMEOUT_IRQ_EN		(1 << 24)
+#define	SSP_CTRL1_DATA_CRC_IRQ			(1 << 23)
+#define	SSP_CTRL1_DATA_CRC_IRQ_EN		(1 << 22)
+#define	SSP_CTRL1_FIFO_UNDERRUN_IRQ		(1 << 21)
+#define	SSP_CTRL1_FIFO_UNDERRUN_EN		(1 << 20)
+#define	SSP_CTRL1_CEATA_CCS_ERR_IRQ		(1 << 19)
+#define	SSP_CTRL1_CEATA_CCS_ERR_IRQ_EN		(1 << 18)
+#define	SSP_CTRL1_RECV_TIMEOUT_IRQ		(1 << 17)
+#define	SSP_CTRL1_RECV_TIMEOUT_IRQ_EN		(1 << 16)
+#define	SSP_CTRL1_FIFO_OVERRUN_IRQ		(1 << 15)
+#define	SSP_CTRL1_FIFO_OVERRUN_IRQ_EN		(1 << 14)
+#define	SSP_CTRL1_DMA_ENABLE			(1 << 13)
+#define	SSP_CTRL1_CEATA_CCS_ERR_EN		(1 << 12)
+#define	SSP_CTRL1_SLAVE_OUT_DISABLE		(1 << 11)
+#define	SSP_CTRL1_PHASE				(1 << 10)
+#define	SSP_CTRL1_POLARITY			(1 << 9)
+#define	SSP_CTRL1_SLAVE_MODE			(1 << 8)
+#define	SSP_CTRL1_WORD_LENGTH_MASK		(0xf << 4)
+#define	SSP_CTRL1_WORD_LENGTH_OFFSET		4
+#define	SSP_CTRL1_WORD_LENGTH_RESERVED0		(0x0 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_RESERVED1		(0x1 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_RESERVED2		(0x2 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_FOUR_BITS		(0x3 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_EIGHT_BITS	(0x7 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_SIXTEEN_BITS	(0xf << 4)
+#define	SSP_CTRL1_SSP_MODE_MASK			0xf
+#define	SSP_CTRL1_SSP_MODE_OFFSET		0
+#define	SSP_CTRL1_SSP_MODE_SPI			0x0
+#define	SSP_CTRL1_SSP_MODE_SSI			0x1
+#define	SSP_CTRL1_SSP_MODE_SD_MMC		0x3
+#define	SSP_CTRL1_SSP_MODE_MS			0x4
+
+#define	SSP_DATA_DATA_MASK			0xffffffff
+#define	SSP_DATA_DATA_OFFSET			0
+
+#define	SSP_SDRESP0_RESP0_MASK			0xffffffff
+#define	SSP_SDRESP0_RESP0_OFFSET		0
+
+#define	SSP_SDRESP1_RESP1_MASK			0xffffffff
+#define	SSP_SDRESP1_RESP1_OFFSET		0
+
+#define	SSP_SDRESP2_RESP2_MASK			0xffffffff
+#define	SSP_SDRESP2_RESP2_OFFSET		0
+
+#define	SSP_SDRESP3_RESP3_MASK			0xffffffff
+#define	SSP_SDRESP3_RESP3_OFFSET		0
+
+#define	SSP_DDR_CTRL_DMA_BURST_TYPE_MASK	(0x3 << 30)
+#define	SSP_DDR_CTRL_DMA_BURST_TYPE_OFFSET	30
+#define	SSP_DDR_CTRL_NIBBLE_POS			(1 << 1)
+#define	SSP_DDR_CTRL_TXCLK_DELAY_TYPE		(1 << 0)
+
+#define	SSP_DLL_CTRL_REF_UPDATE_INT_MASK	(0xf << 28)
+#define	SSP_DLL_CTRL_REF_UPDATE_INT_OFFSET	28
+#define	SSP_DLL_CTRL_SLV_UPDATE_INT_MASK	(0xff << 20)
+#define	SSP_DLL_CTRL_SLV_UPDATE_INT_OFFSET	20
+#define	SSP_DLL_CTRL_SLV_OVERRIDE_VAL_MASK	(0x3f << 10)
+#define	SSP_DLL_CTRL_SLV_OVERRIDE_VAL_OFFSET	10
+#define	SSP_DLL_CTRL_SLV_OVERRIDE		(1 << 9)
+#define	SSP_DLL_CTRL_GATE_UPDATE		(1 << 7)
+#define	SSP_DLL_CTRL_SLV_DLY_TARGET_MASK	(0xf << 3)
+#define	SSP_DLL_CTRL_SLV_DLY_TARGET_OFFSET	3
+#define	SSP_DLL_CTRL_SLV_FORCE_UPD		(1 << 2)
+#define	SSP_DLL_CTRL_RESET			(1 << 1)
+#define	SSP_DLL_CTRL_ENABLE			(1 << 0)
+
+#define	SSP_STATUS_PRESENT			(1 << 31)
+#define	SSP_STATUS_MS_PRESENT			(1 << 30)
+#define	SSP_STATUS_SD_PRESENT			(1 << 29)
+#define	SSP_STATUS_CARD_DETECT			(1 << 28)
+#define	SSP_STATUS_DMABURST			(1 << 22)
+#define	SSP_STATUS_DMASENSE			(1 << 21)
+#define	SSP_STATUS_DMATERM			(1 << 20)
+#define	SSP_STATUS_DMAREQ			(1 << 19)
+#define	SSP_STATUS_DMAEND			(1 << 18)
+#define	SSP_STATUS_SDIO_IRQ			(1 << 17)
+#define	SSP_STATUS_RESP_CRC_ERR			(1 << 16)
+#define	SSP_STATUS_RESP_ERR			(1 << 15)
+#define	SSP_STATUS_RESP_TIMEOUT			(1 << 14)
+#define	SSP_STATUS_DATA_CRC_ERR			(1 << 13)
+#define	SSP_STATUS_TIMEOUT			(1 << 12)
+#define	SSP_STATUS_RECV_TIMEOUT_STAT		(1 << 11)
+#define	SSP_STATUS_CEATA_CCS_ERR		(1 << 10)
+#define	SSP_STATUS_FIFO_OVRFLW			(1 << 9)
+#define	SSP_STATUS_FIFO_FULL			(1 << 8)
+#define	SSP_STATUS_FIFO_EMPTY			(1 << 5)
+#define	SSP_STATUS_FIFO_UNDRFLW			(1 << 4)
+#define	SSP_STATUS_CMD_BUSY			(1 << 3)
+#define	SSP_STATUS_DATA_BUSY			(1 << 2)
+#define	SSP_STATUS_BUSY				(1 << 0)
+
+#define	SSP_DLL_STS_REF_SEL_MASK		(0x3f << 8)
+#define	SSP_DLL_STS_REF_SEL_OFFSET		8
+#define	SSP_DLL_STS_SLV_SEL_MASK		(0x3f << 2)
+#define	SSP_DLL_STS_SLV_SEL_OFFSET		2
+#define	SSP_DLL_STS_REF_LOCK			(1 << 1)
+#define	SSP_DLL_STS_SLV_LOCK			(1 << 0)
+
+#define	SSP_DEBUG_DATACRC_ERR_MASK		(0xf << 28)
+#define	SSP_DEBUG_DATACRC_ERR_OFFSET		28
+#define	SSP_DEBUG_DATA_STALL			(1 << 27)
+#define	SSP_DEBUG_DAT_SM_MASK			(0x7 << 24)
+#define	SSP_DEBUG_DAT_SM_OFFSET			24
+#define	SSP_DEBUG_DAT_SM_DSM_IDLE		(0x0 << 24)
+#define	SSP_DEBUG_DAT_SM_DSM_WORD		(0x2 << 24)
+#define	SSP_DEBUG_DAT_SM_DSM_CRC1		(0x3 << 24)
+#define	SSP_DEBUG_DAT_SM_DSM_CRC2		(0x4 << 24)
+#define	SSP_DEBUG_DAT_SM_DSM_END		(0x5 << 24)
+#define	SSP_DEBUG_MSTK_SM_MASK			(0xf << 20)
+#define	SSP_DEBUG_MSTK_SM_OFFSET		20
+#define	SSP_DEBUG_MSTK_SM_MSTK_IDLE		(0x0 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_CKON		(0x1 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_BS1		(0x2 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_TPC		(0x3 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_BS2		(0x4 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_HDSHK		(0x5 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_BS3		(0x6 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_RW		(0x7 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_CRC1		(0x8 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_CRC2		(0x9 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_BS0		(0xa << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_END1		(0xb << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_END2W		(0xc << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_END2R		(0xd << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_DONE		(0xe << 20)
+#define	SSP_DEBUG_CMD_OE			(1 << 19)
+#define	SSP_DEBUG_DMA_SM_MASK			(0x7 << 16)
+#define	SSP_DEBUG_DMA_SM_OFFSET			16
+#define	SSP_DEBUG_DMA_SM_DMA_IDLE		(0x0 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_DMAREQ		(0x1 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_DMAACK		(0x2 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_STALL		(0x3 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_BUSY		(0x4 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_DONE		(0x5 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_COUNT		(0x6 << 16)
+#define	SSP_DEBUG_MMC_SM_MASK			(0xf << 12)
+#define	SSP_DEBUG_MMC_SM_OFFSET			12
+#define	SSP_DEBUG_MMC_SM_MMC_IDLE		(0x0 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_CMD		(0x1 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_TRC		(0x2 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_RESP		(0x3 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_RPRX		(0x4 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_TX			(0x5 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_CTOK		(0x6 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_RX			(0x7 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_CCS		(0x8 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_PUP		(0x9 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_WAIT		(0xa << 12)
+#define	SSP_DEBUG_CMD_SM_MASK			(0x3 << 10)
+#define	SSP_DEBUG_CMD_SM_OFFSET			10
+#define	SSP_DEBUG_CMD_SM_CSM_IDLE		(0x0 << 10)
+#define	SSP_DEBUG_CMD_SM_CSM_INDEX		(0x1 << 10)
+#define	SSP_DEBUG_CMD_SM_CSM_ARG		(0x2 << 10)
+#define	SSP_DEBUG_CMD_SM_CSM_CRC		(0x3 << 10)
+#define	SSP_DEBUG_SSP_CMD			(1 << 9)
+#define	SSP_DEBUG_SSP_RESP			(1 << 8)
+#define	SSP_DEBUG_SSP_RXD_MASK			0xff
+#define	SSP_DEBUG_SSP_RXD_OFFSET		0
+
+#define	SSP_VERSION_MAJOR_MASK			(0xff << 24)
+#define	SSP_VERSION_MAJOR_OFFSET		24
+#define	SSP_VERSION_MINOR_MASK			(0xff << 16)
+#define	SSP_VERSION_MINOR_OFFSET		16
+#define	SSP_VERSION_STEP_MASK			0xffff
+#define	SSP_VERSION_STEP_OFFSET			0
+
+#endif /* __MX28_REGS_SSP_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-timrot.h b/arch/arm/include/asm/arch-mx28/regs-timrot.h
new file mode 100644
index 0000000..1b941cf
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-timrot.h
@@ -0,0 +1,171 @@
+/*
+ * Freescale i.MX28 TIMROT Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_TIMROT_H__
+#define __MX28_REGS_TIMROT_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_timrot_regs {
+	mx28_reg(hw_timrot_rotctrl)
+	mx28_reg(hw_timrot_rotcount)
+	mx28_reg(hw_timrot_timctrl0)
+	mx28_reg(hw_timrot_running_count0)
+	mx28_reg(hw_timrot_fixed_count0)
+	mx28_reg(hw_timrot_match_count0)
+	mx28_reg(hw_timrot_timctrl1)
+	mx28_reg(hw_timrot_running_count1)
+	mx28_reg(hw_timrot_fixed_count1)
+	mx28_reg(hw_timrot_match_count1)
+	mx28_reg(hw_timrot_timctrl2)
+	mx28_reg(hw_timrot_running_count2)
+	mx28_reg(hw_timrot_fixed_count2)
+	mx28_reg(hw_timrot_match_count2)
+	mx28_reg(hw_timrot_timctrl3)
+	mx28_reg(hw_timrot_running_count3)
+	mx28_reg(hw_timrot_fixed_count3)
+	mx28_reg(hw_timrot_match_count3)
+	mx28_reg(hw_timrot_version)
+};
+#endif
+
+#define	TIMROT_ROTCTRL_SFTRST				(1 << 31)
+#define	TIMROT_ROTCTRL_CLKGATE				(1 << 30)
+#define	TIMROT_ROTCTRL_ROTARY_PRESENT			(1 << 29)
+#define	TIMROT_ROTCTRL_TIM3_PRESENT			(1 << 28)
+#define	TIMROT_ROTCTRL_TIM2_PRESENT			(1 << 27)
+#define	TIMROT_ROTCTRL_TIM1_PRESENT			(1 << 26)
+#define	TIMROT_ROTCTRL_TIM0_PRESENT			(1 << 25)
+#define	TIMROT_ROTCTRL_STATE_MASK			(0x7 << 22)
+#define	TIMROT_ROTCTRL_STATE_OFFSET			22
+#define	TIMROT_ROTCTRL_DIVIDER_MASK			(0x3f << 16)
+#define	TIMROT_ROTCTRL_DIVIDER_OFFSET			16
+#define	TIMROT_ROTCTRL_RELATIVE				(1 << 12)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_MASK			(0x3 << 10)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_OFFSET		10
+#define	TIMROT_ROTCTRL_OVERSAMPLE_8X			(0x0 << 10)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_4X			(0x1 << 10)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_2X			(0x2 << 10)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_1X			(0x3 << 10)
+#define	TIMROT_ROTCTRL_POLARITY_B			(1 << 9)
+#define	TIMROT_ROTCTRL_POLARITY_A			(1 << 8)
+#define	TIMROT_ROTCTRL_SELECT_B_MASK			(0xf << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_OFFSET			4
+#define	TIMROT_ROTCTRL_SELECT_B_NEVER_TICK		(0x0 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM0			(0x1 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM1			(0x2 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM2			(0x3 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM3			(0x4 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM4			(0x5 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM5			(0x6 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM6			(0x7 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM7			(0x8 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_ROTARYA			(0x9 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_ROTARYB			(0xa << 4)
+#define	TIMROT_ROTCTRL_SELECT_A_MASK			0xf
+#define	TIMROT_ROTCTRL_SELECT_A_OFFSET			0
+#define	TIMROT_ROTCTRL_SELECT_A_NEVER_TICK		0x0
+#define	TIMROT_ROTCTRL_SELECT_A_PWM0			0x1
+#define	TIMROT_ROTCTRL_SELECT_A_PWM1			0x2
+#define	TIMROT_ROTCTRL_SELECT_A_PWM2			0x3
+#define	TIMROT_ROTCTRL_SELECT_A_PWM3			0x4
+#define	TIMROT_ROTCTRL_SELECT_A_PWM4			0x5
+#define	TIMROT_ROTCTRL_SELECT_A_PWM5			0x6
+#define	TIMROT_ROTCTRL_SELECT_A_PWM6			0x7
+#define	TIMROT_ROTCTRL_SELECT_A_PWM7			0x8
+#define	TIMROT_ROTCTRL_SELECT_A_ROTARYA			0x9
+#define	TIMROT_ROTCTRL_SELECT_A_ROTARYB			0xa
+
+#define	TIMROT_ROTCOUNT_UPDOWN_MASK			0xffff
+#define	TIMROT_ROTCOUNT_UPDOWN_OFFSET			0
+
+#define	TIMROT_TIMCTRLn_IRQ				(1 << 15)
+#define	TIMROT_TIMCTRLn_IRQ_EN				(1 << 14)
+#define	TIMROT_TIMCTRLn_MATCH_MODE			(1 << 11)
+#define	TIMROT_TIMCTRLn_POLARITY			(1 << 8)
+#define	TIMROT_TIMCTRLn_UPDATE				(1 << 7)
+#define	TIMROT_TIMCTRLn_RELOAD				(1 << 6)
+#define	TIMROT_TIMCTRLn_PRESCALE_MASK			(0x3 << 4)
+#define	TIMROT_TIMCTRLn_PRESCALE_OFFSET			4
+#define	TIMROT_TIMCTRLn_PRESCALE_DIV_BY_1		(0x0 << 4)
+#define	TIMROT_TIMCTRLn_PRESCALE_DIV_BY_2		(0x1 << 4)
+#define	TIMROT_TIMCTRLn_PRESCALE_DIV_BY_4		(0x2 << 4)
+#define	TIMROT_TIMCTRLn_PRESCALE_DIV_BY_8		(0x3 << 4)
+#define	TIMROT_TIMCTRLn_SELECT_MASK			0xf
+#define	TIMROT_TIMCTRLn_SELECT_OFFSET			0
+#define	TIMROT_TIMCTRLn_SELECT_NEVER_TICK		0x0
+#define	TIMROT_TIMCTRLn_SELECT_PWM0			0x1
+#define	TIMROT_TIMCTRLn_SELECT_PWM1			0x2
+#define	TIMROT_TIMCTRLn_SELECT_PWM2			0x3
+#define	TIMROT_TIMCTRLn_SELECT_PWM3			0x4
+#define	TIMROT_TIMCTRLn_SELECT_PWM4			0x5
+#define	TIMROT_TIMCTRLn_SELECT_PWM5			0x6
+#define	TIMROT_TIMCTRLn_SELECT_PWM6			0x7
+#define	TIMROT_TIMCTRLn_SELECT_PWM7			0x8
+#define	TIMROT_TIMCTRLn_SELECT_ROTARYA			0x9
+#define	TIMROT_TIMCTRLn_SELECT_ROTARYB			0xa
+#define	TIMROT_TIMCTRLn_SELECT_32KHZ_XTAL		0xb
+#define	TIMROT_TIMCTRLn_SELECT_8KHZ_XTAL		0xc
+#define	TIMROT_TIMCTRLn_SELECT_4KHZ_XTAL		0xd
+#define	TIMROT_TIMCTRLn_SELECT_1KHZ_XTAL		0xe
+#define	TIMROT_TIMCTRLn_SELECT_TICK_ALWAYS		0xf
+
+#define	TIMROT_RUNNING_COUNTn_RUNNING_COUNT_MASK	0xffffffff
+#define	TIMROT_RUNNING_COUNTn_RUNNING_COUNT_OFFSET	0
+
+#define	TIMROT_FIXED_COUNTn_FIXED_COUNT_MASK		0xffffffff
+#define	TIMROT_FIXED_COUNTn_FIXED_COUNT_OFFSET		0
+
+#define	TIMROT_MATCH_COUNTn_MATCH_COUNT_MASK		0xffffffff
+#define	TIMROT_MATCH_COUNTn_MATCH_COUNT_OFFSET		0
+
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_MASK		(0xf << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_OFFSET		16
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_NEVER_TICK		(0x0 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM0		(0x1 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM1		(0x2 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM2		(0x3 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM3		(0x4 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM4		(0x5 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM5		(0x6 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM6		(0x7 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM7		(0x8 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_ROTARYA		(0x9 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_ROTARYB		(0xa << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_32KHZ_XTAL		(0xb << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_8KHZ_XTAL		(0xc << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_4KHZ_XTAL		(0xd << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_1KHZ_XTAL		(0xe << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_TICK_ALWAYS		(0xf << 16)
+#define	TIMROT_TIMCTRL3_DUTY_CYCLE			(1 << 9)
+
+#define	TIMROT_VERSION_MAJOR_MASK			(0xff << 24)
+#define	TIMROT_VERSION_MAJOR_OFFSET			24
+#define	TIMROT_VERSION_MINOR_MASK			(0xff << 16)
+#define	TIMROT_VERSION_MINOR_OFFSET			16
+#define	TIMROT_VERSION_STEP_MASK			0xffff
+#define	TIMROT_VERSION_STEP_OFFSET			0
+
+#endif /* __MX28_REGS_TIMROT_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/sys_proto.h b/arch/arm/include/asm/arch-mx28/sys_proto.h
new file mode 100644
index 0000000..a262c05
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/sys_proto.h
@@ -0,0 +1,30 @@
+/*
+ * Freescale i.MX28 MX28 specific functions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __MX28_H__
+#define __MX28_H__
+
+int mx28_reset_block(struct mx28_register *reg);
+int mx28_wait_mask_set(struct mx28_register *reg, uint32_t mask, int timeout);
+int mx28_wait_mask_clr(struct mx28_register *reg, uint32_t mask, int timeout);
+
+#endif	/* __MX28_H__ */
-- 
1.7.5.4

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

* [U-Boot] [PATCH 02/15] iMX28: Add SSP MMC driver
  2011-09-12  4:06 [U-Boot] [PATCH 00/15 V2] Support for the DENX M28 SoM Marek Vasut
  2011-09-12  4:06 ` [U-Boot] [PATCH 01/15] iMX28: Initial support for iMX28 CPU Marek Vasut
@ 2011-09-12  4:06 ` Marek Vasut
  2011-09-12  4:06 ` [U-Boot] [PATCH 03/15] FEC: Add support for iMX28 quirks Marek Vasut
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-09-12  4:06 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Andy Fleming <afleming@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 arch/arm/include/asm/arch-mx28/sys_proto.h |    2 +
 drivers/mmc/Makefile                       |    1 +
 drivers/mmc/mxsmmc.c                       |  351 ++++++++++++++++++++++++++++
 3 files changed, 354 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mmc/mxsmmc.c

diff --git a/arch/arm/include/asm/arch-mx28/sys_proto.h b/arch/arm/include/asm/arch-mx28/sys_proto.h
index a262c05..a226ea4 100644
--- a/arch/arm/include/asm/arch-mx28/sys_proto.h
+++ b/arch/arm/include/asm/arch-mx28/sys_proto.h
@@ -27,4 +27,6 @@ int mx28_reset_block(struct mx28_register *reg);
 int mx28_wait_mask_set(struct mx28_register *reg, uint32_t mask, int timeout);
 int mx28_wait_mask_clr(struct mx28_register *reg, uint32_t mask, int timeout);
 
+int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int));
+
 #endif	/* __MX28_H__ */
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 6e94860..550d289 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -36,6 +36,7 @@ COBJS-$(CONFIG_MMC_SPI) += mmc_spi.o
 COBJS-$(CONFIG_ARM_PL180_MMCI) += arm_pl180_mmci.o
 COBJS-$(CONFIG_MV_SDHCI) += mv_sdhci.o
 COBJS-$(CONFIG_MXC_MMC) += mxcmmc.o
+COBJS-$(CONFIG_MXS_MMC) += mxsmmc.o
 COBJS-$(CONFIG_OMAP_HSMMC) += omap_hsmmc.o
 COBJS-$(CONFIG_PXA_MMC) += pxa_mmc.o
 COBJS-$(CONFIG_S5P_MMC) += s5p_mmc.o
diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c
new file mode 100644
index 0000000..2a9949e
--- /dev/null
+++ b/drivers/mmc/mxsmmc.c
@@ -0,0 +1,351 @@
+/*
+ * Freescale i.MX28 SSP MMC driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * (C) Copyright 2008-2010 Freescale Semiconductor, Inc.
+ * Terry Lv
+ *
+ * Copyright 2007, Freescale Semiconductor, Inc
+ * Andy Fleming
+ *
+ * Based vaguely on the pxa mmc code:
+ * (C) Copyright 2003
+ * Kyle Harris, Nexus Technologies, Inc. kharris at nexus-tech.net
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#include <common.h>
+#include <malloc.h>
+#include <mmc.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+
+struct mxsmmc_priv {
+	int			id;
+	struct mx28_ssp_regs	*regs;
+	uint32_t		clkseq_bypass;
+	uint32_t		*clkctrl_ssp;
+	uint32_t		buswidth;
+	int			(*mmc_is_wp)(int);
+};
+
+#define	MXSMMC_MAX_TIMEOUT	10000
+
+/*
+ * Sends a command out on the bus.  Takes the mmc pointer,
+ * a command pointer, and an optional data pointer.
+ */
+static int
+mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
+{
+	struct mxsmmc_priv *priv = (struct mxsmmc_priv *)mmc->priv;
+	struct mx28_ssp_regs *ssp_regs = priv->regs;
+	uint32_t reg;
+	int timeout;
+	uint32_t data_count;
+	uint32_t *data_ptr;
+	uint32_t ctrl0;
+
+	debug("MMC%d: CMD%d\n", mmc->block_dev.dev, cmd->cmdidx);
+
+	/* Check bus busy */
+	timeout = MXSMMC_MAX_TIMEOUT;
+	while (--timeout) {
+		udelay(1000);
+		reg = readl(&ssp_regs->hw_ssp_status);
+		if (!(reg &
+			(SSP_STATUS_BUSY | SSP_STATUS_DATA_BUSY |
+			SSP_STATUS_CMD_BUSY))) {
+			break;
+		}
+	}
+
+	if (!timeout) {
+		printf("MMC%d: Bus busy timeout!\n", mmc->block_dev.dev);
+		return TIMEOUT;
+	}
+
+	/* See if card is present */
+	if (readl(&ssp_regs->hw_ssp_status) & SSP_STATUS_CARD_DETECT) {
+		printf("MMC%d: No card detected!\n", mmc->block_dev.dev);
+		return NO_CARD_ERR;
+	}
+
+	/* Start building CTRL0 contents */
+	ctrl0 = priv->buswidth;
+
+	/* Set up command */
+	if (!(cmd->resp_type & MMC_RSP_CRC))
+		ctrl0 |= SSP_CTRL0_IGNORE_CRC;
+	if (cmd->resp_type & MMC_RSP_PRESENT)	/* Need to get response */
+		ctrl0 |= SSP_CTRL0_GET_RESP;
+	if (cmd->resp_type & MMC_RSP_136)	/* It's a 136 bits response */
+		ctrl0 |= SSP_CTRL0_LONG_RESP;
+
+	/* Command index */
+	reg = readl(&ssp_regs->hw_ssp_cmd0);
+	reg &= ~(SSP_CMD0_CMD_MASK | SSP_CMD0_APPEND_8CYC);
+	reg |= cmd->cmdidx << SSP_CMD0_CMD_OFFSET;
+	if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
+		reg |= SSP_CMD0_APPEND_8CYC;
+	writel(reg, &ssp_regs->hw_ssp_cmd0);
+
+	/* Command argument */
+	writel(cmd->cmdarg, &ssp_regs->hw_ssp_cmd1);
+
+	/* Set up data */
+	if (data) {
+		/* READ or WRITE */
+		if (data->flags & MMC_DATA_READ) {
+			ctrl0 |= SSP_CTRL0_READ;
+		} else if (priv->mmc_is_wp(mmc->block_dev.dev)) {
+			printf("MMC%d: Can not write a locked card!\n",
+				mmc->block_dev.dev);
+			return UNUSABLE_ERR;
+		}
+
+		ctrl0 |= SSP_CTRL0_DATA_XFER;
+		reg = ((data->blocks - 1) <<
+			SSP_BLOCK_SIZE_BLOCK_COUNT_OFFSET) |
+			((ffs(data->blocksize) - 1) <<
+			SSP_BLOCK_SIZE_BLOCK_SIZE_OFFSET);
+		writel(reg, &ssp_regs->hw_ssp_block_size);
+
+		reg = data->blocksize * data->blocks;
+		writel(reg, &ssp_regs->hw_ssp_xfer_size);
+	}
+
+	/* Kick off the command */
+	ctrl0 |= SSP_CTRL0_WAIT_FOR_IRQ | SSP_CTRL0_ENABLE | SSP_CTRL0_RUN;
+	writel(ctrl0, &ssp_regs->hw_ssp_ctrl0);
+
+	/* Wait for the command to complete */
+	timeout = MXSMMC_MAX_TIMEOUT;
+	while (--timeout) {
+		udelay(1000);
+		reg = readl(&ssp_regs->hw_ssp_status);
+		if (!(reg & SSP_STATUS_CMD_BUSY))
+			break;
+	}
+
+	if (!timeout) {
+		printf("MMC%d: Command %d busy\n",
+			mmc->block_dev.dev, cmd->cmdidx);
+		return TIMEOUT;
+	}
+
+	/* Check command timeout */
+	if (reg & SSP_STATUS_RESP_TIMEOUT) {
+		printf("MMC%d: Command %d timeout (status 0x%08x)\n",
+			mmc->block_dev.dev, cmd->cmdidx, reg);
+		return TIMEOUT;
+	}
+
+	/* Check command errors */
+	if (reg & (SSP_STATUS_RESP_CRC_ERR | SSP_STATUS_RESP_ERR)) {
+		printf("MMC%d: Command %d error (status 0x%08x)!\n",
+			mmc->block_dev.dev, cmd->cmdidx, reg);
+		return COMM_ERR;
+	}
+
+	/* Copy response to response buffer */
+	if (cmd->resp_type & MMC_RSP_136) {
+		cmd->response[3] = readl(&ssp_regs->hw_ssp_sdresp0);
+		cmd->response[2] = readl(&ssp_regs->hw_ssp_sdresp1);
+		cmd->response[1] = readl(&ssp_regs->hw_ssp_sdresp2);
+		cmd->response[0] = readl(&ssp_regs->hw_ssp_sdresp3);
+	} else
+		cmd->response[0] = readl(&ssp_regs->hw_ssp_sdresp0);
+
+	/* Return if no data to process */
+	if (!data)
+		return 0;
+
+	/* Process the data */
+	data_count = data->blocksize * data->blocks;
+	timeout = MXSMMC_MAX_TIMEOUT;
+	if (data->flags & MMC_DATA_READ) {
+		data_ptr = (uint32_t *)data->dest;
+		while (data_count && --timeout) {
+			reg = readl(&ssp_regs->hw_ssp_status);
+			if (!(reg & SSP_STATUS_FIFO_EMPTY)) {
+				*data_ptr++ = readl(&ssp_regs->hw_ssp_data);
+				data_count -= 4;
+				timeout = MXSMMC_MAX_TIMEOUT;
+			} else
+				udelay(1000);
+		}
+	} else {
+		data_ptr = (uint32_t *)data->src;
+		timeout *= 100;
+		while (data_count && --timeout) {
+			reg = readl(&ssp_regs->hw_ssp_status);
+			if (!(reg & SSP_STATUS_FIFO_FULL)) {
+				writel(*data_ptr++, &ssp_regs->hw_ssp_data);
+				data_count -= 4;
+				timeout = MXSMMC_MAX_TIMEOUT;
+			} else
+				udelay(1000);
+		}
+	}
+
+	if (!timeout) {
+		printf("MMC%d: Data timeout with command %d (status 0x%08x)!\n",
+			mmc->block_dev.dev, cmd->cmdidx, reg);
+		return COMM_ERR;
+	}
+
+	/* Check data errors */
+	reg = readl(&ssp_regs->hw_ssp_status);
+	if (reg &
+		(SSP_STATUS_TIMEOUT | SSP_STATUS_DATA_CRC_ERR |
+		SSP_STATUS_FIFO_OVRFLW | SSP_STATUS_FIFO_UNDRFLW)) {
+		printf("MMC%d: Data error with command %d (status 0x%08x)!\n",
+			mmc->block_dev.dev, cmd->cmdidx, reg);
+		return COMM_ERR;
+	}
+
+	return 0;
+}
+
+static void mxsmmc_set_ios(struct mmc *mmc)
+{
+	struct mxsmmc_priv *priv = (struct mxsmmc_priv *)mmc->priv;
+	struct mx28_ssp_regs *ssp_regs = priv->regs;
+
+	/* Set the clock speed */
+	if (mmc->clock)
+		mx28_set_ssp_busclock(priv->id, mmc->clock / 1000);
+
+	switch (mmc->bus_width) {
+	case 1:
+		priv->buswidth = SSP_CTRL0_BUS_WIDTH_ONE_BIT;
+		break;
+	case 4:
+		priv->buswidth = SSP_CTRL0_BUS_WIDTH_FOUR_BIT;
+		break;
+	case 8:
+		priv->buswidth = SSP_CTRL0_BUS_WIDTH_EIGHT_BIT;
+		break;
+	}
+
+	/* Set the bus width */
+	clrsetbits_le32(&ssp_regs->hw_ssp_ctrl0,
+			SSP_CTRL0_BUS_WIDTH_MASK, priv->buswidth);
+
+	debug("MMC%d: Set %d bits bus width\n",
+		mmc->block_dev.dev, mmc->bus_width);
+}
+
+static int mxsmmc_init(struct mmc *mmc)
+{
+	struct mxsmmc_priv *priv = (struct mxsmmc_priv *)mmc->priv;
+	struct mx28_ssp_regs *ssp_regs = priv->regs;
+
+	/* Reset SSP */
+	mx28_reset_block(&ssp_regs->hw_ssp_ctrl0_reg);
+
+	/* 8 bits word length in MMC mode */
+	clrsetbits_le32(&ssp_regs->hw_ssp_ctrl1,
+		SSP_CTRL1_SSP_MODE_MASK | SSP_CTRL1_WORD_LENGTH_MASK,
+		SSP_CTRL1_SSP_MODE_SD_MMC | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS);
+
+	/* Set initial bit clock 400 KHz */
+	mx28_set_ssp_busclock(priv->id, 400);
+
+	/* Send initial 74 clock cycles (185 us @ 400 KHz)*/
+	writel(SSP_CMD0_CONT_CLKING_EN, &ssp_regs->hw_ssp_cmd0_set);
+	udelay(200);
+	writel(SSP_CMD0_CONT_CLKING_EN, &ssp_regs->hw_ssp_cmd0_clr);
+
+	return 0;
+}
+
+int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int))
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	struct mmc *mmc = NULL;
+	struct mxsmmc_priv *priv = NULL;
+
+	mmc = malloc(sizeof(struct mmc));
+	if (!mmc)
+		return -ENOMEM;
+
+	priv = malloc(sizeof(struct mxsmmc_priv));
+	if (!priv) {
+		free(mmc);
+		return -ENOMEM;
+	}
+
+	priv->mmc_is_wp = wp;
+	priv->id = id;
+	switch (id) {
+	case 0:
+		priv->regs = (struct mx28_ssp_regs *)MXS_SSP0_BASE;
+		priv->clkseq_bypass = CLKCTRL_CLKSEQ_BYPASS_SSP0;
+		priv->clkctrl_ssp = &clkctrl_regs->hw_clkctrl_ssp0;
+		break;
+	case 1:
+		priv->regs = (struct mx28_ssp_regs *)MXS_SSP1_BASE;
+		priv->clkseq_bypass = CLKCTRL_CLKSEQ_BYPASS_SSP1;
+		priv->clkctrl_ssp = &clkctrl_regs->hw_clkctrl_ssp1;
+		break;
+	case 2:
+		priv->regs = (struct mx28_ssp_regs *)MXS_SSP2_BASE;
+		priv->clkseq_bypass = CLKCTRL_CLKSEQ_BYPASS_SSP2;
+		priv->clkctrl_ssp = &clkctrl_regs->hw_clkctrl_ssp2;
+		break;
+	case 3:
+		priv->regs = (struct mx28_ssp_regs *)MXS_SSP3_BASE;
+		priv->clkseq_bypass = CLKCTRL_CLKSEQ_BYPASS_SSP3;
+		priv->clkctrl_ssp = &clkctrl_regs->hw_clkctrl_ssp3;
+		break;
+	}
+
+	sprintf(mmc->name, "MXS MMC");
+	mmc->send_cmd = mxsmmc_send_cmd;
+	mmc->set_ios = mxsmmc_set_ios;
+	mmc->init = mxsmmc_init;
+	mmc->priv = priv;
+
+	mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
+
+	mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT |
+			 MMC_MODE_HS_52MHz | MMC_MODE_HS;
+
+	/*
+	 * SSPCLK = 480 * 18 / 29 / 1 = 297.731 MHz
+	 * SSP bit rate = SSPCLK / (CLOCK_DIVIDE * (1 + CLOCK_RATE)),
+	 * CLOCK_DIVIDE has to be an even value from 2 to 254, and
+	 * CLOCK_RATE could be any integer from 0 to 255.
+	 */
+	mmc->f_min = 400000;
+	mmc->f_max = mxc_get_clock(MXC_SSP0_CLK + id) * 1000 / 2;
+	mmc->b_max = 0;
+
+	mmc_register(mmc);
+	return 0;
+}
-- 
1.7.5.4

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

* [U-Boot] [PATCH 03/15] FEC: Add support for iMX28 quirks
  2011-09-12  4:06 [U-Boot] [PATCH 00/15 V2] Support for the DENX M28 SoM Marek Vasut
  2011-09-12  4:06 ` [U-Boot] [PATCH 01/15] iMX28: Initial support for iMX28 CPU Marek Vasut
  2011-09-12  4:06 ` [U-Boot] [PATCH 02/15] iMX28: Add SSP MMC driver Marek Vasut
@ 2011-09-12  4:06 ` Marek Vasut
  2011-09-14  7:17   ` Stefano Babic
  2011-09-12  4:06 ` [U-Boot] [PATCH 04/15] iMX28: Add PINMUX control Marek Vasut
                   ` (12 subsequent siblings)
  15 siblings, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-09-12  4:06 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Ben Warren <biggerbadderben@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 drivers/net/fec_mxc.c |   44 ++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index cfe2176..f50433dd 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -42,6 +42,14 @@ DECLARE_GLOBAL_DATA_PTR;
 #define	CONFIG_FEC_XCV_TYPE	MII100
 #endif
 
+/*
+ * The i.MX28 operates with packets in big endian. We need to swap them before
+ * sending and after receiving.
+ */
+#ifdef	CONFIG_MX28
+#define	CONFIG_FEC_MXC_SWAP_PACKET
+#endif
+
 #undef DEBUG
 
 struct nbuf {
@@ -51,6 +59,32 @@ struct nbuf {
 	uint8_t head[16];	/**< MAC header(6 + 6 + 2) + 2(aligned) */
 };
 
+#ifdef	CONFIG_FEC_MXC_SWAP_PACKET
+static void swap_packet(uint32_t *packet, int length)
+{
+	int i;
+
+	for (i = 0; i < DIV_ROUND_UP(length, 4); i++)
+		packet[i] = __swab32(packet[i]);
+}
+#endif
+
+/*
+ * The i.MX28 has two ethernet interfaces, but they are not equal.
+ * Only the first one can access the MDIO bus.
+ */
+#ifdef	CONFIG_MX28
+static inline struct ethernet_regs *fec_miiphy_fec_to_eth(struct fec_priv *fec)
+{
+	return (struct ethernet_regs *)MXS_ENET0_BASE;
+}
+#else
+static inline struct ethernet_regs *fec_miiphy_fec_to_eth(struct fec_priv *fec)
+{
+	return fec->eth;
+}
+#endif
+
 /*
  * MII-interface related functions
  */
@@ -59,7 +93,7 @@ static int fec_miiphy_read(const char *dev, uint8_t phyAddr, uint8_t regAddr,
 {
 	struct eth_device *edev = eth_get_dev_by_name(dev);
 	struct fec_priv *fec = (struct fec_priv *)edev->priv;
-	struct ethernet_regs *eth = fec->eth;
+	struct ethernet_regs *eth = fec_miiphy_fec_to_eth(fec);
 
 	uint32_t reg;		/* convenient holder for the PHY register */
 	uint32_t phy;		/* convenient holder for the PHY */
@@ -117,7 +151,7 @@ static int fec_miiphy_write(const char *dev, uint8_t phyAddr, uint8_t regAddr,
 {
 	struct eth_device *edev = eth_get_dev_by_name(dev);
 	struct fec_priv *fec = (struct fec_priv *)edev->priv;
-	struct ethernet_regs *eth = fec->eth;
+	struct ethernet_regs *eth = fec_miiphy_fec_to_eth(fec);
 
 	uint32_t reg;		/* convenient holder for the PHY register */
 	uint32_t phy;		/* convenient holder for the PHY */
@@ -572,6 +606,9 @@ static int fec_send(struct eth_device *dev, volatile void* packet, int length)
 	 * Note: We are always using the first buffer for transmission,
 	 * the second will be empty and only used to stop the DMA engine
 	 */
+#ifdef	CONFIG_FEC_MXC_SWAP_PACKET
+	swap_packet((uint32_t *)packet, length);
+#endif
 	writew(length, &fec->tbd_base[fec->tbd_index].data_length);
 	writel((uint32_t)packet, &fec->tbd_base[fec->tbd_index].data_pointer);
 	/*
@@ -668,6 +705,9 @@ static int fec_recv(struct eth_device *dev)
 			/*
 			 *  Fill the buffer and pass it to upper layers
 			 */
+#ifdef	CONFIG_FEC_MXC_SWAP_PACKET
+			swap_packet((uint32_t *)frame->data, frame_length);
+#endif
 			memcpy(buff, frame->data, frame_length);
 			NetReceive(buff, frame_length);
 			len = frame_length;
-- 
1.7.5.4

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

* [U-Boot] [PATCH 04/15] iMX28: Add PINMUX control
  2011-09-12  4:06 [U-Boot] [PATCH 00/15 V2] Support for the DENX M28 SoM Marek Vasut
                   ` (2 preceding siblings ...)
  2011-09-12  4:06 ` [U-Boot] [PATCH 03/15] FEC: Add support for iMX28 quirks Marek Vasut
@ 2011-09-12  4:06 ` Marek Vasut
  2011-09-12  4:06 ` [U-Boot] [PATCH 05/15] iMX28: Add I2C bus driver Marek Vasut
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-09-12  4:06 UTC (permalink / raw)
  To: u-boot

Taken from Linux kernel with minor modifications:

commit bf985969e27b507f734435a99df8bf745a3dbb2b
Author: Shawn Guo <shawn.guo@freescale.com>
Date:   Mon Dec 20 22:57:43 2010 +0800

    ARM: mxs: Add iomux support

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 arch/arm/cpu/arm926ejs/mx28/Makefile        |    2 +-
 arch/arm/cpu/arm926ejs/mx28/iomux.c         |  109 ++++++
 arch/arm/include/asm/arch-mx28/iomux-mx28.h |  537 +++++++++++++++++++++++++++
 arch/arm/include/asm/arch-mx28/iomux.h      |  168 +++++++++
 4 files changed, 815 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/iomux.c
 create mode 100644 arch/arm/include/asm/arch-mx28/iomux-mx28.h
 create mode 100644 arch/arm/include/asm/arch-mx28/iomux.h

diff --git a/arch/arm/cpu/arm926ejs/mx28/Makefile b/arch/arm/cpu/arm926ejs/mx28/Makefile
index 98504f9..7845310 100644
--- a/arch/arm/cpu/arm926ejs/mx28/Makefile
+++ b/arch/arm/cpu/arm926ejs/mx28/Makefile
@@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk
 
 LIB	= $(obj)lib$(SOC).o
 
-COBJS	= clock.o mx28.o timer.o
+COBJS	= clock.o mx28.o iomux.o timer.o
 
 SRCS	:= $(START:.o=.S) $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS))
diff --git a/arch/arm/cpu/arm926ejs/mx28/iomux.c b/arch/arm/cpu/arm926ejs/mx28/iomux.c
new file mode 100644
index 0000000..9ea411f
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/iomux.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2004-2006,2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
+ * Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH,
+ *                       <armlinux@phytec.de>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <common.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/iomux.h>
+#include <asm/arch/imx-regs.h>
+
+#if	defined(CONFIG_MX23)
+#define	DRIVE_OFFSET	0x200
+#define	PULL_OFFSET	0x400
+#elif	defined(CONFIG_MX28)
+#define	DRIVE_OFFSET	0x300
+#define	PULL_OFFSET	0x600
+#else
+#error "Please select CONFIG_MX23 or CONFIG_MX28"
+#endif
+
+/*
+ * configures a single pad in the iomuxer
+ */
+int mxs_iomux_setup_pad(iomux_cfg_t pad)
+{
+	u32 reg, ofs, bp, bm;
+	void *iomux_base = (void *)MXS_PINCTRL_BASE;
+	struct mx28_register *mxs_reg;
+
+	/* muxsel */
+	ofs = 0x100;
+	ofs += PAD_BANK(pad) * 0x20 + PAD_PIN(pad) / 16 * 0x10;
+	bp = PAD_PIN(pad) % 16 * 2;
+	bm = 0x3 << bp;
+	reg = readl(iomux_base + ofs);
+	reg &= ~bm;
+	reg |= PAD_MUXSEL(pad) << bp;
+	writel(reg, iomux_base + ofs);
+
+	/* drive */
+	ofs = DRIVE_OFFSET;
+	ofs += PAD_BANK(pad) * 0x40 + PAD_PIN(pad) / 8 * 0x10;
+	/* mA */
+	if (PAD_MA_VALID(pad)) {
+		bp = PAD_PIN(pad) % 8 * 4;
+		bm = 0x3 << bp;
+		reg = readl(iomux_base + ofs);
+		reg &= ~bm;
+		reg |= PAD_MA(pad) << bp;
+		writel(reg, iomux_base + ofs);
+	}
+	/* vol */
+	if (PAD_VOL_VALID(pad)) {
+		bp = PAD_PIN(pad) % 8 * 4 + 2;
+		mxs_reg = (struct mx28_register *)(iomux_base + ofs);
+		if (PAD_VOL(pad))
+			writel(1 << bp, &mxs_reg->reg_set);
+		else
+			writel(1 << bp, &mxs_reg->reg_clr);
+	}
+
+	/* pull */
+	if (PAD_PULL_VALID(pad)) {
+		ofs = PULL_OFFSET;
+		ofs += PAD_BANK(pad) * 0x10;
+		bp = PAD_PIN(pad);
+		mxs_reg = (struct mx28_register *)(iomux_base + ofs);
+		if (PAD_PULL(pad))
+			writel(1 << bp, &mxs_reg->reg_set);
+		else
+			writel(1 << bp, &mxs_reg->reg_clr);
+	}
+
+	return 0;
+}
+
+int mxs_iomux_setup_multiple_pads(const iomux_cfg_t *pad_list, unsigned count)
+{
+	const iomux_cfg_t *p = pad_list;
+	int i;
+	int ret;
+
+	for (i = 0; i < count; i++) {
+		ret = mxs_iomux_setup_pad(*p);
+		if (ret)
+			return ret;
+		p++;
+	}
+
+	return 0;
+}
diff --git a/arch/arm/include/asm/arch-mx28/iomux-mx28.h b/arch/arm/include/asm/arch-mx28/iomux-mx28.h
new file mode 100644
index 0000000..b42820d
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/iomux-mx28.h
@@ -0,0 +1,537 @@
+/*
+ * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * 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
+ */
+
+#ifndef __MACH_IOMUX_MX28_H__
+#define __MACH_IOMUX_MX28_H__
+
+#include <asm/arch/iomux.h>
+
+/*
+ * The naming convention for the pad modes is MX28_PAD_<padname>__<padmode>
+ * If <padname> or <padmode> refers to a GPIO, it is named GPIO_<unit>_<num>
+ * See also iomux.h
+ *
+ *									BANK	PIN	MUX
+ */
+/* MUXSEL_0 */
+#define MX28_PAD_GPMI_D00__GPMI_D0			MXS_IOMUX_PAD_NAKED(0,  0, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_D01__GPMI_D1			MXS_IOMUX_PAD_NAKED(0,  1, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_D02__GPMI_D2			MXS_IOMUX_PAD_NAKED(0,  2, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_D03__GPMI_D3			MXS_IOMUX_PAD_NAKED(0,  3, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_D04__GPMI_D4			MXS_IOMUX_PAD_NAKED(0,  4, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_D05__GPMI_D5			MXS_IOMUX_PAD_NAKED(0,  5, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_D06__GPMI_D6			MXS_IOMUX_PAD_NAKED(0,  6, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_D07__GPMI_D7			MXS_IOMUX_PAD_NAKED(0,  7, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_CE0N__GPMI_CE0N			MXS_IOMUX_PAD_NAKED(0, 16, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_CE1N__GPMI_CE1N			MXS_IOMUX_PAD_NAKED(0, 17, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_CE2N__GPMI_CE2N			MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_CE3N__GPMI_CE3N			MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_RDY0__GPMI_READY0			MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_RDY1__GPMI_READY1			MXS_IOMUX_PAD_NAKED(0, 21, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_RDY2__GPMI_READY2			MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_RDY3__GPMI_READY3			MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_RDN__GPMI_RDN			MXS_IOMUX_PAD_NAKED(0, 24, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_WRN__GPMI_WRN			MXS_IOMUX_PAD_NAKED(0, 25, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_ALE__GPMI_ALE			MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_CLE__GPMI_CLE			MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_RESETN__GPMI_RESETN		MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_0)
+
+#define MX28_PAD_LCD_D00__LCD_D0			MXS_IOMUX_PAD_NAKED(1,  0, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D01__LCD_D1			MXS_IOMUX_PAD_NAKED(1,  1, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D02__LCD_D2			MXS_IOMUX_PAD_NAKED(1,  2, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D03__LCD_D3			MXS_IOMUX_PAD_NAKED(1,  3, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D04__LCD_D4			MXS_IOMUX_PAD_NAKED(1,  4, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D05__LCD_D5			MXS_IOMUX_PAD_NAKED(1,  5, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D06__LCD_D6			MXS_IOMUX_PAD_NAKED(1,  6, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D07__LCD_D7			MXS_IOMUX_PAD_NAKED(1,  7, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D08__LCD_D8			MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D09__LCD_D9			MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D10__LCD_D10			MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D11__LCD_D11			MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D12__LCD_D12			MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D13__LCD_D13			MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D14__LCD_D14			MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D15__LCD_D15			MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D16__LCD_D16			MXS_IOMUX_PAD_NAKED(1, 16, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D17__LCD_D17			MXS_IOMUX_PAD_NAKED(1, 17, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D18__LCD_D18			MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D19__LCD_D19			MXS_IOMUX_PAD_NAKED(1, 19, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D20__LCD_D20			MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D21__LCD_D21			MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D22__LCD_D22			MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D23__LCD_D23			MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_RD_E__LCD_RD_E			MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_WR_RWN__LCD_WR_RWN			MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_RS__LCD_RS				MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_CS__LCD_CS				MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_VSYNC__LCD_VSYNC			MXS_IOMUX_PAD_NAKED(1, 28, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_HSYNC__LCD_HSYNC			MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_DOTCLK__LCD_DOTCLK			MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_ENABLE__LCD_ENABLE			MXS_IOMUX_PAD_NAKED(1, 31, PAD_MUXSEL_0)
+
+#define MX28_PAD_SSP0_DATA0__SSP0_D0			MXS_IOMUX_PAD_NAKED(2,  0, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_DATA1__SSP0_D1			MXS_IOMUX_PAD_NAKED(2,  1, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_DATA2__SSP0_D2			MXS_IOMUX_PAD_NAKED(2,  2, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_DATA3__SSP0_D3			MXS_IOMUX_PAD_NAKED(2,  3, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_DATA4__SSP0_D4			MXS_IOMUX_PAD_NAKED(2,  4, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_DATA5__SSP0_D5			MXS_IOMUX_PAD_NAKED(2,  5, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_DATA6__SSP0_D6			MXS_IOMUX_PAD_NAKED(2,  6, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_DATA7__SSP0_D7			MXS_IOMUX_PAD_NAKED(2,  7, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_CMD__SSP0_CMD			MXS_IOMUX_PAD_NAKED(2,  8, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT		MXS_IOMUX_PAD_NAKED(2,  9, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_SCK__SSP0_SCK			MXS_IOMUX_PAD_NAKED(2, 10, PAD_MUXSEL_0)
+#define MX28_PAD_SSP1_SCK__SSP1_SCK			MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_0)
+#define MX28_PAD_SSP1_CMD__SSP1_CMD			MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_0)
+#define MX28_PAD_SSP1_DATA0__SSP1_D0			MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_0)
+#define MX28_PAD_SSP1_DATA3__SSP1_D3			MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_0)
+#define MX28_PAD_SSP2_SCK__SSP2_SCK			MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_0)
+#define MX28_PAD_SSP2_MOSI__SSP2_CMD			MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_0)
+#define MX28_PAD_SSP2_MISO__SSP2_D0			MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_0)
+#define MX28_PAD_SSP2_SS0__SSP2_D3			MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_0)
+#define MX28_PAD_SSP2_SS1__SSP2_D4			MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_0)
+#define MX28_PAD_SSP2_SS2__SSP2_D5			MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_0)
+#define MX28_PAD_SSP3_SCK__SSP3_SCK			MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_0)
+#define MX28_PAD_SSP3_MOSI__SSP3_CMD			MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_0)
+#define MX28_PAD_SSP3_MISO__SSP3_D0			MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_0)
+#define MX28_PAD_SSP3_SS0__SSP3_D3			MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_0)
+
+#define MX28_PAD_AUART0_RX__AUART0_RX			MXS_IOMUX_PAD_NAKED(3,  0, PAD_MUXSEL_0)
+#define MX28_PAD_AUART0_TX__AUART0_TX			MXS_IOMUX_PAD_NAKED(3,  1, PAD_MUXSEL_0)
+#define MX28_PAD_AUART0_CTS__AUART0_CTS			MXS_IOMUX_PAD_NAKED(3,  2, PAD_MUXSEL_0)
+#define MX28_PAD_AUART0_RTS__AUART0_RTS			MXS_IOMUX_PAD_NAKED(3,  3, PAD_MUXSEL_0)
+#define MX28_PAD_AUART1_RX__AUART1_RX			MXS_IOMUX_PAD_NAKED(3,  4, PAD_MUXSEL_0)
+#define MX28_PAD_AUART1_TX__AUART1_TX			MXS_IOMUX_PAD_NAKED(3,  5, PAD_MUXSEL_0)
+#define MX28_PAD_AUART1_CTS__AUART1_CTS			MXS_IOMUX_PAD_NAKED(3,  6, PAD_MUXSEL_0)
+#define MX28_PAD_AUART1_RTS__AUART1_RTS			MXS_IOMUX_PAD_NAKED(3,  7, PAD_MUXSEL_0)
+#define MX28_PAD_AUART2_RX__AUART2_RX			MXS_IOMUX_PAD_NAKED(3,  8, PAD_MUXSEL_0)
+#define MX28_PAD_AUART2_TX__AUART2_TX			MXS_IOMUX_PAD_NAKED(3,  9, PAD_MUXSEL_0)
+#define MX28_PAD_AUART2_CTS__AUART2_CTS			MXS_IOMUX_PAD_NAKED(3, 10, PAD_MUXSEL_0)
+#define MX28_PAD_AUART2_RTS__AUART2_RTS			MXS_IOMUX_PAD_NAKED(3, 11, PAD_MUXSEL_0)
+#define MX28_PAD_AUART3_RX__AUART3_RX			MXS_IOMUX_PAD_NAKED(3, 12, PAD_MUXSEL_0)
+#define MX28_PAD_AUART3_TX__AUART3_TX			MXS_IOMUX_PAD_NAKED(3, 13, PAD_MUXSEL_0)
+#define MX28_PAD_AUART3_CTS__AUART3_CTS			MXS_IOMUX_PAD_NAKED(3, 14, PAD_MUXSEL_0)
+#define MX28_PAD_AUART3_RTS__AUART3_RTS			MXS_IOMUX_PAD_NAKED(3, 15, PAD_MUXSEL_0)
+#define MX28_PAD_PWM0__PWM_0				MXS_IOMUX_PAD_NAKED(3, 16, PAD_MUXSEL_0)
+#define MX28_PAD_PWM1__PWM_1				MXS_IOMUX_PAD_NAKED(3, 17, PAD_MUXSEL_0)
+#define MX28_PAD_PWM2__PWM_2				MXS_IOMUX_PAD_NAKED(3, 18, PAD_MUXSEL_0)
+#define MX28_PAD_SAIF0_MCLK__SAIF0_MCLK			MXS_IOMUX_PAD_NAKED(3, 20, PAD_MUXSEL_0)
+#define MX28_PAD_SAIF0_LRCLK__SAIF0_LRCLK		MXS_IOMUX_PAD_NAKED(3, 21, PAD_MUXSEL_0)
+#define MX28_PAD_SAIF0_BITCLK__SAIF0_BITCLK		MXS_IOMUX_PAD_NAKED(3, 22, PAD_MUXSEL_0)
+#define MX28_PAD_SAIF0_SDATA0__SAIF0_SDATA0		MXS_IOMUX_PAD_NAKED(3, 23, PAD_MUXSEL_0)
+#define MX28_PAD_I2C0_SCL__I2C0_SCL			MXS_IOMUX_PAD_NAKED(3, 24, PAD_MUXSEL_0)
+#define MX28_PAD_I2C0_SDA__I2C0_SDA			MXS_IOMUX_PAD_NAKED(3, 25, PAD_MUXSEL_0)
+#define MX28_PAD_SAIF1_SDATA0__SAIF1_SDATA0		MXS_IOMUX_PAD_NAKED(3, 26, PAD_MUXSEL_0)
+#define MX28_PAD_SPDIF__SPDIF_TX			MXS_IOMUX_PAD_NAKED(3, 27, PAD_MUXSEL_0)
+#define MX28_PAD_PWM3__PWM_3				MXS_IOMUX_PAD_NAKED(3, 28, PAD_MUXSEL_0)
+#define MX28_PAD_PWM4__PWM_4				MXS_IOMUX_PAD_NAKED(3, 29, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_RESET__LCD_RESET			MXS_IOMUX_PAD_NAKED(3, 30, PAD_MUXSEL_0)
+
+#define MX28_PAD_ENET0_MDC__ENET0_MDC			MXS_IOMUX_PAD_NAKED(4,  0, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_MDIO__ENET0_MDIO			MXS_IOMUX_PAD_NAKED(4,  1, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_RX_EN__ENET0_RX_EN		MXS_IOMUX_PAD_NAKED(4,  2, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_RXD0__ENET0_RXD0			MXS_IOMUX_PAD_NAKED(4,  3, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_RXD1__ENET0_RXD1			MXS_IOMUX_PAD_NAKED(4,  4, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_TX_CLK__ENET0_TX_CLK		MXS_IOMUX_PAD_NAKED(4,  5, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_TX_EN__ENET0_TX_EN		MXS_IOMUX_PAD_NAKED(4,  6, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_TXD0__ENET0_TXD0			MXS_IOMUX_PAD_NAKED(4,  7, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_TXD1__ENET0_TXD1			MXS_IOMUX_PAD_NAKED(4,  8, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_RXD2__ENET0_RXD2			MXS_IOMUX_PAD_NAKED(4,  9, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_RXD3__ENET0_RXD3			MXS_IOMUX_PAD_NAKED(4, 10, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_TXD2__ENET0_TXD2			MXS_IOMUX_PAD_NAKED(4, 11, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_TXD3__ENET0_TXD3			MXS_IOMUX_PAD_NAKED(4, 12, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_RX_CLK__ENET0_RX_CLK		MXS_IOMUX_PAD_NAKED(4, 13, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_COL__ENET0_COL			MXS_IOMUX_PAD_NAKED(4, 14, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_CRS__ENET0_CRS			MXS_IOMUX_PAD_NAKED(4, 15, PAD_MUXSEL_0)
+#define MX28_PAD_ENET_CLK__CLKCTRL_ENET			MXS_IOMUX_PAD_NAKED(4, 16, PAD_MUXSEL_0)
+#define MX28_PAD_JTAG_RTCK__JTAG_RTCK			MXS_IOMUX_PAD_NAKED(4, 20, PAD_MUXSEL_0)
+
+#define MX28_PAD_EMI_D00__EMI_DATA0			MXS_IOMUX_PAD_NAKED(5,  0, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D01__EMI_DATA1			MXS_IOMUX_PAD_NAKED(5,  1, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D02__EMI_DATA2			MXS_IOMUX_PAD_NAKED(5,  2, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D03__EMI_DATA3			MXS_IOMUX_PAD_NAKED(5,  3, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D04__EMI_DATA4			MXS_IOMUX_PAD_NAKED(5,  4, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D05__EMI_DATA5			MXS_IOMUX_PAD_NAKED(5,  5, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D06__EMI_DATA6			MXS_IOMUX_PAD_NAKED(5,  6, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D07__EMI_DATA7			MXS_IOMUX_PAD_NAKED(5,  7, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D08__EMI_DATA8			MXS_IOMUX_PAD_NAKED(5,  8, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D09__EMI_DATA9			MXS_IOMUX_PAD_NAKED(5,  9, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D10__EMI_DATA10			MXS_IOMUX_PAD_NAKED(5, 10, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D11__EMI_DATA11			MXS_IOMUX_PAD_NAKED(5, 11, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D12__EMI_DATA12			MXS_IOMUX_PAD_NAKED(5, 12, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D13__EMI_DATA13			MXS_IOMUX_PAD_NAKED(5, 13, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D14__EMI_DATA14			MXS_IOMUX_PAD_NAKED(5, 14, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D15__EMI_DATA15			MXS_IOMUX_PAD_NAKED(5, 15, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_ODT0__EMI_ODT0			MXS_IOMUX_PAD_NAKED(5, 16, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_DQM0__EMI_DQM0			MXS_IOMUX_PAD_NAKED(5, 17, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_ODT1__EMI_ODT1			MXS_IOMUX_PAD_NAKED(5, 18, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_DQM1__EMI_DQM1			MXS_IOMUX_PAD_NAKED(5, 19, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_DDR_OPEN_FB__EMI_DDR_OPEN_FEEDBACK	MXS_IOMUX_PAD_NAKED(5, 20, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_CLK__EMI_CLK			MXS_IOMUX_PAD_NAKED(5, 21, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_DQS0__EMI_DQS0			MXS_IOMUX_PAD_NAKED(5, 22, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_DQS1__EMI_DQS1			MXS_IOMUX_PAD_NAKED(5, 23, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_DDR_OPEN__EMI_DDR_OPEN		MXS_IOMUX_PAD_NAKED(5, 26, PAD_MUXSEL_0)
+
+#define MX28_PAD_EMI_A00__EMI_ADDR0			MXS_IOMUX_PAD_NAKED(6,  0, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A01__EMI_ADDR1			MXS_IOMUX_PAD_NAKED(6,  1, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A02__EMI_ADDR2			MXS_IOMUX_PAD_NAKED(6,  2, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A03__EMI_ADDR3			MXS_IOMUX_PAD_NAKED(6,  3, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A04__EMI_ADDR4			MXS_IOMUX_PAD_NAKED(6,  4, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A05__EMI_ADDR5			MXS_IOMUX_PAD_NAKED(6,  5, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A06__EMI_ADDR6			MXS_IOMUX_PAD_NAKED(6,  6, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A07__EMI_ADDR7			MXS_IOMUX_PAD_NAKED(6,  7, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A08__EMI_ADDR8			MXS_IOMUX_PAD_NAKED(6,  8, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A09__EMI_ADDR9			MXS_IOMUX_PAD_NAKED(6,  9, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A10__EMI_ADDR10			MXS_IOMUX_PAD_NAKED(6, 10, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A11__EMI_ADDR11			MXS_IOMUX_PAD_NAKED(6, 11, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A12__EMI_ADDR12			MXS_IOMUX_PAD_NAKED(6, 12, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A13__EMI_ADDR13			MXS_IOMUX_PAD_NAKED(6, 13, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A14__EMI_ADDR14			MXS_IOMUX_PAD_NAKED(6, 14, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_BA0__EMI_BA0			MXS_IOMUX_PAD_NAKED(6, 16, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_BA1__EMI_BA1			MXS_IOMUX_PAD_NAKED(6, 17, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_BA2__EMI_BA2			MXS_IOMUX_PAD_NAKED(6, 18, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_CASN__EMI_CASN			MXS_IOMUX_PAD_NAKED(6, 19, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_RASN__EMI_RASN			MXS_IOMUX_PAD_NAKED(6, 20, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_WEN__EMI_WEN			MXS_IOMUX_PAD_NAKED(6, 21, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_CE0N__EMI_CE0N			MXS_IOMUX_PAD_NAKED(6, 22, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_CE1N__EMI_CE1N			MXS_IOMUX_PAD_NAKED(6, 23, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_CKE__EMI_CKE			MXS_IOMUX_PAD_NAKED(6, 24, PAD_MUXSEL_0)
+
+/* MUXSEL_1 */
+#define MX28_PAD_GPMI_D00__SSP1_D0			MXS_IOMUX_PAD_NAKED(0,  0, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_D01__SSP1_D1			MXS_IOMUX_PAD_NAKED(0,  1, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_D02__SSP1_D2			MXS_IOMUX_PAD_NAKED(0,  2, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_D03__SSP1_D3			MXS_IOMUX_PAD_NAKED(0,  3, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_D04__SSP1_D4			MXS_IOMUX_PAD_NAKED(0,  4, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_D05__SSP1_D5			MXS_IOMUX_PAD_NAKED(0,  5, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_D06__SSP1_D6			MXS_IOMUX_PAD_NAKED(0,  6, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_D07__SSP1_D7			MXS_IOMUX_PAD_NAKED(0,  7, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_CE0N__SSP3_D0			MXS_IOMUX_PAD_NAKED(0, 16, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_CE1N__SSP3_D3			MXS_IOMUX_PAD_NAKED(0, 17, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_CE2N__CAN1_TX			MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_CE3N__CAN1_RX			MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_RDY0__SSP1_CARD_DETECT		MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_RDY1__SSP1_CMD			MXS_IOMUX_PAD_NAKED(0, 21, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_RDY2__CAN0_TX			MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_RDY3__CAN0_RX			MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_RDN__SSP3_SCK			MXS_IOMUX_PAD_NAKED(0, 24, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_WRN__SSP1_SCK			MXS_IOMUX_PAD_NAKED(0, 25, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_ALE__SSP3_D1			MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_CLE__SSP3_D2			MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_RESETN__SSP3_CMD			MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_1)
+
+#define MX28_PAD_LCD_D03__ETM_DA8			MXS_IOMUX_PAD_NAKED(1,  3, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_D04__ETM_DA9			MXS_IOMUX_PAD_NAKED(1,  4, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_D08__ETM_DA3			MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_D09__ETM_DA4			MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_D20__ENET1_1588_EVENT2_OUT		MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_D21__ENET1_1588_EVENT2_IN		MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_D22__ENET1_1588_EVENT3_OUT		MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_D23__ENET1_1588_EVENT3_IN		MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_RD_E__LCD_VSYNC			MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_WR_RWN__LCD_HSYNC			MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_RS__LCD_DOTCLK			MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_CS__LCD_ENABLE			MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_VSYNC__SAIF1_SDATA0		MXS_IOMUX_PAD_NAKED(1, 28, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_HSYNC__SAIF1_SDATA1		MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_DOTCLK__SAIF1_MCLK			MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_1)
+
+#define MX28_PAD_SSP0_DATA4__SSP2_D0			MXS_IOMUX_PAD_NAKED(2,  4, PAD_MUXSEL_1)
+#define MX28_PAD_SSP0_DATA5__SSP2_D3			MXS_IOMUX_PAD_NAKED(2,  5, PAD_MUXSEL_1)
+#define MX28_PAD_SSP0_DATA6__SSP2_CMD			MXS_IOMUX_PAD_NAKED(2,  6, PAD_MUXSEL_1)
+#define MX28_PAD_SSP0_DATA7__SSP2_SCK			MXS_IOMUX_PAD_NAKED(2,  7, PAD_MUXSEL_1)
+#define MX28_PAD_SSP1_SCK__SSP2_D1			MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_1)
+#define MX28_PAD_SSP1_CMD__SSP2_D2			MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_1)
+#define MX28_PAD_SSP1_DATA0__SSP2_D6			MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_1)
+#define MX28_PAD_SSP1_DATA3__SSP2_D7			MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_1)
+#define MX28_PAD_SSP2_SCK__AUART2_RX			MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_1)
+#define MX28_PAD_SSP2_MOSI__AUART2_TX			MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_1)
+#define MX28_PAD_SSP2_MISO__AUART3_RX			MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_1)
+#define MX28_PAD_SSP2_SS0__AUART3_TX			MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_1)
+#define MX28_PAD_SSP2_SS1__SSP2_D1			MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_1)
+#define MX28_PAD_SSP2_SS2__SSP2_D2			MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_1)
+#define MX28_PAD_SSP3_SCK__AUART4_TX			MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_1)
+#define MX28_PAD_SSP3_MOSI__AUART4_RX			MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_1)
+#define MX28_PAD_SSP3_MISO__AUART4_RTS			MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_1)
+#define MX28_PAD_SSP3_SS0__AUART4_CTS			MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_1)
+
+#define MX28_PAD_AUART0_RX__I2C0_SCL			MXS_IOMUX_PAD_NAKED(3,  0, PAD_MUXSEL_1)
+#define MX28_PAD_AUART0_TX__I2C0_SDA			MXS_IOMUX_PAD_NAKED(3,  1, PAD_MUXSEL_1)
+#define MX28_PAD_AUART0_CTS__AUART4_RX			MXS_IOMUX_PAD_NAKED(3,  2, PAD_MUXSEL_1)
+#define MX28_PAD_AUART0_RTS__AUART4_TX			MXS_IOMUX_PAD_NAKED(3,  3, PAD_MUXSEL_1)
+#define MX28_PAD_AUART1_RX__SSP2_CARD_DETECT		MXS_IOMUX_PAD_NAKED(3,  4, PAD_MUXSEL_1)
+#define MX28_PAD_AUART1_TX__SSP3_CARD_DETECT		MXS_IOMUX_PAD_NAKED(3,  5, PAD_MUXSEL_1)
+#define MX28_PAD_AUART1_CTS__USB0_OVERCURRENT		MXS_IOMUX_PAD_NAKED(3,  6, PAD_MUXSEL_1)
+#define MX28_PAD_AUART1_RTS__USB0_ID			MXS_IOMUX_PAD_NAKED(3,  7, PAD_MUXSEL_1)
+#define MX28_PAD_AUART2_RX__SSP3_D1			MXS_IOMUX_PAD_NAKED(3,  8, PAD_MUXSEL_1)
+#define MX28_PAD_AUART2_TX__SSP3_D2			MXS_IOMUX_PAD_NAKED(3,  9, PAD_MUXSEL_1)
+#define MX28_PAD_AUART2_CTS__I2C1_SCL			MXS_IOMUX_PAD_NAKED(3, 10, PAD_MUXSEL_1)
+#define MX28_PAD_AUART2_RTS__I2C1_SDA			MXS_IOMUX_PAD_NAKED(3, 11, PAD_MUXSEL_1)
+#define MX28_PAD_AUART3_RX__CAN0_TX			MXS_IOMUX_PAD_NAKED(3, 12, PAD_MUXSEL_1)
+#define MX28_PAD_AUART3_TX__CAN0_RX			MXS_IOMUX_PAD_NAKED(3, 13, PAD_MUXSEL_1)
+#define MX28_PAD_AUART3_CTS__CAN1_TX			MXS_IOMUX_PAD_NAKED(3, 14, PAD_MUXSEL_1)
+#define MX28_PAD_AUART3_RTS__CAN1_RX			MXS_IOMUX_PAD_NAKED(3, 15, PAD_MUXSEL_1)
+#define MX28_PAD_PWM0__I2C1_SCL				MXS_IOMUX_PAD_NAKED(3, 16, PAD_MUXSEL_1)
+#define MX28_PAD_PWM1__I2C1_SDA				MXS_IOMUX_PAD_NAKED(3, 17, PAD_MUXSEL_1)
+#define MX28_PAD_PWM2__USB0_ID				MXS_IOMUX_PAD_NAKED(3, 18, PAD_MUXSEL_1)
+#define MX28_PAD_SAIF0_MCLK__PWM_3			MXS_IOMUX_PAD_NAKED(3, 20, PAD_MUXSEL_1)
+#define MX28_PAD_SAIF0_LRCLK__PWM_4			MXS_IOMUX_PAD_NAKED(3, 21, PAD_MUXSEL_1)
+#define MX28_PAD_SAIF0_BITCLK__PWM_5			MXS_IOMUX_PAD_NAKED(3, 22, PAD_MUXSEL_1)
+#define MX28_PAD_SAIF0_SDATA0__PWM_6			MXS_IOMUX_PAD_NAKED(3, 23, PAD_MUXSEL_1)
+#define MX28_PAD_I2C0_SCL__TIMROT_ROTARYA		MXS_IOMUX_PAD_NAKED(3, 24, PAD_MUXSEL_1)
+#define MX28_PAD_I2C0_SDA__TIMROT_ROTARYB		MXS_IOMUX_PAD_NAKED(3, 25, PAD_MUXSEL_1)
+#define MX28_PAD_SAIF1_SDATA0__PWM_7			MXS_IOMUX_PAD_NAKED(3, 26, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_RESET__LCD_VSYNC			MXS_IOMUX_PAD_NAKED(3, 30, PAD_MUXSEL_1)
+
+#define MX28_PAD_ENET0_MDC__GPMI_CE4N			MXS_IOMUX_PAD_NAKED(4,  0, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_MDIO__GPMI_CE5N			MXS_IOMUX_PAD_NAKED(4,  1, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_RX_EN__GPMI_CE6N			MXS_IOMUX_PAD_NAKED(4,  2, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_RXD0__GPMI_CE7N			MXS_IOMUX_PAD_NAKED(4,  3, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_RXD1__GPMI_READY4		MXS_IOMUX_PAD_NAKED(4,  4, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_TX_CLK__HSADC_TRIGGER		MXS_IOMUX_PAD_NAKED(4,  5, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_TX_EN__GPMI_READY5		MXS_IOMUX_PAD_NAKED(4,  6, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_TXD0__GPMI_READY6		MXS_IOMUX_PAD_NAKED(4,  7, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_TXD1__GPMI_READY7		MXS_IOMUX_PAD_NAKED(4,  8, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_RXD2__ENET1_RXD0			MXS_IOMUX_PAD_NAKED(4,  9, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_RXD3__ENET1_RXD1			MXS_IOMUX_PAD_NAKED(4, 10, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_TXD2__ENET1_TXD0			MXS_IOMUX_PAD_NAKED(4, 11, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_TXD3__ENET1_TXD1			MXS_IOMUX_PAD_NAKED(4, 12, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_RX_CLK__ENET0_RX_ER		MXS_IOMUX_PAD_NAKED(4, 13, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_COL__ENET1_TX_EN			MXS_IOMUX_PAD_NAKED(4, 14, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_CRS__ENET1_RX_EN			MXS_IOMUX_PAD_NAKED(4, 15, PAD_MUXSEL_1)
+
+/* MUXSEL_2 */
+#define MX28_PAD_GPMI_CE2N__ENET0_RX_ER			MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_2)
+#define MX28_PAD_GPMI_CE3N__SAIF1_MCLK			MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_2)
+#define MX28_PAD_GPMI_RDY0__USB0_ID			MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_2)
+#define MX28_PAD_GPMI_RDY2__ENET0_TX_ER			MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_2)
+#define MX28_PAD_GPMI_RDY3__HSADC_TRIGGER		MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_2)
+#define MX28_PAD_GPMI_ALE__SSP3_D4			MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_2)
+#define MX28_PAD_GPMI_CLE__SSP3_D5			MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_2)
+
+#define MX28_PAD_LCD_D00__ETM_DA0			MXS_IOMUX_PAD_NAKED(1,  0, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D01__ETM_DA1			MXS_IOMUX_PAD_NAKED(1,  1, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D02__ETM_DA2			MXS_IOMUX_PAD_NAKED(1,  2, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D03__ETM_DA3			MXS_IOMUX_PAD_NAKED(1,  3, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D04__ETM_DA4			MXS_IOMUX_PAD_NAKED(1,  4, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D05__ETM_DA5			MXS_IOMUX_PAD_NAKED(1,  5, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D06__ETM_DA6			MXS_IOMUX_PAD_NAKED(1,  6, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D07__ETM_DA7			MXS_IOMUX_PAD_NAKED(1,  7, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D08__ETM_DA8			MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D09__ETM_DA9			MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D10__ETM_DA10			MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D11__ETM_DA11			MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D12__ETM_DA12			MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D13__ETM_DA13			MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D14__ETM_DA14			MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D15__ETM_DA15			MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D16__ETM_DA7			MXS_IOMUX_PAD_NAKED(1, 16, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D17__ETM_DA6			MXS_IOMUX_PAD_NAKED(1, 17, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D18__ETM_DA5			MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D19__ETM_DA4			MXS_IOMUX_PAD_NAKED(1, 19, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D20__ETM_DA3			MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D21__ETM_DA2			MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D22__ETM_DA1			MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D23__ETM_DA0			MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_RD_E__ETM_TCTL			MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_WR_RWN__ETM_TCLK			MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_HSYNC__ETM_TCTL			MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_DOTCLK__ETM_TCLK			MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_2)
+
+#define MX28_PAD_SSP1_SCK__ENET0_1588_EVENT2_OUT	MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_2)
+#define MX28_PAD_SSP1_CMD__ENET0_1588_EVENT2_IN		MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_2)
+#define MX28_PAD_SSP1_DATA0__ENET0_1588_EVENT3_OUT	MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_2)
+#define MX28_PAD_SSP1_DATA3__ENET0_1588_EVENT3_IN	MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_2)
+#define MX28_PAD_SSP2_SCK__SAIF0_SDATA1			MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_2)
+#define MX28_PAD_SSP2_MOSI__SAIF0_SDATA2		MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_2)
+#define MX28_PAD_SSP2_MISO__SAIF1_SDATA1		MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_2)
+#define MX28_PAD_SSP2_SS0__SAIF1_SDATA2			MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_2)
+#define MX28_PAD_SSP2_SS1__USB1_OVERCURRENT		MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_2)
+#define MX28_PAD_SSP2_SS2__USB0_OVERCURRENT		MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_2)
+#define MX28_PAD_SSP3_SCK__ENET1_1588_EVENT0_OUT	MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_2)
+#define MX28_PAD_SSP3_MOSI__ENET1_1588_EVENT0_IN	MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_2)
+#define MX28_PAD_SSP3_MISO__ENET1_1588_EVENT1_OUT	MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_2)
+#define MX28_PAD_SSP3_SS0__ENET1_1588_EVENT1_IN		MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_2)
+
+#define MX28_PAD_AUART0_RX__DUART_CTS			MXS_IOMUX_PAD_NAKED(3,  0, PAD_MUXSEL_2)
+#define MX28_PAD_AUART0_TX__DUART_RTS			MXS_IOMUX_PAD_NAKED(3,  1, PAD_MUXSEL_2)
+#define MX28_PAD_AUART0_CTS__DUART_RX			MXS_IOMUX_PAD_NAKED(3,  2, PAD_MUXSEL_2)
+#define MX28_PAD_AUART0_RTS__DUART_TX			MXS_IOMUX_PAD_NAKED(3,  3, PAD_MUXSEL_2)
+#define MX28_PAD_AUART1_RX__PWM_0			MXS_IOMUX_PAD_NAKED(3,  4, PAD_MUXSEL_2)
+#define MX28_PAD_AUART1_TX__PWM_1			MXS_IOMUX_PAD_NAKED(3,  5, PAD_MUXSEL_2)
+#define MX28_PAD_AUART1_CTS__TIMROT_ROTARYA		MXS_IOMUX_PAD_NAKED(3,  6, PAD_MUXSEL_2)
+#define MX28_PAD_AUART1_RTS__TIMROT_ROTARYB		MXS_IOMUX_PAD_NAKED(3,  7, PAD_MUXSEL_2)
+#define MX28_PAD_AUART2_RX__SSP3_D4			MXS_IOMUX_PAD_NAKED(3,  8, PAD_MUXSEL_2)
+#define MX28_PAD_AUART2_TX__SSP3_D5			MXS_IOMUX_PAD_NAKED(3,  9, PAD_MUXSEL_2)
+#define MX28_PAD_AUART2_CTS__SAIF1_BITCLK		MXS_IOMUX_PAD_NAKED(3, 10, PAD_MUXSEL_2)
+#define MX28_PAD_AUART2_RTS__SAIF1_LRCLK		MXS_IOMUX_PAD_NAKED(3, 11, PAD_MUXSEL_2)
+#define MX28_PAD_AUART3_RX__ENET0_1588_EVENT0_OUT	MXS_IOMUX_PAD_NAKED(3, 12, PAD_MUXSEL_2)
+#define MX28_PAD_AUART3_TX__ENET0_1588_EVENT0_IN	MXS_IOMUX_PAD_NAKED(3, 13, PAD_MUXSEL_2)
+#define MX28_PAD_AUART3_CTS__ENET0_1588_EVENT1_OUT	MXS_IOMUX_PAD_NAKED(3, 14, PAD_MUXSEL_2)
+#define MX28_PAD_AUART3_RTS__ENET0_1588_EVENT1_IN	MXS_IOMUX_PAD_NAKED(3, 15, PAD_MUXSEL_2)
+#define MX28_PAD_PWM0__DUART_RX				MXS_IOMUX_PAD_NAKED(3, 16, PAD_MUXSEL_2)
+#define MX28_PAD_PWM1__DUART_TX				MXS_IOMUX_PAD_NAKED(3, 17, PAD_MUXSEL_2)
+#define MX28_PAD_PWM2__USB1_OVERCURRENT			MXS_IOMUX_PAD_NAKED(3, 18, PAD_MUXSEL_2)
+#define MX28_PAD_SAIF0_MCLK__AUART4_CTS			MXS_IOMUX_PAD_NAKED(3, 20, PAD_MUXSEL_2)
+#define MX28_PAD_SAIF0_LRCLK__AUART4_RTS		MXS_IOMUX_PAD_NAKED(3, 21, PAD_MUXSEL_2)
+#define MX28_PAD_SAIF0_BITCLK__AUART4_RX		MXS_IOMUX_PAD_NAKED(3, 22, PAD_MUXSEL_2)
+#define MX28_PAD_SAIF0_SDATA0__AUART4_TX		MXS_IOMUX_PAD_NAKED(3, 23, PAD_MUXSEL_2)
+#define MX28_PAD_I2C0_SCL__DUART_RX			MXS_IOMUX_PAD_NAKED(3, 24, PAD_MUXSEL_2)
+#define MX28_PAD_I2C0_SDA__DUART_TX			MXS_IOMUX_PAD_NAKED(3, 25, PAD_MUXSEL_2)
+#define MX28_PAD_SAIF1_SDATA0__SAIF0_SDATA1		MXS_IOMUX_PAD_NAKED(3, 26, PAD_MUXSEL_2)
+#define MX28_PAD_SPDIF__ENET1_RX_ER			MXS_IOMUX_PAD_NAKED(3, 27, PAD_MUXSEL_2)
+
+#define MX28_PAD_ENET0_MDC__SAIF0_SDATA1		MXS_IOMUX_PAD_NAKED(4,  0, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_MDIO__SAIF0_SDATA2		MXS_IOMUX_PAD_NAKED(4,  1, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_RX_EN__SAIF1_SDATA1		MXS_IOMUX_PAD_NAKED(4,  2, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_RXD0__SAIF1_SDATA2		MXS_IOMUX_PAD_NAKED(4,  3, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_TX_CLK__ENET0_1588_EVENT2_OUT	MXS_IOMUX_PAD_NAKED(4,  5, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_RXD2__ENET0_1588_EVENT0_OUT	MXS_IOMUX_PAD_NAKED(4,  9, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_RXD3__ENET0_1588_EVENT0_IN	MXS_IOMUX_PAD_NAKED(4, 10, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_TXD2__ENET0_1588_EVENT1_OUT	MXS_IOMUX_PAD_NAKED(4, 11, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_TXD3__ENET0_1588_EVENT1_IN	MXS_IOMUX_PAD_NAKED(4, 12, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_RX_CLK__ENET0_1588_EVENT2_IN	MXS_IOMUX_PAD_NAKED(4, 13, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_COL__ENET0_1588_EVENT3_OUT	MXS_IOMUX_PAD_NAKED(4, 14, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_CRS__ENET0_1588_EVENT3_IN	MXS_IOMUX_PAD_NAKED(4, 15, PAD_MUXSEL_2)
+
+/* MUXSEL_GPIO */
+#define MX28_PAD_GPMI_D00__GPIO_0_0			MXS_IOMUX_PAD_NAKED(0,  0, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_D01__GPIO_0_1			MXS_IOMUX_PAD_NAKED(0,  1, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_D02__GPIO_0_2			MXS_IOMUX_PAD_NAKED(0,  2, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_D03__GPIO_0_3			MXS_IOMUX_PAD_NAKED(0,  3, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_D04__GPIO_0_4			MXS_IOMUX_PAD_NAKED(0,  4, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_D05__GPIO_0_5			MXS_IOMUX_PAD_NAKED(0,  5, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_D06__GPIO_0_6			MXS_IOMUX_PAD_NAKED(0,  6, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_D07__GPIO_0_7			MXS_IOMUX_PAD_NAKED(0,  7, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_CE0N__GPIO_0_16			MXS_IOMUX_PAD_NAKED(0, 16, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_CE1N__GPIO_0_17			MXS_IOMUX_PAD_NAKED(0, 17, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_CE2N__GPIO_0_18			MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_CE3N__GPIO_0_19			MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_RDY0__GPIO_0_20			MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_RDY1__GPIO_0_21			MXS_IOMUX_PAD_NAKED(0, 21, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_RDY2__GPIO_0_22			MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_RDY3__GPIO_0_23			MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_RDN__GPIO_0_24			MXS_IOMUX_PAD_NAKED(0, 24, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_WRN__GPIO_0_25			MXS_IOMUX_PAD_NAKED(0, 25, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_ALE__GPIO_0_26			MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_CLE__GPIO_0_27			MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_RESETN__GPIO_0_28			MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_GPIO)
+
+#define MX28_PAD_LCD_D00__GPIO_1_0			MXS_IOMUX_PAD_NAKED(1,  0, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D01__GPIO_1_1			MXS_IOMUX_PAD_NAKED(1,  1, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D02__GPIO_1_2			MXS_IOMUX_PAD_NAKED(1,  2, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D03__GPIO_1_3			MXS_IOMUX_PAD_NAKED(1,  3, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D04__GPIO_1_4			MXS_IOMUX_PAD_NAKED(1,  4, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D05__GPIO_1_5			MXS_IOMUX_PAD_NAKED(1,  5, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D06__GPIO_1_6			MXS_IOMUX_PAD_NAKED(1,  6, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D07__GPIO_1_7			MXS_IOMUX_PAD_NAKED(1,  7, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D08__GPIO_1_8			MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D09__GPIO_1_9			MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D10__GPIO_1_10			MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D11__GPIO_1_11			MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D12__GPIO_1_12			MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D13__GPIO_1_13			MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D14__GPIO_1_14			MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D15__GPIO_1_15			MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D16__GPIO_1_16			MXS_IOMUX_PAD_NAKED(1, 16, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D17__GPIO_1_17			MXS_IOMUX_PAD_NAKED(1, 17, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D18__GPIO_1_18			MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D19__GPIO_1_19			MXS_IOMUX_PAD_NAKED(1, 19, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D20__GPIO_1_20			MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D21__GPIO_1_21			MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D22__GPIO_1_22			MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D23__GPIO_1_23			MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_RD_E__GPIO_1_24			MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_WR_RWN__GPIO_1_25			MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_RS__GPIO_1_26			MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_CS__GPIO_1_27			MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_VSYNC__GPIO_1_28			MXS_IOMUX_PAD_NAKED(1, 28, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_HSYNC__GPIO_1_29			MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_DOTCLK__GPIO_1_30			MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_ENABLE__GPIO_1_31			MXS_IOMUX_PAD_NAKED(1, 31, PAD_MUXSEL_GPIO)
+
+#define MX28_PAD_SSP0_DATA0__GPIO_2_0			MXS_IOMUX_PAD_NAKED(2,  0, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_DATA1__GPIO_2_1			MXS_IOMUX_PAD_NAKED(2,  1, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_DATA2__GPIO_2_2			MXS_IOMUX_PAD_NAKED(2,  2, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_DATA3__GPIO_2_3			MXS_IOMUX_PAD_NAKED(2,  3, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_DATA4__GPIO_2_4			MXS_IOMUX_PAD_NAKED(2,  4, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_DATA5__GPIO_2_5			MXS_IOMUX_PAD_NAKED(2,  5, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_DATA6__GPIO_2_6			MXS_IOMUX_PAD_NAKED(2,  6, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_DATA7__GPIO_2_7			MXS_IOMUX_PAD_NAKED(2,  7, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_CMD__GPIO_2_8			MXS_IOMUX_PAD_NAKED(2,  8, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_DETECT__GPIO_2_9			MXS_IOMUX_PAD_NAKED(2,  9, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_SCK__GPIO_2_10			MXS_IOMUX_PAD_NAKED(2, 10, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP1_SCK__GPIO_2_12			MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP1_CMD__GPIO_2_13			MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP1_DATA0__GPIO_2_14			MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP1_DATA3__GPIO_2_15			MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP2_SCK__GPIO_2_16			MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP2_MOSI__GPIO_2_17			MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP2_MISO__GPIO_2_18			MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP2_SS0__GPIO_2_19			MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP2_SS1__GPIO_2_20			MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP2_SS2__GPIO_2_21			MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP3_SCK__GPIO_2_24			MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP3_MOSI__GPIO_2_25			MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP3_MISO__GPIO_2_26			MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP3_SS0__GPIO_2_27			MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_GPIO)
+
+#define MX28_PAD_AUART0_RX__GPIO_3_0			MXS_IOMUX_PAD_NAKED(3,  0, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART0_TX__GPIO_3_1			MXS_IOMUX_PAD_NAKED(3,  1, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART0_CTS__GPIO_3_2			MXS_IOMUX_PAD_NAKED(3,  2, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART0_RTS__GPIO_3_3			MXS_IOMUX_PAD_NAKED(3,  3, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART1_RX__GPIO_3_4			MXS_IOMUX_PAD_NAKED(3,  4, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART1_TX__GPIO_3_5			MXS_IOMUX_PAD_NAKED(3,  5, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART1_CTS__GPIO_3_6			MXS_IOMUX_PAD_NAKED(3,  6, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART1_RTS__GPIO_3_7			MXS_IOMUX_PAD_NAKED(3,  7, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART2_RX__GPIO_3_8			MXS_IOMUX_PAD_NAKED(3,  8, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART2_TX__GPIO_3_9			MXS_IOMUX_PAD_NAKED(3,  9, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART2_CTS__GPIO_3_10			MXS_IOMUX_PAD_NAKED(3, 10, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART2_RTS__GPIO_3_11			MXS_IOMUX_PAD_NAKED(3, 11, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART3_RX__GPIO_3_12			MXS_IOMUX_PAD_NAKED(3, 12, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART3_TX__GPIO_3_13			MXS_IOMUX_PAD_NAKED(3, 13, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART3_CTS__GPIO_3_14			MXS_IOMUX_PAD_NAKED(3, 14, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART3_RTS__GPIO_3_15			MXS_IOMUX_PAD_NAKED(3, 15, PAD_MUXSEL_GPIO)
+#define MX28_PAD_PWM0__GPIO_3_16			MXS_IOMUX_PAD_NAKED(3, 16, PAD_MUXSEL_GPIO)
+#define MX28_PAD_PWM1__GPIO_3_17			MXS_IOMUX_PAD_NAKED(3, 17, PAD_MUXSEL_GPIO)
+#define MX28_PAD_PWM2__GPIO_3_18			MXS_IOMUX_PAD_NAKED(3, 18, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SAIF0_MCLK__GPIO_3_20			MXS_IOMUX_PAD_NAKED(3, 20, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SAIF0_LRCLK__GPIO_3_21			MXS_IOMUX_PAD_NAKED(3, 21, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SAIF0_BITCLK__GPIO_3_22		MXS_IOMUX_PAD_NAKED(3, 22, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SAIF0_SDATA0__GPIO_3_23		MXS_IOMUX_PAD_NAKED(3, 23, PAD_MUXSEL_GPIO)
+#define MX28_PAD_I2C0_SCL__GPIO_3_24			MXS_IOMUX_PAD_NAKED(3, 24, PAD_MUXSEL_GPIO)
+#define MX28_PAD_I2C0_SDA__GPIO_3_25			MXS_IOMUX_PAD_NAKED(3, 25, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SAIF1_SDATA0__GPIO_3_26		MXS_IOMUX_PAD_NAKED(3, 26, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SPDIF__GPIO_3_27			MXS_IOMUX_PAD_NAKED(3, 27, PAD_MUXSEL_GPIO)
+#define MX28_PAD_PWM3__GPIO_3_28			MXS_IOMUX_PAD_NAKED(3, 28, PAD_MUXSEL_GPIO)
+#define MX28_PAD_PWM4__GPIO_3_29			MXS_IOMUX_PAD_NAKED(3, 29, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_RESET__GPIO_3_30			MXS_IOMUX_PAD_NAKED(3, 30, PAD_MUXSEL_GPIO)
+
+#define MX28_PAD_ENET0_MDC__GPIO_4_0			MXS_IOMUX_PAD_NAKED(4,  0, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_MDIO__GPIO_4_1			MXS_IOMUX_PAD_NAKED(4,  1, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_RX_EN__GPIO_4_2			MXS_IOMUX_PAD_NAKED(4,  2, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_RXD0__GPIO_4_3			MXS_IOMUX_PAD_NAKED(4,  3, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_RXD1__GPIO_4_4			MXS_IOMUX_PAD_NAKED(4,  4, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_TX_CLK__GPIO_4_5			MXS_IOMUX_PAD_NAKED(4,  5, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_TX_EN__GPIO_4_6			MXS_IOMUX_PAD_NAKED(4,  6, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_TXD0__GPIO_4_7			MXS_IOMUX_PAD_NAKED(4,  7, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_TXD1__GPIO_4_8			MXS_IOMUX_PAD_NAKED(4,  8, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_RXD2__GPIO_4_9			MXS_IOMUX_PAD_NAKED(4,  9, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_RXD3__GPIO_4_10			MXS_IOMUX_PAD_NAKED(4, 10, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_TXD2__GPIO_4_11			MXS_IOMUX_PAD_NAKED(4, 11, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_TXD3__GPIO_4_12			MXS_IOMUX_PAD_NAKED(4, 12, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_RX_CLK__GPIO_4_13		MXS_IOMUX_PAD_NAKED(4, 13, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_COL__GPIO_4_14			MXS_IOMUX_PAD_NAKED(4, 14, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_CRS__GPIO_4_15			MXS_IOMUX_PAD_NAKED(4, 15, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET_CLK__GPIO_4_16			MXS_IOMUX_PAD_NAKED(4, 16, PAD_MUXSEL_GPIO)
+#define MX28_PAD_JTAG_RTCK__GPIO_4_20			MXS_IOMUX_PAD_NAKED(4, 20, PAD_MUXSEL_GPIO)
+
+#endif /* __MACH_IOMUX_MX28_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/iomux.h b/arch/arm/include/asm/arch-mx28/iomux.h
new file mode 100644
index 0000000..7abdf58
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/iomux.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH,
+ *			<armlinux@phytec.de>
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifndef __MACH_MXS_IOMUX_H__
+#define __MACH_MXS_IOMUX_H__
+
+/*
+ * IOMUX/PAD Bit field definitions
+ *
+ * PAD_BANK:		 0..2	(3)
+ * PAD_PIN:		 3..7	(5)
+ * PAD_MUXSEL:		 8..9	(2)
+ * PAD_MA:		10..11	(2)
+ * PAD_MA_VALID:	12	(1)
+ * PAD_VOL:		13	(1)
+ * PAD_VOL_VALID:	14	(1)
+ * PAD_PULL:		15	(1)
+ * PAD_PULL_VALID:	16	(1)
+ * RESERVED:		17..31	(15)
+ */
+typedef u32 iomux_cfg_t;
+
+#define MXS_PAD_BANK_SHIFT	0
+#define MXS_PAD_BANK_MASK	((iomux_cfg_t)0x7 << MXS_PAD_BANK_SHIFT)
+#define MXS_PAD_PIN_SHIFT	3
+#define MXS_PAD_PIN_MASK	((iomux_cfg_t)0x1f << MXS_PAD_PIN_SHIFT)
+#define MXS_PAD_MUXSEL_SHIFT	8
+#define MXS_PAD_MUXSEL_MASK	((iomux_cfg_t)0x3 << MXS_PAD_MUXSEL_SHIFT)
+#define MXS_PAD_MA_SHIFT	10
+#define MXS_PAD_MA_MASK		((iomux_cfg_t)0x3 << MXS_PAD_MA_SHIFT)
+#define MXS_PAD_MA_VALID_SHIFT	12
+#define MXS_PAD_MA_VALID_MASK	((iomux_cfg_t)0x1 << MXS_PAD_MA_VALID_SHIFT)
+#define MXS_PAD_VOL_SHIFT	13
+#define MXS_PAD_VOL_MASK	((iomux_cfg_t)0x1 << MXS_PAD_VOL_SHIFT)
+#define MXS_PAD_VOL_VALID_SHIFT	14
+#define MXS_PAD_VOL_VALID_MASK	((iomux_cfg_t)0x1 << MXS_PAD_VOL_VALID_SHIFT)
+#define MXS_PAD_PULL_SHIFT	15
+#define MXS_PAD_PULL_MASK	((iomux_cfg_t)0x1 << MXS_PAD_PULL_SHIFT)
+#define MXS_PAD_PULL_VALID_SHIFT 16
+#define MXS_PAD_PULL_VALID_MASK	((iomux_cfg_t)0x1 << MXS_PAD_PULL_VALID_SHIFT)
+
+#define PAD_MUXSEL_0		0
+#define PAD_MUXSEL_1		1
+#define PAD_MUXSEL_2		2
+#define PAD_MUXSEL_GPIO		3
+
+#define PAD_4MA			0
+#define PAD_8MA			1
+#define PAD_12MA		2
+#define PAD_16MA		3
+
+#define PAD_1V8			0
+#define PAD_3V3			1
+
+#define PAD_NOPULL		0
+#define PAD_PULLUP		1
+
+#define MXS_PAD_4MA	((PAD_4MA << MXS_PAD_MA_SHIFT) | \
+					MXS_PAD_MA_VALID_MASK)
+#define MXS_PAD_8MA	((PAD_8MA << MXS_PAD_MA_SHIFT) | \
+					MXS_PAD_MA_VALID_MASK)
+#define MXS_PAD_12MA	((PAD_12MA << MXS_PAD_MA_SHIFT) | \
+					MXS_PAD_MA_VALID_MASK)
+#define MXS_PAD_16MA	((PAD_16MA << MXS_PAD_MA_SHIFT) | \
+					MXS_PAD_MA_VALID_MASK)
+
+#define MXS_PAD_1V8	((PAD_1V8 << MXS_PAD_VOL_SHIFT) | \
+					MXS_PAD_VOL_VALID_MASK)
+#define MXS_PAD_3V3	((PAD_3V3 << MXS_PAD_VOL_SHIFT) | \
+					MXS_PAD_VOL_VALID_MASK)
+
+#define MXS_PAD_NOPULL	((PAD_NOPULL << MXS_PAD_PULL_SHIFT) | \
+					MXS_PAD_PULL_VALID_MASK)
+#define MXS_PAD_PULLUP	((PAD_PULLUP << MXS_PAD_PULL_SHIFT) | \
+					MXS_PAD_PULL_VALID_MASK)
+
+/* generic pad control used in most cases */
+#define MXS_PAD_CTRL	(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL)
+
+#define MXS_IOMUX_PAD(_bank, _pin, _muxsel, _ma, _vol, _pull)		\
+		(((iomux_cfg_t)(_bank) << MXS_PAD_BANK_SHIFT) |		\
+		((iomux_cfg_t)(_pin) << MXS_PAD_PIN_SHIFT) |		\
+		((iomux_cfg_t)(_muxsel) << MXS_PAD_MUXSEL_SHIFT) |	\
+		((iomux_cfg_t)(_ma) << MXS_PAD_MA_SHIFT) |		\
+		((iomux_cfg_t)(_vol) << MXS_PAD_VOL_SHIFT) |		\
+		((iomux_cfg_t)(_pull) << MXS_PAD_PULL_SHIFT))
+
+/*
+ * A pad becomes naked, when none of mA, vol or pull
+ * validity bits is set.
+ */
+#define MXS_IOMUX_PAD_NAKED(_bank, _pin, _muxsel) \
+		MXS_IOMUX_PAD(_bank, _pin, _muxsel, 0, 0, 0)
+
+static inline unsigned int PAD_BANK(iomux_cfg_t pad)
+{
+	return (pad & MXS_PAD_BANK_MASK) >> MXS_PAD_BANK_SHIFT;
+}
+
+static inline unsigned int PAD_PIN(iomux_cfg_t pad)
+{
+	return (pad & MXS_PAD_PIN_MASK) >> MXS_PAD_PIN_SHIFT;
+}
+
+static inline unsigned int PAD_MUXSEL(iomux_cfg_t pad)
+{
+	return (pad & MXS_PAD_MUXSEL_MASK) >> MXS_PAD_MUXSEL_SHIFT;
+}
+
+static inline unsigned int PAD_MA(iomux_cfg_t pad)
+{
+	return (pad & MXS_PAD_MA_MASK) >> MXS_PAD_MA_SHIFT;
+}
+
+static inline unsigned int PAD_MA_VALID(iomux_cfg_t pad)
+{
+	return (pad & MXS_PAD_MA_VALID_MASK) >> MXS_PAD_MA_VALID_SHIFT;
+}
+
+static inline unsigned int PAD_VOL(iomux_cfg_t pad)
+{
+	return (pad & MXS_PAD_VOL_MASK) >> MXS_PAD_VOL_SHIFT;
+}
+
+static inline unsigned int PAD_VOL_VALID(iomux_cfg_t pad)
+{
+	return (pad & MXS_PAD_VOL_VALID_MASK) >> MXS_PAD_VOL_VALID_SHIFT;
+}
+
+static inline unsigned int PAD_PULL(iomux_cfg_t pad)
+{
+	return (pad & MXS_PAD_PULL_MASK) >> MXS_PAD_PULL_SHIFT;
+}
+
+static inline unsigned int PAD_PULL_VALID(iomux_cfg_t pad)
+{
+	return (pad & MXS_PAD_PULL_VALID_MASK) >> MXS_PAD_PULL_VALID_SHIFT;
+}
+
+/*
+ * configures a single pad in the iomuxer
+ */
+int mxs_iomux_setup_pad(iomux_cfg_t pad);
+
+/*
+ * configures multiple pads
+ * convenient way to call the above function with tables
+ */
+int mxs_iomux_setup_multiple_pads(const iomux_cfg_t *pad_list, unsigned count);
+
+#endif /* __MACH_MXS_IOMUX_H__*/
-- 
1.7.5.4

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

* [U-Boot] [PATCH 05/15] iMX28: Add I2C bus driver
  2011-09-12  4:06 [U-Boot] [PATCH 00/15 V2] Support for the DENX M28 SoM Marek Vasut
                   ` (3 preceding siblings ...)
  2011-09-12  4:06 ` [U-Boot] [PATCH 04/15] iMX28: Add PINMUX control Marek Vasut
@ 2011-09-12  4:06 ` Marek Vasut
  2011-09-12  5:30   ` Heiko Schocher
                     ` (2 more replies)
  2011-09-12  4:06 ` [U-Boot] [PATCH 06/15] iMX28: Add GPIO control Marek Vasut
                   ` (10 subsequent siblings)
  15 siblings, 3 replies; 116+ messages in thread
From: Marek Vasut @ 2011-09-12  4:06 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Heiko Schocher <hs@denx.de>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 drivers/i2c/Makefile  |    1 +
 drivers/i2c/mxs_i2c.c |  240 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 241 insertions(+), 0 deletions(-)
 create mode 100644 drivers/i2c/mxs_i2c.c

diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index a48047a..2fb521e 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -31,6 +31,7 @@ COBJS-$(CONFIG_FSL_I2C) += fsl_i2c.o
 COBJS-$(CONFIG_I2C_MVTWSI) += mvtwsi.o
 COBJS-$(CONFIG_I2C_MV) += mv_i2c.o
 COBJS-$(CONFIG_I2C_MXC) += mxc_i2c.o
+COBJS-$(CONFIG_I2C_MXS) += mxs_i2c.o
 COBJS-$(CONFIG_DRIVER_OMAP1510_I2C) += omap1510_i2c.o
 COBJS-$(CONFIG_DRIVER_OMAP24XX_I2C) += omap24xx_i2c.o
 COBJS-$(CONFIG_DRIVER_OMAP34XX_I2C) += omap24xx_i2c.o
diff --git a/drivers/i2c/mxs_i2c.c b/drivers/i2c/mxs_i2c.c
new file mode 100644
index 0000000..9f380a0
--- /dev/null
+++ b/drivers/i2c/mxs_i2c.c
@@ -0,0 +1,240 @@
+/*
+ * Freescale i.MX28 I2C Driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+
+#define	MXS_I2C_MAX_TIMEOUT	1000000
+
+void mxs_i2c_reset(void)
+{
+	struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE;
+	int ret;
+
+	ret = mx28_reset_block(&i2c_regs->hw_i2c_ctrl0_reg);
+	if (ret) {
+		debug("MXS I2C: Block reset timeout\n");
+		return;
+	}
+
+	writel(I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ | I2C_CTRL1_NO_SLAVE_ACK_IRQ |
+		I2C_CTRL1_EARLY_TERM_IRQ | I2C_CTRL1_MASTER_LOSS_IRQ |
+		I2C_CTRL1_SLAVE_STOP_IRQ | I2C_CTRL1_SLAVE_IRQ,
+		&i2c_regs->hw_i2c_ctrl1_clr);
+
+	writel(I2C_QUEUECTRL_PIO_QUEUE_MODE, &i2c_regs->hw_i2c_queuectrl_set);
+}
+
+void mxs_i2c_setup_read(uint8_t chip, int len)
+{
+	struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE;
+
+	writel(I2C_QUEUECMD_RETAIN_CLOCK | I2C_QUEUECMD_PRE_SEND_START |
+		I2C_QUEUECMD_MASTER_MODE | I2C_QUEUECMD_DIRECTION |
+		(1 << I2C_QUEUECMD_XFER_COUNT_OFFSET),
+		&i2c_regs->hw_i2c_queuecmd);
+
+	writel((chip << 1) | 1, &i2c_regs->hw_i2c_data);
+
+	writel(I2C_QUEUECMD_SEND_NAK_ON_LAST | I2C_QUEUECMD_MASTER_MODE |
+		(len << I2C_QUEUECMD_XFER_COUNT_OFFSET) |
+		I2C_QUEUECMD_POST_SEND_STOP, &i2c_regs->hw_i2c_queuecmd);
+
+	writel(I2C_QUEUECTRL_QUEUE_RUN, &i2c_regs->hw_i2c_queuectrl_set);
+}
+
+void mxs_i2c_write(uchar chip, uint addr, int alen,
+			uchar *buf, int blen, int stop)
+{
+	struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE;
+	uint32_t data;
+	int i, remain, off;
+
+	if ((alen > 4) || (alen == 0)) {
+		debug("MXS I2C: Invalid address length\n");
+		return;
+	}
+
+	if (stop)
+		stop = I2C_QUEUECMD_POST_SEND_STOP;
+
+	writel(I2C_QUEUECMD_PRE_SEND_START |
+		I2C_QUEUECMD_MASTER_MODE | I2C_QUEUECMD_DIRECTION |
+		((blen + alen + 1) << I2C_QUEUECMD_XFER_COUNT_OFFSET) | stop,
+		&i2c_regs->hw_i2c_queuecmd);
+
+	data = (chip << 1) << 24;
+
+	for (i = 0; i < alen; i++) {
+		data >>= 8;
+		data |= ((char *)&addr)[i] << 24;
+		if ((i & 3) == 2)
+			writel(data, &i2c_regs->hw_i2c_data);
+	}
+
+	off = i;
+	for (; i < off + blen; i++) {
+		data >>= 8;
+		data |= buf[i - off] << 24;
+		if ((i & 3) == 2)
+			writel(data, &i2c_regs->hw_i2c_data);
+	}
+
+	remain = 24 - ((i & 3) * 8);
+	if (remain)
+		writel(data >> remain, &i2c_regs->hw_i2c_data);
+
+	writel(I2C_QUEUECTRL_QUEUE_RUN, &i2c_regs->hw_i2c_queuectrl_set);
+}
+
+int mxs_i2c_wait_for_ack(void)
+{
+	struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE;
+	uint32_t tmp;
+	int timeout = MXS_I2C_MAX_TIMEOUT;
+
+	for (;;) {
+		tmp = readl(&i2c_regs->hw_i2c_ctrl1);
+		if (tmp & I2C_CTRL1_NO_SLAVE_ACK_IRQ) {
+			debug("MXS I2C: No slave ACK\n");
+			goto err;
+		}
+
+		if (tmp & (
+			I2C_CTRL1_EARLY_TERM_IRQ | I2C_CTRL1_MASTER_LOSS_IRQ |
+			I2C_CTRL1_SLAVE_STOP_IRQ | I2C_CTRL1_SLAVE_IRQ)) {
+			debug("MXS I2C: Error (CTRL1 = %08x)\n", tmp);
+			goto err;
+		}
+
+		if (tmp & I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ)
+			break;
+
+		if (!timeout--) {
+			debug("MXS I2C: Operation timed out\n");
+			goto err;
+		}
+
+		udelay(1);
+	}
+
+	return 0;
+
+err:
+	mxs_i2c_reset();
+	return 1;
+}
+
+int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+	struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE;
+	uint32_t tmp = 0;
+	int ret;
+	int i;
+
+	mxs_i2c_write(chip, addr, alen, NULL, 0, 0);
+	ret = mxs_i2c_wait_for_ack();
+	if (ret) {
+		debug("MXS I2C: Failed writing address\n");
+		return ret;
+	}
+
+	mxs_i2c_setup_read(chip, len);
+	ret = mxs_i2c_wait_for_ack();
+	if (ret) {
+		debug("MXS I2C: Failed reading address\n");
+		return ret;
+	}
+
+	for (i = 0; i < len; i++) {
+		if (!(i & 3)) {
+			while (readl(&i2c_regs->hw_i2c_queuestat) &
+				I2C_QUEUESTAT_RD_QUEUE_EMPTY)
+				;
+			tmp = readl(&i2c_regs->hw_i2c_queuedata);
+		}
+		buffer[i] = tmp & 0xff;
+		tmp >>= 8;
+	}
+
+	return 0;
+}
+
+int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+	int ret;
+	mxs_i2c_write(chip, addr, alen, buffer, len, 1);
+	ret = mxs_i2c_wait_for_ack();
+	if (ret)
+		debug("MXS I2C: Failed writing address\n");
+
+	return ret;
+}
+
+int i2c_probe(uchar chip)
+{
+	int ret;
+	mxs_i2c_write(chip, 0, 1, NULL, 0, 1);
+	ret = mxs_i2c_wait_for_ack();
+	mxs_i2c_reset();
+	return ret;
+}
+
+void i2c_init(int speed, int slaveadd)
+{
+	struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE;
+
+	mxs_i2c_reset();
+
+	switch (speed) {
+	case 100000:
+		writel((0x0078 << I2C_TIMING0_HIGH_COUNT_OFFSET) |
+			(0x0030 << I2C_TIMING0_RCV_COUNT_OFFSET),
+			&i2c_regs->hw_i2c_timing0);
+		writel((0x0080 << I2C_TIMING1_LOW_COUNT_OFFSET) |
+			(0x0030 << I2C_TIMING1_XMIT_COUNT_OFFSET),
+			&i2c_regs->hw_i2c_timing1);
+		break;
+	case 400000:
+		writel((0x000f << I2C_TIMING0_HIGH_COUNT_OFFSET) |
+			(0x0007 << I2C_TIMING0_RCV_COUNT_OFFSET),
+			&i2c_regs->hw_i2c_timing0);
+		writel((0x001f << I2C_TIMING1_LOW_COUNT_OFFSET) |
+			(0x000f << I2C_TIMING1_XMIT_COUNT_OFFSET),
+			&i2c_regs->hw_i2c_timing1);
+		break;
+	default:
+		printf("MXS I2C: Invalid speed selected (%d Hz)\n", speed);
+		return;
+	}
+
+	writel((0x0015 << I2C_TIMING2_BUS_FREE_OFFSET) |
+		(0x000d << I2C_TIMING2_LEADIN_COUNT_OFFSET),
+		&i2c_regs->hw_i2c_timing2);
+
+	return;
+}
-- 
1.7.5.4

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

* [U-Boot] [PATCH 06/15] iMX28: Add GPIO control
  2011-09-12  4:06 [U-Boot] [PATCH 00/15 V2] Support for the DENX M28 SoM Marek Vasut
                   ` (4 preceding siblings ...)
  2011-09-12  4:06 ` [U-Boot] [PATCH 05/15] iMX28: Add I2C bus driver Marek Vasut
@ 2011-09-12  4:06 ` Marek Vasut
  2011-09-14  7:25   ` Stefano Babic
  2011-09-12  4:06 ` [U-Boot] [PATCH 07/15] iMX28: Add SPI driver Marek Vasut
                   ` (9 subsequent siblings)
  15 siblings, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-09-12  4:06 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 arch/arm/cpu/arm926ejs/mx28/mx28.c    |    6 ++
 arch/arm/include/asm/arch-mx28/gpio.h |   32 ++++++++
 drivers/gpio/Makefile                 |    1 +
 drivers/gpio/mxs_gpio.c               |  136 +++++++++++++++++++++++++++++++++
 4 files changed, 175 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-mx28/gpio.h
 create mode 100644 drivers/gpio/mxs_gpio.c

diff --git a/arch/arm/cpu/arm926ejs/mx28/mx28.c b/arch/arm/cpu/arm926ejs/mx28/mx28.c
index 58ac9ae..d53ce99 100644
--- a/arch/arm/cpu/arm926ejs/mx28/mx28.c
+++ b/arch/arm/cpu/arm926ejs/mx28/mx28.c
@@ -31,6 +31,7 @@
 #include <asm/io.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/gpio.h>
+#include <asm/arch/iomux.h>
 #include <asm/arch/imx-regs.h>
 #include <asm/arch/sys_proto.h>
 
@@ -135,6 +136,11 @@ int arch_cpu_init(void)
 
 	udelay(1000);
 
+	/*
+	 * Configure GPIO unit
+	 */
+	mxs_gpio_init();
+
 	return 0;
 }
 #endif
diff --git a/arch/arm/include/asm/arch-mx28/gpio.h b/arch/arm/include/asm/arch-mx28/gpio.h
new file mode 100644
index 0000000..be1c944
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/gpio.h
@@ -0,0 +1,32 @@
+/*
+ * Freescale i.MX28 GPIO
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef	__MX28_GPIO_H__
+#define	__MX28_GPIO_H__
+
+#ifdef	CONFIG_MXS_GPIO
+void mxs_gpio_init(void);
+#else
+inline void mxs_gpio_init(void) {}
+#endif
+
+#endif	/* __MX28_GPIO_H__ */
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 62ec97d..4332418 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -29,6 +29,7 @@ COBJS-$(CONFIG_AT91_GPIO)	+= at91_gpio.o
 COBJS-$(CONFIG_KIRKWOOD_GPIO)	+= kw_gpio.o
 COBJS-$(CONFIG_MARVELL_MFP)	+= mvmfp.o
 COBJS-$(CONFIG_MXC_GPIO)	+= mxc_gpio.o
+COBJS-$(CONFIG_MXS_GPIO)	+= mxs_gpio.o
 COBJS-$(CONFIG_PCA953X)		+= pca953x.o
 COBJS-$(CONFIG_S5P)		+= s5p_gpio.o
 COBJS-$(CONFIG_TEGRA2_GPIO)	+= tegra2_gpio.o
diff --git a/drivers/gpio/mxs_gpio.c b/drivers/gpio/mxs_gpio.c
new file mode 100644
index 0000000..b7e9591
--- /dev/null
+++ b/drivers/gpio/mxs_gpio.c
@@ -0,0 +1,136 @@
+/*
+ * Freescale i.MX28 GPIO control code
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <netdev.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/iomux.h>
+#include <asm/arch/imx-regs.h>
+
+#if	defined(CONFIG_MX23)
+#define	PINCTRL_BANKS		3
+#define	PINCTRL_DOUT(n)		(0x0500 + ((n) * 0x10))
+#define	PINCTRL_DIN(n)		(0x0600 + ((n) * 0x10))
+#define	PINCTRL_DOE(n)		(0x0700 + ((n) * 0x10))
+#define	PINCTRL_PIN2IRQ(n)	(0x0800 + ((n) * 0x10))
+#define	PINCTRL_IRQEN(n)	(0x0900 + ((n) * 0x10))
+#define	PINCTRL_IRQSTAT(n)	(0x0c00 + ((n) * 0x10))
+#elif	defined(CONFIG_MX28)
+#define	PINCTRL_BANKS		5
+#define	PINCTRL_DOUT(n)		(0x0700 + ((n) * 0x10))
+#define	PINCTRL_DIN(n)		(0x0900 + ((n) * 0x10))
+#define	PINCTRL_DOE(n)		(0x0b00 + ((n) * 0x10))
+#define	PINCTRL_PIN2IRQ(n)	(0x1000 + ((n) * 0x10))
+#define	PINCTRL_IRQEN(n)	(0x1100 + ((n) * 0x10))
+#define	PINCTRL_IRQSTAT(n)	(0x1400 + ((n) * 0x10))
+#else
+#error "Please select CONFIG_MX23 or CONFIG_MX28"
+#endif
+
+#define GPIO_INT_FALL_EDGE	0x0
+#define GPIO_INT_LOW_LEV	0x1
+#define GPIO_INT_RISE_EDGE	0x2
+#define GPIO_INT_HIGH_LEV	0x3
+#define GPIO_INT_LEV_MASK	(1 << 0)
+#define GPIO_INT_POL_MASK	(1 << 1)
+
+void mxs_gpio_init(void)
+{
+	int i;
+
+	for (i = 0; i < PINCTRL_BANKS; i++) {
+		writel(0, MXS_PINCTRL_BASE + PINCTRL_PIN2IRQ(i));
+		writel(0, MXS_PINCTRL_BASE + PINCTRL_IRQEN(i));
+		/* Use SCT address here to clear the IRQSTAT bits */
+		writel(0xffffffff, MXS_PINCTRL_BASE + PINCTRL_IRQSTAT(i) + 8);
+	}
+}
+
+int gpio_get_value(int gp)
+{
+	uint32_t bank = PAD_BANK(gp);
+	uint32_t offset = PINCTRL_DIN(bank);
+	struct mx28_register *reg =
+		(struct mx28_register *)(MXS_PINCTRL_BASE + offset);
+
+	return (readl(&reg->reg) >> PAD_PIN(gp)) & 1;
+}
+
+void gpio_set_value(int gp, int value)
+{
+	uint32_t bank = PAD_BANK(gp);
+	uint32_t offset = PINCTRL_DOUT(bank);
+	struct mx28_register *reg =
+		(struct mx28_register *)(MXS_PINCTRL_BASE + offset);
+
+	if (value)
+		writel(1 << PAD_PIN(gp), &reg->reg_set);
+	else
+		writel(1 << PAD_PIN(gp), &reg->reg_clr);
+}
+
+int gpio_direction_input(int gp)
+{
+	uint32_t bank = PAD_BANK(gp);
+	uint32_t offset = PINCTRL_DOE(bank);
+	struct mx28_register *reg =
+		(struct mx28_register *)(MXS_PINCTRL_BASE + offset);
+
+	writel(1 << PAD_PIN(gp), &reg->reg_clr);
+
+	return 0;
+}
+
+int gpio_direction_output(int gp, int value)
+{
+	uint32_t bank = PAD_BANK(gp);
+	uint32_t offset = PINCTRL_DOE(bank);
+	struct mx28_register *reg =
+		(struct mx28_register *)(MXS_PINCTRL_BASE + offset);
+
+	writel(1 << PAD_PIN(gp), &reg->reg_set);
+
+	gpio_set_value(gp, value);
+
+	return 0;
+}
+
+int gpio_request(int gp, const char *label)
+{
+	if (PAD_BANK(gp) > PINCTRL_BANKS)
+		return -EINVAL;
+
+	return 0;
+}
+
+void gpio_free(int gp)
+{
+}
+
+void gpio_toggle_value(int gp)
+{
+	gpio_set_value(gp, !gpio_get_value(gp));
+}
-- 
1.7.5.4

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

* [U-Boot] [PATCH 07/15] iMX28: Add SPI driver
  2011-09-12  4:06 [U-Boot] [PATCH 00/15 V2] Support for the DENX M28 SoM Marek Vasut
                   ` (5 preceding siblings ...)
  2011-09-12  4:06 ` [U-Boot] [PATCH 06/15] iMX28: Add GPIO control Marek Vasut
@ 2011-09-12  4:06 ` Marek Vasut
  2011-09-12 16:35   ` Mike Frysinger
  2011-09-13 22:26   ` [U-Boot] [PATCH 07/15 V2] " Marek Vasut
  2011-09-12  4:06 ` [U-Boot] [PATCH 08/15] iMX28: Add APBH DMA driver Marek Vasut
                   ` (8 subsequent siblings)
  15 siblings, 2 replies; 116+ messages in thread
From: Marek Vasut @ 2011-09-12  4:06 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 drivers/spi/Makefile  |    1 +
 drivers/spi/mxs_spi.c |  172 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 173 insertions(+), 0 deletions(-)
 create mode 100644 drivers/spi/mxs_spi.c

diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 96c9642..9a0c475 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -36,6 +36,7 @@ COBJS-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
 COBJS-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o
 COBJS-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
 COBJS-$(CONFIG_MXC_SPI) += mxc_spi.o
+COBJS-$(CONFIG_MXS_SPI) += mxs_spi.o
 COBJS-$(CONFIG_OC_TINY_SPI) += oc_tiny_spi.o
 COBJS-$(CONFIG_OMAP3_SPI) += omap3_spi.o
 COBJS-$(CONFIG_SOFT_SPI) += soft_spi.o
diff --git a/drivers/spi/mxs_spi.c b/drivers/spi/mxs_spi.c
new file mode 100644
index 0000000..f0d60d7
--- /dev/null
+++ b/drivers/spi/mxs_spi.c
@@ -0,0 +1,172 @@
+/*
+ * Freescale i.MX28 SPI driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * NOTE: This driver only supports the SPI-controller chipselects,
+ *       GPIO driven chipselects are not supported.
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+
+#define	MXS_SPI_MAX_TIMEOUT	1000000
+
+static inline struct mx28_ssp_regs *to_mxs_regs(struct spi_slave *slave)
+{
+	return (struct mx28_ssp_regs *)(MXS_SSP0_BASE + (slave->bus * 0x2000));
+}
+
+void spi_init(void)
+{
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+				  unsigned int max_hz, unsigned int mode)
+{
+	struct spi_slave *slave;
+	struct mx28_ssp_regs *ssp_regs;
+	uint32_t reg = 0;
+
+	if (bus > 3) {
+		printf("MXS SPI: Max bus number is 3\n");
+		return NULL;
+	}
+
+	slave = malloc(sizeof(struct spi_slave));
+	if (!slave)
+		return NULL;
+
+	slave->bus = bus;
+	slave->cs = cs;
+
+	ssp_regs = to_mxs_regs(slave);
+
+	mx28_reset_block(&ssp_regs->hw_ssp_ctrl0_reg);
+
+	writel(SSP_CTRL0_BUS_WIDTH_ONE_BIT, &ssp_regs->hw_ssp_ctrl0);
+
+	reg = SSP_CTRL1_SSP_MODE_SPI | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS;
+	reg |= (mode & SPI_CPOL) ? SSP_CTRL1_POLARITY : 0;
+	reg |= (mode & SPI_CPHA) ? SSP_CTRL1_PHASE : 0;
+	writel(reg, &ssp_regs->hw_ssp_ctrl1);
+
+	writel(0, &ssp_regs->hw_ssp_cmd0);
+
+	mx28_set_ssp_busclock(bus, max_hz / 1000);
+
+	return slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+	free(slave);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+	return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+}
+
+void mxs_spi_start_xfer(struct spi_slave *slave)
+{
+	struct mx28_ssp_regs *ssp_regs = to_mxs_regs(slave);
+	writel(SSP_CTRL0_LOCK_CS, &ssp_regs->hw_ssp_ctrl0_set);
+	writel(SSP_CTRL0_IGNORE_CRC, &ssp_regs->hw_ssp_ctrl0_clr);
+}
+
+void mxs_spi_end_xfer(struct spi_slave *slave)
+{
+	struct mx28_ssp_regs *ssp_regs = to_mxs_regs(slave);
+	writel(SSP_CTRL0_LOCK_CS, &ssp_regs->hw_ssp_ctrl0_clr);
+	writel(SSP_CTRL0_IGNORE_CRC, &ssp_regs->hw_ssp_ctrl0_set);
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+		const void *dout, void *din, unsigned long flags)
+{
+	struct mx28_ssp_regs *ssp_regs = to_mxs_regs(slave);
+	int len = bitlen / 8;
+	const char *tx = dout;
+	char *rx = din;
+
+	if (bitlen == 0)
+		return 0;
+
+	if (!rx && !tx)
+		return 0;
+
+	if (flags & SPI_XFER_BEGIN)
+		mxs_spi_start_xfer(slave);
+
+	while (len--) {
+		/* We transfer 1 byte */
+		writel(1, &ssp_regs->hw_ssp_xfer_size);
+
+		if ((flags & SPI_XFER_END) && !len)
+			mxs_spi_end_xfer(slave);
+
+		if (tx)
+			writel(SSP_CTRL0_READ, &ssp_regs->hw_ssp_ctrl0_clr);
+		else
+			writel(SSP_CTRL0_READ, &ssp_regs->hw_ssp_ctrl0_set);
+
+		writel(SSP_CTRL0_RUN, &ssp_regs->hw_ssp_ctrl0_set);
+
+		if (mx28_wait_mask_set(&ssp_regs->hw_ssp_ctrl0_reg,
+			SSP_CTRL0_RUN, MXS_SPI_MAX_TIMEOUT)) {
+			printf("MXS SPI: Timeout waiting for start\n");
+			return -1;
+		}
+
+		if (tx)
+			writel(*tx++, &ssp_regs->hw_ssp_data);
+
+		writel(SSP_CTRL0_DATA_XFER, &ssp_regs->hw_ssp_ctrl0_set);
+
+		if (rx) {
+			if (mx28_wait_mask_clr(&ssp_regs->hw_ssp_status_reg,
+				SSP_STATUS_FIFO_EMPTY, MXS_SPI_MAX_TIMEOUT)) {
+				printf("MXS SPI: Timeout waiting for data\n");
+				return -1;
+			}
+
+			*rx = readl(&ssp_regs->hw_ssp_data);
+			rx++;
+		}
+
+		if (mx28_wait_mask_clr(&ssp_regs->hw_ssp_ctrl0_reg,
+			SSP_CTRL0_RUN, MXS_SPI_MAX_TIMEOUT)) {
+			printf("MXS SPI: Timeout waiting for finish\n");
+			return -1;
+		}
+	}
+
+	return 0;
+}
-- 
1.7.5.4

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

* [U-Boot] [PATCH 08/15] iMX28: Add APBH DMA driver
  2011-09-12  4:06 [U-Boot] [PATCH 00/15 V2] Support for the DENX M28 SoM Marek Vasut
                   ` (6 preceding siblings ...)
  2011-09-12  4:06 ` [U-Boot] [PATCH 07/15] iMX28: Add SPI driver Marek Vasut
@ 2011-09-12  4:06 ` Marek Vasut
  2011-09-12  4:06 ` [U-Boot] [PATCH 09/15] iMX28: Add GPMI NAND driver Marek Vasut
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-09-12  4:06 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 arch/arm/include/asm/arch-mx28/dma.h       |  170 +++++++
 arch/arm/include/asm/arch-mx28/imx-regs.h  |    1 +
 arch/arm/include/asm/arch-mx28/regs-apbh.h |  466 +++++++++++++++++++
 drivers/dma/Makefile                       |    1 +
 drivers/dma/apbh_dma.c                     |  691 ++++++++++++++++++++++++++++
 5 files changed, 1329 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-mx28/dma.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-apbh.h
 create mode 100644 drivers/dma/apbh_dma.c

diff --git a/arch/arm/include/asm/arch-mx28/dma.h b/arch/arm/include/asm/arch-mx28/dma.h
new file mode 100644
index 0000000..7061e7c
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/dma.h
@@ -0,0 +1,170 @@
+/*
+ * Freescale i.MX28 APBH DMA
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __DMA_H__
+#define __DMA_H__
+
+#include <linux/list.h>
+
+#ifndef	CONFIG_ARCH_DMA_PIO_WORDS
+#define	DMA_PIO_WORDS		15
+#else
+#define	DMA_PIO_WORDS		CONFIG_ARCH_DMA_PIO_WORDS
+#endif
+
+#define MXS_DMA_ALIGNMENT	32
+
+/*
+ * MXS DMA channels
+ */
+enum {
+	MXS_DMA_CHANNEL_AHB_APBH_SSP0 = 0,
+	MXS_DMA_CHANNEL_AHB_APBH_SSP1,
+	MXS_DMA_CHANNEL_AHB_APBH_SSP2,
+	MXS_DMA_CHANNEL_AHB_APBH_SSP3,
+	MXS_DMA_CHANNEL_AHB_APBH_GPMI0,
+	MXS_DMA_CHANNEL_AHB_APBH_GPMI1,
+	MXS_DMA_CHANNEL_AHB_APBH_GPMI2,
+	MXS_DMA_CHANNEL_AHB_APBH_GPMI3,
+	MXS_DMA_CHANNEL_AHB_APBH_GPMI4,
+	MXS_DMA_CHANNEL_AHB_APBH_GPMI5,
+	MXS_DMA_CHANNEL_AHB_APBH_GPMI6,
+	MXS_DMA_CHANNEL_AHB_APBH_GPMI7,
+	MXS_DMA_CHANNEL_AHB_APBH_SSP,
+	MXS_MAX_DMA_CHANNELS,
+};
+
+/*
+ * MXS DMA hardware command.
+ *
+ * This structure describes the in-memory layout of an entire DMA command,
+ * including space for the maximum number of PIO accesses. See the appropriate
+ * reference manual for a detailed description of what these fields mean to the
+ * DMA hardware.
+ */
+#define	MXS_DMA_DESC_COMMAND_MASK	0x3
+#define	MXS_DMA_DESC_COMMAND_OFFSET	0
+#define	MXS_DMA_DESC_COMMAND_NO_DMAXFER	0x0
+#define	MXS_DMA_DESC_COMMAND_DMA_WRITE	0x1
+#define	MXS_DMA_DESC_COMMAND_DMA_READ	0x2
+#define	MXS_DMA_DESC_COMMAND_DMA_SENSE	0x3
+#define	MXS_DMA_DESC_CHAIN		(1 << 2)
+#define	MXS_DMA_DESC_IRQ		(1 << 3)
+#define	MXS_DMA_DESC_NAND_LOCK		(1 << 4)
+#define	MXS_DMA_DESC_NAND_WAIT_4_READY	(1 << 5)
+#define	MXS_DMA_DESC_DEC_SEM		(1 << 6)
+#define	MXS_DMA_DESC_WAIT4END		(1 << 7)
+#define	MXS_DMA_DESC_HALT_ON_TERMINATE	(1 << 8)
+#define	MXS_DMA_DESC_TERMINATE_FLUSH	(1 << 9)
+#define	MXS_DMA_DESC_PIO_WORDS_MASK	(0xf << 12)
+#define	MXS_DMA_DESC_PIO_WORDS_OFFSET	12
+#define	MXS_DMA_DESC_BYTES_MASK		(0xffff << 16)
+#define	MXS_DMA_DESC_BYTES_OFFSET	16
+
+struct mxs_dma_cmd {
+	unsigned long		next;
+	unsigned long		data;
+	union {
+		dma_addr_t	address;
+		unsigned long	alternate;
+	};
+	unsigned long		pio_words[DMA_PIO_WORDS];
+};
+
+/*
+ * MXS DMA command descriptor.
+ *
+ * This structure incorporates an MXS DMA hardware command structure, along
+ * with metadata.
+ */
+#define	MXS_DMA_DESC_FIRST	(1 << 0)
+#define	MXS_DMA_DESC_LAST	(1 << 1)
+#define	MXS_DMA_DESC_READY	(1 << 31)
+
+struct mxs_dma_desc {
+	struct mxs_dma_cmd	cmd;
+	unsigned int		flags;
+	dma_addr_t		address;
+	void			*buffer;
+	struct list_head	node;
+};
+
+/**
+ * MXS DMA channel
+ *
+ * This structure represents a single DMA channel. The MXS platform code
+ * maintains an array of these structures to represent every DMA channel in the
+ * system (see mxs_dma_channels).
+ */
+#define	MXS_DMA_FLAGS_IDLE	0
+#define	MXS_DMA_FLAGS_BUSY	(1 << 0)
+#define	MXS_DMA_FLAGS_FREE	0
+#define	MXS_DMA_FLAGS_ALLOCATED	(1 << 16)
+#define	MXS_DMA_FLAGS_VALID	(1 << 31)
+
+struct mxs_dma_chan {
+	const char *name;
+	unsigned long dev;
+	struct mxs_dma_device *dma;
+	unsigned int flags;
+	unsigned int active_num;
+	unsigned int pending_num;
+	struct list_head active;
+	struct list_head done;
+};
+
+/* Hardware management ops */
+int mxs_dma_enable(int channel);
+int mxs_dma_disable(int channel);
+int mxs_dma_reset(int channel);
+int mxs_dma_freeze(int channel);
+int mxs_dma_unfreeze(int channel);
+int mxs_dma_read_semaphore(int channel);
+int mxs_dma_enable_irq(int channel, int enable);
+int mxs_dma_irq_is_pending(int channel);
+int mxs_dma_ack_irq(int channel);
+
+/* Channel management ops */
+int mxs_dma_request(int channel);
+int mxs_dma_release(int channel);
+
+/* Descriptor management ops */
+struct mxs_dma_desc *mxs_dma_desc_alloc(void);
+void mxs_dma_desc_free(struct mxs_dma_desc *);
+
+unsigned int mxs_dma_cmd_address(struct mxs_dma_desc *desc);
+int mxs_dma_desc_pending(struct mxs_dma_desc *pdesc);
+
+int mxs_dma_desc_append(int channel, struct mxs_dma_desc *pdesc);
+
+int mxs_dma_get_finished(int channel, struct list_head *head);
+int mxs_dma_finish(int channel, struct list_head *head);
+
+int mxs_dma_wait_complete(uint32_t timeout, unsigned int chan);
+int mxs_dma_go(int chan);
+
+int mxs_dma_init(void);
+
+#endif	/* __DMA_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/imx-regs.h b/arch/arm/include/asm/arch-mx28/imx-regs.h
index 32bfd7e..9561b5e 100644
--- a/arch/arm/include/asm/arch-mx28/imx-regs.h
+++ b/arch/arm/include/asm/arch-mx28/imx-regs.h
@@ -23,6 +23,7 @@
 #ifndef __IMX_REGS_H__
 #define __IMX_REGS_H__
 
+#include <asm/arch/regs-apbh.h>
 #include <asm/arch/regs-base.h>
 #include <asm/arch/regs-bch.h>
 #include <asm/arch/regs-clkctrl.h>
diff --git a/arch/arm/include/asm/arch-mx28/regs-apbh.h b/arch/arm/include/asm/arch-mx28/regs-apbh.h
new file mode 100644
index 0000000..a7fa1ec
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-apbh.h
@@ -0,0 +1,466 @@
+/*
+ * Freescale i.MX28 APBH Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __REGS_APBH_H__
+#define __REGS_APBH_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_apbh_regs {
+	mx28_reg(hw_apbh_ctrl0)
+	mx28_reg(hw_apbh_ctrl1)
+	mx28_reg(hw_apbh_ctrl2)
+	mx28_reg(hw_apbh_channel_ctrl)
+	mx28_reg(hw_apbh_devsel)
+	mx28_reg(hw_apbh_dma_burst_size)
+	mx28_reg(hw_apbh_debug)
+
+	uint32_t	reserved[36];
+
+	union {
+	struct {
+		mx28_reg(hw_apbh_ch_curcmdar)
+		mx28_reg(hw_apbh_ch_nxtcmdar)
+		mx28_reg(hw_apbh_ch_cmd)
+		mx28_reg(hw_apbh_ch_bar)
+		mx28_reg(hw_apbh_ch_sema)
+		mx28_reg(hw_apbh_ch_debug1)
+		mx28_reg(hw_apbh_ch_debug2)
+	} ch[16];
+	struct {
+		mx28_reg(hw_apbh_ch0_curcmdar)
+		mx28_reg(hw_apbh_ch0_nxtcmdar)
+		mx28_reg(hw_apbh_ch0_cmd)
+		mx28_reg(hw_apbh_ch0_bar)
+		mx28_reg(hw_apbh_ch0_sema)
+		mx28_reg(hw_apbh_ch0_debug1)
+		mx28_reg(hw_apbh_ch0_debug2)
+		mx28_reg(hw_apbh_ch1_curcmdar)
+		mx28_reg(hw_apbh_ch1_nxtcmdar)
+		mx28_reg(hw_apbh_ch1_cmd)
+		mx28_reg(hw_apbh_ch1_bar)
+		mx28_reg(hw_apbh_ch1_sema)
+		mx28_reg(hw_apbh_ch1_debug1)
+		mx28_reg(hw_apbh_ch1_debug2)
+		mx28_reg(hw_apbh_ch2_curcmdar)
+		mx28_reg(hw_apbh_ch2_nxtcmdar)
+		mx28_reg(hw_apbh_ch2_cmd)
+		mx28_reg(hw_apbh_ch2_bar)
+		mx28_reg(hw_apbh_ch2_sema)
+		mx28_reg(hw_apbh_ch2_debug1)
+		mx28_reg(hw_apbh_ch2_debug2)
+		mx28_reg(hw_apbh_ch3_curcmdar)
+		mx28_reg(hw_apbh_ch3_nxtcmdar)
+		mx28_reg(hw_apbh_ch3_cmd)
+		mx28_reg(hw_apbh_ch3_bar)
+		mx28_reg(hw_apbh_ch3_sema)
+		mx28_reg(hw_apbh_ch3_debug1)
+		mx28_reg(hw_apbh_ch3_debug2)
+		mx28_reg(hw_apbh_ch4_curcmdar)
+		mx28_reg(hw_apbh_ch4_nxtcmdar)
+		mx28_reg(hw_apbh_ch4_cmd)
+		mx28_reg(hw_apbh_ch4_bar)
+		mx28_reg(hw_apbh_ch4_sema)
+		mx28_reg(hw_apbh_ch4_debug1)
+		mx28_reg(hw_apbh_ch4_debug2)
+		mx28_reg(hw_apbh_ch5_curcmdar)
+		mx28_reg(hw_apbh_ch5_nxtcmdar)
+		mx28_reg(hw_apbh_ch5_cmd)
+		mx28_reg(hw_apbh_ch5_bar)
+		mx28_reg(hw_apbh_ch5_sema)
+		mx28_reg(hw_apbh_ch5_debug1)
+		mx28_reg(hw_apbh_ch5_debug2)
+		mx28_reg(hw_apbh_ch6_curcmdar)
+		mx28_reg(hw_apbh_ch6_nxtcmdar)
+		mx28_reg(hw_apbh_ch6_cmd)
+		mx28_reg(hw_apbh_ch6_bar)
+		mx28_reg(hw_apbh_ch6_sema)
+		mx28_reg(hw_apbh_ch6_debug1)
+		mx28_reg(hw_apbh_ch6_debug2)
+		mx28_reg(hw_apbh_ch7_curcmdar)
+		mx28_reg(hw_apbh_ch7_nxtcmdar)
+		mx28_reg(hw_apbh_ch7_cmd)
+		mx28_reg(hw_apbh_ch7_bar)
+		mx28_reg(hw_apbh_ch7_sema)
+		mx28_reg(hw_apbh_ch7_debug1)
+		mx28_reg(hw_apbh_ch7_debug2)
+		mx28_reg(hw_apbh_ch8_curcmdar)
+		mx28_reg(hw_apbh_ch8_nxtcmdar)
+		mx28_reg(hw_apbh_ch8_cmd)
+		mx28_reg(hw_apbh_ch8_bar)
+		mx28_reg(hw_apbh_ch8_sema)
+		mx28_reg(hw_apbh_ch8_debug1)
+		mx28_reg(hw_apbh_ch8_debug2)
+		mx28_reg(hw_apbh_ch9_curcmdar)
+		mx28_reg(hw_apbh_ch9_nxtcmdar)
+		mx28_reg(hw_apbh_ch9_cmd)
+		mx28_reg(hw_apbh_ch9_bar)
+		mx28_reg(hw_apbh_ch9_sema)
+		mx28_reg(hw_apbh_ch9_debug1)
+		mx28_reg(hw_apbh_ch9_debug2)
+		mx28_reg(hw_apbh_ch10_curcmdar)
+		mx28_reg(hw_apbh_ch10_nxtcmdar)
+		mx28_reg(hw_apbh_ch10_cmd)
+		mx28_reg(hw_apbh_ch10_bar)
+		mx28_reg(hw_apbh_ch10_sema)
+		mx28_reg(hw_apbh_ch10_debug1)
+		mx28_reg(hw_apbh_ch10_debug2)
+		mx28_reg(hw_apbh_ch11_curcmdar)
+		mx28_reg(hw_apbh_ch11_nxtcmdar)
+		mx28_reg(hw_apbh_ch11_cmd)
+		mx28_reg(hw_apbh_ch11_bar)
+		mx28_reg(hw_apbh_ch11_sema)
+		mx28_reg(hw_apbh_ch11_debug1)
+		mx28_reg(hw_apbh_ch11_debug2)
+		mx28_reg(hw_apbh_ch12_curcmdar)
+		mx28_reg(hw_apbh_ch12_nxtcmdar)
+		mx28_reg(hw_apbh_ch12_cmd)
+		mx28_reg(hw_apbh_ch12_bar)
+		mx28_reg(hw_apbh_ch12_sema)
+		mx28_reg(hw_apbh_ch12_debug1)
+		mx28_reg(hw_apbh_ch12_debug2)
+		mx28_reg(hw_apbh_ch13_curcmdar)
+		mx28_reg(hw_apbh_ch13_nxtcmdar)
+		mx28_reg(hw_apbh_ch13_cmd)
+		mx28_reg(hw_apbh_ch13_bar)
+		mx28_reg(hw_apbh_ch13_sema)
+		mx28_reg(hw_apbh_ch13_debug1)
+		mx28_reg(hw_apbh_ch13_debug2)
+		mx28_reg(hw_apbh_ch14_curcmdar)
+		mx28_reg(hw_apbh_ch14_nxtcmdar)
+		mx28_reg(hw_apbh_ch14_cmd)
+		mx28_reg(hw_apbh_ch14_bar)
+		mx28_reg(hw_apbh_ch14_sema)
+		mx28_reg(hw_apbh_ch14_debug1)
+		mx28_reg(hw_apbh_ch14_debug2)
+		mx28_reg(hw_apbh_ch15_curcmdar)
+		mx28_reg(hw_apbh_ch15_nxtcmdar)
+		mx28_reg(hw_apbh_ch15_cmd)
+		mx28_reg(hw_apbh_ch15_bar)
+		mx28_reg(hw_apbh_ch15_sema)
+		mx28_reg(hw_apbh_ch15_debug1)
+		mx28_reg(hw_apbh_ch15_debug2)
+	};
+	};
+	mx28_reg(hw_apbh_version)
+};
+#endif
+
+#define	APBH_CTRL0_SFTRST				(1 << 31)
+#define	APBH_CTRL0_CLKGATE				(1 << 30)
+#define	APBH_CTRL0_AHB_BURST8_EN			(1 << 29)
+#define	APBH_CTRL0_APB_BURST_EN				(1 << 28)
+#define	APBH_CTRL0_RSVD0_MASK				(0xfff << 16)
+#define	APBH_CTRL0_RSVD0_OFFSET				16
+#define	APBH_CTRL0_CLKGATE_CHANNEL_MASK			0xffff
+#define	APBH_CTRL0_CLKGATE_CHANNEL_OFFSET		0
+#define	APBH_CTRL0_CLKGATE_CHANNEL_SSP0			0x0001
+#define	APBH_CTRL0_CLKGATE_CHANNEL_SSP1			0x0002
+#define	APBH_CTRL0_CLKGATE_CHANNEL_SSP2			0x0004
+#define	APBH_CTRL0_CLKGATE_CHANNEL_SSP3			0x0008
+#define	APBH_CTRL0_CLKGATE_CHANNEL_NAND0		0x0010
+#define	APBH_CTRL0_CLKGATE_CHANNEL_NAND1		0x0020
+#define	APBH_CTRL0_CLKGATE_CHANNEL_NAND2		0x0040
+#define	APBH_CTRL0_CLKGATE_CHANNEL_NAND3		0x0080
+#define	APBH_CTRL0_CLKGATE_CHANNEL_NAND4		0x0100
+#define	APBH_CTRL0_CLKGATE_CHANNEL_NAND5		0x0200
+#define	APBH_CTRL0_CLKGATE_CHANNEL_NAND6		0x0400
+#define	APBH_CTRL0_CLKGATE_CHANNEL_NAND7		0x0800
+#define	APBH_CTRL0_CLKGATE_CHANNEL_HSADC		0x1000
+#define	APBH_CTRL0_CLKGATE_CHANNEL_LCDIF		0x2000
+
+#define	APBH_CTRL1_CH15_CMDCMPLT_IRQ_EN			(1 << 31)
+#define	APBH_CTRL1_CH14_CMDCMPLT_IRQ_EN			(1 << 30)
+#define	APBH_CTRL1_CH13_CMDCMPLT_IRQ_EN			(1 << 29)
+#define	APBH_CTRL1_CH12_CMDCMPLT_IRQ_EN			(1 << 28)
+#define	APBH_CTRL1_CH11_CMDCMPLT_IRQ_EN			(1 << 27)
+#define	APBH_CTRL1_CH10_CMDCMPLT_IRQ_EN			(1 << 26)
+#define	APBH_CTRL1_CH9_CMDCMPLT_IRQ_EN			(1 << 25)
+#define	APBH_CTRL1_CH8_CMDCMPLT_IRQ_EN			(1 << 24)
+#define	APBH_CTRL1_CH7_CMDCMPLT_IRQ_EN			(1 << 23)
+#define	APBH_CTRL1_CH6_CMDCMPLT_IRQ_EN			(1 << 22)
+#define	APBH_CTRL1_CH5_CMDCMPLT_IRQ_EN			(1 << 21)
+#define	APBH_CTRL1_CH4_CMDCMPLT_IRQ_EN			(1 << 20)
+#define	APBH_CTRL1_CH3_CMDCMPLT_IRQ_EN			(1 << 19)
+#define	APBH_CTRL1_CH2_CMDCMPLT_IRQ_EN			(1 << 18)
+#define	APBH_CTRL1_CH1_CMDCMPLT_IRQ_EN			(1 << 17)
+#define	APBH_CTRL1_CH0_CMDCMPLT_IRQ_EN			(1 << 16)
+#define	APBH_CTRL1_CH_CMDCMPLT_IRQ_EN_OFFSET		16
+#define	APBH_CTRL1_CH_CMDCMPLT_IRQ_EN_MASK		(0xffff << 16)
+#define	APBH_CTRL1_CH15_CMDCMPLT_IRQ			(1 << 15)
+#define	APBH_CTRL1_CH14_CMDCMPLT_IRQ			(1 << 14)
+#define	APBH_CTRL1_CH13_CMDCMPLT_IRQ			(1 << 13)
+#define	APBH_CTRL1_CH12_CMDCMPLT_IRQ			(1 << 12)
+#define	APBH_CTRL1_CH11_CMDCMPLT_IRQ			(1 << 11)
+#define	APBH_CTRL1_CH10_CMDCMPLT_IRQ			(1 << 10)
+#define	APBH_CTRL1_CH9_CMDCMPLT_IRQ			(1 << 9)
+#define	APBH_CTRL1_CH8_CMDCMPLT_IRQ			(1 << 8)
+#define	APBH_CTRL1_CH7_CMDCMPLT_IRQ			(1 << 7)
+#define	APBH_CTRL1_CH6_CMDCMPLT_IRQ			(1 << 6)
+#define	APBH_CTRL1_CH5_CMDCMPLT_IRQ			(1 << 5)
+#define	APBH_CTRL1_CH4_CMDCMPLT_IRQ			(1 << 4)
+#define	APBH_CTRL1_CH3_CMDCMPLT_IRQ			(1 << 3)
+#define	APBH_CTRL1_CH2_CMDCMPLT_IRQ			(1 << 2)
+#define	APBH_CTRL1_CH1_CMDCMPLT_IRQ			(1 << 1)
+#define	APBH_CTRL1_CH0_CMDCMPLT_IRQ			(1 << 0)
+
+#define	APBH_CTRL2_CH15_ERROR_STATUS			(1 << 31)
+#define	APBH_CTRL2_CH14_ERROR_STATUS			(1 << 30)
+#define	APBH_CTRL2_CH13_ERROR_STATUS			(1 << 29)
+#define	APBH_CTRL2_CH12_ERROR_STATUS			(1 << 28)
+#define	APBH_CTRL2_CH11_ERROR_STATUS			(1 << 27)
+#define	APBH_CTRL2_CH10_ERROR_STATUS			(1 << 26)
+#define	APBH_CTRL2_CH9_ERROR_STATUS			(1 << 25)
+#define	APBH_CTRL2_CH8_ERROR_STATUS			(1 << 24)
+#define	APBH_CTRL2_CH7_ERROR_STATUS			(1 << 23)
+#define	APBH_CTRL2_CH6_ERROR_STATUS			(1 << 22)
+#define	APBH_CTRL2_CH5_ERROR_STATUS			(1 << 21)
+#define	APBH_CTRL2_CH4_ERROR_STATUS			(1 << 20)
+#define	APBH_CTRL2_CH3_ERROR_STATUS			(1 << 19)
+#define	APBH_CTRL2_CH2_ERROR_STATUS			(1 << 18)
+#define	APBH_CTRL2_CH1_ERROR_STATUS			(1 << 17)
+#define	APBH_CTRL2_CH0_ERROR_STATUS			(1 << 16)
+#define	APBH_CTRL2_CH15_ERROR_IRQ			(1 << 15)
+#define	APBH_CTRL2_CH14_ERROR_IRQ			(1 << 14)
+#define	APBH_CTRL2_CH13_ERROR_IRQ			(1 << 13)
+#define	APBH_CTRL2_CH12_ERROR_IRQ			(1 << 12)
+#define	APBH_CTRL2_CH11_ERROR_IRQ			(1 << 11)
+#define	APBH_CTRL2_CH10_ERROR_IRQ			(1 << 10)
+#define	APBH_CTRL2_CH9_ERROR_IRQ			(1 << 9)
+#define	APBH_CTRL2_CH8_ERROR_IRQ			(1 << 8)
+#define	APBH_CTRL2_CH7_ERROR_IRQ			(1 << 7)
+#define	APBH_CTRL2_CH6_ERROR_IRQ			(1 << 6)
+#define	APBH_CTRL2_CH5_ERROR_IRQ			(1 << 5)
+#define	APBH_CTRL2_CH4_ERROR_IRQ			(1 << 4)
+#define	APBH_CTRL2_CH3_ERROR_IRQ			(1 << 3)
+#define	APBH_CTRL2_CH2_ERROR_IRQ			(1 << 2)
+#define	APBH_CTRL2_CH1_ERROR_IRQ			(1 << 1)
+#define	APBH_CTRL2_CH0_ERROR_IRQ			(1 << 0)
+
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_MASK		(0xffff << 16)
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_OFFSET		16
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_SSP0		(0x0001 << 16)
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_SSP1		(0x0002 << 16)
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_SSP2		(0x0004 << 16)
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_SSP3		(0x0008 << 16)
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_NAND0		(0x0010 << 16)
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_NAND1		(0x0020 << 16)
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_NAND2		(0x0040 << 16)
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_NAND3		(0x0080 << 16)
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_NAND4		(0x0100 << 16)
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_NAND5		(0x0200 << 16)
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_NAND6		(0x0400 << 16)
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_NAND7		(0x0800 << 16)
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_HSADC		(0x1000 << 16)
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_LCDIF		(0x2000 << 16)
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_MASK		0xffff
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_OFFSET		0
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_SSP0		0x0001
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_SSP1		0x0002
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_SSP2		0x0004
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_SSP3		0x0008
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_NAND0		0x0010
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_NAND1		0x0020
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_NAND2		0x0040
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_NAND3		0x0080
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_NAND4		0x0100
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_NAND5		0x0200
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_NAND6		0x0400
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_NAND7		0x0800
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_HSADC		0x1000
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_LCDIF		0x2000
+
+#define	APBH_DEVSEL_CH15_MASK				(0x3 << 30)
+#define	APBH_DEVSEL_CH15_OFFSET				30
+#define	APBH_DEVSEL_CH14_MASK				(0x3 << 28)
+#define	APBH_DEVSEL_CH14_OFFSET				28
+#define	APBH_DEVSEL_CH13_MASK				(0x3 << 26)
+#define	APBH_DEVSEL_CH13_OFFSET				26
+#define	APBH_DEVSEL_CH12_MASK				(0x3 << 24)
+#define	APBH_DEVSEL_CH12_OFFSET				24
+#define	APBH_DEVSEL_CH11_MASK				(0x3 << 22)
+#define	APBH_DEVSEL_CH11_OFFSET				22
+#define	APBH_DEVSEL_CH10_MASK				(0x3 << 20)
+#define	APBH_DEVSEL_CH10_OFFSET				20
+#define	APBH_DEVSEL_CH9_MASK				(0x3 << 18)
+#define	APBH_DEVSEL_CH9_OFFSET				18
+#define	APBH_DEVSEL_CH8_MASK				(0x3 << 16)
+#define	APBH_DEVSEL_CH8_OFFSET				16
+#define	APBH_DEVSEL_CH7_MASK				(0x3 << 14)
+#define	APBH_DEVSEL_CH7_OFFSET				14
+#define	APBH_DEVSEL_CH6_MASK				(0x3 << 12)
+#define	APBH_DEVSEL_CH6_OFFSET				12
+#define	APBH_DEVSEL_CH5_MASK				(0x3 << 10)
+#define	APBH_DEVSEL_CH5_OFFSET				10
+#define	APBH_DEVSEL_CH4_MASK				(0x3 << 8)
+#define	APBH_DEVSEL_CH4_OFFSET				8
+#define	APBH_DEVSEL_CH3_MASK				(0x3 << 6)
+#define	APBH_DEVSEL_CH3_OFFSET				6
+#define	APBH_DEVSEL_CH2_MASK				(0x3 << 4)
+#define	APBH_DEVSEL_CH2_OFFSET				4
+#define	APBH_DEVSEL_CH1_MASK				(0x3 << 2)
+#define	APBH_DEVSEL_CH1_OFFSET				2
+#define	APBH_DEVSEL_CH0_MASK				(0x3 << 0)
+#define	APBH_DEVSEL_CH0_OFFSET				0
+
+#define	APBH_DMA_BURST_SIZE_CH15_MASK			(0x3 << 30)
+#define	APBH_DMA_BURST_SIZE_CH15_OFFSET			30
+#define	APBH_DMA_BURST_SIZE_CH14_MASK			(0x3 << 28)
+#define	APBH_DMA_BURST_SIZE_CH14_OFFSET			28
+#define	APBH_DMA_BURST_SIZE_CH13_MASK			(0x3 << 26)
+#define	APBH_DMA_BURST_SIZE_CH13_OFFSET			26
+#define	APBH_DMA_BURST_SIZE_CH12_MASK			(0x3 << 24)
+#define	APBH_DMA_BURST_SIZE_CH12_OFFSET			24
+#define	APBH_DMA_BURST_SIZE_CH11_MASK			(0x3 << 22)
+#define	APBH_DMA_BURST_SIZE_CH11_OFFSET			22
+#define	APBH_DMA_BURST_SIZE_CH10_MASK			(0x3 << 20)
+#define	APBH_DMA_BURST_SIZE_CH10_OFFSET			20
+#define	APBH_DMA_BURST_SIZE_CH9_MASK			(0x3 << 18)
+#define	APBH_DMA_BURST_SIZE_CH9_OFFSET			18
+#define	APBH_DMA_BURST_SIZE_CH8_MASK			(0x3 << 16)
+#define	APBH_DMA_BURST_SIZE_CH8_OFFSET			16
+#define	APBH_DMA_BURST_SIZE_CH8_BURST0			(0x0 << 16)
+#define	APBH_DMA_BURST_SIZE_CH8_BURST4			(0x1 << 16)
+#define	APBH_DMA_BURST_SIZE_CH8_BURST8			(0x2 << 16)
+#define	APBH_DMA_BURST_SIZE_CH7_MASK			(0x3 << 14)
+#define	APBH_DMA_BURST_SIZE_CH7_OFFSET			14
+#define	APBH_DMA_BURST_SIZE_CH6_MASK			(0x3 << 12)
+#define	APBH_DMA_BURST_SIZE_CH6_OFFSET			12
+#define	APBH_DMA_BURST_SIZE_CH5_MASK			(0x3 << 10)
+#define	APBH_DMA_BURST_SIZE_CH5_OFFSET			10
+#define	APBH_DMA_BURST_SIZE_CH4_MASK			(0x3 << 8)
+#define	APBH_DMA_BURST_SIZE_CH4_OFFSET			8
+#define	APBH_DMA_BURST_SIZE_CH3_MASK			(0x3 << 6)
+#define	APBH_DMA_BURST_SIZE_CH3_OFFSET			6
+#define	APBH_DMA_BURST_SIZE_CH3_BURST0			(0x0 << 6)
+#define	APBH_DMA_BURST_SIZE_CH3_BURST4			(0x1 << 6)
+#define	APBH_DMA_BURST_SIZE_CH3_BURST8			(0x2 << 6)
+
+#define	APBH_DMA_BURST_SIZE_CH2_MASK			(0x3 << 4)
+#define	APBH_DMA_BURST_SIZE_CH2_OFFSET			4
+#define	APBH_DMA_BURST_SIZE_CH2_BURST0			(0x0 << 4)
+#define	APBH_DMA_BURST_SIZE_CH2_BURST4			(0x1 << 4)
+#define	APBH_DMA_BURST_SIZE_CH2_BURST8			(0x2 << 4)
+#define	APBH_DMA_BURST_SIZE_CH1_MASK			(0x3 << 2)
+#define	APBH_DMA_BURST_SIZE_CH1_OFFSET			2
+#define	APBH_DMA_BURST_SIZE_CH1_BURST0			(0x0 << 2)
+#define	APBH_DMA_BURST_SIZE_CH1_BURST4			(0x1 << 2)
+#define	APBH_DMA_BURST_SIZE_CH1_BURST8			(0x2 << 2)
+
+#define	APBH_DMA_BURST_SIZE_CH0_MASK			0x3
+#define	APBH_DMA_BURST_SIZE_CH0_OFFSET			0
+#define	APBH_DMA_BURST_SIZE_CH0_BURST0			0x0
+#define	APBH_DMA_BURST_SIZE_CH0_BURST4			0x1
+#define	APBH_DMA_BURST_SIZE_CH0_BURST8			0x2
+
+#define	APBH_DEBUG_GPMI_ONE_FIFO			(1 << 0)
+
+#define	APBH_CHn_CURCMDAR_CMD_ADDR_MASK			0xffffffff
+#define	APBH_CHn_CURCMDAR_CMD_ADDR_OFFSET		0
+
+#define	APBH_CHn_NXTCMDAR_CMD_ADDR_MASK			0xffffffff
+#define	APBH_CHn_NXTCMDAR_CMD_ADDR_OFFSET		0
+
+#define	APBH_CHn_CMD_XFER_COUNT_MASK			(0xffff << 16)
+#define	APBH_CHn_CMD_XFER_COUNT_OFFSET			16
+#define	APBH_CHn_CMD_CMDWORDS_MASK			(0xf << 12)
+#define	APBH_CHn_CMD_CMDWORDS_OFFSET			12
+#define	APBH_CHn_CMD_HALTONTERMINATE			(1 << 8)
+#define	APBH_CHn_CMD_WAIT4ENDCMD			(1 << 7)
+#define	APBH_CHn_CMD_SEMAPHORE				(1 << 6)
+#define	APBH_CHn_CMD_NANDWAIT4READY			(1 << 5)
+#define	APBH_CHn_CMD_NANDLOCK				(1 << 4)
+#define	APBH_CHn_CMD_IRQONCMPLT				(1 << 3)
+#define	APBH_CHn_CMD_CHAIN				(1 << 2)
+#define	APBH_CHn_CMD_COMMAND_MASK			0x3
+#define	APBH_CHn_CMD_COMMAND_OFFSET			0
+#define	APBH_CHn_CMD_COMMAND_NO_DMA_XFER		0x0
+#define	APBH_CHn_CMD_COMMAND_DMA_WRITE			0x1
+#define	APBH_CHn_CMD_COMMAND_DMA_READ			0x2
+#define	APBH_CHn_CMD_COMMAND_DMA_SENSE			0x3
+
+#define	APBH_CHn_BAR_ADDRESS_MASK			0xffffffff
+#define	APBH_CHn_BAR_ADDRESS_OFFSET			0
+
+#define	APBH_CHn_SEMA_RSVD2_MASK			(0xff << 24)
+#define	APBH_CHn_SEMA_RSVD2_OFFSET			24
+#define	APBH_CHn_SEMA_PHORE_MASK			(0xff << 16)
+#define	APBH_CHn_SEMA_PHORE_OFFSET			16
+#define	APBH_CHn_SEMA_RSVD1_MASK			(0xff << 8)
+#define	APBH_CHn_SEMA_RSVD1_OFFSET			8
+#define	APBH_CHn_SEMA_INCREMENT_SEMA_MASK		(0xff << 0)
+#define	APBH_CHn_SEMA_INCREMENT_SEMA_OFFSET		0
+
+#define	APBH_CHn_DEBUG1_REQ				(1 << 31)
+#define	APBH_CHn_DEBUG1_BURST				(1 << 30)
+#define	APBH_CHn_DEBUG1_KICK				(1 << 29)
+#define	APBH_CHn_DEBUG1_END				(1 << 28)
+#define	APBH_CHn_DEBUG1_SENSE				(1 << 27)
+#define	APBH_CHn_DEBUG1_READY				(1 << 26)
+#define	APBH_CHn_DEBUG1_LOCK				(1 << 25)
+#define	APBH_CHn_DEBUG1_NEXTCMDADDRVALID		(1 << 24)
+#define	APBH_CHn_DEBUG1_RD_FIFO_EMPTY			(1 << 23)
+#define	APBH_CHn_DEBUG1_RD_FIFO_FULL			(1 << 22)
+#define	APBH_CHn_DEBUG1_WR_FIFO_EMPTY			(1 << 21)
+#define	APBH_CHn_DEBUG1_WR_FIFO_FULL			(1 << 20)
+#define	APBH_CHn_DEBUG1_RSVD1_MASK			(0x7fff << 5)
+#define	APBH_CHn_DEBUG1_RSVD1_OFFSET			5
+#define	APBH_CHn_DEBUG1_STATEMACHINE_MASK		0x1f
+#define	APBH_CHn_DEBUG1_STATEMACHINE_OFFSET		0
+#define	APBH_CHn_DEBUG1_STATEMACHINE_IDLE		0x00
+#define	APBH_CHn_DEBUG1_STATEMACHINE_REQ_CMD1		0x01
+#define	APBH_CHn_DEBUG1_STATEMACHINE_REQ_CMD3		0x02
+#define	APBH_CHn_DEBUG1_STATEMACHINE_REQ_CMD2		0x03
+#define	APBH_CHn_DEBUG1_STATEMACHINE_XFER_DECODE	0x04
+#define	APBH_CHn_DEBUG1_STATEMACHINE_REQ_WAIT		0x05
+#define	APBH_CHn_DEBUG1_STATEMACHINE_REQ_CMD4		0x06
+#define	APBH_CHn_DEBUG1_STATEMACHINE_PIO_REQ		0x07
+#define	APBH_CHn_DEBUG1_STATEMACHINE_READ_FLUSH		0x08
+#define	APBH_CHn_DEBUG1_STATEMACHINE_READ_WAIT		0x09
+#define	APBH_CHn_DEBUG1_STATEMACHINE_WRITE		0x0c
+#define	APBH_CHn_DEBUG1_STATEMACHINE_READ_REQ		0x0d
+#define	APBH_CHn_DEBUG1_STATEMACHINE_CHECK_CHAIN	0x0e
+#define	APBH_CHn_DEBUG1_STATEMACHINE_XFER_COMPLETE	0x0f
+#define	APBH_CHn_DEBUG1_STATEMACHINE_TERMINATE		0x14
+#define	APBH_CHn_DEBUG1_STATEMACHINE_WAIT_END		0x15
+#define	APBH_CHn_DEBUG1_STATEMACHINE_WRITE_WAIT		0x1c
+#define	APBH_CHn_DEBUG1_STATEMACHINE_HALT_AFTER_TERM	0x1d
+#define	APBH_CHn_DEBUG1_STATEMACHINE_CHECK_WAIT		0x1e
+#define	APBH_CHn_DEBUG1_STATEMACHINE_WAIT_READY		0x1f
+
+#define	APBH_CHn_DEBUG2_APB_BYTES_MASK			(0xffff << 16)
+#define	APBH_CHn_DEBUG2_APB_BYTES_OFFSET		16
+#define	APBH_CHn_DEBUG2_AHB_BYTES_MASK			0xffff
+#define	APBH_CHn_DEBUG2_AHB_BYTES_OFFSET		0
+
+#define	APBH_VERSION_MAJOR_MASK				(0xff << 24)
+#define	APBH_VERSION_MAJOR_OFFSET			24
+#define	APBH_VERSION_MINOR_MASK				(0xff << 16)
+#define	APBH_VERSION_MINOR_OFFSET			16
+#define	APBH_VERSION_STEP_MASK				0xffff
+#define	APBH_VERSION_STEP_OFFSET			0
+
+#endif	/* __REGS_APBH_H__ */
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 9d945a0..514828b 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -26,6 +26,7 @@ include $(TOPDIR)/config.mk
 LIB	:= $(obj)libdma.o
 
 COBJS-$(CONFIG_FSLDMAFEC) += MCD_tasksInit.o MCD_dmaApi.o MCD_tasks.o
+COBJS-$(CONFIG_APBH_DMA) += apbh_dma.o
 COBJS-$(CONFIG_FSL_DMA) += fsl_dma.o
 
 COBJS	:= $(COBJS-y)
diff --git a/drivers/dma/apbh_dma.c b/drivers/dma/apbh_dma.c
new file mode 100644
index 0000000..69a1042
--- /dev/null
+++ b/drivers/dma/apbh_dma.c
@@ -0,0 +1,691 @@
+/*
+ * Freescale i.MX28 APBH DMA driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/list.h>
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/dma.h>
+
+static struct mxs_dma_chan mxs_dma_channels[MXS_MAX_DMA_CHANNELS];
+
+/*
+ * Test is the DMA channel is valid channel
+ */
+int mxs_dma_validate_chan(int channel)
+{
+	struct mxs_dma_chan *pchan;
+
+	if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS))
+		return -EINVAL;
+
+	pchan = mxs_dma_channels + channel;
+	if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+		return -EINVAL;
+
+	return 0;
+}
+
+/*
+ * Enable a DMA channel.
+ *
+ * If the given channel has any DMA descriptors on its active list, this
+ * function causes the DMA hardware to begin processing them.
+ *
+ * This function marks the DMA channel as "busy," whether or not there are any
+ * descriptors to process.
+ */
+int mxs_dma_enable(int channel)
+{
+	struct mx28_apbh_regs *apbh_regs =
+		(struct mx28_apbh_regs *)MXS_APBH_BASE;
+	unsigned int sem;
+	struct mxs_dma_chan *pchan;
+	struct mxs_dma_desc *pdesc;
+	int ret;
+
+	ret = mxs_dma_validate_chan(channel);
+	if (ret)
+		return ret;
+
+	pchan = mxs_dma_channels + channel;
+
+	if (pchan->pending_num == 0) {
+		pchan->flags |= MXS_DMA_FLAGS_BUSY;
+		return 0;
+	}
+
+	pdesc = list_first_entry(&pchan->active, struct mxs_dma_desc, node);
+	if (pdesc == NULL)
+		return -EFAULT;
+
+	if (pchan->flags & MXS_DMA_FLAGS_BUSY) {
+		if (!(pdesc->cmd.data & MXS_DMA_DESC_CHAIN))
+			return 0;
+
+		sem = mxs_dma_read_semaphore(channel);
+		if (sem == 0)
+			return 0;
+
+		if (sem == 1) {
+			pdesc = list_entry(pdesc->node.next,
+					   struct mxs_dma_desc, node);
+			writel(mxs_dma_cmd_address(pdesc),
+				&apbh_regs->ch[channel].hw_apbh_ch_nxtcmdar);
+		}
+		writel(pchan->pending_num,
+			&apbh_regs->ch[channel].hw_apbh_ch_sema);
+		pchan->active_num += pchan->pending_num;
+		pchan->pending_num = 0;
+	} else {
+		pchan->active_num += pchan->pending_num;
+		pchan->pending_num = 0;
+		writel(mxs_dma_cmd_address(pdesc),
+			&apbh_regs->ch[channel].hw_apbh_ch_nxtcmdar);
+		writel(pchan->active_num,
+			&apbh_regs->ch[channel].hw_apbh_ch_sema);
+		writel(1 << (channel + APBH_CTRL0_CLKGATE_CHANNEL_OFFSET),
+			&apbh_regs->hw_apbh_ctrl0_clr);
+	}
+
+	pchan->flags |= MXS_DMA_FLAGS_BUSY;
+	return 0;
+}
+
+/*
+ * Disable a DMA channel.
+ *
+ * This function shuts down a DMA channel and marks it as "not busy." Any
+ * descriptors on the active list are immediately moved to the head of the
+ * "done" list, whether or not they have actually been processed by the
+ * hardware. The "ready" flags of these descriptors are NOT cleared, so they
+ * still appear to be active.
+ *
+ * This function immediately shuts down a DMA channel's hardware, aborting any
+ * I/O that may be in progress, potentially leaving I/O hardware in an undefined
+ * state. It is unwise to call this function if there is ANY chance the hardware
+ * is still processing a command.
+ */
+int mxs_dma_disable(int channel)
+{
+	struct mxs_dma_chan *pchan;
+	struct mx28_apbh_regs *apbh_regs =
+		(struct mx28_apbh_regs *)MXS_APBH_BASE;
+	int ret;
+
+	ret = mxs_dma_validate_chan(channel);
+	if (ret)
+		return ret;
+
+	pchan = mxs_dma_channels + channel;
+
+	if (!(pchan->flags & MXS_DMA_FLAGS_BUSY))
+		return -EINVAL;
+
+	writel(1 << (channel + APBH_CTRL0_CLKGATE_CHANNEL_OFFSET),
+		&apbh_regs->hw_apbh_ctrl0_set);
+
+	pchan->flags &= ~MXS_DMA_FLAGS_BUSY;
+	pchan->active_num = 0;
+	pchan->pending_num = 0;
+	list_splice_init(&pchan->active, &pchan->done);
+
+	return 0;
+}
+
+/*
+ * Resets the DMA channel hardware.
+ */
+int mxs_dma_reset(int channel)
+{
+	struct mx28_apbh_regs *apbh_regs =
+		(struct mx28_apbh_regs *)MXS_APBH_BASE;
+	int ret;
+
+	ret = mxs_dma_validate_chan(channel);
+	if (ret)
+		return ret;
+
+	writel(1 << (channel + APBH_CHANNEL_CTRL_RESET_CHANNEL_OFFSET),
+		&apbh_regs->hw_apbh_channel_ctrl_set);
+
+	return 0;
+}
+
+/*
+ * Freeze a DMA channel.
+ *
+ * This function causes the channel to continuously fail arbitration for bus
+ * access, which halts all forward progress without losing any state. A call to
+ * mxs_dma_unfreeze() will cause the channel to continue its current operation
+ * with no ill effect.
+ */
+int mxs_dma_freeze(int channel)
+{
+	struct mx28_apbh_regs *apbh_regs =
+		(struct mx28_apbh_regs *)MXS_APBH_BASE;
+	int ret;
+
+	ret = mxs_dma_validate_chan(channel);
+	if (ret)
+		return ret;
+
+	writel(1 << (channel + APBH_CHANNEL_CTRL_FREEZE_CHANNEL_OFFSET),
+		&apbh_regs->hw_apbh_channel_ctrl_set);
+
+	return 0;
+}
+
+/*
+ * Unfreeze a DMA channel.
+ *
+ * This function reverses the effect of mxs_dma_freeze(), enabling the DMA
+ * channel to continue from where it was frozen.
+ */
+int mxs_dma_unfreeze(int channel)
+{
+	struct mx28_apbh_regs *apbh_regs =
+		(struct mx28_apbh_regs *)MXS_APBH_BASE;
+	int ret;
+
+	ret = mxs_dma_validate_chan(channel);
+	if (ret)
+		return ret;
+
+	writel(1 << (channel + APBH_CHANNEL_CTRL_FREEZE_CHANNEL_OFFSET),
+		&apbh_regs->hw_apbh_channel_ctrl_clr);
+
+	return 0;
+}
+
+/*
+ * Read a DMA channel's hardware semaphore.
+ *
+ * As used by the MXS platform's DMA software, the DMA channel's hardware
+ * semaphore reflects the number of DMA commands the hardware will process, but
+ * has not yet finished. This is a volatile value read directly from hardware,
+ * so it must be be viewed as immediately stale.
+ *
+ * If the channel is not marked busy, or has finished processing all its
+ * commands, this value should be zero.
+ *
+ * See mxs_dma_append() for details on how DMA command blocks must be configured
+ * to maintain the expected behavior of the semaphore's value.
+ */
+int mxs_dma_read_semaphore(int channel)
+{
+	struct mx28_apbh_regs *apbh_regs =
+		(struct mx28_apbh_regs *)MXS_APBH_BASE;
+	uint32_t tmp;
+	int ret;
+
+	ret = mxs_dma_validate_chan(channel);
+	if (ret)
+		return ret;
+
+	tmp = readl(&apbh_regs->ch[channel].hw_apbh_ch_sema);
+
+	tmp &= APBH_CHn_SEMA_PHORE_MASK;
+	tmp >>= APBH_CHn_SEMA_PHORE_OFFSET;
+
+	return tmp;
+}
+
+/*
+ * Enable or disable DMA interrupt.
+ *
+ * This function enables the given DMA channel to interrupt the CPU.
+ */
+int mxs_dma_enable_irq(int channel, int enable)
+{
+	struct mx28_apbh_regs *apbh_regs =
+		(struct mx28_apbh_regs *)MXS_APBH_BASE;
+	int ret;
+
+	ret = mxs_dma_validate_chan(channel);
+	if (ret)
+		return ret;
+
+	if (enable)
+		writel(1 << (channel + APBH_CTRL1_CH_CMDCMPLT_IRQ_EN_OFFSET),
+			&apbh_regs->hw_apbh_ctrl1_set);
+	else
+		writel(1 << (channel + APBH_CTRL1_CH_CMDCMPLT_IRQ_EN_OFFSET),
+			&apbh_regs->hw_apbh_ctrl1_clr);
+
+	return 0;
+}
+
+/*
+ * Check if a DMA interrupt is pending.
+ */
+int mxs_dma_irq_is_pending(int channel)
+{
+	struct mx28_apbh_regs *apbh_regs =
+		(struct mx28_apbh_regs *)MXS_APBH_BASE;
+	uint32_t tmp;
+	int ret;
+
+	ret = mxs_dma_validate_chan(channel);
+	if (ret)
+		return ret;
+
+	tmp = readl(&apbh_regs->hw_apbh_ctrl1);
+	tmp |= readl(&apbh_regs->hw_apbh_ctrl2);
+
+	return (tmp >> channel) & 1;
+}
+
+/*
+ * Clear DMA interrupt.
+ *
+ * The software that is using the DMA channel must register to receive its
+ * interrupts and, when they arrive, must call this function to clear them.
+ */
+int mxs_dma_ack_irq(int channel)
+{
+	struct mx28_apbh_regs *apbh_regs =
+		(struct mx28_apbh_regs *)MXS_APBH_BASE;
+	int ret;
+
+	ret = mxs_dma_validate_chan(channel);
+	if (ret)
+		return ret;
+
+	writel(1 << channel, &apbh_regs->hw_apbh_ctrl1_clr);
+	writel(1 << channel, &apbh_regs->hw_apbh_ctrl2_clr);
+
+	return 0;
+}
+
+/*
+ * Request to reserve a DMA channel
+ */
+int mxs_dma_request(int channel)
+{
+	struct mxs_dma_chan *pchan;
+
+	if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS))
+		return -EINVAL;
+
+	pchan = mxs_dma_channels + channel;
+	if ((pchan->flags & MXS_DMA_FLAGS_VALID) != MXS_DMA_FLAGS_VALID)
+		return -ENODEV;
+
+	if (pchan->flags & MXS_DMA_FLAGS_ALLOCATED)
+		return -EBUSY;
+
+	pchan->flags |= MXS_DMA_FLAGS_ALLOCATED;
+	pchan->active_num = 0;
+	pchan->pending_num = 0;
+
+	INIT_LIST_HEAD(&pchan->active);
+	INIT_LIST_HEAD(&pchan->done);
+
+	return 0;
+}
+
+/*
+ * Release a DMA channel.
+ *
+ * This function releases a DMA channel from its current owner.
+ *
+ * The channel will NOT be released if it's marked "busy" (see
+ * mxs_dma_enable()).
+ */
+int mxs_dma_release(int channel)
+{
+	struct mxs_dma_chan *pchan;
+	int ret;
+
+	ret = mxs_dma_validate_chan(channel);
+	if (ret)
+		return ret;
+
+	pchan = mxs_dma_channels + channel;
+
+	if (pchan->flags & MXS_DMA_FLAGS_BUSY)
+		return -EBUSY;
+
+	pchan->dev = 0;
+	pchan->active_num = 0;
+	pchan->pending_num = 0;
+	pchan->flags &= ~MXS_DMA_FLAGS_ALLOCATED;
+
+	return 0;
+}
+
+/*
+ * Allocate DMA descriptor
+ */
+struct mxs_dma_desc *mxs_dma_desc_alloc(void)
+{
+	struct mxs_dma_desc *pdesc;
+
+	pdesc = memalign(MXS_DMA_ALIGNMENT, sizeof(struct mxs_dma_desc));
+
+	if (pdesc == NULL)
+		return NULL;
+
+	memset(pdesc, 0, sizeof(*pdesc));
+	pdesc->address = (dma_addr_t)pdesc;
+
+	return pdesc;
+};
+
+/*
+ * Free DMA descriptor
+ */
+void mxs_dma_desc_free(struct mxs_dma_desc *pdesc)
+{
+	if (pdesc == NULL)
+		return;
+
+	free(pdesc);
+}
+
+/*
+ * Return the address of the command within a descriptor.
+ */
+unsigned int mxs_dma_cmd_address(struct mxs_dma_desc *desc)
+{
+	return desc->address + offsetof(struct mxs_dma_desc, cmd);
+}
+
+/*
+ * Check if descriptor is on a channel's active list.
+ *
+ * This function returns the state of a descriptor's "ready" flag. This flag is
+ * usually set only if the descriptor appears on a channel's active list. The
+ * descriptor may or may not have already been processed by the hardware.
+ *
+ * The "ready" flag is set when the descriptor is submitted to a channel by a
+ * call to mxs_dma_append() or mxs_dma_append_list(). The "ready" flag is
+ * cleared when a processed descriptor is moved off the active list by a call
+ * to mxs_dma_finish(). The "ready" flag is NOT cleared if the descriptor is
+ * aborted by a call to mxs_dma_disable().
+ */
+int mxs_dma_desc_pending(struct mxs_dma_desc *pdesc)
+{
+	return pdesc->flags & MXS_DMA_DESC_READY;
+}
+
+/*
+ * Add a DMA descriptor to a channel.
+ *
+ * If the descriptor list for this channel is not empty, this function sets the
+ * CHAIN bit and the NEXTCMD_ADDR fields in the last descriptor's DMA command so
+ * it will chain to the new descriptor's command.
+ *
+ * Then, this function marks the new descriptor as "ready," adds it to the end
+ * of the active descriptor list, and increments the count of pending
+ * descriptors.
+ *
+ * The MXS platform DMA software imposes some rules on DMA commands to maintain
+ * important invariants. These rules are NOT checked, but they must be carefully
+ * applied by software that uses MXS DMA channels.
+ *
+ * Invariant:
+ *     The DMA channel's hardware semaphore must reflect the number of DMA
+ *     commands the hardware will process, but has not yet finished.
+ *
+ * Explanation:
+ *     A DMA channel begins processing commands when its hardware semaphore is
+ *     written with a value greater than zero, and it stops processing commands
+ *     when the semaphore returns to zero.
+ *
+ *     When a channel finishes a DMA command, it will decrement its semaphore if
+ *     the DECREMENT_SEMAPHORE bit is set in that command's flags bits.
+ *
+ *     In principle, it's not necessary for the DECREMENT_SEMAPHORE to be set,
+ *     unless it suits the purposes of the software. For example, one could
+ *     construct a series of five DMA commands, with the DECREMENT_SEMAPHORE
+ *     bit set only in the last one. Then, setting the DMA channel's hardware
+ *     semaphore to one would cause the entire series of five commands to be
+ *     processed. However, this example would violate the invariant given above.
+ *
+ * Rule:
+ *    ALL DMA commands MUST have the DECREMENT_SEMAPHORE bit set so that the DMA
+ *    channel's hardware semaphore will be decremented EVERY time a command is
+ *    processed.
+ */
+int mxs_dma_desc_append(int channel, struct mxs_dma_desc *pdesc)
+{
+	struct mxs_dma_chan *pchan;
+	struct mxs_dma_desc *last;
+	int ret;
+
+	ret = mxs_dma_validate_chan(channel);
+	if (ret)
+		return ret;
+
+	pchan = mxs_dma_channels + channel;
+
+	pdesc->cmd.next = mxs_dma_cmd_address(pdesc);
+	pdesc->flags |= MXS_DMA_DESC_FIRST | MXS_DMA_DESC_LAST;
+
+	if (!list_empty(&pchan->active)) {
+		last = list_entry(pchan->active.prev, struct mxs_dma_desc,
+					node);
+
+		pdesc->flags &= ~MXS_DMA_DESC_FIRST;
+		last->flags &= ~MXS_DMA_DESC_LAST;
+
+		last->cmd.next = mxs_dma_cmd_address(pdesc);
+		last->cmd.data |= MXS_DMA_DESC_CHAIN;
+	}
+	pdesc->flags |= MXS_DMA_DESC_READY;
+	if (pdesc->flags & MXS_DMA_DESC_FIRST)
+		pchan->pending_num++;
+	list_add_tail(&pdesc->node, &pchan->active);
+
+	return ret;
+}
+
+/*
+ * Retrieve processed DMA descriptors.
+ *
+ * This function moves all the descriptors from the DMA channel's "done" list to
+ * the head of the given list.
+ */
+int mxs_dma_get_finished(int channel, struct list_head *head)
+{
+	struct mxs_dma_chan *pchan;
+	int ret;
+
+	ret = mxs_dma_validate_chan(channel);
+	if (ret)
+		return ret;
+
+	if (head == NULL)
+		return 0;
+
+	pchan = mxs_dma_channels + channel;
+
+	list_splice(&pchan->done, head);
+
+	return 0;
+}
+
+/*
+ * Clean up processed DMA descriptors.
+ *
+ * This function removes processed DMA descriptors from the "active" list. Pass
+ * in a non-NULL list head to get the descriptors moved to your list. Pass NULL
+ * to get the descriptors moved to the channel's "done" list. Descriptors on
+ * the "done" list can be retrieved with mxs_dma_get_finished().
+ *
+ * This function marks the DMA channel as "not busy" if no unprocessed
+ * descriptors remain on the "active" list.
+ */
+int mxs_dma_finish(int channel, struct list_head *head)
+{
+	int sem;
+	struct mxs_dma_chan *pchan;
+	struct list_head *p, *q;
+	struct mxs_dma_desc *pdesc;
+	int ret;
+
+	ret = mxs_dma_validate_chan(channel);
+	if (ret)
+		return ret;
+
+	pchan = mxs_dma_channels + channel;
+
+	sem = mxs_dma_read_semaphore(channel);
+	if (sem < 0)
+		return sem;
+
+	if (sem == pchan->active_num)
+		return 0;
+
+	list_for_each_safe(p, q, &pchan->active) {
+		if ((pchan->active_num) <= sem)
+			break;
+
+		pdesc = list_entry(p, struct mxs_dma_desc, node);
+		pdesc->flags &= ~MXS_DMA_DESC_READY;
+
+		if (head)
+			list_move_tail(p, head);
+		else
+			list_move_tail(p, &pchan->done);
+
+		if (pdesc->flags & MXS_DMA_DESC_LAST)
+			pchan->active_num--;
+	}
+
+	if (sem == 0)
+		pchan->flags &= ~MXS_DMA_FLAGS_BUSY;
+
+	return 0;
+}
+
+/*
+ * Wait for DMA channel to complete
+ */
+int mxs_dma_wait_complete(uint32_t timeout, unsigned int chan)
+{
+	struct mx28_apbh_regs *apbh_regs =
+		(struct mx28_apbh_regs *)MXS_APBH_BASE;
+	int ret;
+
+	ret = mxs_dma_validate_chan(chan);
+	if (ret)
+		return ret;
+
+	if (mx28_wait_mask_set(&apbh_regs->hw_apbh_ctrl1_reg,
+				1 << chan, timeout)) {
+		ret = -ETIMEDOUT;
+		mxs_dma_reset(chan);
+	}
+
+	return 0;
+}
+
+/*
+ * Execute the DMA channel
+ */
+int mxs_dma_go(int chan)
+{
+	uint32_t timeout = 10000;
+	int ret;
+
+	LIST_HEAD(tmp_desc_list);
+
+	mxs_dma_enable_irq(chan, 1);
+	mxs_dma_enable(chan);
+
+	/* Wait for DMA to finish. */
+	ret = mxs_dma_wait_complete(timeout, chan);
+
+	/* Clear out the descriptors we just ran. */
+	mxs_dma_finish(chan, &tmp_desc_list);
+
+	/* Shut the DMA channel down. */
+	mxs_dma_ack_irq(chan);
+	mxs_dma_reset(chan);
+	mxs_dma_enable_irq(chan, 0);
+	mxs_dma_disable(chan);
+
+	return ret;
+}
+
+/*
+ * Initialize the DMA hardware
+ */
+int mxs_dma_init(void)
+{
+	struct mx28_apbh_regs *apbh_regs =
+		(struct mx28_apbh_regs *)MXS_APBH_BASE;
+	struct mxs_dma_chan *pchan;
+	int ret, channel;
+
+	mx28_reset_block(&apbh_regs->hw_apbh_ctrl0_reg);
+
+#ifdef CONFIG_APBH_DMA_BURST8
+	writel(APBH_CTRL0_AHB_BURST8_EN,
+		&apbh_regs->hw_apbh_ctrl0_set);
+#else
+	writel(APBH_CTRL0_AHB_BURST8_EN,
+		&apbh_regs->hw_apbh_ctrl0_clr);
+#endif
+
+#ifdef CONFIG_APBH_DMA_BURST
+	writel(APBH_CTRL0_APB_BURST_EN,
+		&apbh_regs->hw_apbh_ctrl0_set);
+#else
+	writel(APBH_CTRL0_APB_BURST_EN,
+		&apbh_regs->hw_apbh_ctrl0_clr);
+#endif
+
+	for (channel = 0; channel < MXS_MAX_DMA_CHANNELS; channel++) {
+		pchan = mxs_dma_channels + channel;
+		pchan->flags = MXS_DMA_FLAGS_VALID;
+
+		ret = mxs_dma_request(channel);
+
+		if (ret) {
+			printf("MXS DMA: Can't acquire DMA channel %i\n",
+				channel);
+
+			goto err;
+		}
+
+		mxs_dma_reset(channel);
+		mxs_dma_ack_irq(channel);
+	}
+
+	return 0;
+
+err:
+	while (--channel >= 0)
+		mxs_dma_release(channel);
+	return ret;
+}
-- 
1.7.5.4

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

* [U-Boot] [PATCH 09/15] iMX28: Add GPMI NAND driver
  2011-09-12  4:06 [U-Boot] [PATCH 00/15 V2] Support for the DENX M28 SoM Marek Vasut
                   ` (7 preceding siblings ...)
  2011-09-12  4:06 ` [U-Boot] [PATCH 08/15] iMX28: Add APBH DMA driver Marek Vasut
@ 2011-09-12  4:06 ` Marek Vasut
  2011-09-28 21:26   ` Scott Wood
  2011-09-28 22:17   ` [U-Boot] [PATCH 09/15 V2] " Marek Vasut
  2011-09-12  4:06 ` [U-Boot] [PATCH 10/15] iMX28: Add driver for internal RTC Marek Vasut
                   ` (6 subsequent siblings)
  15 siblings, 2 replies; 116+ messages in thread
From: Marek Vasut @ 2011-09-12  4:06 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Scott Wood <scottwood@freescale.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 drivers/mtd/nand/Makefile   |    1 +
 drivers/mtd/nand/mxs_nand.c | 1159 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1160 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/nand/mxs_nand.c

diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 8b598f6..8b6e8bf 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -43,6 +43,7 @@ COBJS-$(CONFIG_NAND_KIRKWOOD) += kirkwood_nand.o
 COBJS-$(CONFIG_NAND_KMETER1) += kmeter1_nand.o
 COBJS-$(CONFIG_NAND_MPC5121_NFC) += mpc5121_nfc.o
 COBJS-$(CONFIG_NAND_MXC) += mxc_nand.o
+COBJS-$(CONFIG_NAND_MXS) += mxs_nand.o
 COBJS-$(CONFIG_NAND_NDFC) += ndfc.o
 COBJS-$(CONFIG_NAND_NOMADIK) += nomadik.o
 COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o
diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c
new file mode 100644
index 0000000..af2c571
--- /dev/null
+++ b/drivers/mtd/nand/mxs_nand.c
@@ -0,0 +1,1159 @@
+/*
+ * Freescale i.MX28 NAND flash driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Freescale GPMI NFC NAND Flash Driver
+ *
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ * Copyright (C) 2008 Embedded Alley Solutions, Inc.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/types.h>
+#include <common.h>
+#include <malloc.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/dma.h>
+
+#define	MXS_NAND_DMA_DESCRIPTOR_COUNT		4
+
+#define	MXS_NAND_CHUNK_DATA_CHUNK_SIZE		512
+#define	MXS_NAND_METADATA_SIZE			10
+
+#define	MXS_NAND_COMMAND_BUFFER_SIZE		32
+
+#define	MXS_NAND_BCH_TIMEOUT			10000
+
+struct mxs_nand_info {
+	int		cur_chip;
+
+	uint32_t	cmd_queue_len;
+
+	uint8_t		*cmd_buf;
+	uint8_t		*data_buf;
+	uint8_t		*oob_buf;
+
+	uint8_t		marking_block_bad;
+	uint8_t		raw_oob_mode;
+
+	/* Functions with altered behaviour */
+	int		(*hooked_read_oob)(struct mtd_info *mtd,
+				loff_t from, struct mtd_oob_ops *ops);
+	int		(*hooked_write_oob)(struct mtd_info *mtd,
+				loff_t to, struct mtd_oob_ops *ops);
+	int		(*hooked_block_markbad)(struct mtd_info *mtd,
+				loff_t ofs);
+
+	/* DMA descriptors */
+	struct mxs_dma_desc	**desc;
+	uint32_t		desc_index;
+};
+
+struct nand_ecclayout fake_ecc_layout;
+
+static struct mxs_dma_desc *mxs_nand_get_dma_desc(struct mxs_nand_info *info)
+{
+	struct mxs_dma_desc *desc;
+
+	if (info->desc_index >= MXS_NAND_DMA_DESCRIPTOR_COUNT) {
+		printf("MXS NAND: Too many DMA descriptors requested\n");
+		return NULL;
+	}
+
+	desc = info->desc[info->desc_index];
+	info->desc_index++;
+
+	return desc;
+}
+
+static void mxs_nand_return_dma_descs(struct mxs_nand_info *info)
+{
+	int i = info->desc_index;
+	struct mxs_dma_desc *desc;
+
+	for (--i; i >= 0; i--) {
+		desc = info->desc[i];
+		memset(desc, 0, sizeof(struct mxs_dma_desc));
+		desc->address = (dma_addr_t)desc;
+	}
+
+	info->desc_index = 0;
+}
+
+static inline uint32_t mxs_nand_ecc_chunk_cnt(uint32_t page_data_size)
+{
+	return page_data_size / MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
+}
+
+static inline uint32_t mxs_nand_ecc_size_in_bits(uint32_t ecc_strength)
+{
+	return ecc_strength * 13;
+}
+
+static inline uint32_t mxs_nand_aux_status_offset(void)
+{
+	return (MXS_NAND_METADATA_SIZE + 0x3) & ~0x3;
+}
+
+static inline uint32_t mxs_nand_aux_size(uint32_t page_size)
+{
+	uint32_t aux_status_off = mxs_nand_aux_status_offset();
+	uint32_t ecc_chunk_cnt =
+		(mxs_nand_ecc_chunk_cnt(page_size) + 0x3) & ~0x3;
+
+	return ecc_chunk_cnt + aux_status_off;
+}
+
+static inline uint32_t mxs_nand_get_ecc_strength(uint32_t page_data_size,
+						uint32_t page_oob_size)
+{
+	if (page_data_size == 2048)
+		return 8;
+
+	if (page_data_size == 4096) {
+		if (page_oob_size == 128)
+			return 8;
+
+		if (page_oob_size == 218)
+			return 16;
+	}
+
+	return 0;
+}
+
+static inline uint32_t mxs_nand_get_mark_offset(uint32_t page_data_size,
+						uint32_t ecc_strength)
+{
+	uint32_t chunk_data_size_in_bits;
+	uint32_t chunk_ecc_size_in_bits;
+	uint32_t chunk_total_size_in_bits;
+	uint32_t block_mark_chunk_number;
+	uint32_t block_mark_chunk_bit_offset;
+	uint32_t block_mark_bit_offset;
+
+	chunk_data_size_in_bits = MXS_NAND_CHUNK_DATA_CHUNK_SIZE * 8;
+	chunk_ecc_size_in_bits  = mxs_nand_ecc_size_in_bits(ecc_strength);
+
+	chunk_total_size_in_bits =
+			chunk_data_size_in_bits + chunk_ecc_size_in_bits;
+
+	/* Compute the bit offset of the block mark within the physical page. */
+	block_mark_bit_offset = page_data_size * 8;
+
+	/* Subtract the metadata bits. */
+	block_mark_bit_offset -= MXS_NAND_METADATA_SIZE * 8;
+
+	/*
+	 * Compute the chunk number (starting at zero) in which the block mark
+	 * appears.
+	 */
+	block_mark_chunk_number =
+			block_mark_bit_offset / chunk_total_size_in_bits;
+
+	/*
+	 * Compute the bit offset of the block mark within its chunk, and
+	 * validate it.
+	 */
+	block_mark_chunk_bit_offset = block_mark_bit_offset -
+			(block_mark_chunk_number * chunk_total_size_in_bits);
+
+	if (block_mark_chunk_bit_offset > chunk_data_size_in_bits)
+		return 1;
+
+	/*
+	 * Now that we know the chunk number in which the block mark appears,
+	 * we can subtract all the ECC bits that appear before it.
+	 */
+	block_mark_bit_offset -=
+		block_mark_chunk_number * chunk_ecc_size_in_bits;
+
+	return block_mark_bit_offset;
+}
+
+static inline uint32_t mxs_nand_mark_byte_offset(struct mtd_info *mtd)
+{
+	uint32_t ecc_strength;
+	ecc_strength = mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize);
+	return mxs_nand_get_mark_offset(mtd->writesize, ecc_strength) >> 3;
+}
+
+static inline uint32_t mxs_nand_mark_bit_offset(struct mtd_info *mtd)
+{
+	uint32_t ecc_strength;
+	ecc_strength = mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize);
+	return mxs_nand_get_mark_offset(mtd->writesize, ecc_strength) & 0x7;
+}
+
+/*
+ * Wait for BCH complete IRQ and clear the IRQ
+ */
+static int mxs_nand_wait_for_bch_complete(void)
+{
+	struct mx28_bch_regs *bch_regs = (struct mx28_bch_regs *)MXS_BCH_BASE;
+	int timeout = MXS_NAND_BCH_TIMEOUT;
+	int ret;
+
+	ret = mx28_wait_mask_set(&bch_regs->hw_bch_ctrl_reg,
+		BCH_CTRL_COMPLETE_IRQ, timeout);
+
+	writel(BCH_CTRL_COMPLETE_IRQ, &bch_regs->hw_bch_ctrl_clr);
+
+	return ret;
+}
+
+/*
+ * This is the function that we install in the cmd_ctrl function pointer of the
+ * owning struct nand_chip. The only functions in the reference implementation
+ * that use these functions pointers are cmdfunc and select_chip.
+ *
+ * In this driver, we implement our own select_chip, so this function will only
+ * be called by the reference implementation's cmdfunc. For this reason, we can
+ * ignore the chip enable bit and concentrate only on sending bytes to the
+ * NAND Flash.
+ */
+static void mxs_nand_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	int ret;
+
+	/*
+	 * If this condition is true, something is _VERY_ wrong in MTD
+	 * subsystem!
+	 */
+	if (nand_info->cmd_queue_len == MXS_NAND_COMMAND_BUFFER_SIZE) {
+		printf("MXS NAND: Command queue too long\n");
+		return;
+	}
+
+	/*
+	 * Every operation begins with a command byte and a series of zero or
+	 * more address bytes. These are distinguished by either the Address
+	 * Latch Enable (ALE) or Command Latch Enable (CLE) signals being
+	 * asserted. When MTD is ready to execute the command, it will
+	 * deasert both latch enables.
+	 *
+	 * Rather than run a separate DMA operation for every single byte, we
+	 * queue them up and run a single DMA operation for the entire series
+	 * of command and data bytes.
+	 */
+	if (ctrl & (NAND_ALE | NAND_CLE)) {
+		if (data != NAND_CMD_NONE)
+			nand_info->cmd_buf[nand_info->cmd_queue_len++] = data;
+		return;
+	}
+
+	/*
+	 * If control arrives here, MTD has deasserted both the ALE and CLE,
+	 * which means it's ready to run an operation. Check if we have any
+	 * bytes to send.
+	 */
+	if (nand_info->cmd_queue_len == 0)
+		return;
+
+	/* Compile the DMA descriptor -- a descriptor that sends command. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_DMA_READ | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_CHAIN | MXS_DMA_DESC_DEC_SEM |
+		MXS_DMA_DESC_WAIT4END | (3 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
+		(nand_info->cmd_queue_len << MXS_DMA_DESC_BYTES_OFFSET);
+
+	d->cmd.address = (dma_addr_t)nand_info->cmd_buf;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_CLE |
+		GPMI_CTRL0_ADDRESS_INCREMENT |
+		nand_info->cmd_queue_len;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret)
+		printf("MXS NAND: Error sending command\n");
+
+	mxs_nand_return_dma_descs(nand_info);
+
+	/* Reset the command queue. */
+	nand_info->cmd_queue_len = 0;
+}
+
+/*
+ * Test if the NAND flash is ready.
+ */
+static int mxs_nand_device_ready(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mxs_nand_info *nand_info = chip->priv;
+	struct mx28_gpmi_regs *gpmi_regs =
+		(struct mx28_gpmi_regs *)MXS_GPMI_BASE;
+	uint32_t tmp;
+
+	tmp = readl(&gpmi_regs->hw_gpmi_stat);
+	tmp >>= (GPMI_STAT_READY_BUSY_OFFSET + nand_info->cur_chip);
+
+	return tmp & 1;
+}
+
+/*
+ * Select the NAND chip.
+ */
+static void mxs_nand_select_chip(struct mtd_info *mtd, int chip)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+
+	nand_info->cur_chip = chip;
+}
+
+/*
+ * Handle block mark swapping.
+ *
+ * Note that, when this function is called, it doesn't know whether it's
+ * swapping the block mark, or swapping it *back* -- but it doesn't matter
+ * because the the operation is the same.
+ */
+static void mxs_nand_swap_block_mark(struct mtd_info *mtd,
+					uint8_t *data_buf, uint8_t *oob_buf)
+{
+	uint32_t bit_offset;
+	uint32_t buf_offset;
+
+	uint32_t src;
+	uint32_t dst;
+
+	bit_offset = mxs_nand_mark_bit_offset(mtd);
+	buf_offset = mxs_nand_mark_byte_offset(mtd);
+
+	/*
+	 * Get the byte from the data area that overlays the block mark. Since
+	 * the ECC engine applies its own view to the bits in the page, the
+	 * physical block mark won't (in general) appear on a byte boundary in
+	 * the data.
+	 */
+	src = data_buf[buf_offset] >> bit_offset;
+	src |= data_buf[buf_offset + 1] << (8 - bit_offset);
+
+	dst = oob_buf[0];
+
+	oob_buf[0] = src;
+
+	data_buf[buf_offset] &= ~(0xff << bit_offset);
+	data_buf[buf_offset + 1] &= 0xff << bit_offset;
+
+	data_buf[buf_offset] |= dst << bit_offset;
+	data_buf[buf_offset + 1] |= dst >> (8 - bit_offset);
+}
+
+/*
+ * Read data from NAND.
+ */
+static void mxs_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int length)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	int ret;
+
+	if (length > NAND_MAX_PAGESIZE) {
+		printf("MXS NAND: DMA buffer too big\n");
+		return;
+	}
+
+	if (!buf) {
+		printf("MXS NAND: DMA buffer is NULL\n");
+		return;
+	}
+
+	/* Compile the DMA descriptor - a descriptor that reads data. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_DMA_WRITE | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
+		(1 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
+		(length << MXS_DMA_DESC_BYTES_OFFSET);
+
+	d->cmd.address = (dma_addr_t)nand_info->data_buf;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_READ |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		length;
+
+	mxs_dma_desc_append(channel, d);
+
+	/*
+	 * A DMA descriptor that waits for the command to end and the chip to
+	 * become ready.
+	 *
+	 * I think we actually should *not* be waiting for the chip to become
+	 * ready because, after all, we don't care. I think the original code
+	 * did that and no one has re-thought it yet.
+	 */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_DEC_SEM |
+		MXS_DMA_DESC_WAIT4END | (4 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret) {
+		printf("MXS NAND: DMA read error\n");
+		goto rtn;
+	}
+
+	memcpy(buf, nand_info->data_buf, length);
+
+rtn:
+	mxs_nand_return_dma_descs(nand_info);
+}
+
+/*
+ * Write data to NAND.
+ */
+static void mxs_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf,
+				int length)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	int ret;
+
+	if (length > NAND_MAX_PAGESIZE) {
+		printf("MXS NAND: DMA buffer too big\n");
+		return;
+	}
+
+	if (!buf) {
+		printf("MXS NAND: DMA buffer is NULL\n");
+		return;
+	}
+
+	memcpy(nand_info->data_buf, buf, length);
+
+	/* Compile the DMA descriptor - a descriptor that writes data. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_DMA_READ | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
+		(4 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
+		(length << MXS_DMA_DESC_BYTES_OFFSET);
+
+	d->cmd.address = (dma_addr_t)nand_info->data_buf;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		length;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret)
+		printf("MXS NAND: DMA write error\n");
+
+	mxs_nand_return_dma_descs(nand_info);
+}
+
+/*
+ * Read a single byte from NAND.
+ */
+static uint8_t mxs_nand_read_byte(struct mtd_info *mtd)
+{
+	uint8_t buf;
+	mxs_nand_read_buf(mtd, &buf, 1);
+	return buf;
+}
+
+/*
+ * Read a page from NAND.
+ */
+static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
+					uint8_t *buf, int page)
+{
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	uint32_t corrected = 0, failed = 0;
+	uint8_t	*status;
+	int i, ret;
+
+	/* Compile the DMA descriptor - wait for ready. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
+		MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_WAIT4END |
+		(1 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Compile the DMA descriptor - enable the BCH block and read. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
+		MXS_DMA_DESC_WAIT4END |	(6 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_READ |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		(mtd->writesize + mtd->oobsize);
+	d->cmd.pio_words[1] = 0;
+	d->cmd.pio_words[2] =
+		GPMI_ECCCTRL_ENABLE_ECC |
+		GPMI_ECCCTRL_ECC_CMD_DECODE |
+		GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE;
+	d->cmd.pio_words[3] = mtd->writesize + mtd->oobsize;
+	d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf;
+	d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Compile the DMA descriptor - disable the BCH block. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
+		MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_WAIT4END |
+		(3 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		(mtd->writesize + mtd->oobsize);
+	d->cmd.pio_words[1] = 0;
+	d->cmd.pio_words[2] = 0;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Compile the DMA descriptor - deassert the NAND lock and interrupt. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_DEC_SEM;
+
+	d->cmd.address = 0;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret) {
+		printf("MXS NAND: DMA read error\n");
+		goto rtn;
+	}
+
+	ret = mxs_nand_wait_for_bch_complete();
+	if (ret) {
+		printf("MXS NAND: BCH read timeout\n");
+		goto rtn;
+	}
+
+	/* Read DMA completed, now do the mark swapping. */
+	mxs_nand_swap_block_mark(mtd, nand_info->data_buf, nand_info->oob_buf);
+
+	/* Loop over status bytes, accumulating ECC status. */
+	status = nand_info->oob_buf + mxs_nand_aux_status_offset();
+	for (i = 0; i < mxs_nand_ecc_chunk_cnt(mtd->writesize); i++) {
+		if (status[i] == 0x00)
+			continue;
+
+		if (status[i] == 0xff)
+			continue;
+
+		if (status[i] == 0xfe) {
+			failed++;
+			continue;
+		}
+
+		corrected += status[i];
+	}
+
+	/* Propagate ECC status to the owning MTD. */
+	mtd->ecc_stats.failed += failed;
+	mtd->ecc_stats.corrected += corrected;
+
+	/*
+	 * It's time to deliver the OOB bytes. See mxs_nand_ecc_read_oob() for
+	 * details about our policy for delivering the OOB.
+	 *
+	 * We fill the caller's buffer with set bits, and then copy the block
+	 * mark to th caller's buffer. Note that, if block mark swapping was
+	 * necessary, it has already been done, so we can rely on the first
+	 * byte of the auxiliary buffer to contain the block mark.
+	 */
+	memset(nand->oob_poi, 0xff, mtd->oobsize);
+
+	nand->oob_poi[0] = nand_info->oob_buf[0];
+
+	memcpy(buf, nand_info->data_buf, mtd->writesize);
+
+rtn:
+	mxs_nand_return_dma_descs(nand_info);
+
+	return ret;
+}
+
+/*
+ * Write a page to NAND.
+ */
+static void mxs_nand_ecc_write_page(struct mtd_info *mtd,
+				struct nand_chip *nand, const uint8_t *buf)
+{
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	int ret;
+
+	memcpy(nand_info->data_buf, buf, mtd->writesize);
+	memcpy(nand_info->oob_buf, nand->oob_poi, mtd->oobsize);
+
+	/* Handle block mark swapping. */
+	mxs_nand_swap_block_mark(mtd, nand_info->data_buf, nand_info->oob_buf);
+
+	/* Compile the DMA descriptor - write data. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
+		(6 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA;
+	d->cmd.pio_words[1] = 0;
+	d->cmd.pio_words[2] =
+		GPMI_ECCCTRL_ENABLE_ECC |
+		GPMI_ECCCTRL_ECC_CMD_ENCODE |
+		GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE;
+	d->cmd.pio_words[3] = (mtd->writesize + mtd->oobsize);
+	d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf;
+	d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret) {
+		printf("MXS NAND: DMA write error\n");
+		goto rtn;
+	}
+
+	ret = mxs_nand_wait_for_bch_complete();
+	if (ret) {
+		printf("MXS NAND: BCH write timeout\n");
+		goto rtn;
+	}
+
+rtn:
+	mxs_nand_return_dma_descs(nand_info);
+}
+
+/*
+ * Read OOB from NAND.
+ *
+ * This function is a veneer that replaces the function originally installed by
+ * the NAND Flash MTD code.
+ */
+static int mxs_nand_hook_read_oob(struct mtd_info *mtd, loff_t from,
+					struct mtd_oob_ops *ops)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mxs_nand_info *nand_info = chip->priv;
+	int ret;
+
+	if (ops->mode == MTD_OOB_RAW)
+		nand_info->raw_oob_mode = 1;
+	else
+		nand_info->raw_oob_mode = 0;
+
+	ret = nand_info->hooked_read_oob(mtd, from, ops);
+
+	nand_info->raw_oob_mode = 0;
+
+	return ret;
+}
+
+/*
+ * Write OOB to NAND.
+ *
+ * This function is a veneer that replaces the function originally installed by
+ * the NAND Flash MTD code.
+ */
+static int mxs_nand_hook_write_oob(struct mtd_info *mtd, loff_t to,
+					struct mtd_oob_ops *ops)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mxs_nand_info *nand_info = chip->priv;
+	int ret;
+
+	if (ops->mode == MTD_OOB_RAW)
+		nand_info->raw_oob_mode = 1;
+	else
+		nand_info->raw_oob_mode = 0;
+
+	ret = nand_info->hooked_write_oob(mtd, to, ops);
+
+	nand_info->raw_oob_mode = 0;
+
+	return ret;
+}
+
+/*
+ * Mark a block bad in NAND.
+ *
+ * This function is a veneer that replaces the function originally installed by
+ * the NAND Flash MTD code.
+ */
+static int mxs_nand_hook_block_markbad(struct mtd_info *mtd, loff_t ofs)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mxs_nand_info *nand_info = chip->priv;
+	int ret;
+
+	nand_info->marking_block_bad = 1;
+
+	ret = nand_info->hooked_block_markbad(mtd, ofs);
+
+	nand_info->marking_block_bad = 0;
+
+	return ret;
+}
+
+/*
+ * There are several places in this driver where we have to handle the OOB and
+ * block marks. This is the function where things are the most complicated, so
+ * this is where we try to explain it all. All the other places refer back to
+ * here.
+ *
+ * These are the rules, in order of decreasing importance:
+ *
+ * 1) Nothing the caller does can be allowed to imperil the block mark, so all
+ *    write operations take measures to protect it.
+ *
+ * 2) In read operations, the first byte of the OOB we return must reflect the
+ *    true state of the block mark, no matter where that block mark appears in
+ *    the physical page.
+ *
+ * 3) ECC-based read operations return an OOB full of set bits (since we never
+ *    allow ECC-based writes to the OOB, it doesn't matter what ECC-based reads
+ *    return).
+ *
+ * 4) "Raw" read operations return a direct view of the physical bytes in the
+ *    page, using the conventional definition of which bytes are data and which
+ *    are OOB. This gives the caller a way to see the actual, physical bytes
+ *    in the page, without the distortions applied by our ECC engine.
+ *
+ *
+ * What we do for this specific read operation depends on two questions:
+ *
+ * 1) Are we doing a "raw" read, or an ECC-based read?
+ *
+ * 2) Are we using block mark swapping or transcription?
+ *
+ * There are four cases, illustrated by the following Karnaugh map:
+ *
+ *                    |           Raw           |         ECC-based       |
+ *       -------------+-------------------------+-------------------------+
+ *                    | Read the conventional   |                         |
+ *                    | OOB at the end of the   |                         |
+ *       Swapping     | page and return it. It  |                         |
+ *                    | contains exactly what   |                         |
+ *                    | we want.                | Read the block mark and |
+ *       -------------+-------------------------+ return it in a buffer   |
+ *                    | Read the conventional   | full of set bits.       |
+ *                    | OOB at the end of the   |                         |
+ *                    | page and also the block |                         |
+ *       Transcribing | mark in the metadata.   |                         |
+ *                    | Copy the block mark     |                         |
+ *                    | into the first byte of  |                         |
+ *                    | the OOB.                |                         |
+ *       -------------+-------------------------+-------------------------+
+ *
+ * Note that we break rule #4 in the Transcribing/Raw case because we're not
+ * giving an accurate view of the actual, physical bytes in the page (we're
+ * overwriting the block mark). That's OK because it's more important to follow
+ * rule #2.
+ *
+ * It turns out that knowing whether we want an "ECC-based" or "raw" read is not
+ * easy. When reading a page, for example, the NAND Flash MTD code calls our
+ * ecc.read_page or ecc.read_page_raw function. Thus, the fact that MTD wants an
+ * ECC-based or raw view of the page is implicit in which function it calls
+ * (there is a similar pair of ECC-based/raw functions for writing).
+ *
+ * Since MTD assumes the OOB is not covered by ECC, there is no pair of
+ * ECC-based/raw functions for reading or or writing the OOB. The fact that the
+ * caller wants an ECC-based or raw view of the page is not propagated down to
+ * this driver.
+ *
+ * Since our OOB *is* covered by ECC, we need this information. So, we hook the
+ * ecc.read_oob and ecc.write_oob function pointers in the owning
+ * struct mtd_info with our own functions. These hook functions set the
+ * raw_oob_mode field so that, when control finally arrives here, we'll know
+ * what to do.
+ */
+static int mxs_nand_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *nand,
+				int page, int cmd)
+{
+	struct mxs_nand_info *nand_info = nand->priv;
+
+	/*
+	 * First, fill in the OOB buffer. If we're doing a raw read, we need to
+	 * get the bytes from the physical page. If we're not doing a raw read,
+	 * we need to fill the buffer with set bits.
+	 */
+	if (nand_info->raw_oob_mode) {
+		/*
+		 * If control arrives here, we're doing a "raw" read. Send the
+		 * command to read the conventional OOB and read it.
+		 */
+		nand->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page);
+		nand->read_buf(mtd, nand->oob_poi, mtd->oobsize);
+	} else {
+		/*
+		 * If control arrives here, we're not doing a "raw" read. Fill
+		 * the OOB buffer with set bits and correct the block mark.
+		 */
+		memset(nand->oob_poi, 0xff, mtd->oobsize);
+
+		nand->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page);
+		mxs_nand_read_buf(mtd, nand->oob_poi, 1);
+	}
+
+	return 0;
+
+}
+
+/*
+ * Write OOB data to NAND.
+ */
+static int mxs_nand_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *nand,
+					int page)
+{
+	struct mxs_nand_info *nand_info = nand->priv;
+	uint8_t block_mark = 0;
+
+	/*
+	 * There are fundamental incompatibilities between the i.MX GPMI NFC and
+	 * the NAND Flash MTD model that make it essentially impossible to write
+	 * the out-of-band bytes.
+	 *
+	 * We permit *ONE* exception. If the *intent* of writing the OOB is to
+	 * mark a block bad, we can do that.
+	 */
+
+	if (nand_info->marking_block_bad) {
+		printf("NXS NAND: Writing OOB isn't supported\n");
+		return -EIO;
+	}
+
+	/* Write the block mark. */
+	nand->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
+	nand->write_buf(mtd, &block_mark, 1);
+	nand->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+
+	/* Check if it worked. */
+	if (nand->waitfunc(mtd, nand) & NAND_STATUS_FAIL)
+		return -EIO;
+
+	return 0;
+}
+
+/*
+ * Claims all blocks are good.
+ *
+ * In principle, this function is *only* called when the NAND Flash MTD system
+ * isn't allowed to keep an in-memory bad block table, so it is forced to ask
+ * the driver for bad block information.
+ *
+ * In fact, we permit the NAND Flash MTD system to have an in-memory BBT, so
+ * this function is *only* called when we take it away.
+ *
+ * We take away the in-memory BBT when the user sets the "ignorebad" parameter,
+ * which indicates that all blocks should be reported good.
+ *
+ * Thus, this function is only called when we want *all* blocks to look good,
+ * so it *always* return success.
+ */
+static int mxs_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
+{
+	return 0;
+}
+
+/*
+ * Nominally, the purpose of this function is to look for or create the bad
+ * block table. In fact, since the HIL calls this function at the very end of
+ * the initialization process started by nand_scan(), and the HIL doesn't have a
+ * more formal mechanism, everyone "hooks" this function to continue the
+ * initialization process.
+ *
+ * At this point, the physical NAND Flash chips have been identified and
+ * counted, so we know the physical geometry. This enables us to make some
+ * important configuration decisions.
+ *
+ * The return value of this function propogates directly back to this driver's
+ * call to nand_scan(). Anything other than zero will cause this driver to
+ * tear everything down and declare failure.
+ */
+static int mxs_nand_scan_bbt(struct mtd_info *mtd)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mx28_bch_regs *bch_regs = (struct mx28_bch_regs *)MXS_BCH_BASE;
+	uint32_t tmp;
+
+	/* Configure BCH and set NFC geometry */
+	mx28_reset_block(&bch_regs->hw_bch_ctrl_reg);
+
+	/* Configure layout 0 */
+	tmp = (mxs_nand_ecc_chunk_cnt(mtd->writesize) - 1)
+		<< BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
+	tmp |= MXS_NAND_METADATA_SIZE << BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
+	tmp |= (mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1)
+		<< BCH_FLASHLAYOUT0_ECC0_OFFSET;
+	tmp |= MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
+	writel(tmp, &bch_regs->hw_bch_flash0layout0);
+
+	tmp = (mtd->writesize + mtd->oobsize)
+		<< BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
+	tmp |= (mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1)
+		<< BCH_FLASHLAYOUT1_ECCN_OFFSET;
+	tmp |= MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
+	writel(tmp, &bch_regs->hw_bch_flash0layout1);
+
+	/* Set *all* chip selects to use layout 0 */
+	writel(0, &bch_regs->hw_bch_layoutselect);
+
+	/* Enable BCH complete interrupt */
+	writel(BCH_CTRL_COMPLETE_IRQ_EN, &bch_regs->hw_bch_ctrl_set);
+
+	/* Hook some operations at the MTD level. */
+	if (mtd->read_oob != mxs_nand_hook_read_oob) {
+		nand_info->hooked_read_oob = mtd->read_oob;
+		mtd->read_oob = mxs_nand_hook_read_oob;
+	}
+
+	if (mtd->write_oob != mxs_nand_hook_write_oob) {
+		nand_info->hooked_write_oob = mtd->write_oob;
+		mtd->write_oob = mxs_nand_hook_write_oob;
+	}
+
+	if (mtd->block_markbad != mxs_nand_hook_block_markbad) {
+		nand_info->hooked_block_markbad = mtd->block_markbad;
+		mtd->block_markbad = mxs_nand_hook_block_markbad;
+	}
+
+	/* We use the reference implementation for bad block management. */
+	return nand_default_bbt(mtd);
+}
+
+/*
+ * Allocate DMA buffers
+ */
+int mxs_nand_alloc_buffers(struct mxs_nand_info *nand_info)
+{
+	uint8_t *buf;
+	const int size = NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE;
+
+	/* DMA buffers */
+	buf = memalign(MXS_DMA_ALIGNMENT, size);
+	if (!buf) {
+		printf("MXS NAND: Error allocating DMA buffers\n");
+		return -ENOMEM;
+	}
+
+	memset(buf, 0, size);
+
+	nand_info->data_buf = buf;
+	nand_info->oob_buf = buf + NAND_MAX_PAGESIZE;
+
+	/* Command buffers */
+	nand_info->cmd_buf = memalign(MXS_DMA_ALIGNMENT,
+				MXS_NAND_COMMAND_BUFFER_SIZE);
+	if (!nand_info->cmd_buf) {
+		free(buf);
+		printf("MXS NAND: Error allocating command buffers\n");
+		return -ENOMEM;
+	}
+	memset(nand_info->cmd_buf, 0, MXS_NAND_COMMAND_BUFFER_SIZE);
+	nand_info->cmd_queue_len = 0;
+
+	return 0;
+}
+
+/*
+ * Initializes the NFC hardware.
+ */
+int mxs_nand_init(struct mxs_nand_info *info)
+{
+	struct mx28_gpmi_regs *gpmi_regs =
+		(struct mx28_gpmi_regs *)MXS_GPMI_BASE;
+	int i = 0;
+
+	info->desc = malloc(sizeof(struct mxs_dma_desc *) *
+				MXS_NAND_DMA_DESCRIPTOR_COUNT);
+	if (!info->desc)
+		goto err1;
+
+	/* Allocate the DMA descriptors. */
+	for (i = 0; i < MXS_NAND_DMA_DESCRIPTOR_COUNT; i++) {
+		info->desc[i] = mxs_dma_desc_alloc();
+		if (!info->desc[i])
+			goto err2;
+	}
+
+	/* Init the DMA controller. */
+	mxs_dma_init();
+
+	/* Reset the GPMI block. */
+	mx28_reset_block(&gpmi_regs->hw_gpmi_ctrl0_reg);
+
+	/*
+	 * Choose NAND mode, set IRQ polarity, disable write protection and
+	 * select BCH ECC.
+	 */
+	clrsetbits_le32(&gpmi_regs->hw_gpmi_ctrl1,
+			GPMI_CTRL1_GPMI_MODE,
+			GPMI_CTRL1_ATA_IRQRDY_POLARITY | GPMI_CTRL1_DEV_RESET |
+			GPMI_CTRL1_BCH_MODE);
+
+	return 0;
+
+err2:
+	free(info->desc);
+err1:
+	for (--i; i >= 0; i--)
+		mxs_dma_desc_free(info->desc[i]);
+	printf("MXS NAND: Unable to allocate DMA descriptors\n");
+	return -ENOMEM;
+}
+
+/*!
+ * This function is called during the driver binding process.
+ *
+ * @param   pdev  the device structure used to store device specific
+ *                information that is used by the suspend, resume and
+ *                remove functions
+ *
+ * @return  The function always returns 0.
+ */
+int board_nand_init(struct nand_chip *nand)
+{
+	struct mxs_nand_info *nand_info;
+	int err;
+
+	nand_info = malloc(sizeof(struct mxs_nand_info));
+	if (!nand_info) {
+		printf("MXS NAND: Failed to allocate private data\n");
+		return -ENOMEM;
+	}
+	memset(nand_info, 0, sizeof(struct mxs_nand_info));
+
+	err = mxs_nand_alloc_buffers(nand_info);
+	if (err)
+		goto err1;
+
+	err = mxs_nand_init(nand_info);
+	if (err)
+		goto err2;
+
+	memset(&fake_ecc_layout, 0, sizeof(fake_ecc_layout));
+
+	nand->priv = nand_info;
+	nand->options |= NAND_NO_SUBPAGE_WRITE;
+
+	nand->cmd_ctrl		= mxs_nand_cmd_ctrl;
+
+	nand->dev_ready		= mxs_nand_device_ready;
+	nand->select_chip	= mxs_nand_select_chip;
+	nand->block_bad		= mxs_nand_block_bad;
+	nand->scan_bbt		= mxs_nand_scan_bbt;
+
+	nand->read_byte		= mxs_nand_read_byte;
+
+	nand->read_buf		= mxs_nand_read_buf;
+	nand->write_buf		= mxs_nand_write_buf;
+
+	nand->ecc.read_page	= mxs_nand_ecc_read_page;
+	nand->ecc.write_page	= mxs_nand_ecc_write_page;
+	nand->ecc.read_oob	= mxs_nand_ecc_read_oob;
+	nand->ecc.write_oob	= mxs_nand_ecc_write_oob;
+
+	nand->ecc.layout	= &fake_ecc_layout;
+	nand->ecc.mode		= NAND_ECC_HW;
+	nand->ecc.bytes		= 9;
+	nand->ecc.size		= 512;
+
+	return 0;
+
+err2:
+	free(nand_info->data_buf);
+	free(nand_info->cmd_buf);
+err1:
+	free(nand_info);
+	return err;
+}
-- 
1.7.5.4

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

* [U-Boot] [PATCH 10/15] iMX28: Add driver for internal RTC
  2011-09-12  4:06 [U-Boot] [PATCH 00/15 V2] Support for the DENX M28 SoM Marek Vasut
                   ` (8 preceding siblings ...)
  2011-09-12  4:06 ` [U-Boot] [PATCH 09/15] iMX28: Add GPMI NAND driver Marek Vasut
@ 2011-09-12  4:06 ` Marek Vasut
  2011-09-12  4:06 ` [U-Boot] [PATCH 11/15] iMX28: Add image header generator tool Marek Vasut
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-09-12  4:06 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 drivers/rtc/Makefile |    1 +
 drivers/rtc/mxsrtc.c |   86 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 87 insertions(+), 0 deletions(-)
 create mode 100644 drivers/rtc/mxsrtc.c

diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index ca27745..5d7da6a 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -56,6 +56,7 @@ COBJS-$(CONFIG_RTC_MK48T59) += mk48t59.o
 COBJS-$(CONFIG_RTC_MPC5200) += mpc5xxx.o
 COBJS-$(CONFIG_RTC_MPC8xx) += mpc8xx.o
 COBJS-$(CONFIG_RTC_MV) += mvrtc.o
+COBJS-$(CONFIG_RTC_MXS) += mxsrtc.o
 COBJS-$(CONFIG_RTC_PCF8563) += pcf8563.o
 COBJS-$(CONFIG_RTC_PL031) += pl031.o
 COBJS-$(CONFIG_RTC_PT7C4338) += pt7c4338.o
diff --git a/drivers/rtc/mxsrtc.c b/drivers/rtc/mxsrtc.c
new file mode 100644
index 0000000..5beb1a0
--- /dev/null
+++ b/drivers/rtc/mxsrtc.c
@@ -0,0 +1,86 @@
+/*
+ * Freescale i.MX28 RTC Driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <rtc.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+
+#define	MXS_RTC_MAX_TIMEOUT	1000000
+
+/* Set time in seconds since 1970-01-01 */
+int mxs_rtc_set_time(uint32_t secs)
+{
+	struct mx28_rtc_regs *rtc_regs = (struct mx28_rtc_regs *)MXS_RTC_BASE;
+	int ret;
+
+	writel(secs, &rtc_regs->hw_rtc_seconds);
+
+	/*
+	 * The 0x80 here means seconds were copied to analog. This information
+	 * is taken from the linux kernel driver for the STMP37xx RTC since
+	 * documentation doesn't mention it.
+	 */
+	ret = mx28_wait_mask_clr(&rtc_regs->hw_rtc_stat_reg,
+		0x80 << RTC_STAT_STALE_REGS_OFFSET, MXS_RTC_MAX_TIMEOUT);
+
+	if (ret)
+		printf("MXS RTC: Timeout waiting for update\n");
+
+	return ret;
+}
+
+int rtc_get(struct rtc_time *time)
+{
+	struct mx28_rtc_regs *rtc_regs = (struct mx28_rtc_regs *)MXS_RTC_BASE;
+	uint32_t secs;
+
+	secs = readl(&rtc_regs->hw_rtc_seconds);
+	to_tm(secs, time);
+
+	return 0;
+}
+
+int rtc_set(struct rtc_time *time)
+{
+	uint32_t secs;
+
+	secs = mktime(time->tm_year, time->tm_mon, time->tm_mday,
+		time->tm_hour, time->tm_min, time->tm_sec);
+
+	return mxs_rtc_set_time(secs);
+}
+
+void rtc_reset(void)
+{
+	struct mx28_rtc_regs *rtc_regs = (struct mx28_rtc_regs *)MXS_RTC_BASE;
+	int ret;
+
+	/* Set time to 1970-01-01 */
+	mxs_rtc_set_time(0);
+
+	/* Reset the RTC block */
+	ret = mx28_reset_block(&rtc_regs->hw_rtc_ctrl_reg);
+	if (ret)
+		printf("MXS RTC: Block reset timeout\n");
+}
-- 
1.7.5.4

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

* [U-Boot] [PATCH 11/15] iMX28: Add image header generator tool
  2011-09-12  4:06 [U-Boot] [PATCH 00/15 V2] Support for the DENX M28 SoM Marek Vasut
                   ` (9 preceding siblings ...)
  2011-09-12  4:06 ` [U-Boot] [PATCH 10/15] iMX28: Add driver for internal RTC Marek Vasut
@ 2011-09-12  4:06 ` Marek Vasut
  2011-09-12 16:38   ` Mike Frysinger
  2011-09-13 22:27   ` [U-Boot] [PATCH 11/15 V2] " Marek Vasut
  2011-09-12  4:06 ` [U-Boot] [PATCH 12/15] iMX28: Add u-boot.sb target to Makefile Marek Vasut
                   ` (4 subsequent siblings)
  15 siblings, 2 replies; 116+ messages in thread
From: Marek Vasut @ 2011-09-12  4:06 UTC (permalink / raw)
  To: u-boot

This tool can now generate proper image for "BootStream" files.

NOTE: This tool now works only for NAND.

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 tools/Makefile  |    6 +
 tools/mxsboot.c |  687 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 693 insertions(+), 0 deletions(-)
 create mode 100644 tools/mxsboot.c

diff --git a/tools/Makefile b/tools/Makefile
index fc741d3..2caac78 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -67,6 +67,7 @@ BIN_FILES-$(CONFIG_CMD_NET) += gen_eth_addr$(SFX)
 BIN_FILES-$(CONFIG_CMD_LOADS) += img2srec$(SFX)
 BIN_FILES-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes$(SFX)
 BIN_FILES-y += mkimage$(SFX)
+BIN_FILES-$(CONFIG_MX28) += mxsboot$(SFX)
 BIN_FILES-$(CONFIG_NETCONSOLE) += ncb$(SFX)
 BIN_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1$(SFX)
 
@@ -90,6 +91,7 @@ NOPED_OBJ_FILES-y += kwbimage.o
 NOPED_OBJ_FILES-y += imximage.o
 NOPED_OBJ_FILES-y += omapimage.o
 NOPED_OBJ_FILES-y += mkimage.o
+OBJ_FILES-$(CONFIG_MX28) += mxsboot.o
 OBJ_FILES-$(CONFIG_NETCONSOLE) += ncb.o
 NOPED_OBJ_FILES-y += os_support.o
 OBJ_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1.o
@@ -204,6 +206,10 @@ $(obj)mpc86x_clk$(SFX):	$(obj)mpc86x_clk.o
 	$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
 	$(HOSTSTRIP) $@
 
+$(obj)mxsboot$(SFX):	$(obj)mxsboot.o
+	$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
+	$(HOSTSTRIP) $@
+
 $(obj)ncb$(SFX):	$(obj)ncb.o
 	$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
 	$(HOSTSTRIP) $@
diff --git a/tools/mxsboot.c b/tools/mxsboot.c
new file mode 100644
index 0000000..2feda19
--- /dev/null
+++ b/tools/mxsboot.c
@@ -0,0 +1,687 @@
+/*
+ * Freescale i.MX28 image generator
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <fcntl.h>
+#include <malloc.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+/*
+ * Default BCB layout.
+ *
+ * TWEAK this if you have blown any OCOTP fuses.
+ */
+#define	STRIDE_PAGES		64
+#define	STRIDE_COUNT		4
+
+/*
+ * Layout for 256Mb big NAND with 2048b page size, 64b OOB size and
+ * 128kb erase size.
+ *
+ * TWEAK this if you have different kind of NAND chip.
+ */
+uint32_t nand_writesize = 2048;
+uint32_t nand_oobsize = 64;
+uint32_t nand_erasesize = 128 * 1024;
+
+/*
+ * Sector on which the SigmaTel boot partition (0x53) starts.
+ */
+uint32_t sd_sector = 2048;
+
+/*
+ * Each of the U-Boot bootstreams is at maximum 1MB big.
+ *
+ * TWEAK this if, for some wild reason, you need to boot bigger image.
+ */
+#define	MAX_BOOTSTREAM_SIZE	(1 * 1024 * 1024)
+
+/* i.MX28 NAND controller-specific constants. DO NOT TWEAK! */
+#define	MXS_NAND_DMA_DESCRIPTOR_COUNT		4
+#define	MXS_NAND_CHUNK_DATA_CHUNK_SIZE		512
+#define	MXS_NAND_METADATA_SIZE			10
+#define	MXS_NAND_COMMAND_BUFFER_SIZE		32
+
+struct mx28_nand_fcb {
+	uint32_t		checksum;
+	uint32_t		fingerprint;
+	uint32_t		version;
+	struct {
+		uint8_t			data_setup;
+		uint8_t			data_hold;
+		uint8_t			address_setup;
+		uint8_t			dsample_time;
+		uint8_t			nand_timing_state;
+		uint8_t			rea;
+		uint8_t			rloh;
+		uint8_t			rhoh;
+	}			timing;
+	uint32_t		page_data_size;
+	uint32_t		total_page_size;
+	uint32_t		sectors_per_block;
+	uint32_t		number_of_nands;		/* Ignored */
+	uint32_t		total_internal_die;		/* Ignored */
+	uint32_t		cell_type;			/* Ignored */
+	uint32_t		ecc_block_n_ecc_type;
+	uint32_t		ecc_block_0_size;
+	uint32_t		ecc_block_n_size;
+	uint32_t		ecc_block_0_ecc_type;
+	uint32_t		metadata_bytes;
+	uint32_t		num_ecc_blocks_per_page;
+	uint32_t		ecc_block_n_ecc_level_sdk;	/* Ignored */
+	uint32_t		ecc_block_0_size_sdk;		/* Ignored */
+	uint32_t		ecc_block_n_size_sdk;		/* Ignored */
+	uint32_t		ecc_block_0_ecc_level_sdk;	/* Ignored */
+	uint32_t		num_ecc_blocks_per_page_sdk;	/* Ignored */
+	uint32_t		metadata_bytes_sdk;		/* Ignored */
+	uint32_t		erase_threshold;
+	uint32_t		boot_patch;
+	uint32_t		patch_sectors;
+	uint32_t		firmware1_starting_sector;
+	uint32_t		firmware2_starting_sector;
+	uint32_t		sectors_in_firmware1;
+	uint32_t		sectors_in_firmware2;
+	uint32_t		dbbt_search_area_start_address;
+	uint32_t		badblock_marker_byte;
+	uint32_t		badblock_marker_start_bit;
+	uint32_t		bb_marker_physical_offset;
+};
+
+struct mx28_nand_dbbt {
+	uint32_t		checksum;
+	uint32_t		fingerprint;
+	uint32_t		version;
+	uint32_t		number_bb;
+	uint32_t		number_2k_pages_bb;
+};
+
+struct mx28_nand_bbt {
+	uint32_t		nand;
+	uint32_t		number_bb;
+	uint32_t		badblock[510];
+};
+
+struct mx28_sd_drive_info {
+	uint32_t		chip_num;
+	uint32_t		drive_type;
+	uint32_t		tag;
+	uint32_t		first_sector_number;
+	uint32_t		sector_count;
+};
+
+struct mx28_sd_config_block {
+	uint32_t			signature;
+	uint32_t			primary_boot_tag;
+	uint32_t			secondary_boot_tag;
+	uint32_t			num_copies;
+	struct mx28_sd_drive_info	drv_info[1];
+};
+
+static inline uint32_t mx28_nand_ecc_size_in_bits(uint32_t ecc_strength)
+{
+	return ecc_strength * 13;
+}
+
+static inline uint32_t mx28_nand_get_ecc_strength(uint32_t page_data_size,
+						uint32_t page_oob_size)
+{
+	if (page_data_size == 2048)
+		return 8;
+
+	if (page_data_size == 4096) {
+		if (page_oob_size == 128)
+			return 8;
+
+		if (page_oob_size == 218)
+			return 16;
+	}
+
+	return 0;
+}
+
+static inline uint32_t mx28_nand_get_mark_offset(uint32_t page_data_size,
+						uint32_t ecc_strength)
+{
+	uint32_t chunk_data_size_in_bits;
+	uint32_t chunk_ecc_size_in_bits;
+	uint32_t chunk_total_size_in_bits;
+	uint32_t block_mark_chunk_number;
+	uint32_t block_mark_chunk_bit_offset;
+	uint32_t block_mark_bit_offset;
+
+	chunk_data_size_in_bits = MXS_NAND_CHUNK_DATA_CHUNK_SIZE * 8;
+	chunk_ecc_size_in_bits  = mx28_nand_ecc_size_in_bits(ecc_strength);
+
+	chunk_total_size_in_bits =
+			chunk_data_size_in_bits + chunk_ecc_size_in_bits;
+
+	/* Compute the bit offset of the block mark within the physical page. */
+	block_mark_bit_offset = page_data_size * 8;
+
+	/* Subtract the metadata bits. */
+	block_mark_bit_offset -= MXS_NAND_METADATA_SIZE * 8;
+
+	/*
+	 * Compute the chunk number (starting at zero) in which the block mark
+	 * appears.
+	 */
+	block_mark_chunk_number =
+			block_mark_bit_offset / chunk_total_size_in_bits;
+
+	/*
+	 * Compute the bit offset of the block mark within its chunk, and
+	 * validate it.
+	 */
+	block_mark_chunk_bit_offset = block_mark_bit_offset -
+			(block_mark_chunk_number * chunk_total_size_in_bits);
+
+	if (block_mark_chunk_bit_offset > chunk_data_size_in_bits)
+		return 1;
+
+	/*
+	 * Now that we know the chunk number in which the block mark appears,
+	 * we can subtract all the ECC bits that appear before it.
+	 */
+	block_mark_bit_offset -=
+		block_mark_chunk_number * chunk_ecc_size_in_bits;
+
+	return block_mark_bit_offset;
+}
+
+static inline uint32_t mx28_nand_mark_byte_offset(void)
+{
+	uint32_t ecc_strength;
+	ecc_strength = mx28_nand_get_ecc_strength(nand_writesize, nand_oobsize);
+	return mx28_nand_get_mark_offset(nand_writesize, ecc_strength) >> 3;
+}
+
+static inline uint32_t mx28_nand_mark_bit_offset(void)
+{
+	uint32_t ecc_strength;
+	ecc_strength = mx28_nand_get_ecc_strength(nand_writesize, nand_oobsize);
+	return mx28_nand_get_mark_offset(nand_writesize, ecc_strength) & 0x7;
+}
+
+static uint32_t mx28_nand_block_csum(uint8_t *block, uint32_t size)
+{
+	uint32_t csum = 0;
+	int i;
+
+	for (i = 0; i < size; i++)
+		csum += block[i];
+
+	return csum ^ 0xffffffff;
+}
+
+static struct mx28_nand_fcb *mx28_nand_get_fcb(uint32_t size)
+{
+	struct mx28_nand_fcb *fcb;
+	uint32_t bcb_size_bytes;
+	uint32_t stride_size_bytes;
+	uint32_t bootstream_size_pages;
+	uint32_t fw1_start_page;
+	uint32_t fw2_start_page;
+
+	fcb = malloc(nand_writesize);
+	if (!fcb) {
+		printf("MX28 NAND: Unable to allocate FCB\n");
+		return NULL;
+	}
+
+	memset(fcb, 0, nand_writesize);
+
+	fcb->fingerprint =			0x20424346;
+	fcb->version =				0x01000000;
+
+	/*
+	 * FIXME: These here are default values as found in kobs-ng. We should
+	 * probably retrieve the data from NAND or something.
+	 */
+	fcb->timing.data_setup =		80;
+	fcb->timing.data_hold =			60;
+	fcb->timing.address_setup =		25;
+	fcb->timing.dsample_time =		6;
+
+	fcb->page_data_size =		nand_writesize;
+	fcb->total_page_size =		nand_writesize + nand_oobsize;
+	fcb->sectors_per_block =	nand_erasesize / nand_writesize;
+
+	fcb->num_ecc_blocks_per_page =	(nand_writesize / 512) - 1;
+	fcb->ecc_block_0_size =		512;
+	fcb->ecc_block_n_size =		512;
+	fcb->metadata_bytes =		10;
+
+	if (nand_writesize == 2048) {
+		fcb->ecc_block_n_ecc_type =		4;
+		fcb->ecc_block_0_ecc_type =		4;
+	} else if (nand_writesize == 4096) {
+		if (nand_oobsize == 128) {
+			fcb->ecc_block_n_ecc_type =	4;
+			fcb->ecc_block_0_ecc_type =	4;
+		} else if (nand_oobsize == 218) {
+			fcb->ecc_block_n_ecc_type =	8;
+			fcb->ecc_block_0_ecc_type =	8;
+		}
+	}
+
+	if (fcb->ecc_block_n_ecc_type == 0) {
+		printf("MX28 NAND: Unsupported NAND geometry\n");
+		goto err;
+	}
+
+	fcb->boot_patch =			0;
+	fcb->patch_sectors =			0;
+
+	fcb->badblock_marker_byte =	mx28_nand_mark_byte_offset();
+	fcb->badblock_marker_start_bit = mx28_nand_mark_bit_offset();
+	fcb->bb_marker_physical_offset = nand_writesize;
+
+	stride_size_bytes = STRIDE_PAGES * nand_writesize;
+	bcb_size_bytes = stride_size_bytes * STRIDE_COUNT;
+
+	bootstream_size_pages = (size + (nand_writesize - 1)) /
+					nand_writesize;
+
+	fw1_start_page = 2 * bcb_size_bytes / nand_writesize;
+	fw2_start_page = (2 * bcb_size_bytes + MAX_BOOTSTREAM_SIZE) /
+				nand_writesize;
+
+	fcb->firmware1_starting_sector =	fw1_start_page;
+	fcb->firmware2_starting_sector =	fw2_start_page;
+	fcb->sectors_in_firmware1 =		bootstream_size_pages;
+	fcb->sectors_in_firmware2 =		bootstream_size_pages;
+
+	fcb->dbbt_search_area_start_address =	STRIDE_PAGES * STRIDE_COUNT;
+
+	return fcb;
+
+err:
+	free(fcb);
+	return NULL;
+}
+
+static struct mx28_nand_dbbt *mx28_nand_get_dbbt(void)
+{
+	struct mx28_nand_dbbt *dbbt;
+
+	dbbt = malloc(nand_writesize);
+	if (!dbbt) {
+		printf("MX28 NAND: Unable to allocate DBBT\n");
+		return NULL;
+	}
+
+	memset(dbbt, 0, nand_writesize);
+
+	dbbt->fingerprint	= 0x54424244;
+	dbbt->version		= 0x1;
+
+	return dbbt;
+}
+
+static inline uint8_t mx28_nand_parity_13_8(const uint8_t b)
+{
+	uint32_t parity = 0, tmp;
+
+	tmp = ((b >> 6) ^ (b >> 5) ^ (b >> 3) ^ (b >> 2)) & 1;
+	parity |= tmp << 0;
+
+	tmp = ((b >> 7) ^ (b >> 5) ^ (b >> 4) ^ (b >> 2) ^ (b >> 1)) & 1;
+	parity |= tmp << 1;
+
+	tmp = ((b >> 7) ^ (b >> 6) ^ (b >> 5) ^ (b >> 1) ^ (b >> 0)) & 1;
+	parity |= tmp << 2;
+
+	tmp = ((b >> 7) ^ (b >> 4) ^ (b >> 3) ^ (b >> 0)) & 1;
+	parity |= tmp << 3;
+
+	tmp = ((b >> 6) ^ (b >> 4) ^ (b >> 3) ^
+		(b >> 2) ^ (b >> 1) ^ (b >> 0)) & 1;
+	parity |= tmp << 4;
+
+	return parity;
+}
+
+static uint8_t *mx28_nand_fcb_block(struct mx28_nand_fcb *fcb)
+{
+	uint8_t *block;
+	uint8_t *ecc;
+	int i;
+
+	block = malloc(nand_writesize + nand_oobsize);
+	if (!block) {
+		printf("MX28 NAND: Unable to allocate FCB block\n");
+		return NULL;
+	}
+
+	memset(block, 0, nand_writesize + nand_oobsize);
+
+	/* Update the FCB checksum */
+	fcb->checksum = mx28_nand_block_csum(((uint8_t *)fcb) + 4, 508);
+
+	/* Figure 12-11. in iMX28RM, rev. 1, says FCB is at offset 12 */
+	memcpy(block + 12, fcb, sizeof(struct mx28_nand_fcb));
+
+	/* ECC is at offset 12 + 512 */
+	ecc = block + 12 + 512;
+
+	/* Compute the ECC parity */
+	for (i = 0; i < sizeof(struct mx28_nand_fcb); i++)
+		ecc[i] = mx28_nand_parity_13_8(block[i + 12]);
+
+	return block;
+}
+
+static int mx28_nand_write_fcb(struct mx28_nand_fcb *fcb, char *buf)
+{
+	uint32_t offset;
+	uint8_t *fcbblock;
+	int ret = 0;
+	int i;
+
+	fcbblock = mx28_nand_fcb_block(fcb);
+	if (!fcbblock)
+		return -1;
+
+	for (i = 0; i < STRIDE_PAGES * STRIDE_COUNT; i += STRIDE_PAGES) {
+		offset = i * nand_writesize;
+		memcpy(buf + offset, fcbblock, nand_writesize + nand_oobsize);
+	}
+
+	free(fcbblock);
+	return ret;
+}
+
+static int mx28_nand_write_dbbt(struct mx28_nand_dbbt *dbbt, char *buf)
+{
+	uint32_t offset;
+	int i = STRIDE_PAGES * STRIDE_COUNT;
+
+	for (; i < 2 * STRIDE_PAGES * STRIDE_COUNT; i += STRIDE_PAGES) {
+		offset = i * nand_writesize;
+		memcpy(buf + offset, dbbt, sizeof(struct mx28_nand_dbbt));
+	}
+
+	return 0;
+}
+
+static int mx28_nand_write_firmware(struct mx28_nand_fcb *fcb, int infd,
+					char *buf)
+{
+	int ret;
+	off_t size;
+	uint32_t offset1, offset2;
+
+	size = lseek(infd, 0, SEEK_END);
+	lseek(infd, 0, SEEK_SET);
+
+	offset1 = fcb->firmware1_starting_sector * nand_writesize;
+	offset2 = fcb->firmware2_starting_sector * nand_writesize;
+
+	ret = read(infd, buf + offset1, size);
+	if (ret != size)
+		return -1;
+
+	memcpy(buf + offset2, buf + offset1, size);
+
+	return 0;
+}
+
+void usage(void)
+{
+	printf(
+		"Usage: mx28image [ops] <type> <infile> <outfile>\n"
+		"Augment BootStream file with a proper header for i.MX28 boot\n"
+		"\n"
+		"  <type>	type of image:\n"
+		"                 \"nand\" for NAND image\n"
+		"                 \"sd\" for SD image\n"
+		"  <infile>     input file, the u-boot.sb bootstream\n"
+		"  <outfile>    output file, the bootable image\n"
+		"\n");
+	printf(
+		"For NAND boot, these options are accepted:\n"
+		"  -w <size>    NAND page size\n"
+		"  -o <size>    NAND OOB size\n"
+		"  -e <size>    NAND erase size\n"
+		"\n"
+		"For SD boot, these options are accepted:\n"
+		"  -p <sector>  Sector where the SGTL partition starts\n"
+	);
+}
+
+static int mx28_create_nand_image(int infd, int outfd)
+{
+	struct mx28_nand_fcb *fcb;
+	struct mx28_nand_dbbt *dbbt;
+	int ret = -1;
+	char *buf;
+	int size;
+	ssize_t wr_size;
+
+	size = nand_writesize * 512 + 2 * MAX_BOOTSTREAM_SIZE;
+
+	buf = malloc(size);
+	if (!buf) {
+		printf("Can not allocate output buffer of %d bytes\n", size);
+		goto err0;
+	}
+
+	memset(buf, 0, size);
+
+	fcb = mx28_nand_get_fcb(MAX_BOOTSTREAM_SIZE);
+	if (!fcb) {
+		printf("Unable to compile FCB\n");
+		goto err1;
+	}
+
+	dbbt = mx28_nand_get_dbbt();
+	if (!dbbt) {
+		printf("Unable to compile DBBT\n");
+		goto err2;
+	}
+
+	ret = mx28_nand_write_fcb(fcb, buf);
+	if (ret) {
+		printf("Unable to write FCB to buffer\n");
+		goto err3;
+	}
+
+	ret = mx28_nand_write_dbbt(dbbt, buf);
+	if (ret) {
+		printf("Unable to write DBBT to buffer\n");
+		goto err3;
+	}
+
+	ret = mx28_nand_write_firmware(fcb, infd, buf);
+	if (ret) {
+		printf("Unable to write firmware to buffer\n");
+		goto err3;
+	}
+
+	wr_size = write(outfd, buf, size);
+	if (wr_size != size) {
+		ret = -1;
+		goto err3;
+	}
+
+	ret = 0;
+
+err3:
+	free(dbbt);
+err2:
+	free(fcb);
+err1:
+	free(buf);
+err0:
+	return ret;
+}
+
+static int mx28_create_sd_image(int infd, int outfd)
+{
+	int ret = -1;
+	uint32_t *buf;
+	int size;
+	off_t fsize;
+	ssize_t wr_size;
+	struct mx28_sd_config_block *cb;
+
+	fsize = lseek(infd, 0, SEEK_END);
+	lseek(infd, 0, SEEK_SET);
+	size = fsize + 512;
+
+	buf = malloc(size);
+	if (!buf) {
+		printf("Can not allocate output buffer of %d bytes\n", size);
+		goto err0;
+	}
+
+	ret = read(infd, (uint8_t *)buf + 512, fsize);
+	if (ret != fsize) {
+		ret = -1;
+		goto err1;
+	}
+
+	cb = (struct mx28_sd_config_block *)buf;
+
+	cb->signature = 0x00112233;
+	cb->primary_boot_tag = 0x1;
+	cb->secondary_boot_tag = 0x1;
+	cb->num_copies = 1;
+	cb->drv_info[0].chip_num = 0x0;
+	cb->drv_info[0].drive_type = 0x0;
+	cb->drv_info[0].tag = 0x1;
+	cb->drv_info[0].first_sector_number = sd_sector + 1;
+	cb->drv_info[0].sector_count = (size - 1) / 512;
+
+	wr_size = write(outfd, buf, size);
+	if (wr_size != size) {
+		ret = -1;
+		goto err1;
+	}
+
+	ret = 0;
+
+err1:
+	free(buf);
+err0:
+	return ret;
+}
+
+int parse_ops(int argc, char **argv)
+{
+	int i;
+	int tmp;
+	char *end;
+	enum param {
+		PARAM_WRITE,
+		PARAM_OOB,
+		PARAM_ERASE,
+		PARAM_PART,
+		PARAM_SD,
+		PARAM_NAND
+	};
+	int type;
+
+	for (i = 1; i < argc; i++) {
+		if (!strncmp(argv[i], "-w", 2))
+			type = PARAM_WRITE;
+		else if (!strncmp(argv[i], "-o", 2))
+			type = PARAM_OOB;
+		else if (!strncmp(argv[i], "-e", 2))
+			type = PARAM_ERASE;
+		else if (!strncmp(argv[i], "-p", 2))
+			type = PARAM_PART;
+		else	/* SD/MMC */
+			break;
+
+		tmp = strtol(argv[++i], &end, 10);
+		if (tmp % 2)
+			return -1;
+		if (tmp <= 0)
+			return -1;
+
+		if (type == PARAM_WRITE)
+			nand_writesize = tmp;
+		if (type == PARAM_OOB)
+			nand_oobsize = tmp;
+		if (type == PARAM_ERASE)
+			nand_erasesize = tmp;
+		if (type == PARAM_PART)
+			sd_sector = tmp;
+	}
+
+	if (strcmp(argv[i], "sd") && strcmp(argv[i], "nand"))
+		return -1;
+
+	if (i + 3 != argc)
+		return -1;
+
+	return i;
+}
+
+int main(int argc, char **argv)
+{
+	int infd, outfd;
+	int ret = 0;
+	int offset;
+
+	offset = parse_ops(argc, argv);
+	if (offset < 0) {
+		usage();
+		ret = 1;
+		goto err1;
+	}
+
+	infd = open(argv[offset + 1], O_RDONLY);
+	if (infd < 0) {
+		printf("Input BootStream file can not be opened\n");
+		ret = 2;
+		goto err1;
+	}
+
+	outfd = open(argv[offset + 2], O_CREAT | O_TRUNC | O_WRONLY,
+					S_IRUSR | S_IWUSR);
+	if (outfd < 0) {
+		printf("Output file can not be created\n");
+		ret = 3;
+		goto err2;
+	}
+
+	if (!strcmp(argv[offset], "sd"))
+		ret = mx28_create_sd_image(infd, outfd);
+	else if (!strcmp(argv[offset], "nand"))
+		ret = mx28_create_nand_image(infd, outfd);
+
+	close(outfd);
+err2:
+	close(infd);
+err1:
+	return ret;
+}
-- 
1.7.5.4

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

* [U-Boot] [PATCH 12/15] iMX28: Add u-boot.sb target to Makefile
  2011-09-12  4:06 [U-Boot] [PATCH 00/15 V2] Support for the DENX M28 SoM Marek Vasut
                   ` (10 preceding siblings ...)
  2011-09-12  4:06 ` [U-Boot] [PATCH 11/15] iMX28: Add image header generator tool Marek Vasut
@ 2011-09-12  4:06 ` Marek Vasut
  2011-09-12 16:33   ` Mike Frysinger
  2011-09-13 22:28   ` [U-Boot] [PATCH 12/15 V2] " Marek Vasut
  2011-09-12  4:06 ` [U-Boot] [PATCH 13/15] iMX28: Add support for DENX M28EVK board Marek Vasut
                   ` (3 subsequent siblings)
  15 siblings, 2 replies; 116+ messages in thread
From: Marek Vasut @ 2011-09-12  4:06 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 Makefile |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/Makefile b/Makefile
index ee05fb3..69dfe88 100644
--- a/Makefile
+++ b/Makefile
@@ -398,6 +398,10 @@ $(obj)u-boot.ubl:       $(obj)u-boot-nand.bin
 		$(obj)tools/mkimage -n $(UBL_CONFIG) -T ublimage \
 		-e $(CONFIG_SYS_TEXT_BASE) -d $< $@
 
+$(obj)u-boot.sb:       $(obj)u-boot.bin $(obj)spl/u-boot-spl.bin
+		elftosb -zdf imx28 -c board/denx/m28evk/u-boot.bd \
+			-o $(obj)u-boot.sb
+
 GEN_UBOOT = \
 		UNDEF_SYM=`$(OBJDUMP) -x $(LIBBOARD) $(LIBS) | \
 		sed  -n -e 's/.*\($(SYM_PREFIX)__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
@@ -980,6 +984,7 @@ clobber:	clean
 	@rm -f $(obj)u-boot.kwb
 	@rm -f $(obj)u-boot.imx
 	@rm -f $(obj)u-boot.ubl
+	@rm -f $(obj)u-boot.sb
 	@rm -f $(obj)tools/{env/crc32.c,inca-swap-bytes}
 	@rm -f $(obj)arch/powerpc/cpu/mpc824x/bedbug_603e.c
 	@rm -fr $(obj)include/asm/proc $(obj)include/asm/arch $(obj)include/asm
-- 
1.7.5.4

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

* [U-Boot] [PATCH 13/15] iMX28: Add support for DENX M28EVK board
  2011-09-12  4:06 [U-Boot] [PATCH 00/15 V2] Support for the DENX M28 SoM Marek Vasut
                   ` (11 preceding siblings ...)
  2011-09-12  4:06 ` [U-Boot] [PATCH 12/15] iMX28: Add u-boot.sb target to Makefile Marek Vasut
@ 2011-09-12  4:06 ` Marek Vasut
  2011-09-13 22:29   ` [U-Boot] [PATCH 13/15 V2] " Marek Vasut
  2011-09-12  4:06 ` [U-Boot] [PATCH 14/15] M28: Add MMC SPL Marek Vasut
                   ` (2 subsequent siblings)
  15 siblings, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-09-12  4:06 UTC (permalink / raw)
  To: u-boot

This contains support for the following components:
- DUART
- MMC
- Both FEC interfaces
- NAND
- I2C (RTC, EEPROM)
- SPI (FLASH)

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 MAINTAINERS                |    1 +
 board/denx/m28evk/Makefile |   49 ++++++++
 board/denx/m28evk/m28evk.c |  195 ++++++++++++++++++++++++++++++
 boards.cfg                 |    1 +
 include/configs/m28evk.h   |  281 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 527 insertions(+), 0 deletions(-)
 create mode 100644 board/denx/m28evk/Makefile
 create mode 100644 board/denx/m28evk/m28evk.c
 create mode 100644 include/configs/m28evk.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 2f60a60..61a55a8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -847,6 +847,7 @@ Marek Vasut <marek.vasut@gmail.com>
 	palmtc		xscale/pxa
 	vpac270		xscale/pxa
 	zipitz2		xscale/pxa
+	m28evk		i.MX28
  	efikamx		i.MX51
 
 Hugo Villeneuve <hugo.villeneuve@lyrtech.com>
diff --git a/board/denx/m28evk/Makefile b/board/denx/m28evk/Makefile
new file mode 100644
index 0000000..4037199
--- /dev/null
+++ b/board/denx/m28evk/Makefile
@@ -0,0 +1,49 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(BOARD).o
+
+COBJS	:= m28evk.o
+
+SRCS	:= $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+clean:
+	rm -f $(OBJS)
+
+distclean:	clean
+	rm -f $(LIB) core *.bak .depend
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/denx/m28evk/m28evk.c b/board/denx/m28evk/m28evk.c
new file mode 100644
index 0000000..118e222
--- /dev/null
+++ b/board/denx/m28evk/m28evk.c
@@ -0,0 +1,195 @@
+/*
+ * DENX M28 module
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/iomux-mx28.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sys_proto.h>
+#include <linux/mii.h>
+#include <miiphy.h>
+#include <netdev.h>
+#include <errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Functions
+ */
+int board_early_init_f(void)
+{
+	/* IO0 clock at 480MHz */
+	mx28_set_ioclk(MXC_IOCLK0, 480000);
+	/* IO1 clock at 480MHz */
+	mx28_set_ioclk(MXC_IOCLK1, 480000);
+
+	/* SSP0 clock at 96MHz */
+	mx28_set_sspclk(MXC_SSPCLK0, 96000, 0);
+	/* SSP2 clock at 96MHz */
+	mx28_set_sspclk(MXC_SSPCLK2, 96000, 0);
+
+	return 0;
+}
+
+int board_init(void)
+{
+	/* Adress of boot parameters */
+	gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
+
+	return 0;
+}
+
+int dram_init(void)
+{
+	/* dram_init must store complete ramsize in gd->ram_size */
+	gd->ram_size = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE);
+	return 0;
+}
+
+#ifdef	CONFIG_CMD_MMC
+static int m28_mmc_wp(int id)
+{
+	if (id != 0) {
+		printf("MXS MMC: Invalid card selected (card id = %d)\n", id);
+		return 1;
+	}
+
+	return gpio_get_value(MX28_PAD_AUART2_CTS__GPIO_3_10);
+}
+
+int board_mmc_init(bd_t *bis)
+{
+	/* Configure WP as output */
+	gpio_direction_input(MX28_PAD_AUART2_CTS__GPIO_3_10);
+
+	return mxsmmc_initialize(bis, 0, m28_mmc_wp);
+}
+#endif
+
+#ifdef	CONFIG_CMD_NET
+
+#define	MII_OPMODE_STRAP_OVERRIDE	0x16
+#define	MII_PHY_CTRL1			0x1e
+#define	MII_PHY_CTRL2			0x1f
+
+int fecmxc_mii_postcall(int phy)
+{
+	miiphy_write("FEC1", phy, MII_BMCR, 0x9000);
+	miiphy_write("FEC1", phy, MII_OPMODE_STRAP_OVERRIDE, 0x0202);
+	if (phy == 3)
+		miiphy_write("FEC1", 3, MII_PHY_CTRL2, 0x8180);
+	return 0;
+}
+
+int board_eth_init(bd_t *bis)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	struct eth_device *dev;
+	int ret;
+
+	ret = cpu_eth_init(bis);
+
+	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_enet,
+		CLKCTRL_ENET_TIME_SEL_MASK | CLKCTRL_ENET_CLK_OUT_EN,
+		CLKCTRL_ENET_TIME_SEL_RMII_CLK);
+
+	ret = fecmxc_initialize_multi(bis, 0, 0, MXS_ENET0_BASE);
+	if (ret) {
+		printf("FEC MXS: Unable to init FEC0\n");
+		return ret;
+	}
+
+	ret = fecmxc_initialize_multi(bis, 1, 3, MXS_ENET1_BASE);
+	if (ret) {
+		printf("FEC MXS: Unable to init FEC1\n");
+		return ret;
+	}
+
+	dev = eth_get_dev_by_name("FEC0");
+	if (!dev) {
+		printf("FEC MXS: Unable to get FEC0 device entry\n");
+		return -EINVAL;
+	}
+
+	ret = fecmxc_register_mii_postcall(dev, fecmxc_mii_postcall);
+	if (ret) {
+		printf("FEC MXS: Unable to register FEC0 mii postcall\n");
+		return ret;
+	}
+
+	dev = eth_get_dev_by_name("FEC1");
+	if (!dev) {
+		printf("FEC MXS: Unable to get FEC1 device entry\n");
+		return -EINVAL;
+	}
+
+	ret = fecmxc_register_mii_postcall(dev, fecmxc_mii_postcall);
+	if (ret) {
+		printf("FEC MXS: Unable to register FEC1 mii postcall\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+#ifdef	CONFIG_M28_FEC_MAC_IN_OCOTP
+
+#define	MXS_OCOTP_MAX_TIMEOUT	1000000
+void imx_get_mac_from_fuse(char *mac)
+{
+	struct mx28_ocotp_regs *ocotp_regs =
+		(struct mx28_ocotp_regs *)MXS_OCOTP_BASE;
+	uint32_t data;
+
+	memset(mac, 0, 6);
+
+	writel(OCOTP_CTRL_RD_BANK_OPEN, &ocotp_regs->hw_ocotp_ctrl_set);
+
+	if (mx28_wait_mask_clr(&ocotp_regs->hw_ocotp_ctrl_reg, OCOTP_CTRL_BUSY,
+				MXS_OCOTP_MAX_TIMEOUT)) {
+		printf("MXS FEC: Can't get MAC from OCOTP\n");
+		return;
+	}
+
+	data = readl(&ocotp_regs->hw_ocotp_cust0);
+
+	mac[0] = 0x00;
+	mac[1] = 0x04;
+	mac[2] = (data >> 24) & 0xff;
+	mac[3] = (data >> 16) & 0xff;
+	mac[4] = (data >> 8) & 0xff;
+	mac[5] = data & 0xff;
+}
+#else
+void imx_get_mac_from_fuse(char *mac)
+{
+	memset(mac, 0, 6);
+}
+#endif
+
+#endif
diff --git a/boards.cfg b/boards.cfg
index 8a5bfc1..c5d8a90 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -147,6 +147,7 @@ jadecpu                      arm         arm926ejs   jadecpu             syteco
 zmx25                        arm         arm926ejs   zmx25               syteco         mx25
 imx27lite                    arm         arm926ejs   imx27lite           logicpd        mx27
 magnesium                    arm         arm926ejs   imx27lite           logicpd        mx27
+m28evk                       arm         arm926ejs   -                   denx           mx28
 nhk8815                      arm         arm926ejs   nhk8815             st             nomadik
 nhk8815_onenand              arm         arm926ejs   nhk8815             st             nomadik       nhk8815:BOOT_ONENAND
 omap5912osk                  arm         arm926ejs   -                   ti             omap
diff --git a/include/configs/m28evk.h b/include/configs/m28evk.h
new file mode 100644
index 0000000..c50f104
--- /dev/null
+++ b/include/configs/m28evk.h
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef __M28_H__
+#define __M28_H__
+
+#include <asm/arch/regs-base.h>
+
+/*
+ * SoC configurations
+ */
+#define	CONFIG_MX28				/* i.MX28 SoC */
+#define	CONFIG_MXS_GPIO				/* GPIO control */
+#define	CONFIG_SYS_HZ		1000		/* Ticks per second */
+
+/*
+ * Define M28EVK machine type by hand until it lands in mach-types
+ */
+#define	MACH_TYPE_M28EVK	3613
+
+#define	CONFIG_MACH_TYPE	MACH_TYPE_M28EVK
+
+#define	CONFIG_SYS_NO_FLASH
+#define	CONFIG_SYS_ICACHE_OFF
+#define	CONFIG_SYS_DCACHE_OFF
+#define	CONFIG_BOARD_EARLY_INIT_F
+#define	CONFIG_ARCH_CPU_INIT
+
+/*
+ * U-Boot Commands
+ */
+#include <config_cmd_default.h>
+#define	CONFIG_DISPLAY_CPUINFO
+#define	CONFIG_DOS_PARTITION
+
+#define	CONFIG_CMD_CACHE
+#define	CONFIG_CMD_DATE
+#define	CONFIG_CMD_DHCP
+#define	CONFIG_CMD_EEPROM
+#define	CONFIG_CMD_EXT2
+#define	CONFIG_CMD_FAT
+#define	CONFIG_CMD_GPIO
+#define	CONFIG_CMD_I2C
+#define	CONFIG_CMD_MII
+#define	CONFIG_CMD_MMC
+#define	CONFIG_CMD_NAND
+#define	CONFIG_CMD_NET
+#define	CONFIG_CMD_NFS
+#define	CONFIG_CMD_PING
+#define	CONFIG_CMD_SETEXPR
+#define	CONFIG_CMD_SF
+#define	CONFIG_CMD_SPI
+
+/*
+ * Memory configurations
+ */
+#define	CONFIG_NR_DRAM_BANKS		1		/* 2 banks of DRAM */
+#define	PHYS_SDRAM_1			0x40000000	/* Base address */
+#define	PHYS_SDRAM_1_SIZE		0x10000000	/* 256 MB */
+#define	CONFIG_STACKSIZE		0x00010000	/* 128 KB stack */
+#define	CONFIG_SYS_MALLOC_LEN		0x00400000	/* 4 MB for malloc */
+#define	CONFIG_SYS_GBL_DATA_SIZE	128		/* Initial data */
+#define	CONFIG_SYS_MEMTEST_START	0x40000000	/* Memtest start adr */
+#define	CONFIG_SYS_MEMTEST_END		0x40400000	/* 4 MB RAM test */
+#define	CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM_1
+/* Point initial SP in SRAM so SPL can use it too. */
+#define	CONFIG_SYS_INIT_SP_ADDR		0x00002000
+/*
+ * We need to sacrifice first 4 bytes of RAM here to avoid triggering some
+ * strange BUG in ROM corrupting first 4 bytes of RAM when loading U-Boot
+ * binary. In case there was more of this mess, 0x100 bytes are skipped.
+ */
+#define	CONFIG_SYS_TEXT_BASE		0x40000100
+
+/*
+ * U-Boot general configurations
+ */
+#define	CONFIG_SYS_LONGHELP
+#define	CONFIG_SYS_PROMPT	"=> "
+#define	CONFIG_SYS_CBSIZE	1024		/* Console I/O buffer size */
+#define	CONFIG_SYS_PBSIZE	\
+	(CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+						/* Print buffer size */
+#define	CONFIG_SYS_MAXARGS	32		/* Max number of command args */
+#define	CONFIG_SYS_BARGSIZE	CONFIG_SYS_CBSIZE
+						/* Boot argument buffer size */
+#define	CONFIG_VERSION_VARIABLE			/* U-BOOT version */
+#define	CONFIG_AUTO_COMPLETE			/* Command auto complete */
+#define	CONFIG_CMDLINE_EDITING			/* Command history etc */
+#define	CONFIG_SYS_HUSH_PARSER
+#define	CONFIG_SYS_PROMPT_HUSH_PS2	"> "
+
+/*
+ * Serial Driver
+ */
+#define	CONFIG_PL011_SERIAL
+#define	CONFIG_PL011_CLOCK		24000000
+#define	CONFIG_PL01x_PORTS		{ (void *)MXS_UARTDBG_BASE }
+#define	CONFIG_CONS_INDEX		0
+#define	CONFIG_BAUDRATE			115200	/* Default baud rate */
+#define	CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 }
+
+/*
+ * MMC Driver
+ */
+#ifdef	CONFIG_CMD_MMC
+#define	CONFIG_MMC
+#define	CONFIG_GENERIC_MMC
+#define	CONFIG_MXS_MMC
+#endif
+
+/*
+ * NAND
+ */
+#ifdef	CONFIG_CMD_NAND
+#define	CONFIG_NAND_MXS
+#define CONFIG_APBH_DMA
+#define	CONFIG_SYS_MAX_NAND_DEVICE	1
+#define	CONFIG_SYS_NAND_BASE		0x60000000
+#define	CONFIG_SYS_NAND_5_ADDR_CYCLE
+#define	NAND_MAX_CHIPS			8
+
+/* Environment is in NAND */
+#define	CONFIG_ENV_IS_IN_NAND		1
+#define	CONFIG_ENV_SECT_SIZE		(128 * 1024)
+#define	CONFIG_ENV_SIZE			(16 * 1024)
+#define	CONFIG_ENV_SIZE_REDUND		CONFIG_ENV_SIZE
+#define	CONFIG_ENV_OFFSET		0x300000
+#define	CONFIG_ENV_OFFSET_REDUND	\
+		(CONFIG_ENV_OFFSET + CONFIG_ENV_SECT_SIZE)
+
+#define	CONFIG_CMD_UBI
+#define	CONFIG_CMD_UBIFS
+#define	CONFIG_CMD_MTDPARTS
+#define	CONFIG_RBTREE
+#define	CONFIG_LZO
+#define	CONFIG_MTD_DEVICE
+#define	CONFIG_MTD_PARTITIONS
+#define	MTDIDS_DEFAULT			"nand0=gpmi-nand.0"
+#define	MTDPARTS_DEFAULT			\
+	"mtdparts=gpmi-nand.0:"			\
+		"3m(bootloader)ro,"		\
+		"128k(environment),"		\
+		"128k(redundant-environment),"	\
+		"4m(kernel),"			\
+		"-(filesystem)"
+#endif
+
+/*
+ * Ethernet on SOC (FEC)
+ */
+#ifdef	CONFIG_CMD_NET
+#define	CONFIG_NET_MULTI
+#define	CONFIG_ETHPRIME			"FEC0"
+#define	CONFIG_FEC_MXC
+#define	CONFIG_FEC_MXC_MULTI
+#define	CONFIG_MII
+#define	CONFIG_DISCOVER_PHY
+#define	CONFIG_FEC_XCV_TYPE		RMII
+#endif
+
+/*
+ * I2C
+ */
+#ifdef	CONFIG_CMD_I2C
+#define	CONFIG_I2C_MXS
+#define	CONFIG_HARD_I2C
+#define	CONFIG_SYS_I2C_SPEED		400000
+#endif
+
+/*
+ * EEPROM
+ */
+#ifdef	CONFIG_CMD_EEPROM
+#define	CONFIG_SYS_I2C_MULTI_EEPROMS
+#define	CONFIG_SYS_I2C_EEPROM_ADDR_LEN	2
+#endif
+
+/*
+ * RTC
+ */
+#ifdef	CONFIG_CMD_DATE
+/* Use the internal RTC in the MXS chip */
+#define	CONFIG_RTC_INTERNAL
+#ifdef	CONFIG_RTC_INTERNAL
+#define	CONFIG_RTC_MXS
+#else
+#define	CONFIG_RTC_M41T62
+#define	CONFIG_SYS_I2C_RTC_ADDR		0x68
+#define	CONFIG_SYS_M41T11_BASE_YEAR	2000
+#endif
+#endif
+
+/*
+ * SPI
+ */
+#ifdef	CONFIG_CMD_SPI
+#define	CONFIG_HARD_SPI
+#define	CONFIG_MXS_SPI
+#define	CONFIG_SPI_HALF_DUPLEX
+#define	CONFIG_DEFAULT_SPI_BUS		2
+#define	CONFIG_DEFAULT_SPI_MODE		SPI_MODE_0
+
+/* SPI FLASH */
+#ifdef	CONFIG_CMD_SF
+#define	CONFIG_SPI_FLASH
+#define	CONFIG_SPI_FLASH_STMICRO
+#define	CONFIG_SPI_FLASH_CS		2
+#define	CONFIG_SF_DEFAULT_MODE		SPI_MODE_0
+#define	CONFIG_SF_DEFAULT_SPEED		24000000
+
+#define	CONFIG_ENV_SPI_CS		0
+#define	CONFIG_ENV_SPI_BUS		2
+#define	CONFIG_ENV_SPI_MAX_HZ		24000000
+#define	CONFIG_ENV_SPI_MODE		SPI_MODE_0
+#endif
+#endif
+
+/*
+ * Boot Linux
+ */
+#define	CONFIG_CMDLINE_TAG
+#define	CONFIG_SETUP_MEMORY_TAGS
+#define	CONFIG_BOOTDELAY	3
+#define	CONFIG_BOOTFILE		"uImage"
+#define	CONFIG_BOOTARGS		"console=ttyAM0,115200n8 "
+#define	CONFIG_BOOTCOMMAND	"run bootcmd_net"
+#define	CONFIG_LOADADDR		0x42000000
+#define	CONFIG_SYS_LOAD_ADDR	CONFIG_LOADADDR
+
+/*
+ * Extra Environments
+ */
+#define	CONFIG_EXTRA_ENV_SETTINGS					\
+	"update_nand_full_filename=u-boot.nand\0"			\
+	"update_nand_firmware_filename=u-boot.sb\0"			\
+	"update_nand_firmware_maxsz=0x100000\0"				\
+	"update_nand_stride=0x40\0"	/* MX28 datasheet ch. 12.12 */	\
+	"update_nand_count=0x4\0"	/* MX28 datasheet ch. 12.12 */	\
+	"update_nand_get_fcb_size="	/* Get size of FCB blocks */	\
+		"nand device 0 ; "					\
+		"nand info ; "						\
+		"setexpr fcb_sz ${update_nand_stride} * ${update_nand_count};" \
+		"setexpr update_nand_fcb ${fcb_sz} * ${nand_writesize}\0" \
+	"update_nand_full="		/* Update FCB, DBBT and FW */	\
+		"if tftp ${update_nand_full_filename} ; then "		\
+		"run update_nand_get_fcb_size ; "			\
+		"nand scrub.quiet 0x0 ${filesize} ; "			\
+		"nand write.raw ${loadaddr} 0x0 ${update_nand_fcb} ; "	\
+		"setexpr update_off ${loadaddr} + ${update_nand_fcb} ; " \
+		"setexpr update_sz ${filesize} - ${update_nand_fcb} ; " \
+		"nand write ${update_off} ${update_nand_fcb} ${update_sz} ; " \
+		"fi\0"							\
+	"update_nand_firmware="		/* Update only firmware */	\
+		"if tftp ${update_nand_firmware_filename} ; then "	\
+		"run update_nand_get_fcb_size ; "			\
+		"setexpr fcb_sz ${update_nand_fcb} * 2 ; " /* FCB + DBBT */ \
+		"setexpr fw_sz ${update_nand_firmware_maxsz} * 2 ; "	\
+		"setexpr fw_off ${fcb_sz} + ${update_nand_firmware_maxsz};" \
+		"nand erase ${fcb_sz} ${fw_sz} ; "			\
+		"nand write ${loadaddr} ${fcb_sz} ${filesize} ; "	\
+		"nand write ${loadaddr} ${fw_off} ${filesize} ; "	\
+		"fi\0"
+
+#endif /* __M28_H__ */
-- 
1.7.5.4

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

* [U-Boot] [PATCH 14/15] M28: Add MMC SPL
  2011-09-12  4:06 [U-Boot] [PATCH 00/15 V2] Support for the DENX M28 SoM Marek Vasut
                   ` (12 preceding siblings ...)
  2011-09-12  4:06 ` [U-Boot] [PATCH 13/15] iMX28: Add support for DENX M28EVK board Marek Vasut
@ 2011-09-12  4:06 ` Marek Vasut
  2011-09-30  9:40   ` [U-Boot] [PATCH 14/15 V2] " Marek Vasut
  2011-09-12  4:06 ` [U-Boot] [PATCH 15/15] M28: Add doc/README.m28 documentation Marek Vasut
  2011-10-21 22:44 ` [U-Boot] [PATCH 00/17 V3] Support for the DENX M28 SoM Marek Vasut
  15 siblings, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-09-12  4:06 UTC (permalink / raw)
  To: u-boot

This patch adds SPL code for the M28 board.

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Andy Fleming <afleming@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 board/denx/m28evk/Makefile       |    8 +
 board/denx/m28evk/m28_init.h     |   36 ++
 board/denx/m28evk/mem_init.c     |  213 +++++++++
 board/denx/m28evk/mmc_boot.c     |  273 ++++++++++++
 board/denx/m28evk/power_init.c   |  911 ++++++++++++++++++++++++++++++++++++++
 board/denx/m28evk/start.S        |  396 +++++++++++++++++
 board/denx/m28evk/u-boot-spl.lds |   87 ++++
 board/denx/m28evk/u-boot.bd      |   14 +
 include/configs/m28evk.h         |    8 +
 9 files changed, 1946 insertions(+), 0 deletions(-)
 create mode 100644 board/denx/m28evk/m28_init.h
 create mode 100644 board/denx/m28evk/mem_init.c
 create mode 100644 board/denx/m28evk/mmc_boot.c
 create mode 100644 board/denx/m28evk/power_init.c
 create mode 100644 board/denx/m28evk/start.S
 create mode 100644 board/denx/m28evk/u-boot-spl.lds
 create mode 100644 board/denx/m28evk/u-boot.bd

diff --git a/board/denx/m28evk/Makefile b/board/denx/m28evk/Makefile
index 4037199..953143a 100644
--- a/board/denx/m28evk/Makefile
+++ b/board/denx/m28evk/Makefile
@@ -25,7 +25,13 @@ include $(TOPDIR)/config.mk
 
 LIB	= $(obj)lib$(BOARD).o
 
+ifndef	CONFIG_SPL_BUILD
 COBJS	:= m28evk.o
+endif
+
+ifdef	CONFIG_SPL_BUILD
+COBJS	:= mem_init.o mmc_boot.o power_init.o
+endif
 
 SRCS	:= $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS))
@@ -33,6 +39,8 @@ OBJS	:= $(addprefix $(obj),$(COBJS))
 $(LIB):	$(obj).depend $(OBJS)
 	$(call cmd_link_o_target, $(OBJS))
 
+all:	$(ALL)
+
 clean:
 	rm -f $(OBJS)
 
diff --git a/board/denx/m28evk/m28_init.h b/board/denx/m28evk/m28_init.h
new file mode 100644
index 0000000..7f569e0
--- /dev/null
+++ b/board/denx/m28evk/m28_init.h
@@ -0,0 +1,36 @@
+/*
+ * Freescale i.MX28 SPL functions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef	__M28_INIT_H__
+#define	__M28_INIT_H__
+
+void early_delay(int delay);
+
+void mx28_power_init(void);
+void mx28_power_wait_pswitch(void);
+
+void mx28_mem_init(void);
+
+#endif	/* __M28_INIT_H__ */
diff --git a/board/denx/m28evk/mem_init.c b/board/denx/m28evk/mem_init.c
new file mode 100644
index 0000000..066fe0d
--- /dev/null
+++ b/board/denx/m28evk/mem_init.c
@@ -0,0 +1,213 @@
+/*
+ * Freescale i.MX28 RAM init
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/io.h>
+#include <asm/arch/iomux-mx28.h>
+#include <asm/arch/imx-regs.h>
+
+#include "m28_init.h"
+
+uint32_t dram_vals[] = {
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000100, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00010101, 0x01010101, 0x000f0f01, 0x0f02020a,
+	0x00000000, 0x00010101, 0x00000100, 0x00000100, 0x00000000,
+	0x00000002, 0x01010000, 0x05060302, 0x06005003, 0x0a0000c8,
+	0x02009c40, 0x0000030c, 0x0036a609, 0x031a0612, 0x02030202,
+	0x00c8001c, 0x00000000, 0x00000000, 0x00012100, 0xffff0303,
+	0x00012100, 0xffff0303, 0x00012100, 0xffff0303, 0x00012100,
+	0xffff0303, 0x00000003, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000612, 0x01000F02, 0x06120612, 0x00000200,
+	0x00020007, 0xf5014b27, 0xf5014b27, 0xf5014b27, 0xf5014b27,
+	0x07000300, 0x07000300, 0x07000300, 0x07000300, 0x00000006,
+	0x00000000, 0x00000000, 0x01000000, 0x01020408, 0x08040201,
+	0x000f1133, 0x00000000, 0x00001f04, 0x00001f04, 0x00001f04,
+	0x00001f04, 0x00001f04, 0x00001f04, 0x00001f04, 0x00001f04,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00010000, 0x00020304, 0x00000004,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x01010000, 0x01000000, 0x03030000, 0x00010303,
+	0x01020202, 0x00000000, 0x02040303, 0x21002103, 0x00061200,
+	0x06120612, 0x04320432, 0x04320432, 0x00040004, 0x00040004,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00010001
+};
+
+void init_m28_200mhz_ddr2(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dram_vals); i++)
+		writel(dram_vals[i], MXS_DRAM_BASE + (4 * i));
+}
+
+void mx28_mem_init_clock(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/* Gate EMI clock */
+	writel(CLKCTRL_FRAC0_CLKGATEEMI,
+		&clkctrl_regs->hw_clkctrl_frac0_set);
+
+	/* EMI = 205MHz */
+	writel(CLKCTRL_FRAC0_EMIFRAC_MASK,
+		&clkctrl_regs->hw_clkctrl_frac0_set);
+	writel((0x2a << CLKCTRL_FRAC0_EMIFRAC_OFFSET) &
+		CLKCTRL_FRAC0_EMIFRAC_MASK,
+		&clkctrl_regs->hw_clkctrl_frac0_clr);
+
+	/* Ungate EMI clock */
+	writel(CLKCTRL_FRAC0_CLKGATEEMI,
+		&clkctrl_regs->hw_clkctrl_frac0_clr);
+
+	early_delay(11000);
+
+	writel((2 << CLKCTRL_EMI_DIV_EMI_OFFSET) |
+		(1 << CLKCTRL_EMI_DIV_XTAL_OFFSET),
+		&clkctrl_regs->hw_clkctrl_emi);
+
+	/* Unbypass EMI */
+	writel(CLKCTRL_CLKSEQ_BYPASS_EMI,
+		&clkctrl_regs->hw_clkctrl_clkseq_clr);
+
+	early_delay(10000);
+}
+
+void mx28_mem_setup_cpu_and_hbus(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/* CPU = 454MHz and ungate CPU clock */
+	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_frac0,
+		CLKCTRL_FRAC0_CPUFRAC_MASK | CLKCTRL_FRAC0_CLKGATECPU,
+		19 << CLKCTRL_FRAC0_CPUFRAC_OFFSET);
+
+	/* Set CPU bypass */
+	writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
+		&clkctrl_regs->hw_clkctrl_clkseq_set);
+
+	/* HBUS = 151MHz */
+	writel(CLKCTRL_HBUS_DIV_MASK, &clkctrl_regs->hw_clkctrl_hbus_set);
+	writel(((~3) << CLKCTRL_HBUS_DIV_OFFSET) & CLKCTRL_HBUS_DIV_MASK,
+		&clkctrl_regs->hw_clkctrl_hbus_clr);
+
+	early_delay(10000);
+
+	/* CPU clock divider = 1 */
+	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_cpu,
+			CLKCTRL_CPU_DIV_CPU_MASK, 1);
+
+	/* Disable CPU bypass */
+	writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
+		&clkctrl_regs->hw_clkctrl_clkseq_clr);
+}
+
+void mx28_mem_setup_vdda(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	writel((0xc << POWER_VDDACTRL_TRG_OFFSET) |
+		(0x7 << POWER_VDDACTRL_BO_OFFSET_OFFSET) |
+		POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW,
+		&power_regs->hw_power_vddactrl);
+}
+
+void mx28_mem_setup_vddd(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	writel((0x1c << POWER_VDDDCTRL_TRG_OFFSET) |
+		(0x7 << POWER_VDDDCTRL_BO_OFFSET_OFFSET) |
+		POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW,
+		&power_regs->hw_power_vdddctrl);
+}
+
+void mx28_mem_init(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	struct mx28_pinctrl_regs *pinctrl_regs =
+		(struct mx28_pinctrl_regs *)MXS_PINCTRL_BASE;
+
+	/* Set DDR2 mode */
+	writel(PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2,
+		&pinctrl_regs->hw_pinctrl_emi_ds_ctrl_set);
+
+	/* Power up PLL0 */
+	writel(CLKCTRL_PLL0CTRL0_POWER,
+		&clkctrl_regs->hw_clkctrl_pll0ctrl0_set);
+
+	early_delay(11000);
+
+	mx28_mem_init_clock();
+
+	mx28_mem_setup_vdda();
+
+	/*
+	 * Configure the DRAM registers
+	 */
+
+	/* Clear START bit from DRAM_CTL16 */
+	clrbits_le32(MXS_DRAM_BASE + 0x40, 1);
+
+	init_m28_200mhz_ddr2();
+
+	/* Clear SREFRESH bit from DRAM_CTL17 */
+	clrbits_le32(MXS_DRAM_BASE + 0x44, 1);
+
+	/* Set START bit in DRAM_CTL16 */
+	setbits_le32(MXS_DRAM_BASE + 0x40, 1);
+
+	/* Wait for bit 20 (DRAM init complete) in DRAM_CTL58 */
+	while (!(readl(MXS_DRAM_BASE + 0xe8) & (1 << 20)))
+		;
+
+	mx28_mem_setup_vddd();
+
+	early_delay(10000);
+
+	mx28_mem_setup_cpu_and_hbus();
+}
diff --git a/board/denx/m28evk/mmc_boot.c b/board/denx/m28evk/mmc_boot.c
new file mode 100644
index 0000000..07aa65b
--- /dev/null
+++ b/board/denx/m28evk/mmc_boot.c
@@ -0,0 +1,273 @@
+/*
+ * Freescale i.MX28 Boot setup
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/io.h>
+#include <asm/arch/iomux-mx28.h>
+
+#include "m28_init.h"
+
+/*
+ * This delay function is intended to be used only in early stage of boot, where
+ * clock are not set up yet. The timer used here is reset on every boot and
+ * takes a few seconds to roll. The boot doesn't take that long, so to keep the
+ * code simple, it doesn't take rolling into consideration.
+ */
+#define	HW_DIGCTRL_MICROSECONDS	0x8001c0c0
+void early_delay(int delay)
+{
+	uint32_t st = readl(HW_DIGCTRL_MICROSECONDS);
+	st += delay;
+	while (st > readl(HW_DIGCTRL_MICROSECONDS))
+		;
+}
+
+#define	MUX_CONFIG_LED	(MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL)
+#define	MUX_CONFIG_LCD	(MXS_PAD_3V3 | MXS_PAD_4MA)
+#define	MUX_CONFIG_TSC	(MXS_PAD_3V3 | MXS_PAD_8MA | MXS_PAD_PULLUP)
+#define	MUX_CONFIG_SSP0	(MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_PULLUP)
+#define	MUX_CONFIG_SSP2	(MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_PULLUP)
+#define	MUX_CONFIG_GPMI	(MXS_PAD_1V8 | MXS_PAD_4MA | MXS_PAD_NOPULL)
+#define	MUX_CONFIG_ENET	(MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_PULLUP)
+#define	MUX_CONFIG_EMI	(MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_NOPULL)
+
+const iomux_cfg_t iomux_setup[] = {
+	/* LED */
+	MX28_PAD_ENET0_RXD3__GPIO_4_10 | MUX_CONFIG_LED,
+
+	/* framebuffer */
+	MX28_PAD_LCD_D00__LCD_D0 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D01__LCD_D1 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D02__LCD_D2 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D03__LCD_D3 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D04__LCD_D4 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D05__LCD_D5 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D06__LCD_D6 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D07__LCD_D7 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D08__LCD_D8 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D09__LCD_D9 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D10__LCD_D10 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D11__LCD_D11 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D12__LCD_D12 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D13__LCD_D13 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D14__LCD_D14 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D15__LCD_D15 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D16__LCD_D16 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D17__LCD_D17 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D18__LCD_D18 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D19__LCD_D19 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D20__LCD_D20 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D21__LCD_D21 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D22__LCD_D22 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D23__LCD_D23 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_RD_E__LCD_VSYNC | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_WR_RWN__LCD_HSYNC | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_RS__LCD_DOTCLK | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_CS__LCD_CS | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_VSYNC__LCD_VSYNC | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_HSYNC__LCD_HSYNC | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_DOTCLK__LCD_DOTCLK | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_ENABLE__GPIO_1_31 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_RESET__GPIO_3_30 | MUX_CONFIG_LCD,
+	MX28_PAD_PWM0__PWM_0 | MUX_CONFIG_LCD,
+
+	/* UART1 */
+	MX28_PAD_AUART0_CTS__DUART_RX,
+	MX28_PAD_AUART0_RTS__DUART_TX,
+	MX28_PAD_AUART0_TX__DUART_RTS,
+	MX28_PAD_AUART0_RX__DUART_CTS,
+
+	/* UART2 */
+	MX28_PAD_AUART1_RX__AUART1_RX,
+	MX28_PAD_AUART1_TX__AUART1_TX,
+	MX28_PAD_AUART1_RTS__AUART1_RTS,
+	MX28_PAD_AUART1_CTS__AUART1_CTS,
+
+	/* CAN */
+	MX28_PAD_GPMI_RDY2__CAN0_TX,
+	MX28_PAD_GPMI_RDY3__CAN0_RX,
+
+	/* I2C */
+	MX28_PAD_I2C0_SCL__I2C0_SCL,
+	MX28_PAD_I2C0_SDA__I2C0_SDA,
+
+	/* TSC2007 */
+	MX28_PAD_SAIF0_MCLK__GPIO_3_20 | MUX_CONFIG_TSC,
+
+	/* MMC0 */
+	MX28_PAD_SSP0_DATA0__SSP0_D0 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA1__SSP0_D1 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA2__SSP0_D2 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA3__SSP0_D3 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA4__SSP0_D4 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA5__SSP0_D5 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA6__SSP0_D6 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA7__SSP0_D7 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_CMD__SSP0_CMD | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT |
+		(MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_NOPULL),
+	MX28_PAD_SSP0_SCK__SSP0_SCK |
+		(MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_NOPULL),
+	MX28_PAD_PWM3__GPIO_3_28 | MUX_CONFIG_SSP0,	/* Power .. FIXME */
+	MX28_PAD_AUART2_CTS__GPIO_3_10,	/* WP ... FIXME */
+
+	/* GPMI NAND */
+	MX28_PAD_GPMI_D00__GPMI_D0 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D01__GPMI_D1 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D02__GPMI_D2 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D03__GPMI_D3 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D04__GPMI_D4 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D05__GPMI_D5 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D06__GPMI_D6 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D07__GPMI_D7 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_CE0N__GPMI_CE0N | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_RDY0__GPMI_READY0 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_RDN__GPMI_RDN |
+		(MXS_PAD_1V8 | MXS_PAD_8MA | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_WRN__GPMI_WRN | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_ALE__GPMI_ALE | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_CLE__GPMI_CLE | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_RESETN__GPMI_RESETN | MUX_CONFIG_GPMI,
+
+	/* FEC Ethernet */
+	MX28_PAD_ENET0_MDC__ENET0_MDC | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_MDIO__ENET0_MDIO | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_RX_EN__ENET0_RX_EN | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_TX_EN__ENET0_TX_EN | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_RXD0__ENET0_RXD0 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_RXD1__ENET0_RXD1 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_TXD0__ENET0_TXD0 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_TXD1__ENET0_TXD1 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET_CLK__CLKCTRL_ENET | MUX_CONFIG_ENET,
+
+	MX28_PAD_ENET0_COL__ENET1_TX_EN | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_CRS__ENET1_RX_EN | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_RXD2__ENET1_RXD0 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_RXD3__ENET1_RXD1 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_TXD2__ENET1_TXD0 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_TXD3__ENET1_TXD1 | MUX_CONFIG_ENET,
+
+	/* I2C */
+	MX28_PAD_I2C0_SCL__I2C0_SCL,
+	MX28_PAD_I2C0_SDA__I2C0_SDA,
+
+	/* EMI */
+	MX28_PAD_EMI_D00__EMI_DATA0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D01__EMI_DATA1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D02__EMI_DATA2 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D03__EMI_DATA3 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D04__EMI_DATA4 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D05__EMI_DATA5 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D06__EMI_DATA6 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D07__EMI_DATA7 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D08__EMI_DATA8 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D09__EMI_DATA9 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D10__EMI_DATA10 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D11__EMI_DATA11 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D12__EMI_DATA12 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D13__EMI_DATA13 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D14__EMI_DATA14 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D15__EMI_DATA15 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_ODT0__EMI_ODT0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DQM0__EMI_DQM0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_ODT1__EMI_ODT1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DQM1__EMI_DQM1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DDR_OPEN_FB__EMI_DDR_OPEN_FEEDBACK | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_CLK__EMI_CLK | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DQS0__EMI_DQS0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DQS1__EMI_DQS1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DDR_OPEN__EMI_DDR_OPEN | MUX_CONFIG_EMI,
+
+	MX28_PAD_EMI_A00__EMI_ADDR0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A01__EMI_ADDR1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A02__EMI_ADDR2 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A03__EMI_ADDR3 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A04__EMI_ADDR4 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A05__EMI_ADDR5 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A06__EMI_ADDR6 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A07__EMI_ADDR7 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A08__EMI_ADDR8 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A09__EMI_ADDR9 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A10__EMI_ADDR10 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A11__EMI_ADDR11 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A12__EMI_ADDR12 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A13__EMI_ADDR13 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A14__EMI_ADDR14 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_BA0__EMI_BA0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_BA1__EMI_BA1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_BA2__EMI_BA2 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_CASN__EMI_CASN | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_RASN__EMI_RASN | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_WEN__EMI_WEN | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_CE0N__EMI_CE0N | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_CE1N__EMI_CE1N | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_CKE__EMI_CKE | MUX_CONFIG_EMI,
+
+	/* SPI2 (for flash) */
+	MX28_PAD_SSP2_SCK__SSP2_SCK | MUX_CONFIG_SSP2,
+	MX28_PAD_SSP2_MOSI__SSP2_CMD | MUX_CONFIG_SSP2,
+	MX28_PAD_SSP2_MISO__SSP2_D0 | MUX_CONFIG_SSP2,
+	MX28_PAD_SSP2_SS0__SSP2_D3 |
+		(MXS_PAD_3V3 | MXS_PAD_8MA | MXS_PAD_PULLUP),
+};
+
+void board_init_ll(void)
+{
+	mxs_iomux_setup_multiple_pads(iomux_setup, ARRAY_SIZE(iomux_setup));
+	mx28_power_init();
+	mx28_mem_init();
+	mx28_power_wait_pswitch();
+}
+
+/* Support aparatus */
+inline void board_init_f(unsigned long bootflag)
+{
+	for (;;)
+		;
+}
+
+inline void board_init_r(gd_t *id, ulong dest_addr)
+{
+	for (;;)
+		;
+}
+
+inline int printf(const char *fmt, ...) {
+	return 0;
+}
+
+inline void __coloured_LED_init(void) {}
+inline void __red_LED_on(void) {}
+void coloured_LED_init(void)
+	__attribute__((weak, alias("__coloured_LED_init")));
+void red_LED_on(void)
+	__attribute__((weak, alias("__red_LED_on")));
+void hang(void) __attribute__ ((noreturn));
+void hang(void)
+{
+	for (;;)
+		;
+}
diff --git a/board/denx/m28evk/power_init.c b/board/denx/m28evk/power_init.c
new file mode 100644
index 0000000..2efe21a
--- /dev/null
+++ b/board/denx/m28evk/power_init.c
@@ -0,0 +1,911 @@
+/*
+ * Freescale i.MX28 Boot PMIC init
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+
+#include "m28_init.h"
+
+void mx28_power_clock2xtal(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/* Set XTAL as CPU reference clock */
+	writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
+		&clkctrl_regs->hw_clkctrl_clkseq_set);
+}
+
+void mx28_power_clock2pll(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	writel(CLKCTRL_PLL0CTRL0_POWER,
+		&clkctrl_regs->hw_clkctrl_pll0ctrl0_set);
+	early_delay(100);
+	writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
+		&clkctrl_regs->hw_clkctrl_clkseq_clr);
+}
+
+void mx28_power_clear_auto_restart(void)
+{
+	struct mx28_rtc_regs *rtc_regs =
+		(struct mx28_rtc_regs *)MXS_RTC_BASE;
+
+	writel(RTC_CTRL_SFTRST, &rtc_regs->hw_rtc_ctrl_clr);
+	while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_SFTRST)
+		;
+
+	writel(RTC_CTRL_CLKGATE, &rtc_regs->hw_rtc_ctrl_clr);
+	while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_CLKGATE)
+		;
+
+	/*
+	 * Due to the hardware design bug of mx28 EVK-A
+	 * we need to set the AUTO_RESTART bit.
+	 */
+	if (readl(&rtc_regs->hw_rtc_persistent0) & RTC_PERSISTENT0_AUTO_RESTART)
+		return;
+
+	while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK)
+		;
+
+	setbits_le32(&rtc_regs->hw_rtc_persistent0,
+			RTC_PERSISTENT0_AUTO_RESTART);
+	writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_set);
+	writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_clr);
+	while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK)
+		;
+	while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_STALE_REGS_MASK)
+		;
+}
+
+void mx28_power_set_linreg(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/* Set linear regulator 25mV below switching converter */
+	clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+			POWER_VDDDCTRL_LINREG_OFFSET_MASK,
+			POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
+
+	clrsetbits_le32(&power_regs->hw_power_vddactrl,
+			POWER_VDDACTRL_LINREG_OFFSET_MASK,
+			POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW);
+
+	clrsetbits_le32(&power_regs->hw_power_vddioctrl,
+			POWER_VDDIOCTRL_LINREG_OFFSET_MASK,
+			POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW);
+}
+
+void mx28_power_setup_5v_detect(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/* Start 5V detection */
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+			POWER_5VCTRL_VBUSVALID_TRSH_MASK,
+			POWER_5VCTRL_VBUSVALID_TRSH_4V4 |
+			POWER_5VCTRL_PWRUP_VBUS_CMPS);
+}
+
+void mx28_src_power_init(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/* Improve efficieny and reduce transient ripple */
+	writel(POWER_LOOPCTRL_TOGGLE_DIF | POWER_LOOPCTRL_EN_CM_HYST |
+		POWER_LOOPCTRL_EN_DF_HYST, &power_regs->hw_power_loopctrl_set);
+
+	clrsetbits_le32(&power_regs->hw_power_dclimits,
+			POWER_DCLIMITS_POSLIMIT_BUCK_MASK,
+			0x30 << POWER_DCLIMITS_POSLIMIT_BUCK_OFFSET);
+
+	setbits_le32(&power_regs->hw_power_battmonitor,
+			POWER_BATTMONITOR_EN_BATADJ);
+
+	/* Increase the RCSCALE level for quick DCDC response to dynamic load */
+	clrsetbits_le32(&power_regs->hw_power_loopctrl,
+			POWER_LOOPCTRL_EN_RCSCALE_MASK,
+			POWER_LOOPCTRL_RCSCALE_THRESH |
+			POWER_LOOPCTRL_EN_RCSCALE_8X);
+
+	clrsetbits_le32(&power_regs->hw_power_minpwr,
+			POWER_MINPWR_HALFFETS, POWER_MINPWR_DOUBLE_FETS);
+
+	/* 5V to battery handoff ... FIXME */
+	setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
+	early_delay(30);
+	clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
+}
+
+void mx28_power_init_4p2_params(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/* Setup 4P2 parameters */
+	clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
+		POWER_DCDC4P2_CMPTRIP_MASK | POWER_DCDC4P2_TRG_MASK,
+		POWER_DCDC4P2_TRG_4V2 | (31 << POWER_DCDC4P2_CMPTRIP_OFFSET));
+
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+		POWER_5VCTRL_HEADROOM_ADJ_MASK,
+		0x4 << POWER_5VCTRL_HEADROOM_ADJ_OFFSET);
+
+	clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
+		POWER_DCDC4P2_DROPOUT_CTRL_MASK,
+		POWER_DCDC4P2_DROPOUT_CTRL_100MV |
+		POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL);
+
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+		POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
+		0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
+}
+
+void mx28_enable_4p2_dcdc_input(int xfer)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp, vbus_thresh, vbus_5vdetect, pwd_bo;
+	uint32_t prev_5v_brnout, prev_5v_droop;
+
+	prev_5v_brnout = readl(&power_regs->hw_power_5vctrl) &
+				POWER_5VCTRL_PWDN_5VBRNOUT;
+	prev_5v_droop = readl(&power_regs->hw_power_ctrl) &
+				POWER_CTRL_ENIRQ_VDD5V_DROOP;
+
+	clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_PWDN_5VBRNOUT);
+	writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
+		&power_regs->hw_power_reset);
+
+	clrbits_le32(&power_regs->hw_power_ctrl, POWER_CTRL_ENIRQ_VDD5V_DROOP);
+
+	if (xfer && (readl(&power_regs->hw_power_5vctrl) &
+			POWER_5VCTRL_ENABLE_DCDC)) {
+		return;
+	}
+
+	/*
+	 * Recording orignal values that will be modified temporarlily
+	 * to handle a chip bug. See chip errata for CQ ENGR00115837
+	 */
+	tmp = readl(&power_regs->hw_power_5vctrl);
+	vbus_thresh = tmp & POWER_5VCTRL_VBUSVALID_TRSH_MASK;
+	vbus_5vdetect = tmp & POWER_5VCTRL_VBUSVALID_5VDETECT;
+
+	pwd_bo = readl(&power_regs->hw_power_minpwr) & POWER_MINPWR_PWD_BO;
+
+	/*
+	 * Disable mechanisms that get erroneously tripped by when setting
+	 * the DCDC4P2 EN_DCDC
+	 */
+	clrbits_le32(&power_regs->hw_power_5vctrl,
+		POWER_5VCTRL_VBUSVALID_5VDETECT |
+		POWER_5VCTRL_VBUSVALID_TRSH_MASK);
+
+	writel(POWER_MINPWR_PWD_BO, &power_regs->hw_power_minpwr_set);
+
+	if (xfer) {
+		setbits_le32(&power_regs->hw_power_5vctrl,
+				POWER_5VCTRL_DCDC_XFER);
+		early_delay(20);
+		clrbits_le32(&power_regs->hw_power_5vctrl,
+				POWER_5VCTRL_DCDC_XFER);
+
+		setbits_le32(&power_regs->hw_power_5vctrl,
+				POWER_5VCTRL_ENABLE_DCDC);
+	} else {
+		setbits_le32(&power_regs->hw_power_dcdc4p2,
+				POWER_DCDC4P2_ENABLE_DCDC);
+	}
+
+	early_delay(25);
+
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+			POWER_5VCTRL_VBUSVALID_TRSH_MASK, vbus_thresh);
+
+	if (vbus_5vdetect)
+		writel(vbus_5vdetect, &power_regs->hw_power_5vctrl_set);
+
+	if (!pwd_bo)
+		clrbits_le32(&power_regs->hw_power_minpwr, POWER_MINPWR_PWD_BO);
+
+	while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ)
+		clrbits_le32(&power_regs->hw_power_ctrl,
+				POWER_CTRL_VBUS_VALID_IRQ);
+
+	if (prev_5v_brnout) {
+		writel(POWER_5VCTRL_PWDN_5VBRNOUT,
+			&power_regs->hw_power_5vctrl_set);
+		writel(POWER_RESET_UNLOCK_KEY,
+			&power_regs->hw_power_reset);
+	} else {
+		writel(POWER_5VCTRL_PWDN_5VBRNOUT,
+			&power_regs->hw_power_5vctrl_clr);
+		writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
+			&power_regs->hw_power_reset);
+	}
+
+	while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VDD5V_DROOP_IRQ)
+		clrbits_le32(&power_regs->hw_power_ctrl,
+				POWER_CTRL_VDD5V_DROOP_IRQ);
+
+	if (prev_5v_droop)
+		clrbits_le32(&power_regs->hw_power_ctrl,
+				POWER_CTRL_ENIRQ_VDD5V_DROOP);
+	else
+		setbits_le32(&power_regs->hw_power_ctrl,
+				POWER_CTRL_ENIRQ_VDD5V_DROOP);
+}
+
+void mx28_power_init_4p2_regulator(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp, tmp2;
+
+	setbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_ENABLE_4P2);
+
+	writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_set);
+
+	writel(POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
+		&power_regs->hw_power_5vctrl_clr);
+	clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_TRG_MASK);
+
+	/* Power up the 4p2 rail and logic/control */
+	writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+		&power_regs->hw_power_5vctrl_clr);
+
+	/*
+	 * Start charging up the 4p2 capacitor. We ramp of this charge
+	 * gradually to avoid large inrush current from the 5V cable which can
+	 * cause transients/problems
+	 */
+	mx28_enable_4p2_dcdc_input(0);
+
+	if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) {
+		/*
+		 * If we arrived here, we were unable to recover from mx23 chip
+		 * errata 5837. 4P2 is disabled and sufficient battery power is
+		 * not present. Exiting to not enable DCDC power during 5V
+		 * connected state.
+		 */
+		clrbits_le32(&power_regs->hw_power_dcdc4p2,
+			POWER_DCDC4P2_ENABLE_DCDC);
+		writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+			&power_regs->hw_power_5vctrl_set);
+		hang();
+	}
+
+	/*
+	 * Here we set the 4p2 brownout level to something very close to 4.2V.
+	 * We then check the brownout status. If the brownout status is false,
+	 * the voltage is already close to the target voltage of 4.2V so we
+	 * can go ahead and set the 4P2 current limit to our max target limit.
+	 * If the brownout status is true, we need to ramp us the current limit
+	 * so that we don't cause large inrush current issues. We step up the
+	 * current limit until the brownout status is false or until we've
+	 * reached our maximum defined 4p2 current limit.
+	 */
+	clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
+			POWER_DCDC4P2_BO_MASK,
+			22 << POWER_DCDC4P2_BO_OFFSET);	/* 4.15V */
+
+	if (!(readl(&power_regs->hw_power_sts) & POWER_STS_DCDC_4P2_BO)) {
+		setbits_le32(&power_regs->hw_power_5vctrl,
+			0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
+	} else {
+		tmp = (readl(&power_regs->hw_power_5vctrl) &
+			POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK) >>
+			POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET;
+		while (tmp < 0x3f) {
+			if (!(readl(&power_regs->hw_power_sts) &
+					POWER_STS_DCDC_4P2_BO)) {
+				tmp = readl(&power_regs->hw_power_5vctrl);
+				tmp |= POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK;
+				early_delay(100);
+				writel(tmp, &power_regs->hw_power_5vctrl);
+				break;
+			} else {
+				tmp++;
+				tmp2 = readl(&power_regs->hw_power_5vctrl);
+				tmp2 &= ~POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK;
+				tmp2 |= tmp <<
+					POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET;
+				writel(tmp2, &power_regs->hw_power_5vctrl);
+				early_delay(100);
+			}
+		}
+	}
+
+	clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_BO_MASK);
+	writel(POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+}
+
+void mx28_power_init_dcdc_4p2_source(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	if (!(readl(&power_regs->hw_power_dcdc4p2) &
+		POWER_DCDC4P2_ENABLE_DCDC)) {
+		hang();
+	}
+
+	mx28_enable_4p2_dcdc_input(1);
+
+	if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) {
+		clrbits_le32(&power_regs->hw_power_dcdc4p2,
+			POWER_DCDC4P2_ENABLE_DCDC);
+		writel(POWER_5VCTRL_ENABLE_DCDC,
+			&power_regs->hw_power_5vctrl_clr);
+		writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+			&power_regs->hw_power_5vctrl_set);
+	}
+}
+
+void mx28_power_enable_4p2(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t vdddctrl, vddactrl, vddioctrl;
+	uint32_t tmp;
+
+	vdddctrl = readl(&power_regs->hw_power_vdddctrl);
+	vddactrl = readl(&power_regs->hw_power_vddactrl);
+	vddioctrl = readl(&power_regs->hw_power_vddioctrl);
+
+	setbits_le32(&power_regs->hw_power_vdddctrl,
+		POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG |
+		POWER_VDDDCTRL_PWDN_BRNOUT);
+
+	setbits_le32(&power_regs->hw_power_vddactrl,
+		POWER_VDDACTRL_DISABLE_FET | POWER_VDDACTRL_ENABLE_LINREG |
+		POWER_VDDACTRL_PWDN_BRNOUT);
+
+	setbits_le32(&power_regs->hw_power_vddioctrl,
+		POWER_VDDIOCTRL_DISABLE_FET | POWER_VDDIOCTRL_PWDN_BRNOUT);
+
+	mx28_power_init_4p2_params();
+	mx28_power_init_4p2_regulator();
+
+	/* Shutdown battery (none present) */
+	clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_BO_MASK);
+	writel(POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+	writel(POWER_CTRL_ENIRQ_DCDC4P2_BO, &power_regs->hw_power_ctrl_clr);
+
+	mx28_power_init_dcdc_4p2_source();
+
+	writel(vdddctrl, &power_regs->hw_power_vdddctrl);
+	early_delay(20);
+	writel(vddactrl, &power_regs->hw_power_vddactrl);
+	early_delay(20);
+	writel(vddioctrl, &power_regs->hw_power_vddioctrl);
+
+	/*
+	 * Check if FET is enabled on either powerout and if so,
+	 * disable load.
+	 */
+	tmp = 0;
+	tmp |= !(readl(&power_regs->hw_power_vdddctrl) &
+			POWER_VDDDCTRL_DISABLE_FET);
+	tmp |= !(readl(&power_regs->hw_power_vddactrl) &
+			POWER_VDDACTRL_DISABLE_FET);
+	tmp |= !(readl(&power_regs->hw_power_vddioctrl) &
+			POWER_VDDIOCTRL_DISABLE_FET);
+	if (tmp)
+		writel(POWER_CHARGE_ENABLE_LOAD,
+			&power_regs->hw_power_charge_clr);
+}
+
+void mx28_boot_valid_5v(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/*
+	 * Use VBUSVALID level instead of VDD5V_GT_VDDIO level to trigger a 5V
+	 * disconnect event. FIXME
+	 */
+	writel(POWER_5VCTRL_VBUSVALID_5VDETECT,
+		&power_regs->hw_power_5vctrl_set);
+
+	/* Configure polarity to check for 5V disconnection. */
+	writel(POWER_CTRL_POLARITY_VBUSVALID |
+		POWER_CTRL_POLARITY_VDD5V_GT_VDDIO,
+		&power_regs->hw_power_ctrl_clr);
+
+	writel(POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_VDD5V_GT_VDDIO_IRQ,
+		&power_regs->hw_power_ctrl_clr);
+
+	mx28_power_enable_4p2();
+}
+
+void mx28_powerdown(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	writel(POWER_RESET_UNLOCK_KEY, &power_regs->hw_power_reset);
+	writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
+		&power_regs->hw_power_reset);
+}
+
+void mx28_handle_5v_conflict(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp;
+
+	setbits_le32(&power_regs->hw_power_vddioctrl,
+			POWER_VDDIOCTRL_BO_OFFSET_MASK);
+
+	for (;;) {
+		tmp = readl(&power_regs->hw_power_sts);
+
+		if (tmp & POWER_STS_VDDIO_BO) {
+			mx28_powerdown();
+			break;
+		}
+
+		if (tmp & POWER_STS_VDD5V_GT_VDDIO) {
+			mx28_boot_valid_5v();
+			break;
+		} else {
+			mx28_powerdown();
+			break;
+		}
+	}
+}
+
+int mx28_get_batt_volt(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t volt = readl(&power_regs->hw_power_battmonitor);
+	volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
+	volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
+	volt *= 8;
+	return volt;
+}
+
+int mx28_is_batt_ready(void)
+{
+	return (mx28_get_batt_volt() >= 3600);
+}
+
+void mx28_5v_boot(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/*
+	 * NOTE: In original IMX-Bootlets, this also checks for VBUSVALID,
+	 * but their implementation always returns 1 so we omit it here.
+	 */
+	if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+		mx28_boot_valid_5v();
+		return;
+	}
+
+	early_delay(1000);
+	if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+		mx28_boot_valid_5v();
+		return;
+	}
+
+	mx28_handle_5v_conflict();
+}
+
+void mx28_init_batt_bo(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/* Brownout at 3V */
+	clrsetbits_le32(&power_regs->hw_power_battmonitor,
+		POWER_BATTMONITOR_BRWNOUT_LVL_MASK,
+		15 << POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET);
+
+	writel(POWER_CTRL_BATT_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+	writel(POWER_CTRL_ENIRQ_BATT_BO, &power_regs->hw_power_ctrl_clr);
+}
+
+void mx28_switch_vddd_to_dcdc_source(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+		POWER_VDDDCTRL_LINREG_OFFSET_MASK,
+		POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
+
+	clrbits_le32(&power_regs->hw_power_vdddctrl,
+		POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG |
+		POWER_VDDDCTRL_DISABLE_STEPPING);
+}
+
+int mx28_is_batt_good(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t volt;
+
+	volt = readl(&power_regs->hw_power_battmonitor);
+	volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
+	volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
+	volt *= 8;
+
+	if ((volt >= 2400) && (volt <= 4300))
+		return 1;
+
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+		POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
+		0x3 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
+	writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+		&power_regs->hw_power_5vctrl_clr);
+
+	clrsetbits_le32(&power_regs->hw_power_charge,
+		POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
+		POWER_CHARGE_STOP_ILIMIT_10MA | 0x3);
+
+	writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_clr);
+	writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+		&power_regs->hw_power_5vctrl_clr);
+
+	early_delay(500000);
+
+	volt = readl(&power_regs->hw_power_battmonitor);
+	volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
+	volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
+	volt *= 8;
+
+	if (volt >= 3500)
+		return 0;
+
+	if (volt >= 2400)
+		return 1;
+
+	writel(POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
+		&power_regs->hw_power_charge_clr);
+	writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_set);
+
+	return 0;
+}
+
+void mx28_power_configure_power_source(void)
+{
+	mx28_src_power_init();
+
+	mx28_5v_boot();
+	mx28_power_clock2pll();
+
+	mx28_init_batt_bo();
+	mx28_switch_vddd_to_dcdc_source();
+}
+
+void mx28_enable_output_rail_protection(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
+		POWER_CTRL_VDDIO_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+
+	setbits_le32(&power_regs->hw_power_vdddctrl,
+			POWER_VDDDCTRL_PWDN_BRNOUT);
+
+	setbits_le32(&power_regs->hw_power_vddactrl,
+			POWER_VDDACTRL_PWDN_BRNOUT);
+
+	setbits_le32(&power_regs->hw_power_vddioctrl,
+			POWER_VDDIOCTRL_PWDN_BRNOUT);
+}
+
+int mx28_get_vddio_power_source_off(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp;
+
+	if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+		tmp = readl(&power_regs->hw_power_vddioctrl);
+		if (tmp & POWER_VDDIOCTRL_DISABLE_FET) {
+			if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
+				POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
+				return 1;
+			}
+		}
+
+		if (!(readl(&power_regs->hw_power_5vctrl) &
+			POWER_5VCTRL_ENABLE_DCDC)) {
+			if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
+				POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
+				return 1;
+			}
+		}
+	}
+
+	return 0;
+
+}
+
+int mx28_get_vddd_power_source_off(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp;
+
+	tmp = readl(&power_regs->hw_power_vdddctrl);
+	if (tmp & POWER_VDDDCTRL_DISABLE_FET) {
+		if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
+			POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
+			return 1;
+		}
+	}
+
+	if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+		if (!(readl(&power_regs->hw_power_5vctrl) &
+			POWER_5VCTRL_ENABLE_DCDC)) {
+			return 1;
+		}
+	}
+
+	if (!(tmp & POWER_VDDDCTRL_ENABLE_LINREG)) {
+		if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
+			POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW) {
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+void mx28_power_set_vddio(uint32_t new_target, uint32_t new_brownout)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t cur_target, diff, bo_int = 0;
+	uint32_t powered_by_linreg = 0;
+
+	new_brownout = new_target - new_brownout;
+
+	cur_target = readl(&power_regs->hw_power_vddioctrl);
+	cur_target &= POWER_VDDIOCTRL_TRG_MASK;
+	cur_target *= 50;	/* 50 mV step*/
+	cur_target += 2800;	/* 2800 mV lowest */
+
+	powered_by_linreg = mx28_get_vddio_power_source_off();
+	if (new_target > cur_target) {
+
+		if (powered_by_linreg) {
+			bo_int = readl(&power_regs->hw_power_vddioctrl);
+			clrbits_le32(&power_regs->hw_power_vddioctrl,
+					POWER_CTRL_ENIRQ_VDDIO_BO);
+		}
+
+		setbits_le32(&power_regs->hw_power_vddioctrl,
+				POWER_VDDIOCTRL_BO_OFFSET_MASK);
+		do {
+			if (new_target - cur_target > 100)
+				diff = cur_target + 100;
+			else
+				diff = new_target;
+
+			diff -= 2800;
+			diff /= 50;
+
+			clrsetbits_le32(&power_regs->hw_power_vddioctrl,
+				POWER_VDDIOCTRL_TRG_MASK, diff);
+
+			if (powered_by_linreg)
+				early_delay(1500);
+			else {
+				while (!(readl(&power_regs->hw_power_sts) &
+					POWER_STS_DC_OK))
+					;
+
+			}
+
+			cur_target = readl(&power_regs->hw_power_vddioctrl);
+			cur_target &= POWER_VDDIOCTRL_TRG_MASK;
+			cur_target *= 50;	/* 50 mV step*/
+			cur_target += 2800;	/* 2800 mV lowest */
+		} while (new_target > cur_target);
+
+		if (powered_by_linreg) {
+			writel(POWER_CTRL_VDDIO_BO_IRQ,
+				&power_regs->hw_power_ctrl_clr);
+			if (bo_int & POWER_CTRL_ENIRQ_VDDIO_BO)
+				setbits_le32(&power_regs->hw_power_vddioctrl,
+						POWER_CTRL_ENIRQ_VDDIO_BO);
+		}
+	} else {
+		do {
+			if (cur_target - new_target > 100)
+				diff = cur_target - 100;
+			else
+				diff = new_target;
+
+			diff -= 2800;
+			diff /= 50;
+
+			clrsetbits_le32(&power_regs->hw_power_vddioctrl,
+				POWER_VDDIOCTRL_TRG_MASK, diff);
+
+			if (powered_by_linreg)
+				early_delay(1500);
+			else {
+				while (!(readl(&power_regs->hw_power_sts) &
+					POWER_STS_DC_OK))
+					;
+
+			}
+
+			cur_target = readl(&power_regs->hw_power_vddioctrl);
+			cur_target &= POWER_VDDIOCTRL_TRG_MASK;
+			cur_target *= 50;	/* 50 mV step*/
+			cur_target += 2800;	/* 2800 mV lowest */
+		} while (new_target < cur_target);
+	}
+
+	clrsetbits_le32(&power_regs->hw_power_vddioctrl,
+			POWER_VDDDCTRL_BO_OFFSET_MASK,
+			new_brownout << POWER_VDDDCTRL_BO_OFFSET_OFFSET);
+}
+
+void mx28_power_set_vddd(uint32_t new_target, uint32_t new_brownout)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t cur_target, diff, bo_int = 0;
+	uint32_t powered_by_linreg = 0;
+
+	new_brownout = new_target - new_brownout;
+
+	cur_target = readl(&power_regs->hw_power_vdddctrl);
+	cur_target &= POWER_VDDDCTRL_TRG_MASK;
+	cur_target *= 25;	/* 25 mV step*/
+	cur_target += 800;	/* 800 mV lowest */
+
+	powered_by_linreg = mx28_get_vddd_power_source_off();
+	if (new_target > cur_target) {
+		if (powered_by_linreg) {
+			bo_int = readl(&power_regs->hw_power_vdddctrl);
+			clrbits_le32(&power_regs->hw_power_vdddctrl,
+					POWER_CTRL_ENIRQ_VDDD_BO);
+		}
+
+		setbits_le32(&power_regs->hw_power_vdddctrl,
+				POWER_VDDDCTRL_BO_OFFSET_MASK);
+
+		do {
+			if (new_target - cur_target > 100)
+				diff = cur_target + 100;
+			else
+				diff = new_target;
+
+			diff -= 800;
+			diff /= 25;
+
+			clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+				POWER_VDDDCTRL_TRG_MASK, diff);
+
+			if (powered_by_linreg)
+				early_delay(1500);
+			else {
+				while (!(readl(&power_regs->hw_power_sts) &
+					POWER_STS_DC_OK))
+					;
+
+			}
+
+			cur_target = readl(&power_regs->hw_power_vdddctrl);
+			cur_target &= POWER_VDDDCTRL_TRG_MASK;
+			cur_target *= 25;	/* 25 mV step*/
+			cur_target += 800;	/* 800 mV lowest */
+		} while (new_target > cur_target);
+
+		if (powered_by_linreg) {
+			writel(POWER_CTRL_VDDD_BO_IRQ,
+				&power_regs->hw_power_ctrl_clr);
+			if (bo_int & POWER_CTRL_ENIRQ_VDDD_BO)
+				setbits_le32(&power_regs->hw_power_vdddctrl,
+						POWER_CTRL_ENIRQ_VDDD_BO);
+		}
+	} else {
+		do {
+			if (cur_target - new_target > 100)
+				diff = cur_target - 100;
+			else
+				diff = new_target;
+
+			diff -= 800;
+			diff /= 25;
+
+			clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+					POWER_VDDDCTRL_TRG_MASK, diff);
+
+			if (powered_by_linreg)
+				early_delay(1500);
+			else {
+				while (!(readl(&power_regs->hw_power_sts) &
+					POWER_STS_DC_OK))
+					;
+
+			}
+
+			cur_target = readl(&power_regs->hw_power_vdddctrl);
+			cur_target &= POWER_VDDDCTRL_TRG_MASK;
+			cur_target *= 25;	/* 25 mV step*/
+			cur_target += 800;	/* 800 mV lowest */
+		} while (new_target < cur_target);
+	}
+
+	clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+			POWER_VDDDCTRL_BO_OFFSET_MASK,
+			new_brownout << POWER_VDDDCTRL_BO_OFFSET_OFFSET);
+}
+
+void mx28_power_init(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	mx28_power_clock2xtal();
+	mx28_power_clear_auto_restart();
+	mx28_power_set_linreg();
+	mx28_power_setup_5v_detect();
+	mx28_power_configure_power_source();
+	mx28_enable_output_rail_protection();
+
+	mx28_power_set_vddio(3300, 3150);
+
+	mx28_power_set_vddd(1350, 1200);
+
+	writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
+		POWER_CTRL_VDDIO_BO_IRQ | POWER_CTRL_VDD5V_DROOP_IRQ |
+		POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_BATT_BO_IRQ |
+		POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+
+	writel(POWER_5VCTRL_PWDN_5VBRNOUT, &power_regs->hw_power_5vctrl_set);
+
+	early_delay(1000);
+}
+
+void mx28_power_wait_pswitch(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	while (!(readl(&power_regs->hw_power_sts) & POWER_STS_PSWITCH_MASK))
+		;
+}
diff --git a/board/denx/m28evk/start.S b/board/denx/m28evk/start.S
new file mode 100644
index 0000000..cf67599
--- /dev/null
+++ b/board/denx/m28evk/start.S
@@ -0,0 +1,396 @@
+/*
+ *  armboot - Startup Code for ARM926EJS CPU-core
+ *
+ *  Copyright (c) 2003  Texas Instruments
+ *
+ *  ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------
+ *
+ *  Copyright (c) 2001	Marius Groger <mag@sysgo.de>
+ *  Copyright (c) 2002	Alex Zupke <azu@sysgo.de>
+ *  Copyright (c) 2002	Gary Jennejohn <garyj@denx.de>
+ *  Copyright (c) 2003	Richard Woodruff <r-woodruff2@ti.com>
+ *  Copyright (c) 2003	Kshitij <kshitij@ti.com>
+ *  Copyright (c) 2010	Albert Aribaud <albert.u.boot@aribaud.net>
+ *
+ * Change to support call back into iMX28 bootrom
+ * Copyright (c) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <common.h>
+#include <version.h>
+
+#if defined(CONFIG_OMAP1610)
+#include <./configs/omap1510.h>
+#elif defined(CONFIG_OMAP730)
+#include <./configs/omap730.h>
+#endif
+
+/*
+ *************************************************************************
+ *
+ * Jump vector table as in table 3.1 in [1]
+ *
+ *************************************************************************
+ */
+
+
+.globl _start
+_start:
+	b	reset
+#ifdef CONFIG_SPL_BUILD
+/* No exception handlers in preloader */
+	ldr	pc, _hang
+	ldr	pc, _hang
+	ldr	pc, _hang
+	ldr	pc, _hang
+	b	reset
+	ldr	pc, _hang
+	ldr	pc, _hang
+
+_hang:
+	.word	do_hang
+/* pad to 64 byte boundary */
+	.word	0x12345678
+	.word	0x12345678
+	.word	0x12345678
+	.word	0x12345678
+	.word	0x12345678
+	.word	0x12345678
+	.word	0x12345678
+#else
+	ldr	pc, _undefined_instruction
+	ldr	pc, _software_interrupt
+	ldr	pc, _prefetch_abort
+	ldr	pc, _data_abort
+	ldr	pc, _not_used
+	ldr	pc, _irq
+	ldr	pc, _fiq
+
+_undefined_instruction:
+	.word undefined_instruction
+_software_interrupt:
+	.word software_interrupt
+_prefetch_abort:
+	.word prefetch_abort
+_data_abort:
+	.word data_abort
+_not_used:
+	.word not_used
+_irq:
+	.word irq
+_fiq:
+	.word fiq
+
+#endif	/* CONFIG_SPL_BUILD */
+	.balignl 16,0xdeadbeef
+
+
+/*
+ *************************************************************************
+ *
+ * Startup Code (reset vector)
+ *
+ * do important init only if we don't start from memory!
+ * setup Memory and board specific bits prior to relocation.
+ * relocate armboot to ram
+ * setup stack
+ *
+ *************************************************************************
+ */
+
+.globl _TEXT_BASE
+_TEXT_BASE:
+	.word	CONFIG_SYS_TEXT_BASE
+
+/*
+ * These are defined in the board-specific linker script.
+ * Subtracting _start from them lets the linker put their
+ * relative position in the executable instead of leaving
+ * them null.
+ */
+.globl _bss_start_ofs
+_bss_start_ofs:
+	.word __bss_start - _start
+
+.globl _bss_end_ofs
+_bss_end_ofs:
+	.word __bss_end__ - _start
+
+.globl _end_ofs
+_end_ofs:
+	.word _end - _start
+
+#ifdef CONFIG_USE_IRQ
+/* IRQ stack memory (calculated at run-time) */
+.globl IRQ_STACK_START
+IRQ_STACK_START:
+	.word	0x0badc0de
+
+/* IRQ stack memory (calculated at run-time) */
+.globl FIQ_STACK_START
+FIQ_STACK_START:
+	.word 0x0badc0de
+#endif
+
+/* IRQ stack memory (calculated at run-time) + 8 bytes */
+.globl IRQ_STACK_START_IN
+IRQ_STACK_START_IN:
+	.word	0x0badc0de
+
+/*
+ * the actual reset code
+ */
+
+reset:
+	/*
+	 * Store all registers on old stack pointer, this will allow us later to
+	 * return to the BootROM and let the BootROM load U-Boot into RAM.
+	 */
+	push	{r0-r12,r14}
+
+	/*
+	 * set the cpu to SVC32 mode
+	 */
+	mrs	r0,cpsr
+	bic	r0,r0,#0x1f
+	orr	r0,r0,#0xd3
+	msr	cpsr,r0
+
+	/*
+	 * we do sys-critical inits only at reboot,
+	 * not when booting from ram!
+	 */
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+	bl	cpu_init_crit
+#endif
+
+	bl	board_init_ll
+
+	pop	{r0-r12,r14}
+	bx	lr
+
+/*
+ *************************************************************************
+ *
+ * CPU_init_critical registers
+ *
+ * setup important registers
+ * setup memory timing
+ *
+ *************************************************************************
+ */
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+cpu_init_crit:
+	/*
+	 * flush v4 I/D caches
+	 */
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c7, 0	/* flush v3/v4 cache */
+	mcr	p15, 0, r0, c8, c7, 0	/* flush v4 TLB */
+
+	/*
+	 * disable MMU stuff and caches
+	 */
+	mrc	p15, 0, r0, c1, c0, 0
+	bic	r0, r0, #0x00002300	/* clear bits 13, 9:8 (--V- --RS) */
+	bic	r0, r0, #0x00000087	/* clear bits 7, 2:0 (B--- -CAM) */
+	orr	r0, r0, #0x00000002	/* set bit 2 (A) Align */
+	orr	r0, r0, #0x00001000	/* set bit 12 (I) I-Cache */
+	mcr	p15, 0, r0, c1, c0, 0
+
+	mov	pc, lr		/* back to my caller */
+#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
+
+#ifndef CONFIG_SPL_BUILD
+/*
+ *************************************************************************
+ *
+ * Interrupt handling
+ *
+ *************************************************************************
+ */
+
+@
+@ IRQ stack frame.
+@
+#define S_FRAME_SIZE	72
+
+#define S_OLD_R0	68
+#define S_PSR		64
+#define S_PC		60
+#define S_LR		56
+#define S_SP		52
+
+#define S_IP		48
+#define S_FP		44
+#define S_R10		40
+#define S_R9		36
+#define S_R8		32
+#define S_R7		28
+#define S_R6		24
+#define S_R5		20
+#define S_R4		16
+#define S_R3		12
+#define S_R2		8
+#define S_R1		4
+#define S_R0		0
+
+#define MODE_SVC 0x13
+#define I_BIT	 0x80
+
+/*
+ * use bad_save_user_regs for abort/prefetch/undef/swi ...
+ * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
+ */
+
+	.macro	bad_save_user_regs
+	@ carve out a frame on current user stack
+	sub	sp, sp, #S_FRAME_SIZE
+	stmia	sp, {r0 - r12}	@ Save user registers (now in svc mode) r0-r12
+	ldr	r2, IRQ_STACK_START_IN
+	@ get values for "aborted" pc and cpsr (into parm regs)
+	ldmia	r2, {r2 - r3}
+	add	r0, sp, #S_FRAME_SIZE		@ grab pointer to old stack
+	add	r5, sp, #S_SP
+	mov	r1, lr
+	stmia	r5, {r0 - r3}	@ save sp_SVC, lr_SVC, pc, cpsr
+	mov	r0, sp		@ save current stack into r0 (param register)
+	.endm
+
+	.macro	irq_save_user_regs
+	sub	sp, sp, #S_FRAME_SIZE
+	stmia	sp, {r0 - r12}			@ Calling r0-r12
+	@ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
+	add	r8, sp, #S_PC
+	stmdb	r8, {sp, lr}^		@ Calling SP, LR
+	str	lr, [r8, #0]		@ Save calling PC
+	mrs	r6, spsr
+	str	r6, [r8, #4]		@ Save CPSR
+	str	r0, [r8, #8]		@ Save OLD_R0
+	mov	r0, sp
+	.endm
+
+	.macro	irq_restore_user_regs
+	ldmia	sp, {r0 - lr}^			@ Calling r0 - lr
+	mov	r0, r0
+	ldr	lr, [sp, #S_PC]			@ Get PC
+	add	sp, sp, #S_FRAME_SIZE
+	subs	pc, lr, #4		@ return & move spsr_svc into cpsr
+	.endm
+
+	.macro get_bad_stack
+	ldr	r13, IRQ_STACK_START_IN		@ setup our mode stack
+
+	str	lr, [r13]	@ save caller lr in position 0 of saved stack
+	mrs	lr, spsr	@ get the spsr
+	str	lr, [r13, #4]	@ save spsr in position 1 of saved stack
+	mov	r13, #MODE_SVC	@ prepare SVC-Mode
+	@ msr	spsr_c, r13
+	msr	spsr, r13	@ switch modes, make sure moves will execute
+	mov	lr, pc		@ capture return pc
+	movs	pc, lr		@ jump to next instruction & switch modes.
+	.endm
+
+	.macro get_irq_stack			@ setup IRQ stack
+	ldr	sp, IRQ_STACK_START
+	.endm
+
+	.macro get_fiq_stack			@ setup FIQ stack
+	ldr	sp, FIQ_STACK_START
+	.endm
+#endif	/* CONFIG_SPL_BUILD */
+
+/*
+ * exception handlers
+ */
+#ifdef CONFIG_SPL_BUILD
+	.align	5
+do_hang:
+	ldr	sp, _TEXT_BASE			/* switch to abort stack */
+1:
+	bl	1b				/* hang and never return */
+#else	/* !CONFIG_SPL_BUILD */
+	.align  5
+undefined_instruction:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_undefined_instruction
+
+	.align	5
+software_interrupt:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_software_interrupt
+
+	.align	5
+prefetch_abort:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_prefetch_abort
+
+	.align	5
+data_abort:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_data_abort
+
+	.align	5
+not_used:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_not_used
+
+#ifdef CONFIG_USE_IRQ
+
+	.align	5
+irq:
+	get_irq_stack
+	irq_save_user_regs
+	bl	do_irq
+	irq_restore_user_regs
+
+	.align	5
+fiq:
+	get_fiq_stack
+	/* someone ought to write a more effiction fiq_save_user_regs */
+	irq_save_user_regs
+	bl	do_fiq
+	irq_restore_user_regs
+
+#else
+
+	.align	5
+irq:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_irq
+
+	.align	5
+fiq:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_fiq
+
+#endif
+#endif	/* CONFIG_SPL_BUILD */
diff --git a/board/denx/m28evk/u-boot-spl.lds b/board/denx/m28evk/u-boot-spl.lds
new file mode 100644
index 0000000..e296a92
--- /dev/null
+++ b/board/denx/m28evk/u-boot-spl.lds
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * January 2004 - Changed to support H4 device
+ * Copyright (c) 2004-2008 Texas Instruments
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+	. = 0x00000000;
+
+	. = ALIGN(4);
+	.text	:
+	{
+		board/denx/m28evk/start.o	(.text)
+		*(.text)
+	}
+
+	. = ALIGN(4);
+	.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
+
+	. = ALIGN(4);
+	.data : {
+		*(.data)
+	}
+
+	. = ALIGN(4);
+	__u_boot_cmd_start = .;
+	.u_boot_cmd : { *(.u_boot_cmd) }
+	__u_boot_cmd_end = .;
+
+	. = ALIGN(4);
+
+	.rel.dyn : {
+		__rel_dyn_start = .;
+		*(.rel*)
+		__rel_dyn_end = .;
+	}
+
+	.dynsym : {
+		__dynsym_start = .;
+		*(.dynsym)
+	}
+
+	_end = .;
+
+	.bss __rel_dyn_start (OVERLAY) : {
+		__bss_start = .;
+		*(.bss)
+		 . = ALIGN(4);
+		__bss_end__ = .;
+	}
+
+	/DISCARD/ : { *(.bss*) }
+	/DISCARD/ : { *(.dynstr*) }
+	/DISCARD/ : { *(.dynsym*) }
+	/DISCARD/ : { *(.dynamic*) }
+	/DISCARD/ : { *(.hash*) }
+	/DISCARD/ : { *(.plt*) }
+	/DISCARD/ : { *(.interp*) }
+	/DISCARD/ : { *(.gnu*) }
+}
diff --git a/board/denx/m28evk/u-boot.bd b/board/denx/m28evk/u-boot.bd
new file mode 100644
index 0000000..3ce7f92
--- /dev/null
+++ b/board/denx/m28evk/u-boot.bd
@@ -0,0 +1,14 @@
+sources {
+	u_boot_spl="spl/u-boot-spl.bin";
+	u_boot="u-boot.bin";
+}
+
+section (0) {
+        load u_boot_spl > 0x0000;
+        load ivt (entry = 0x0014) > 0x8000;
+	hab call 0x8000;
+
+        load u_boot > 0x40000100;
+        load ivt (entry = 0x40000100) > 0x8000;
+	hab call 0x8000;
+}
diff --git a/include/configs/m28evk.h b/include/configs/m28evk.h
index c50f104..d7771bc 100644
--- a/include/configs/m28evk.h
+++ b/include/configs/m28evk.h
@@ -43,6 +43,14 @@
 #define	CONFIG_ARCH_CPU_INIT
 
 /*
+ * SPL
+ */
+#define	CONFIG_SPL
+#define	CONFIG_SPL_NO_CPU_SUPPORT_CODE
+#define	CONFIG_SPL_START_S_PATH		"board/denx/m28evk"
+#define	CONFIG_SPL_LDSCRIPT		"board/denx/m28evk/u-boot-spl.lds"
+
+/*
  * U-Boot Commands
  */
 #include <config_cmd_default.h>
-- 
1.7.5.4

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

* [U-Boot] [PATCH 15/15] M28: Add doc/README.m28 documentation
  2011-09-12  4:06 [U-Boot] [PATCH 00/15 V2] Support for the DENX M28 SoM Marek Vasut
                   ` (13 preceding siblings ...)
  2011-09-12  4:06 ` [U-Boot] [PATCH 14/15] M28: Add MMC SPL Marek Vasut
@ 2011-09-12  4:06 ` Marek Vasut
  2011-10-21 22:44 ` [U-Boot] [PATCH 00/17 V3] Support for the DENX M28 SoM Marek Vasut
  15 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-09-12  4:06 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 doc/README.m28 |  223 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 223 insertions(+), 0 deletions(-)
 create mode 100644 doc/README.m28

diff --git a/doc/README.m28 b/doc/README.m28
new file mode 100644
index 0000000..b749ce0
--- /dev/null
+++ b/doc/README.m28
@@ -0,0 +1,223 @@
+DENX M28EVK
+===========
+
+This document describes the DENX M28/M28EVK U-Boot port. This document mostly
+covers topics related to making the module/board bootable.
+
+Terminology
+-----------
+
+The dollar symbol ($) introduces a snipped of shell code. This shall be typed
+into the unix command prompt in U-Boot source code root directory.
+
+The (=>) introduces a snipped of code that should by typed into U-Boot command
+prompt.
+
+Contents
+--------
+
+0) Files of the M28/M28EVK port
+1) Prerequisites
+2) Compiling U-Boot for M28
+3) Installation of U-Boot for M28EVK to SD card
+4) Installation of U-Boot for M28 to NAND flash
+
+0) Files of the M28/M28EVK port
+-------------------------------
+
+arch/arm/cpu/arm926ejs/mx28/	- The CPU support code for the Freescale i.MX28
+arch/arm/include/asm/arch-mx28/	- Header files for the Freescale i.MX28
+board/denx/m28evk/		- M28EVK board specific files
+include/configs/m28evk.h	- M28EVK configuration file
+
+1) Prerequisites
+----------------
+
+To make the M28 module or the M28 module or M28EVK board bootable, some tools
+are necessary. The first one is the "elftosb" tool distributed by Freescale
+Semiconductor. The other tool is the "mxsboot" tool found in U-Boot source tree.
+
+Firstly, obtain the elftosb archive from the following location:
+
+	http://foss.doredevelopment.dk/mirrors/imx/elftosb-10.12.01.tar.gz
+
+We use a $VER variable here to denote the current version. At the time of
+writing of this document, that is "10.12.01". To obtain the file from command
+line, use:
+
+	$ VER="10.12.01"
+	$ wget http://foss.doredevelopment.dk/mirrors/imx/elftosb-${VER}.tar.gz
+
+Extract the file:
+
+	$ tar xzf elftosb-${VER}.tar.gz
+
+Compile the file. We need to manually tell the linker to use also libm:
+
+	$ cd elftosb-${VER}/
+	$ make LIBS="-lstdc++ -lm" elftosb
+
+Optionally, remove debugging symbols from elftosb:
+
+	$ strip bld/linux/elftosb
+
+Finally, install the "elftosb" binary. The "install" target is missing, so just
+copy the binary by hand:
+
+	$ sudo cp bld/linux/elftosb /usr/local/bin/
+
+Make sure the "elftosb" binary can be found in your $PATH, in this case this
+means "/usr/local/bin/" has to be in your $PATH.
+
+2) Compiling U-Boot for M28
+---------------------------
+
+Compiling the U-Boot for M28 is straightforward and done as compiling U-Boot
+for any other ARM device. For cross-compiler setup, please refer to ELDK5.0
+documentation. First, clean up the source code:
+
+	$ make mrproper
+
+Next, configure U-Boot for M28EVK:
+
+	$ make m28evk_config
+
+Lastly, compile U-Boot and prepare a "BootStream". The "BootStream" is a special
+type of file, which the i.MX28 CPU can boot. This is handled by the following
+command:
+
+	$ make u-boot.sb
+
+HINT: To speed-up the build process, you can add -j<N>, where N is number of
+      compiler instances that'll run in parallel.
+
+The code produces "u-boot.sb" file. This file needs to be augmented with a
+proper header to allow successful boot from SD or NAND. Adding the header is
+discussed in the following chapters.
+
+3) Installation of U-Boot for M28EVK to SD card
+-----------------------------------------------
+
+To boot an M28 from SD, set the boot mode DIP switches according to i.MX28
+manual chapter 12.2.1 (Table 12-2), PORT=SSP0, SD/MMC master on SSP0, 3.3V.
+
+An SD card the i.MX28 CPU can use to boot U-Boot must contain a DOS partition
+table, which in turn carries a partition of special type and which contains a
+special header. The rest of partitions in the DOS partition table can be used
+by the user.
+
+To prepare such partition, use your favourite partitioning tool. The partition
+must have the following parameters:
+
+	* Start sector .......... sector 2048
+	* Partition size ........ at least 1024 kb
+	* Partition type ........ 0x53 (sometimes "OnTrack DM6 Aux3")
+
+For example in Linux fdisk, the sequence for a clear card is the following:
+
+	* o ..................... create a clear partition table
+	* n ..................... create new partition
+		* p ............. primary partition
+		* 1 ............. first partition
+		* 2048 .......... first sector is 2048
+		* +1M ........... make the partition 1Mb big
+	* t 1 ................... change first partition ID
+		* 53 ............ change the ID to 0x53 (OnTrack DM6 Aux3)
+	* <create other partitions>
+	* w ..................... write partition table to disk
+
+The partition layout is ready, next the special partition must be filled with
+proper contents. The contents is generated by running the following command (see
+chapter 2)):
+
+	$ ./tools/mxsboot sd u-boot.sb u-boot.sd
+
+The resulting file, "u-boot.sd", shall then be written to the partition. In this
+case, we assume the first partition of the SD card is /dev/mmcblk0p1:
+
+	$ dd if=u-boot.sd of=/dev/mmcblk0p1
+
+Last step is to insert the card into M28EVK and boot.
+
+NOTE: If the user needs to adjust the start sector, the "mxsboot" tool contains
+      a "-p" switch for that purpose. The "-p" switch takes the sector number as
+      an argument.
+
+4) Installation of U-Boot for M28 to NAND flash
+-----------------------------------------------
+
+To boot an M28 from NAND, set the boot mode DIP switches according to i.MX28
+manual chapter 12.2.1 (Table 12-2), PORT=GPMI, NAND 1.8 V.
+
+There are two possibilities when preparing an image writable to NAND flash.
+
+	I) The NAND wasn't written at all yet or the BCB is broken
+	----------------------------------------------------------
+	   In this case, both BCB (FCB and DBBT) and firmware needs to be
+	   written to NAND. To generate NAND image containing all these,
+	   there is a tool called "mxsboot" in the "tools/" directory. The tool
+	   is invoked on "u-boot.sb" file from chapter 2):
+
+		 $ ./tools/mxsboot nand u-boot.sb u-boot.nand
+
+	   NOTE: The above invokation works for NAND flash with geometry of
+		 2048b per page, 64b OOB data, 128kb erase size. If your chip
+		 has a different geometry, please use:
+
+		 -w <size>	change page size (default 2048 b)
+		 -o <size>	change oob size (default 64 b)
+		 -e <size>	change erase size (default 131072 b)
+
+		 The geometry information can be obtained from running U-Boot
+		 on M28 by issuing the "nand info" command.
+
+	   The resulting file, "u-boot.nand" can be written directly to NAND
+	   from the U-Boot prompt. To simplify the process, the U-Boot default
+	   environment contains script "update_nand_full" to update the system.
+
+	   This script expects a working TFTP server containing the file
+	   "u-boot.nand" in it's root directory. This can be changed by
+	   adjusting the "update_nand_full_filename" varible.
+
+	   To update the system, run the following in U-Boot prompt:
+
+		 => run update_nand_full
+
+	   In case you would only need to update the bootloader in future,
+	   see II) below.
+
+	II) The NAND was already written with a good BCB
+	------------------------------------------------
+	   This part applies after the part I) above was done at least once.
+
+	   If part I) above was done correctly already, there is no need to
+	   write the FCB and DBBT parts of NAND again. It's possible to upgrade
+	   only the bootloader image.
+
+	   To simplify the process of firmware update, the U-Boot default
+	   environment contains script "update_nand_firmware" to update only
+	   the firmware, without rewriting FCB and DBBT.
+
+	   This script expects a working TFTP server containing the file
+	   "u-boot.sb" in it's root directory. This can be changed by
+	   adjusting the "update_nand_firmware_filename" varible.
+
+	   To update the system, run the following in U-Boot prompt:
+
+		 => run update_nand_firmware
+
+	III) Special settings for the update scripts
+	--------------------------------------------
+	   There is a slight possibility of the user wanting to adjust the
+	   STRIDE and COUNT options of the NAND boot. For description of these,
+	   see i.MX28 manual section 12.12.1.2 and 12.12.1.3.
+
+	   The update scripts take this possibility into account. In case the
+	   user changes STRIDE by blowing fuses, the user also has to change
+	   "update_nand_stride" variable. In case the user changes COUNT by
+	   blowing fuses, the user also has to change "update_nand_count"
+	   variable for the update scripts to work correctly.
+
+	   In case the user needs to boot a firmware image bigger than 1Mb, the
+	   user has to adjust the "update_nand_firmware_maxsz" variable for the
+	   update scripts to work properly.
-- 
1.7.5.4

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

* [U-Boot] [PATCH 05/15] iMX28: Add I2C bus driver
  2011-09-12  4:06 ` [U-Boot] [PATCH 05/15] iMX28: Add I2C bus driver Marek Vasut
@ 2011-09-12  5:30   ` Heiko Schocher
  2011-09-12 13:31     ` Marek Vasut
  2011-09-13 12:05   ` Wolfram Sang
  2011-09-13 22:24   ` [U-Boot] [PATCH 05/15 V2] " Marek Vasut
  2 siblings, 1 reply; 116+ messages in thread
From: Heiko Schocher @ 2011-09-12  5:30 UTC (permalink / raw)
  To: u-boot

Hello Marek,

Marek Vasut wrote:
> Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
> Cc: Heiko Schocher <hs@denx.de>
> Cc: Stefano Babic <sbabic@denx.de>
> Cc: Wolfgang Denk <wd@denx.de>
> Cc: Detlev Zundel <dzu@denx.de>
> ---
>  drivers/i2c/Makefile  |    1 +
>  drivers/i2c/mxs_i2c.c |  240 +++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 241 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/i2c/mxs_i2c.c

Hmm I see you worked in my comment, but then your subject line should
contain a "v2", and also a short description, what you changed, would
be nice ... also, patchwork did not recognize, that this patch is a
following up to your first version. When sending patchupdates, you
should use your first Message-id, so patchwork could follow it.

bye,
Heiko
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

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

* [U-Boot] [PATCH 05/15] iMX28: Add I2C bus driver
  2011-09-12  5:30   ` Heiko Schocher
@ 2011-09-12 13:31     ` Marek Vasut
  0 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-09-12 13:31 UTC (permalink / raw)
  To: u-boot

On Monday, September 12, 2011 07:30:17 AM Heiko Schocher wrote:
> Hello Marek,
> 
> Marek Vasut wrote:
> > Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
> > Cc: Heiko Schocher <hs@denx.de>
> > Cc: Stefano Babic <sbabic@denx.de>
> > Cc: Wolfgang Denk <wd@denx.de>
> > Cc: Detlev Zundel <dzu@denx.de>
> > ---
> > 
> >  drivers/i2c/Makefile  |    1 +
> >  drivers/i2c/mxs_i2c.c |  240
> >  +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 241
> >  insertions(+), 0 deletions(-)
> >  create mode 100644 drivers/i2c/mxs_i2c.c
> 
> Hmm I see you worked in my comment, but then your subject line should
> contain a "v2", and also a short description, what you changed, would
> be nice ... also, patchwork did not recognize, that this patch is a
> following up to your first version. When sending patchupdates, you
> should use your first Message-id, so patchwork could follow it.

ACK, will do next time.

> 
> bye,
> Heiko

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

* [U-Boot] [PATCH 12/15] iMX28: Add u-boot.sb target to Makefile
  2011-09-12  4:06 ` [U-Boot] [PATCH 12/15] iMX28: Add u-boot.sb target to Makefile Marek Vasut
@ 2011-09-12 16:33   ` Mike Frysinger
  2011-09-12 17:40     ` Marek Vasut
  2011-09-13 22:28   ` [U-Boot] [PATCH 12/15 V2] " Marek Vasut
  1 sibling, 1 reply; 116+ messages in thread
From: Mike Frysinger @ 2011-09-12 16:33 UTC (permalink / raw)
  To: u-boot

On Monday, September 12, 2011 00:06:46 Marek Vasut wrote:
>  Makefile |    5 +++++
>  1 files changed, 5 insertions(+), 0 deletions(-)
> 
> --- a/Makefile
> +++ b/Makefile
> 
> +$(obj)u-boot.sb:       $(obj)u-boot.bin $(obj)spl/u-boot-spl.bin
> +		elftosb -zdf imx28 -c board/denx/m28evk/u-boot.bd \
> +			-o $(obj)u-boot.sb

generated files should probably be in .gitignore too
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20110912/de2f5e1c/attachment.pgp 

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

* [U-Boot] [PATCH 07/15] iMX28: Add SPI driver
  2011-09-12  4:06 ` [U-Boot] [PATCH 07/15] iMX28: Add SPI driver Marek Vasut
@ 2011-09-12 16:35   ` Mike Frysinger
  2011-09-12 17:42     ` Marek Vasut
  2011-09-13 22:26   ` [U-Boot] [PATCH 07/15 V2] " Marek Vasut
  1 sibling, 1 reply; 116+ messages in thread
From: Mike Frysinger @ 2011-09-12 16:35 UTC (permalink / raw)
  To: u-boot

On Monday, September 12, 2011 00:06:41 Marek Vasut wrote:
> +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
> +				  unsigned int max_hz, unsigned int mode)
> +{
> +
> +	mx28_reset_block(&ssp_regs->hw_ssp_ctrl0_reg);
> +
> +	writel(SSP_CTRL0_BUS_WIDTH_ONE_BIT, &ssp_regs->hw_ssp_ctrl0);
> +
> +	reg = SSP_CTRL1_SSP_MODE_SPI | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS;
> +	reg |= (mode & SPI_CPOL) ? SSP_CTRL1_POLARITY : 0;
> +	reg |= (mode & SPI_CPHA) ? SSP_CTRL1_PHASE : 0;
> +	writel(reg, &ssp_regs->hw_ssp_ctrl1);
> +
> +	writel(0, &ssp_regs->hw_ssp_cmd0);
> +
> +	mx28_set_ssp_busclock(bus, max_hz / 1000);

these steps should be done in the claim_bus func

> +void mxs_spi_start_xfer(struct spi_slave *slave)
> +void mxs_spi_end_xfer(struct spi_slave *slave)

both should be static
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20110912/9b6bf187/attachment.pgp 

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

* [U-Boot] [PATCH 11/15] iMX28: Add image header generator tool
  2011-09-12  4:06 ` [U-Boot] [PATCH 11/15] iMX28: Add image header generator tool Marek Vasut
@ 2011-09-12 16:38   ` Mike Frysinger
  2011-09-12 17:40     ` Marek Vasut
  2011-09-13 22:27   ` [U-Boot] [PATCH 11/15 V2] " Marek Vasut
  1 sibling, 1 reply; 116+ messages in thread
From: Mike Frysinger @ 2011-09-12 16:38 UTC (permalink / raw)
  To: u-boot

On Monday, September 12, 2011 00:06:45 Marek Vasut wrote:
>  tools/Makefile  |    6 +
>  tools/mxsboot.c |  687
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed,
> 693 insertions(+), 0 deletions(-)
>  create mode 100644 tools/mxsboot.c

missing .gitignore update

> --- /dev/null
> +++ b/tools/mxsboot.c
> 
> +#include <fcntl.h>
> +#include <malloc.h>
> +#include <stdint.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <sys/stat.h>
> +#include <sys/types.h>
> +#include <unistd.h>

drop the malloc.h and probably add compiler.h
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20110912/900353f7/attachment.pgp 

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

* [U-Boot] [PATCH 12/15] iMX28: Add u-boot.sb target to Makefile
  2011-09-12 16:33   ` Mike Frysinger
@ 2011-09-12 17:40     ` Marek Vasut
  0 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-09-12 17:40 UTC (permalink / raw)
  To: u-boot

On Monday, September 12, 2011 06:33:29 PM Mike Frysinger wrote:
> On Monday, September 12, 2011 00:06:46 Marek Vasut wrote:
> >  Makefile |    5 +++++
> >  1 files changed, 5 insertions(+), 0 deletions(-)
> > 
> > --- a/Makefile
> > +++ b/Makefile
> > 
> > +$(obj)u-boot.sb:       $(obj)u-boot.bin $(obj)spl/u-boot-spl.bin
> > +		elftosb -zdf imx28 -c board/denx/m28evk/u-boot.bd \
> > +			-o $(obj)u-boot.sb
> 
> generated files should probably be in .gitignore too
> -mike

u-boot.sb added, thanks. Will be in V3

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

* [U-Boot] [PATCH 11/15] iMX28: Add image header generator tool
  2011-09-12 16:38   ` Mike Frysinger
@ 2011-09-12 17:40     ` Marek Vasut
  2011-09-12 20:24       ` Mike Frysinger
  0 siblings, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-09-12 17:40 UTC (permalink / raw)
  To: u-boot

On Monday, September 12, 2011 06:38:29 PM Mike Frysinger wrote:
> On Monday, September 12, 2011 00:06:45 Marek Vasut wrote:
> >  tools/Makefile  |    6 +
> >  tools/mxsboot.c |  687
> > 
> > +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed,
> > 693 insertions(+), 0 deletions(-)
> > 
> >  create mode 100644 tools/mxsboot.c
> 
> missing .gitignore update

Ignore what?

> 
> > --- /dev/null
> > +++ b/tools/mxsboot.c
> > 
> > +#include <fcntl.h>
> > +#include <malloc.h>
> > +#include <stdint.h>
> > +#include <stdio.h>
> > +#include <stdlib.h>
> > +#include <string.h>
> > +#include <sys/stat.h>
> > +#include <sys/types.h>
> > +#include <unistd.h>
> 
> drop the malloc.h and probably add compiler.h
> -mike

Cheers

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

* [U-Boot] [PATCH 07/15] iMX28: Add SPI driver
  2011-09-12 16:35   ` Mike Frysinger
@ 2011-09-12 17:42     ` Marek Vasut
  2011-09-12 20:26       ` Mike Frysinger
  0 siblings, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-09-12 17:42 UTC (permalink / raw)
  To: u-boot

On Monday, September 12, 2011 06:35:10 PM Mike Frysinger wrote:
> On Monday, September 12, 2011 00:06:41 Marek Vasut wrote:
> > +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
> > +				  unsigned int max_hz, unsigned int mode)
> > +{
> > +
> > +	mx28_reset_block(&ssp_regs->hw_ssp_ctrl0_reg);
> > +
> > +	writel(SSP_CTRL0_BUS_WIDTH_ONE_BIT, &ssp_regs->hw_ssp_ctrl0);
> > +
> > +	reg = SSP_CTRL1_SSP_MODE_SPI | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS;
> > +	reg |= (mode & SPI_CPOL) ? SSP_CTRL1_POLARITY : 0;
> > +	reg |= (mode & SPI_CPHA) ? SSP_CTRL1_PHASE : 0;
> > +	writel(reg, &ssp_regs->hw_ssp_ctrl1);
> > +
> > +	writel(0, &ssp_regs->hw_ssp_cmd0);
> > +
> > +	mx28_set_ssp_busclock(bus, max_hz / 1000);
> 
> these steps should be done in the claim_bus func

I don't think so ... I need to access max_hz and mode. This seems more fitting 
to me.

> 
> > +void mxs_spi_start_xfer(struct spi_slave *slave)
> > +void mxs_spi_end_xfer(struct spi_slave *slave)
> 
> both should be static
> -mike

ACK

Cheers

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

* [U-Boot] [PATCH 11/15] iMX28: Add image header generator tool
  2011-09-12 17:40     ` Marek Vasut
@ 2011-09-12 20:24       ` Mike Frysinger
  2011-09-12 22:13         ` Marek Vasut
  0 siblings, 1 reply; 116+ messages in thread
From: Mike Frysinger @ 2011-09-12 20:24 UTC (permalink / raw)
  To: u-boot

On Monday, September 12, 2011 13:40:35 Marek Vasut wrote:
> On Monday, September 12, 2011 06:38:29 PM Mike Frysinger wrote:
> > On Monday, September 12, 2011 00:06:45 Marek Vasut wrote:
> > >  tools/Makefile  |    6 +
> > >  tools/mxsboot.c |  687
> > > 
> > > +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files
> > > changed, 693 insertions(+), 0 deletions(-)
> > > 
> > >  create mode 100644 tools/mxsboot.c
> > 
> > missing .gitignore update
> 
> Ignore what?

the "mxsboot" tool of course
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20110912/f6034b8a/attachment.pgp 

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

* [U-Boot] [PATCH 07/15] iMX28: Add SPI driver
  2011-09-12 17:42     ` Marek Vasut
@ 2011-09-12 20:26       ` Mike Frysinger
  2011-09-12 22:45         ` Marek Vasut
  0 siblings, 1 reply; 116+ messages in thread
From: Mike Frysinger @ 2011-09-12 20:26 UTC (permalink / raw)
  To: u-boot

On Monday, September 12, 2011 13:42:22 Marek Vasut wrote:
> On Monday, September 12, 2011 06:35:10 PM Mike Frysinger wrote:
> > On Monday, September 12, 2011 00:06:41 Marek Vasut wrote:
> > > +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
> > > +				  unsigned int max_hz, unsigned int mode)
> > > +{
> > > +
> > > +	mx28_reset_block(&ssp_regs->hw_ssp_ctrl0_reg);
> > > +
> > > +	writel(SSP_CTRL0_BUS_WIDTH_ONE_BIT, &ssp_regs->hw_ssp_ctrl0);
> > > +
> > > +	reg = SSP_CTRL1_SSP_MODE_SPI | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS;
> > > +	reg |= (mode & SPI_CPOL) ? SSP_CTRL1_POLARITY : 0;
> > > +	reg |= (mode & SPI_CPHA) ? SSP_CTRL1_PHASE : 0;
> > > +	writel(reg, &ssp_regs->hw_ssp_ctrl1);
> > > +
> > > +	writel(0, &ssp_regs->hw_ssp_cmd0);
> > > +
> > > +	mx28_set_ssp_busclock(bus, max_hz / 1000);
> > 
> > these steps should be done in the claim_bus func
> 
> I don't think so ... I need to access max_hz and mode. This seems more
> fitting to me.

that's not how the API works.  you create clients, then you acquire the bus 
for a specific client, do a transfer, and then release it.  your bus breaks 
with the trivial case:
	- setup slave A
	- setup slave B
	- claim bus for slave A
	- transfer with slave A	<- uses settings from slave B
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20110912/92ae84b9/attachment.pgp 

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

* [U-Boot] [PATCH 11/15] iMX28: Add image header generator tool
  2011-09-12 20:24       ` Mike Frysinger
@ 2011-09-12 22:13         ` Marek Vasut
  0 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-09-12 22:13 UTC (permalink / raw)
  To: u-boot

On Monday, September 12, 2011 10:24:38 PM Mike Frysinger wrote:
> On Monday, September 12, 2011 13:40:35 Marek Vasut wrote:
> > On Monday, September 12, 2011 06:38:29 PM Mike Frysinger wrote:
> > > On Monday, September 12, 2011 00:06:45 Marek Vasut wrote:
> > > >  tools/Makefile  |    6 +
> > > >  tools/mxsboot.c |  687
> > > > 
> > > > +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files
> > > > changed, 693 insertions(+), 0 deletions(-)
> > > > 
> > > >  create mode 100644 tools/mxsboot.c
> > > 
> > > missing .gitignore update
> > 
> > Ignore what?
> 
> the "mxsboot" tool of course
> -mike

Oh of course ! Thanks ;-)

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

* [U-Boot] [PATCH 07/15] iMX28: Add SPI driver
  2011-09-12 20:26       ` Mike Frysinger
@ 2011-09-12 22:45         ` Marek Vasut
  0 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-09-12 22:45 UTC (permalink / raw)
  To: u-boot

On Monday, September 12, 2011 10:26:11 PM Mike Frysinger wrote:
> On Monday, September 12, 2011 13:42:22 Marek Vasut wrote:
> > On Monday, September 12, 2011 06:35:10 PM Mike Frysinger wrote:
> > > On Monday, September 12, 2011 00:06:41 Marek Vasut wrote:
> > > > +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
> > > > +				  unsigned int max_hz, unsigned int 
mode)
> > > > +{
> > > > +
> > > > +	mx28_reset_block(&ssp_regs->hw_ssp_ctrl0_reg);
> > > > +
> > > > +	writel(SSP_CTRL0_BUS_WIDTH_ONE_BIT, &ssp_regs->hw_ssp_ctrl0);
> > > > +
> > > > +	reg = SSP_CTRL1_SSP_MODE_SPI | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS;
> > > > +	reg |= (mode & SPI_CPOL) ? SSP_CTRL1_POLARITY : 0;
> > > > +	reg |= (mode & SPI_CPHA) ? SSP_CTRL1_PHASE : 0;
> > > > +	writel(reg, &ssp_regs->hw_ssp_ctrl1);
> > > > +
> > > > +	writel(0, &ssp_regs->hw_ssp_cmd0);
> > > > +
> > > > +	mx28_set_ssp_busclock(bus, max_hz / 1000);
> > > 
> > > these steps should be done in the claim_bus func
> > 
> > I don't think so ... I need to access max_hz and mode. This seems more
> > fitting to me.
> 
> that's not how the API works.  you create clients, then you acquire the bus
> for a specific client, do a transfer, and then release it.  your bus breaks
> with the trivial case:
> 	- setup slave A
> 	- setup slave B
> 	- claim bus for slave A
> 	- transfer with slave A	<- uses settings from slave B
> -mike

Thanks for clearing this, fixed in V3

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

* [U-Boot] [PATCH 05/15] iMX28: Add I2C bus driver
  2011-09-12  4:06 ` [U-Boot] [PATCH 05/15] iMX28: Add I2C bus driver Marek Vasut
  2011-09-12  5:30   ` Heiko Schocher
@ 2011-09-13 12:05   ` Wolfram Sang
  2011-09-13 12:56     ` Marek Vasut
  2011-09-13 22:24   ` [U-Boot] [PATCH 05/15 V2] " Marek Vasut
  2 siblings, 1 reply; 116+ messages in thread
From: Wolfram Sang @ 2011-09-13 12:05 UTC (permalink / raw)
  To: u-boot

Hi Marek,

On Mon, Sep 12, 2011 at 06:06:39AM +0200, Marek Vasut wrote:
> Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
> Cc: Heiko Schocher <hs@denx.de>
> Cc: Stefano Babic <sbabic@denx.de>
> Cc: Wolfgang Denk <wd@denx.de>
> Cc: Detlev Zundel <dzu@denx.de>
> ---
>  drivers/i2c/Makefile  |    1 +
>  drivers/i2c/mxs_i2c.c |  240 +++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 241 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/i2c/mxs_i2c.c
> 
> diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
> index a48047a..2fb521e 100644
> --- a/drivers/i2c/Makefile
> +++ b/drivers/i2c/Makefile
> @@ -31,6 +31,7 @@ COBJS-$(CONFIG_FSL_I2C) += fsl_i2c.o
>  COBJS-$(CONFIG_I2C_MVTWSI) += mvtwsi.o
>  COBJS-$(CONFIG_I2C_MV) += mv_i2c.o
>  COBJS-$(CONFIG_I2C_MXC) += mxc_i2c.o
> +COBJS-$(CONFIG_I2C_MXS) += mxs_i2c.o
>  COBJS-$(CONFIG_DRIVER_OMAP1510_I2C) += omap1510_i2c.o
>  COBJS-$(CONFIG_DRIVER_OMAP24XX_I2C) += omap24xx_i2c.o
>  COBJS-$(CONFIG_DRIVER_OMAP34XX_I2C) += omap24xx_i2c.o
> diff --git a/drivers/i2c/mxs_i2c.c b/drivers/i2c/mxs_i2c.c
> new file mode 100644
> index 0000000..9f380a0
> --- /dev/null
> +++ b/drivers/i2c/mxs_i2c.c
> @@ -0,0 +1,240 @@
> +/*
> + * Freescale i.MX28 I2C Driver
> + *
> + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
> + * on behalf of DENX Software Engineering GmbH

Do you mind adding the copyrights from the kernel driver here? It looks
quite inspired to me, even if you didn't like some of the variable names
and defines :)

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
Url : http://lists.denx.de/pipermail/u-boot/attachments/20110913/80883383/attachment.pgp 

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

* [U-Boot] [PATCH 05/15] iMX28: Add I2C bus driver
  2011-09-13 12:05   ` Wolfram Sang
@ 2011-09-13 12:56     ` Marek Vasut
  2011-09-13 13:12       ` Wolfram Sang
  0 siblings, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-09-13 12:56 UTC (permalink / raw)
  To: u-boot

On Tuesday, September 13, 2011 02:05:30 PM Wolfram Sang wrote:
> Hi Marek,
> 
> On Mon, Sep 12, 2011 at 06:06:39AM +0200, Marek Vasut wrote:
> > Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
> > Cc: Heiko Schocher <hs@denx.de>
> > Cc: Stefano Babic <sbabic@denx.de>
> > Cc: Wolfgang Denk <wd@denx.de>
> > Cc: Detlev Zundel <dzu@denx.de>
> > ---
> > 
> >  drivers/i2c/Makefile  |    1 +
> >  drivers/i2c/mxs_i2c.c |  240
> >  +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 241
> >  insertions(+), 0 deletions(-)
> >  create mode 100644 drivers/i2c/mxs_i2c.c
> > 
> > diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
> > index a48047a..2fb521e 100644
> > --- a/drivers/i2c/Makefile
> > +++ b/drivers/i2c/Makefile
> > @@ -31,6 +31,7 @@ COBJS-$(CONFIG_FSL_I2C) += fsl_i2c.o
> > 
> >  COBJS-$(CONFIG_I2C_MVTWSI) += mvtwsi.o
> >  COBJS-$(CONFIG_I2C_MV) += mv_i2c.o
> >  COBJS-$(CONFIG_I2C_MXC) += mxc_i2c.o
> > 
> > +COBJS-$(CONFIG_I2C_MXS) += mxs_i2c.o
> > 
> >  COBJS-$(CONFIG_DRIVER_OMAP1510_I2C) += omap1510_i2c.o
> >  COBJS-$(CONFIG_DRIVER_OMAP24XX_I2C) += omap24xx_i2c.o
> >  COBJS-$(CONFIG_DRIVER_OMAP34XX_I2C) += omap24xx_i2c.o
> > 
> > diff --git a/drivers/i2c/mxs_i2c.c b/drivers/i2c/mxs_i2c.c
> > new file mode 100644
> > index 0000000..9f380a0
> > --- /dev/null
> > +++ b/drivers/i2c/mxs_i2c.c
> > @@ -0,0 +1,240 @@
> > +/*
> > + * Freescale i.MX28 I2C Driver
> > + *
> > + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
> > + * on behalf of DENX Software Engineering GmbH
> 
> Do you mind adding the copyrights from the kernel driver here? It looks
> quite inspired to me, even if you didn't like some of the variable names
> and defines :)

Bits are from the STMP3xxx driver, not much though.

> 
> Regards,
> 
>    Wolfram

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

* [U-Boot] [PATCH 05/15] iMX28: Add I2C bus driver
  2011-09-13 12:56     ` Marek Vasut
@ 2011-09-13 13:12       ` Wolfram Sang
  2011-09-13 13:20         ` Marek Vasut
  0 siblings, 1 reply; 116+ messages in thread
From: Wolfram Sang @ 2011-09-13 13:12 UTC (permalink / raw)
  To: u-boot

> > > diff --git a/drivers/i2c/mxs_i2c.c b/drivers/i2c/mxs_i2c.c
> > > new file mode 100644
> > > index 0000000..9f380a0
> > > --- /dev/null
> > > +++ b/drivers/i2c/mxs_i2c.c
> > > @@ -0,0 +1,240 @@
> > > +/*
> > > + * Freescale i.MX28 I2C Driver
> > > + *
> > > + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
> > > + * on behalf of DENX Software Engineering GmbH
> > 
> > Do you mind adding the copyrights from the kernel driver here? It looks
> > quite inspired to me, even if you didn't like some of the variable names
> > and defines :)
> 
> Bits are from the STMP3xxx driver, not much though.

Could you point me to that driver? Maybe it needs fixing as well,
because that pattern for example:

+       off = i;
+       for (; i < off + blen; i++) {
+               data >>= 8;
+               data |= buf[i - off] << 24;
+               if ((i & 3) == 2)
+                       writel(data, &i2c_regs->hw_i2c_data);
+       }
+
+       remain = 24 - ((i & 3) * 8);
+       if (remain)
+               writel(data >> remain, &i2c_regs->hw_i2c_data);

is highly similar to my reimplementation of the "let's feed the buffer
code" in the kernel (to name one example). Check current linus-git:

        for (i = 0; i < len; i++) {
                data >>= 8;
                data |= buf[i] << 24;
                if ((i & 3) == 2)
                        writel(data, i2c->regs + MXS_I2C_DATA);
        }

        /* Write out the remaining bytes if any */
        shifts_left = 24 - (i & 3) * 8;
        if (shifts_left)
                writel(data >> shifts_left, i2c->regs + MXS_I2C_DATA);

I'd be very surprised if two programmers would come up with two routines
that equal?

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
Url : http://lists.denx.de/pipermail/u-boot/attachments/20110913/e7ccc63e/attachment.pgp 

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

* [U-Boot] [PATCH 05/15] iMX28: Add I2C bus driver
  2011-09-13 13:12       ` Wolfram Sang
@ 2011-09-13 13:20         ` Marek Vasut
  2011-09-13 13:31           ` Wolfram Sang
  0 siblings, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-09-13 13:20 UTC (permalink / raw)
  To: u-boot

On Tuesday, September 13, 2011 03:12:40 PM Wolfram Sang wrote:
> > > > diff --git a/drivers/i2c/mxs_i2c.c b/drivers/i2c/mxs_i2c.c
> > > > new file mode 100644
> > > > index 0000000..9f380a0
> > > > --- /dev/null
> > > > +++ b/drivers/i2c/mxs_i2c.c
> > > > @@ -0,0 +1,240 @@
> > > > +/*
> > > > + * Freescale i.MX28 I2C Driver
> > > > + *
> > > > + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
> > > > + * on behalf of DENX Software Engineering GmbH
> > > 
> > > Do you mind adding the copyrights from the kernel driver here? It looks
> > > quite inspired to me, even if you didn't like some of the variable
> > > names and defines :)
> > 
> > Bits are from the STMP3xxx driver, not much though.
> 
> Could you point me to that driver? Maybe it needs fixing as well,
> because that pattern for example:
> 
> +       off = i;
> +       for (; i < off + blen; i++) {
> +               data >>= 8;
> +               data |= buf[i - off] << 24;
> +               if ((i & 3) == 2)
> +                       writel(data, &i2c_regs->hw_i2c_data);
> +       }
> +
> +       remain = 24 - ((i & 3) * 8);
> +       if (remain)
> +               writel(data >> remain, &i2c_regs->hw_i2c_data);
> 
> is highly similar to my reimplementation of the "let's feed the buffer
> code" in the kernel (to name one example). Check current linus-git:
> 
>         for (i = 0; i < len; i++) {
>                 data >>= 8;
>                 data |= buf[i] << 24;
>                 if ((i & 3) == 2)
>                         writel(data, i2c->regs + MXS_I2C_DATA);
>         }
> 
>         /* Write out the remaining bytes if any */
>         shifts_left = 24 - (i & 3) * 8;
>         if (shifts_left)
>                 writel(data >> shifts_left, i2c->regs + MXS_I2C_DATA);
> 
> I'd be very surprised if two programmers would come up with two routines
> that equal?

Oh I2C, not SPI. Sorry.

Will add Based on line, cheers!

> 
> Regards,
> 
>    Wolfram

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

* [U-Boot] [PATCH 05/15] iMX28: Add I2C bus driver
  2011-09-13 13:20         ` Marek Vasut
@ 2011-09-13 13:31           ` Wolfram Sang
  0 siblings, 0 replies; 116+ messages in thread
From: Wolfram Sang @ 2011-09-13 13:31 UTC (permalink / raw)
  To: u-boot

> Oh I2C, not SPI. Sorry.
> 
> Will add Based on line, cheers!

Cool, thanks.

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
Url : http://lists.denx.de/pipermail/u-boot/attachments/20110913/21cd75d0/attachment.pgp 

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

* [U-Boot] [PATCH 05/15 V2] iMX28: Add I2C bus driver
  2011-09-12  4:06 ` [U-Boot] [PATCH 05/15] iMX28: Add I2C bus driver Marek Vasut
  2011-09-12  5:30   ` Heiko Schocher
  2011-09-13 12:05   ` Wolfram Sang
@ 2011-09-13 22:24   ` Marek Vasut
  2 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-09-13 22:24 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Heiko Schocher <hs@denx.de>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 drivers/i2c/Makefile  |    1 +
 drivers/i2c/mxs_i2c.c |  246 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 247 insertions(+), 0 deletions(-)
 create mode 100644 drivers/i2c/mxs_i2c.c

V2: Add "based on" text.

diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index a48047a..2fb521e 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -31,6 +31,7 @@ COBJS-$(CONFIG_FSL_I2C) += fsl_i2c.o
 COBJS-$(CONFIG_I2C_MVTWSI) += mvtwsi.o
 COBJS-$(CONFIG_I2C_MV) += mv_i2c.o
 COBJS-$(CONFIG_I2C_MXC) += mxc_i2c.o
+COBJS-$(CONFIG_I2C_MXS) += mxs_i2c.o
 COBJS-$(CONFIG_DRIVER_OMAP1510_I2C) += omap1510_i2c.o
 COBJS-$(CONFIG_DRIVER_OMAP24XX_I2C) += omap24xx_i2c.o
 COBJS-$(CONFIG_DRIVER_OMAP34XX_I2C) += omap24xx_i2c.o
diff --git a/drivers/i2c/mxs_i2c.c b/drivers/i2c/mxs_i2c.c
new file mode 100644
index 0000000..c8fea32
--- /dev/null
+++ b/drivers/i2c/mxs_i2c.c
@@ -0,0 +1,246 @@
+/*
+ * Freescale i.MX28 I2C Driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Partly based on Linux kernel i2c-mxs.c driver:
+ * Copyright (C) 2011 Wolfram Sang, Pengutronix e.K.
+ *
+ * Which was based on a (non-working) driver which was:
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+
+#define	MXS_I2C_MAX_TIMEOUT	1000000
+
+void mxs_i2c_reset(void)
+{
+	struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE;
+	int ret;
+
+	ret = mx28_reset_block(&i2c_regs->hw_i2c_ctrl0_reg);
+	if (ret) {
+		debug("MXS I2C: Block reset timeout\n");
+		return;
+	}
+
+	writel(I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ | I2C_CTRL1_NO_SLAVE_ACK_IRQ |
+		I2C_CTRL1_EARLY_TERM_IRQ | I2C_CTRL1_MASTER_LOSS_IRQ |
+		I2C_CTRL1_SLAVE_STOP_IRQ | I2C_CTRL1_SLAVE_IRQ,
+		&i2c_regs->hw_i2c_ctrl1_clr);
+
+	writel(I2C_QUEUECTRL_PIO_QUEUE_MODE, &i2c_regs->hw_i2c_queuectrl_set);
+}
+
+void mxs_i2c_setup_read(uint8_t chip, int len)
+{
+	struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE;
+
+	writel(I2C_QUEUECMD_RETAIN_CLOCK | I2C_QUEUECMD_PRE_SEND_START |
+		I2C_QUEUECMD_MASTER_MODE | I2C_QUEUECMD_DIRECTION |
+		(1 << I2C_QUEUECMD_XFER_COUNT_OFFSET),
+		&i2c_regs->hw_i2c_queuecmd);
+
+	writel((chip << 1) | 1, &i2c_regs->hw_i2c_data);
+
+	writel(I2C_QUEUECMD_SEND_NAK_ON_LAST | I2C_QUEUECMD_MASTER_MODE |
+		(len << I2C_QUEUECMD_XFER_COUNT_OFFSET) |
+		I2C_QUEUECMD_POST_SEND_STOP, &i2c_regs->hw_i2c_queuecmd);
+
+	writel(I2C_QUEUECTRL_QUEUE_RUN, &i2c_regs->hw_i2c_queuectrl_set);
+}
+
+void mxs_i2c_write(uchar chip, uint addr, int alen,
+			uchar *buf, int blen, int stop)
+{
+	struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE;
+	uint32_t data;
+	int i, remain, off;
+
+	if ((alen > 4) || (alen == 0)) {
+		debug("MXS I2C: Invalid address length\n");
+		return;
+	}
+
+	if (stop)
+		stop = I2C_QUEUECMD_POST_SEND_STOP;
+
+	writel(I2C_QUEUECMD_PRE_SEND_START |
+		I2C_QUEUECMD_MASTER_MODE | I2C_QUEUECMD_DIRECTION |
+		((blen + alen + 1) << I2C_QUEUECMD_XFER_COUNT_OFFSET) | stop,
+		&i2c_regs->hw_i2c_queuecmd);
+
+	data = (chip << 1) << 24;
+
+	for (i = 0; i < alen; i++) {
+		data >>= 8;
+		data |= ((char *)&addr)[i] << 24;
+		if ((i & 3) == 2)
+			writel(data, &i2c_regs->hw_i2c_data);
+	}
+
+	off = i;
+	for (; i < off + blen; i++) {
+		data >>= 8;
+		data |= buf[i - off] << 24;
+		if ((i & 3) == 2)
+			writel(data, &i2c_regs->hw_i2c_data);
+	}
+
+	remain = 24 - ((i & 3) * 8);
+	if (remain)
+		writel(data >> remain, &i2c_regs->hw_i2c_data);
+
+	writel(I2C_QUEUECTRL_QUEUE_RUN, &i2c_regs->hw_i2c_queuectrl_set);
+}
+
+int mxs_i2c_wait_for_ack(void)
+{
+	struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE;
+	uint32_t tmp;
+	int timeout = MXS_I2C_MAX_TIMEOUT;
+
+	for (;;) {
+		tmp = readl(&i2c_regs->hw_i2c_ctrl1);
+		if (tmp & I2C_CTRL1_NO_SLAVE_ACK_IRQ) {
+			debug("MXS I2C: No slave ACK\n");
+			goto err;
+		}
+
+		if (tmp & (
+			I2C_CTRL1_EARLY_TERM_IRQ | I2C_CTRL1_MASTER_LOSS_IRQ |
+			I2C_CTRL1_SLAVE_STOP_IRQ | I2C_CTRL1_SLAVE_IRQ)) {
+			debug("MXS I2C: Error (CTRL1 = %08x)\n", tmp);
+			goto err;
+		}
+
+		if (tmp & I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ)
+			break;
+
+		if (!timeout--) {
+			debug("MXS I2C: Operation timed out\n");
+			goto err;
+		}
+
+		udelay(1);
+	}
+
+	return 0;
+
+err:
+	mxs_i2c_reset();
+	return 1;
+}
+
+int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+	struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE;
+	uint32_t tmp = 0;
+	int ret;
+	int i;
+
+	mxs_i2c_write(chip, addr, alen, NULL, 0, 0);
+	ret = mxs_i2c_wait_for_ack();
+	if (ret) {
+		debug("MXS I2C: Failed writing address\n");
+		return ret;
+	}
+
+	mxs_i2c_setup_read(chip, len);
+	ret = mxs_i2c_wait_for_ack();
+	if (ret) {
+		debug("MXS I2C: Failed reading address\n");
+		return ret;
+	}
+
+	for (i = 0; i < len; i++) {
+		if (!(i & 3)) {
+			while (readl(&i2c_regs->hw_i2c_queuestat) &
+				I2C_QUEUESTAT_RD_QUEUE_EMPTY)
+				;
+			tmp = readl(&i2c_regs->hw_i2c_queuedata);
+		}
+		buffer[i] = tmp & 0xff;
+		tmp >>= 8;
+	}
+
+	return 0;
+}
+
+int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+	int ret;
+	mxs_i2c_write(chip, addr, alen, buffer, len, 1);
+	ret = mxs_i2c_wait_for_ack();
+	if (ret)
+		debug("MXS I2C: Failed writing address\n");
+
+	return ret;
+}
+
+int i2c_probe(uchar chip)
+{
+	int ret;
+	mxs_i2c_write(chip, 0, 1, NULL, 0, 1);
+	ret = mxs_i2c_wait_for_ack();
+	mxs_i2c_reset();
+	return ret;
+}
+
+void i2c_init(int speed, int slaveadd)
+{
+	struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE;
+
+	mxs_i2c_reset();
+
+	switch (speed) {
+	case 100000:
+		writel((0x0078 << I2C_TIMING0_HIGH_COUNT_OFFSET) |
+			(0x0030 << I2C_TIMING0_RCV_COUNT_OFFSET),
+			&i2c_regs->hw_i2c_timing0);
+		writel((0x0080 << I2C_TIMING1_LOW_COUNT_OFFSET) |
+			(0x0030 << I2C_TIMING1_XMIT_COUNT_OFFSET),
+			&i2c_regs->hw_i2c_timing1);
+		break;
+	case 400000:
+		writel((0x000f << I2C_TIMING0_HIGH_COUNT_OFFSET) |
+			(0x0007 << I2C_TIMING0_RCV_COUNT_OFFSET),
+			&i2c_regs->hw_i2c_timing0);
+		writel((0x001f << I2C_TIMING1_LOW_COUNT_OFFSET) |
+			(0x000f << I2C_TIMING1_XMIT_COUNT_OFFSET),
+			&i2c_regs->hw_i2c_timing1);
+		break;
+	default:
+		printf("MXS I2C: Invalid speed selected (%d Hz)\n", speed);
+		return;
+	}
+
+	writel((0x0015 << I2C_TIMING2_BUS_FREE_OFFSET) |
+		(0x000d << I2C_TIMING2_LEADIN_COUNT_OFFSET),
+		&i2c_regs->hw_i2c_timing2);
+
+	return;
+}
-- 
1.7.5.4

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

* [U-Boot] [PATCH 07/15 V2] iMX28: Add SPI driver
  2011-09-12  4:06 ` [U-Boot] [PATCH 07/15] iMX28: Add SPI driver Marek Vasut
  2011-09-12 16:35   ` Mike Frysinger
@ 2011-09-13 22:26   ` Marek Vasut
  2011-09-14  2:50     ` Mike Frysinger
  1 sibling, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-09-13 22:26 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 drivers/spi/Makefile  |    1 +
 drivers/spi/mxs_spi.c |  186 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 187 insertions(+), 0 deletions(-)
 create mode 100644 drivers/spi/mxs_spi.c

V2: Use the SPI API properly.

diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 96c9642..9a0c475 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -36,6 +36,7 @@ COBJS-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
 COBJS-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o
 COBJS-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
 COBJS-$(CONFIG_MXC_SPI) += mxc_spi.o
+COBJS-$(CONFIG_MXS_SPI) += mxs_spi.o
 COBJS-$(CONFIG_OC_TINY_SPI) += oc_tiny_spi.o
 COBJS-$(CONFIG_OMAP3_SPI) += omap3_spi.o
 COBJS-$(CONFIG_SOFT_SPI) += soft_spi.o
diff --git a/drivers/spi/mxs_spi.c b/drivers/spi/mxs_spi.c
new file mode 100644
index 0000000..4c27fef
--- /dev/null
+++ b/drivers/spi/mxs_spi.c
@@ -0,0 +1,186 @@
+/*
+ * Freescale i.MX28 SPI driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * NOTE: This driver only supports the SPI-controller chipselects,
+ *       GPIO driven chipselects are not supported.
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+
+#define	MXS_SPI_MAX_TIMEOUT	1000000
+#define	MXS_SPI_PORT_OFFSET	0x2000
+
+struct mxs_spi_slave {
+	struct spi_slave	slave;
+	uint32_t		max_khz;
+	uint32_t		mode;
+	struct mx28_ssp_regs	*regs;
+};
+
+static inline struct mxs_spi_slave *to_mxs_slave(struct spi_slave *slave)
+{
+	return container_of(slave, struct mxs_spi_slave, slave);
+}
+
+void spi_init(void)
+{
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+				  unsigned int max_hz, unsigned int mode)
+{
+	struct mxs_spi_slave *mxs_slave;
+	uint32_t addr;
+
+	if (bus > 3) {
+		printf("MXS SPI: Max bus number is 3\n");
+		return NULL;
+	}
+
+	mxs_slave = malloc(sizeof(struct mxs_spi_slave));
+	if (!mxs_slave)
+		return NULL;
+
+	addr = MXS_SSP0_BASE + (bus * MXS_SPI_PORT_OFFSET);
+
+	mxs_slave->slave.bus = bus;
+	mxs_slave->slave.cs = cs;
+	mxs_slave->max_khz = max_hz / 1000;
+	mxs_slave->mode = mode;
+	mxs_slave->regs = (struct mx28_ssp_regs *)addr;
+
+	return &mxs_slave->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+	struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave);
+	free(mxs_slave);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+	struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave);
+	struct mx28_ssp_regs *ssp_regs = mxs_slave->regs;
+	uint32_t reg = 0;
+
+	mx28_reset_block(&ssp_regs->hw_ssp_ctrl0_reg);
+
+	writel(SSP_CTRL0_BUS_WIDTH_ONE_BIT, &ssp_regs->hw_ssp_ctrl0);
+
+	reg = SSP_CTRL1_SSP_MODE_SPI | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS;
+	reg |= (mxs_slave->mode & SPI_CPOL) ? SSP_CTRL1_POLARITY : 0;
+	reg |= (mxs_slave->mode & SPI_CPHA) ? SSP_CTRL1_PHASE : 0;
+	writel(reg, &ssp_regs->hw_ssp_ctrl1);
+
+	writel(0, &ssp_regs->hw_ssp_cmd0);
+
+	mx28_set_ssp_busclock(slave->bus, mxs_slave->max_khz);
+
+	return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+}
+
+static void mxs_spi_start_xfer(struct mx28_ssp_regs *ssp_regs)
+{
+	writel(SSP_CTRL0_LOCK_CS, &ssp_regs->hw_ssp_ctrl0_set);
+	writel(SSP_CTRL0_IGNORE_CRC, &ssp_regs->hw_ssp_ctrl0_clr);
+}
+
+static void mxs_spi_end_xfer(struct mx28_ssp_regs *ssp_regs)
+{
+	writel(SSP_CTRL0_LOCK_CS, &ssp_regs->hw_ssp_ctrl0_clr);
+	writel(SSP_CTRL0_IGNORE_CRC, &ssp_regs->hw_ssp_ctrl0_set);
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+		const void *dout, void *din, unsigned long flags)
+{
+	struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave);
+	struct mx28_ssp_regs *ssp_regs = mxs_slave->regs;
+	int len = bitlen / 8;
+	const char *tx = dout;
+	char *rx = din;
+
+	if (bitlen == 0)
+		return 0;
+
+	if (!rx && !tx)
+		return 0;
+
+	if (flags & SPI_XFER_BEGIN)
+		mxs_spi_start_xfer(ssp_regs);
+
+	while (len--) {
+		/* We transfer 1 byte */
+		writel(1, &ssp_regs->hw_ssp_xfer_size);
+
+		if ((flags & SPI_XFER_END) && !len)
+			mxs_spi_end_xfer(ssp_regs);
+
+		if (tx)
+			writel(SSP_CTRL0_READ, &ssp_regs->hw_ssp_ctrl0_clr);
+		else
+			writel(SSP_CTRL0_READ, &ssp_regs->hw_ssp_ctrl0_set);
+
+		writel(SSP_CTRL0_RUN, &ssp_regs->hw_ssp_ctrl0_set);
+
+		if (mx28_wait_mask_set(&ssp_regs->hw_ssp_ctrl0_reg,
+			SSP_CTRL0_RUN, MXS_SPI_MAX_TIMEOUT)) {
+			printf("MXS SPI: Timeout waiting for start\n");
+			return -1;
+		}
+
+		if (tx)
+			writel(*tx++, &ssp_regs->hw_ssp_data);
+
+		writel(SSP_CTRL0_DATA_XFER, &ssp_regs->hw_ssp_ctrl0_set);
+
+		if (rx) {
+			if (mx28_wait_mask_clr(&ssp_regs->hw_ssp_status_reg,
+				SSP_STATUS_FIFO_EMPTY, MXS_SPI_MAX_TIMEOUT)) {
+				printf("MXS SPI: Timeout waiting for data\n");
+				return -1;
+			}
+
+			*rx = readl(&ssp_regs->hw_ssp_data);
+			rx++;
+		}
+
+		if (mx28_wait_mask_clr(&ssp_regs->hw_ssp_ctrl0_reg,
+			SSP_CTRL0_RUN, MXS_SPI_MAX_TIMEOUT)) {
+			printf("MXS SPI: Timeout waiting for finish\n");
+			return -1;
+		}
+	}
+
+	return 0;
+}
-- 
1.7.5.4

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

* [U-Boot] [PATCH 11/15 V2] iMX28: Add image header generator tool
  2011-09-12  4:06 ` [U-Boot] [PATCH 11/15] iMX28: Add image header generator tool Marek Vasut
  2011-09-12 16:38   ` Mike Frysinger
@ 2011-09-13 22:27   ` Marek Vasut
  1 sibling, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-09-13 22:27 UTC (permalink / raw)
  To: u-boot

This tool can now generate proper image for "BootStream" files.

NOTE: This tool now works only for NAND.

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 tools/.gitignore |    1 +
 tools/Makefile   |    6 +
 tools/mxsboot.c  |  684 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 691 insertions(+), 0 deletions(-)
 create mode 100644 tools/mxsboot.c

V2: Add missing .gitignore entry

diff --git a/tools/.gitignore b/tools/.gitignore
index 07f21a3..98a5c78 100644
--- a/tools/.gitignore
+++ b/tools/.gitignore
@@ -4,6 +4,7 @@
 /img2srec
 /mkimage
 /mpc86x_clk
+/mxsboot
 /ncb
 /ncp
 /ubsha1
diff --git a/tools/Makefile b/tools/Makefile
index fc741d3..2caac78 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -67,6 +67,7 @@ BIN_FILES-$(CONFIG_CMD_NET) += gen_eth_addr$(SFX)
 BIN_FILES-$(CONFIG_CMD_LOADS) += img2srec$(SFX)
 BIN_FILES-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes$(SFX)
 BIN_FILES-y += mkimage$(SFX)
+BIN_FILES-$(CONFIG_MX28) += mxsboot$(SFX)
 BIN_FILES-$(CONFIG_NETCONSOLE) += ncb$(SFX)
 BIN_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1$(SFX)
 
@@ -90,6 +91,7 @@ NOPED_OBJ_FILES-y += kwbimage.o
 NOPED_OBJ_FILES-y += imximage.o
 NOPED_OBJ_FILES-y += omapimage.o
 NOPED_OBJ_FILES-y += mkimage.o
+OBJ_FILES-$(CONFIG_MX28) += mxsboot.o
 OBJ_FILES-$(CONFIG_NETCONSOLE) += ncb.o
 NOPED_OBJ_FILES-y += os_support.o
 OBJ_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1.o
@@ -204,6 +206,10 @@ $(obj)mpc86x_clk$(SFX):	$(obj)mpc86x_clk.o
 	$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
 	$(HOSTSTRIP) $@
 
+$(obj)mxsboot$(SFX):	$(obj)mxsboot.o
+	$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
+	$(HOSTSTRIP) $@
+
 $(obj)ncb$(SFX):	$(obj)ncb.o
 	$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
 	$(HOSTSTRIP) $@
diff --git a/tools/mxsboot.c b/tools/mxsboot.c
new file mode 100644
index 0000000..176753d
--- /dev/null
+++ b/tools/mxsboot.c
@@ -0,0 +1,684 @@
+/*
+ * Freescale i.MX28 image generator
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "compiler.h"
+
+/*
+ * Default BCB layout.
+ *
+ * TWEAK this if you have blown any OCOTP fuses.
+ */
+#define	STRIDE_PAGES		64
+#define	STRIDE_COUNT		4
+
+/*
+ * Layout for 256Mb big NAND with 2048b page size, 64b OOB size and
+ * 128kb erase size.
+ *
+ * TWEAK this if you have different kind of NAND chip.
+ */
+uint32_t nand_writesize = 2048;
+uint32_t nand_oobsize = 64;
+uint32_t nand_erasesize = 128 * 1024;
+
+/*
+ * Sector on which the SigmaTel boot partition (0x53) starts.
+ */
+uint32_t sd_sector = 2048;
+
+/*
+ * Each of the U-Boot bootstreams is at maximum 1MB big.
+ *
+ * TWEAK this if, for some wild reason, you need to boot bigger image.
+ */
+#define	MAX_BOOTSTREAM_SIZE	(1 * 1024 * 1024)
+
+/* i.MX28 NAND controller-specific constants. DO NOT TWEAK! */
+#define	MXS_NAND_DMA_DESCRIPTOR_COUNT		4
+#define	MXS_NAND_CHUNK_DATA_CHUNK_SIZE		512
+#define	MXS_NAND_METADATA_SIZE			10
+#define	MXS_NAND_COMMAND_BUFFER_SIZE		32
+
+struct mx28_nand_fcb {
+	uint32_t		checksum;
+	uint32_t		fingerprint;
+	uint32_t		version;
+	struct {
+		uint8_t			data_setup;
+		uint8_t			data_hold;
+		uint8_t			address_setup;
+		uint8_t			dsample_time;
+		uint8_t			nand_timing_state;
+		uint8_t			rea;
+		uint8_t			rloh;
+		uint8_t			rhoh;
+	}			timing;
+	uint32_t		page_data_size;
+	uint32_t		total_page_size;
+	uint32_t		sectors_per_block;
+	uint32_t		number_of_nands;		/* Ignored */
+	uint32_t		total_internal_die;		/* Ignored */
+	uint32_t		cell_type;			/* Ignored */
+	uint32_t		ecc_block_n_ecc_type;
+	uint32_t		ecc_block_0_size;
+	uint32_t		ecc_block_n_size;
+	uint32_t		ecc_block_0_ecc_type;
+	uint32_t		metadata_bytes;
+	uint32_t		num_ecc_blocks_per_page;
+	uint32_t		ecc_block_n_ecc_level_sdk;	/* Ignored */
+	uint32_t		ecc_block_0_size_sdk;		/* Ignored */
+	uint32_t		ecc_block_n_size_sdk;		/* Ignored */
+	uint32_t		ecc_block_0_ecc_level_sdk;	/* Ignored */
+	uint32_t		num_ecc_blocks_per_page_sdk;	/* Ignored */
+	uint32_t		metadata_bytes_sdk;		/* Ignored */
+	uint32_t		erase_threshold;
+	uint32_t		boot_patch;
+	uint32_t		patch_sectors;
+	uint32_t		firmware1_starting_sector;
+	uint32_t		firmware2_starting_sector;
+	uint32_t		sectors_in_firmware1;
+	uint32_t		sectors_in_firmware2;
+	uint32_t		dbbt_search_area_start_address;
+	uint32_t		badblock_marker_byte;
+	uint32_t		badblock_marker_start_bit;
+	uint32_t		bb_marker_physical_offset;
+};
+
+struct mx28_nand_dbbt {
+	uint32_t		checksum;
+	uint32_t		fingerprint;
+	uint32_t		version;
+	uint32_t		number_bb;
+	uint32_t		number_2k_pages_bb;
+};
+
+struct mx28_nand_bbt {
+	uint32_t		nand;
+	uint32_t		number_bb;
+	uint32_t		badblock[510];
+};
+
+struct mx28_sd_drive_info {
+	uint32_t		chip_num;
+	uint32_t		drive_type;
+	uint32_t		tag;
+	uint32_t		first_sector_number;
+	uint32_t		sector_count;
+};
+
+struct mx28_sd_config_block {
+	uint32_t			signature;
+	uint32_t			primary_boot_tag;
+	uint32_t			secondary_boot_tag;
+	uint32_t			num_copies;
+	struct mx28_sd_drive_info	drv_info[1];
+};
+
+static inline uint32_t mx28_nand_ecc_size_in_bits(uint32_t ecc_strength)
+{
+	return ecc_strength * 13;
+}
+
+static inline uint32_t mx28_nand_get_ecc_strength(uint32_t page_data_size,
+						uint32_t page_oob_size)
+{
+	if (page_data_size == 2048)
+		return 8;
+
+	if (page_data_size == 4096) {
+		if (page_oob_size == 128)
+			return 8;
+
+		if (page_oob_size == 218)
+			return 16;
+	}
+
+	return 0;
+}
+
+static inline uint32_t mx28_nand_get_mark_offset(uint32_t page_data_size,
+						uint32_t ecc_strength)
+{
+	uint32_t chunk_data_size_in_bits;
+	uint32_t chunk_ecc_size_in_bits;
+	uint32_t chunk_total_size_in_bits;
+	uint32_t block_mark_chunk_number;
+	uint32_t block_mark_chunk_bit_offset;
+	uint32_t block_mark_bit_offset;
+
+	chunk_data_size_in_bits = MXS_NAND_CHUNK_DATA_CHUNK_SIZE * 8;
+	chunk_ecc_size_in_bits  = mx28_nand_ecc_size_in_bits(ecc_strength);
+
+	chunk_total_size_in_bits =
+			chunk_data_size_in_bits + chunk_ecc_size_in_bits;
+
+	/* Compute the bit offset of the block mark within the physical page. */
+	block_mark_bit_offset = page_data_size * 8;
+
+	/* Subtract the metadata bits. */
+	block_mark_bit_offset -= MXS_NAND_METADATA_SIZE * 8;
+
+	/*
+	 * Compute the chunk number (starting at zero) in which the block mark
+	 * appears.
+	 */
+	block_mark_chunk_number =
+			block_mark_bit_offset / chunk_total_size_in_bits;
+
+	/*
+	 * Compute the bit offset of the block mark within its chunk, and
+	 * validate it.
+	 */
+	block_mark_chunk_bit_offset = block_mark_bit_offset -
+			(block_mark_chunk_number * chunk_total_size_in_bits);
+
+	if (block_mark_chunk_bit_offset > chunk_data_size_in_bits)
+		return 1;
+
+	/*
+	 * Now that we know the chunk number in which the block mark appears,
+	 * we can subtract all the ECC bits that appear before it.
+	 */
+	block_mark_bit_offset -=
+		block_mark_chunk_number * chunk_ecc_size_in_bits;
+
+	return block_mark_bit_offset;
+}
+
+static inline uint32_t mx28_nand_mark_byte_offset(void)
+{
+	uint32_t ecc_strength;
+	ecc_strength = mx28_nand_get_ecc_strength(nand_writesize, nand_oobsize);
+	return mx28_nand_get_mark_offset(nand_writesize, ecc_strength) >> 3;
+}
+
+static inline uint32_t mx28_nand_mark_bit_offset(void)
+{
+	uint32_t ecc_strength;
+	ecc_strength = mx28_nand_get_ecc_strength(nand_writesize, nand_oobsize);
+	return mx28_nand_get_mark_offset(nand_writesize, ecc_strength) & 0x7;
+}
+
+static uint32_t mx28_nand_block_csum(uint8_t *block, uint32_t size)
+{
+	uint32_t csum = 0;
+	int i;
+
+	for (i = 0; i < size; i++)
+		csum += block[i];
+
+	return csum ^ 0xffffffff;
+}
+
+static struct mx28_nand_fcb *mx28_nand_get_fcb(uint32_t size)
+{
+	struct mx28_nand_fcb *fcb;
+	uint32_t bcb_size_bytes;
+	uint32_t stride_size_bytes;
+	uint32_t bootstream_size_pages;
+	uint32_t fw1_start_page;
+	uint32_t fw2_start_page;
+
+	fcb = malloc(nand_writesize);
+	if (!fcb) {
+		printf("MX28 NAND: Unable to allocate FCB\n");
+		return NULL;
+	}
+
+	memset(fcb, 0, nand_writesize);
+
+	fcb->fingerprint =			0x20424346;
+	fcb->version =				0x01000000;
+
+	/*
+	 * FIXME: These here are default values as found in kobs-ng. We should
+	 * probably retrieve the data from NAND or something.
+	 */
+	fcb->timing.data_setup =		80;
+	fcb->timing.data_hold =			60;
+	fcb->timing.address_setup =		25;
+	fcb->timing.dsample_time =		6;
+
+	fcb->page_data_size =		nand_writesize;
+	fcb->total_page_size =		nand_writesize + nand_oobsize;
+	fcb->sectors_per_block =	nand_erasesize / nand_writesize;
+
+	fcb->num_ecc_blocks_per_page =	(nand_writesize / 512) - 1;
+	fcb->ecc_block_0_size =		512;
+	fcb->ecc_block_n_size =		512;
+	fcb->metadata_bytes =		10;
+
+	if (nand_writesize == 2048) {
+		fcb->ecc_block_n_ecc_type =		4;
+		fcb->ecc_block_0_ecc_type =		4;
+	} else if (nand_writesize == 4096) {
+		if (nand_oobsize == 128) {
+			fcb->ecc_block_n_ecc_type =	4;
+			fcb->ecc_block_0_ecc_type =	4;
+		} else if (nand_oobsize == 218) {
+			fcb->ecc_block_n_ecc_type =	8;
+			fcb->ecc_block_0_ecc_type =	8;
+		}
+	}
+
+	if (fcb->ecc_block_n_ecc_type == 0) {
+		printf("MX28 NAND: Unsupported NAND geometry\n");
+		goto err;
+	}
+
+	fcb->boot_patch =			0;
+	fcb->patch_sectors =			0;
+
+	fcb->badblock_marker_byte =	mx28_nand_mark_byte_offset();
+	fcb->badblock_marker_start_bit = mx28_nand_mark_bit_offset();
+	fcb->bb_marker_physical_offset = nand_writesize;
+
+	stride_size_bytes = STRIDE_PAGES * nand_writesize;
+	bcb_size_bytes = stride_size_bytes * STRIDE_COUNT;
+
+	bootstream_size_pages = (size + (nand_writesize - 1)) /
+					nand_writesize;
+
+	fw1_start_page = 2 * bcb_size_bytes / nand_writesize;
+	fw2_start_page = (2 * bcb_size_bytes + MAX_BOOTSTREAM_SIZE) /
+				nand_writesize;
+
+	fcb->firmware1_starting_sector =	fw1_start_page;
+	fcb->firmware2_starting_sector =	fw2_start_page;
+	fcb->sectors_in_firmware1 =		bootstream_size_pages;
+	fcb->sectors_in_firmware2 =		bootstream_size_pages;
+
+	fcb->dbbt_search_area_start_address =	STRIDE_PAGES * STRIDE_COUNT;
+
+	return fcb;
+
+err:
+	free(fcb);
+	return NULL;
+}
+
+static struct mx28_nand_dbbt *mx28_nand_get_dbbt(void)
+{
+	struct mx28_nand_dbbt *dbbt;
+
+	dbbt = malloc(nand_writesize);
+	if (!dbbt) {
+		printf("MX28 NAND: Unable to allocate DBBT\n");
+		return NULL;
+	}
+
+	memset(dbbt, 0, nand_writesize);
+
+	dbbt->fingerprint	= 0x54424244;
+	dbbt->version		= 0x1;
+
+	return dbbt;
+}
+
+static inline uint8_t mx28_nand_parity_13_8(const uint8_t b)
+{
+	uint32_t parity = 0, tmp;
+
+	tmp = ((b >> 6) ^ (b >> 5) ^ (b >> 3) ^ (b >> 2)) & 1;
+	parity |= tmp << 0;
+
+	tmp = ((b >> 7) ^ (b >> 5) ^ (b >> 4) ^ (b >> 2) ^ (b >> 1)) & 1;
+	parity |= tmp << 1;
+
+	tmp = ((b >> 7) ^ (b >> 6) ^ (b >> 5) ^ (b >> 1) ^ (b >> 0)) & 1;
+	parity |= tmp << 2;
+
+	tmp = ((b >> 7) ^ (b >> 4) ^ (b >> 3) ^ (b >> 0)) & 1;
+	parity |= tmp << 3;
+
+	tmp = ((b >> 6) ^ (b >> 4) ^ (b >> 3) ^
+		(b >> 2) ^ (b >> 1) ^ (b >> 0)) & 1;
+	parity |= tmp << 4;
+
+	return parity;
+}
+
+static uint8_t *mx28_nand_fcb_block(struct mx28_nand_fcb *fcb)
+{
+	uint8_t *block;
+	uint8_t *ecc;
+	int i;
+
+	block = malloc(nand_writesize + nand_oobsize);
+	if (!block) {
+		printf("MX28 NAND: Unable to allocate FCB block\n");
+		return NULL;
+	}
+
+	memset(block, 0, nand_writesize + nand_oobsize);
+
+	/* Update the FCB checksum */
+	fcb->checksum = mx28_nand_block_csum(((uint8_t *)fcb) + 4, 508);
+
+	/* Figure 12-11. in iMX28RM, rev. 1, says FCB is at offset 12 */
+	memcpy(block + 12, fcb, sizeof(struct mx28_nand_fcb));
+
+	/* ECC is at offset 12 + 512 */
+	ecc = block + 12 + 512;
+
+	/* Compute the ECC parity */
+	for (i = 0; i < sizeof(struct mx28_nand_fcb); i++)
+		ecc[i] = mx28_nand_parity_13_8(block[i + 12]);
+
+	return block;
+}
+
+static int mx28_nand_write_fcb(struct mx28_nand_fcb *fcb, char *buf)
+{
+	uint32_t offset;
+	uint8_t *fcbblock;
+	int ret = 0;
+	int i;
+
+	fcbblock = mx28_nand_fcb_block(fcb);
+	if (!fcbblock)
+		return -1;
+
+	for (i = 0; i < STRIDE_PAGES * STRIDE_COUNT; i += STRIDE_PAGES) {
+		offset = i * nand_writesize;
+		memcpy(buf + offset, fcbblock, nand_writesize + nand_oobsize);
+	}
+
+	free(fcbblock);
+	return ret;
+}
+
+static int mx28_nand_write_dbbt(struct mx28_nand_dbbt *dbbt, char *buf)
+{
+	uint32_t offset;
+	int i = STRIDE_PAGES * STRIDE_COUNT;
+
+	for (; i < 2 * STRIDE_PAGES * STRIDE_COUNT; i += STRIDE_PAGES) {
+		offset = i * nand_writesize;
+		memcpy(buf + offset, dbbt, sizeof(struct mx28_nand_dbbt));
+	}
+
+	return 0;
+}
+
+static int mx28_nand_write_firmware(struct mx28_nand_fcb *fcb, int infd,
+					char *buf)
+{
+	int ret;
+	off_t size;
+	uint32_t offset1, offset2;
+
+	size = lseek(infd, 0, SEEK_END);
+	lseek(infd, 0, SEEK_SET);
+
+	offset1 = fcb->firmware1_starting_sector * nand_writesize;
+	offset2 = fcb->firmware2_starting_sector * nand_writesize;
+
+	ret = read(infd, buf + offset1, size);
+	if (ret != size)
+		return -1;
+
+	memcpy(buf + offset2, buf + offset1, size);
+
+	return 0;
+}
+
+void usage(void)
+{
+	printf(
+		"Usage: mx28image [ops] <type> <infile> <outfile>\n"
+		"Augment BootStream file with a proper header for i.MX28 boot\n"
+		"\n"
+		"  <type>	type of image:\n"
+		"                 \"nand\" for NAND image\n"
+		"                 \"sd\" for SD image\n"
+		"  <infile>     input file, the u-boot.sb bootstream\n"
+		"  <outfile>    output file, the bootable image\n"
+		"\n");
+	printf(
+		"For NAND boot, these options are accepted:\n"
+		"  -w <size>    NAND page size\n"
+		"  -o <size>    NAND OOB size\n"
+		"  -e <size>    NAND erase size\n"
+		"\n"
+		"For SD boot, these options are accepted:\n"
+		"  -p <sector>  Sector where the SGTL partition starts\n"
+	);
+}
+
+static int mx28_create_nand_image(int infd, int outfd)
+{
+	struct mx28_nand_fcb *fcb;
+	struct mx28_nand_dbbt *dbbt;
+	int ret = -1;
+	char *buf;
+	int size;
+	ssize_t wr_size;
+
+	size = nand_writesize * 512 + 2 * MAX_BOOTSTREAM_SIZE;
+
+	buf = malloc(size);
+	if (!buf) {
+		printf("Can not allocate output buffer of %d bytes\n", size);
+		goto err0;
+	}
+
+	memset(buf, 0, size);
+
+	fcb = mx28_nand_get_fcb(MAX_BOOTSTREAM_SIZE);
+	if (!fcb) {
+		printf("Unable to compile FCB\n");
+		goto err1;
+	}
+
+	dbbt = mx28_nand_get_dbbt();
+	if (!dbbt) {
+		printf("Unable to compile DBBT\n");
+		goto err2;
+	}
+
+	ret = mx28_nand_write_fcb(fcb, buf);
+	if (ret) {
+		printf("Unable to write FCB to buffer\n");
+		goto err3;
+	}
+
+	ret = mx28_nand_write_dbbt(dbbt, buf);
+	if (ret) {
+		printf("Unable to write DBBT to buffer\n");
+		goto err3;
+	}
+
+	ret = mx28_nand_write_firmware(fcb, infd, buf);
+	if (ret) {
+		printf("Unable to write firmware to buffer\n");
+		goto err3;
+	}
+
+	wr_size = write(outfd, buf, size);
+	if (wr_size != size) {
+		ret = -1;
+		goto err3;
+	}
+
+	ret = 0;
+
+err3:
+	free(dbbt);
+err2:
+	free(fcb);
+err1:
+	free(buf);
+err0:
+	return ret;
+}
+
+static int mx28_create_sd_image(int infd, int outfd)
+{
+	int ret = -1;
+	uint32_t *buf;
+	int size;
+	off_t fsize;
+	ssize_t wr_size;
+	struct mx28_sd_config_block *cb;
+
+	fsize = lseek(infd, 0, SEEK_END);
+	lseek(infd, 0, SEEK_SET);
+	size = fsize + 512;
+
+	buf = malloc(size);
+	if (!buf) {
+		printf("Can not allocate output buffer of %d bytes\n", size);
+		goto err0;
+	}
+
+	ret = read(infd, (uint8_t *)buf + 512, fsize);
+	if (ret != fsize) {
+		ret = -1;
+		goto err1;
+	}
+
+	cb = (struct mx28_sd_config_block *)buf;
+
+	cb->signature = 0x00112233;
+	cb->primary_boot_tag = 0x1;
+	cb->secondary_boot_tag = 0x1;
+	cb->num_copies = 1;
+	cb->drv_info[0].chip_num = 0x0;
+	cb->drv_info[0].drive_type = 0x0;
+	cb->drv_info[0].tag = 0x1;
+	cb->drv_info[0].first_sector_number = sd_sector + 1;
+	cb->drv_info[0].sector_count = (size - 1) / 512;
+
+	wr_size = write(outfd, buf, size);
+	if (wr_size != size) {
+		ret = -1;
+		goto err1;
+	}
+
+	ret = 0;
+
+err1:
+	free(buf);
+err0:
+	return ret;
+}
+
+int parse_ops(int argc, char **argv)
+{
+	int i;
+	int tmp;
+	char *end;
+	enum param {
+		PARAM_WRITE,
+		PARAM_OOB,
+		PARAM_ERASE,
+		PARAM_PART,
+		PARAM_SD,
+		PARAM_NAND
+	};
+	int type;
+
+	for (i = 1; i < argc; i++) {
+		if (!strncmp(argv[i], "-w", 2))
+			type = PARAM_WRITE;
+		else if (!strncmp(argv[i], "-o", 2))
+			type = PARAM_OOB;
+		else if (!strncmp(argv[i], "-e", 2))
+			type = PARAM_ERASE;
+		else if (!strncmp(argv[i], "-p", 2))
+			type = PARAM_PART;
+		else	/* SD/MMC */
+			break;
+
+		tmp = strtol(argv[++i], &end, 10);
+		if (tmp % 2)
+			return -1;
+		if (tmp <= 0)
+			return -1;
+
+		if (type == PARAM_WRITE)
+			nand_writesize = tmp;
+		if (type == PARAM_OOB)
+			nand_oobsize = tmp;
+		if (type == PARAM_ERASE)
+			nand_erasesize = tmp;
+		if (type == PARAM_PART)
+			sd_sector = tmp;
+	}
+
+	if (strcmp(argv[i], "sd") && strcmp(argv[i], "nand"))
+		return -1;
+
+	if (i + 3 != argc)
+		return -1;
+
+	return i;
+}
+
+int main(int argc, char **argv)
+{
+	int infd, outfd;
+	int ret = 0;
+	int offset;
+
+	offset = parse_ops(argc, argv);
+	if (offset < 0) {
+		usage();
+		ret = 1;
+		goto err1;
+	}
+
+	infd = open(argv[offset + 1], O_RDONLY);
+	if (infd < 0) {
+		printf("Input BootStream file can not be opened\n");
+		ret = 2;
+		goto err1;
+	}
+
+	outfd = open(argv[offset + 2], O_CREAT | O_TRUNC | O_WRONLY,
+					S_IRUSR | S_IWUSR);
+	if (outfd < 0) {
+		printf("Output file can not be created\n");
+		ret = 3;
+		goto err2;
+	}
+
+	if (!strcmp(argv[offset], "sd"))
+		ret = mx28_create_sd_image(infd, outfd);
+	else if (!strcmp(argv[offset], "nand"))
+		ret = mx28_create_nand_image(infd, outfd);
+
+	close(outfd);
+err2:
+	close(infd);
+err1:
+	return ret;
+}
-- 
1.7.5.4

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

* [U-Boot] [PATCH 12/15 V2] iMX28: Add u-boot.sb target to Makefile
  2011-09-12  4:06 ` [U-Boot] [PATCH 12/15] iMX28: Add u-boot.sb target to Makefile Marek Vasut
  2011-09-12 16:33   ` Mike Frysinger
@ 2011-09-13 22:28   ` Marek Vasut
  1 sibling, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-09-13 22:28 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 .gitignore |    1 +
 Makefile   |    5 +++++
 2 files changed, 6 insertions(+), 0 deletions(-)

V2: Add missing .gitignore entry

diff --git a/.gitignore b/.gitignore
index dbf545f..65dbb73 100644
--- a/.gitignore
+++ b/.gitignore
@@ -34,6 +34,7 @@
 /u-boot.dis
 /u-boot.lds
 /u-boot.ubl
+/u-boot.sb
 
 #
 # Generated files
diff --git a/Makefile b/Makefile
index ee05fb3..69dfe88 100644
--- a/Makefile
+++ b/Makefile
@@ -398,6 +398,10 @@ $(obj)u-boot.ubl:       $(obj)u-boot-nand.bin
 		$(obj)tools/mkimage -n $(UBL_CONFIG) -T ublimage \
 		-e $(CONFIG_SYS_TEXT_BASE) -d $< $@
 
+$(obj)u-boot.sb:       $(obj)u-boot.bin $(obj)spl/u-boot-spl.bin
+		elftosb -zdf imx28 -c board/denx/m28evk/u-boot.bd \
+			-o $(obj)u-boot.sb
+
 GEN_UBOOT = \
 		UNDEF_SYM=`$(OBJDUMP) -x $(LIBBOARD) $(LIBS) | \
 		sed  -n -e 's/.*\($(SYM_PREFIX)__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
@@ -980,6 +984,7 @@ clobber:	clean
 	@rm -f $(obj)u-boot.kwb
 	@rm -f $(obj)u-boot.imx
 	@rm -f $(obj)u-boot.ubl
+	@rm -f $(obj)u-boot.sb
 	@rm -f $(obj)tools/{env/crc32.c,inca-swap-bytes}
 	@rm -f $(obj)arch/powerpc/cpu/mpc824x/bedbug_603e.c
 	@rm -fr $(obj)include/asm/proc $(obj)include/asm/arch $(obj)include/asm
-- 
1.7.5.4

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

* [U-Boot] [PATCH 13/15 V2] iMX28: Add support for DENX M28EVK board
  2011-09-12  4:06 ` [U-Boot] [PATCH 13/15] iMX28: Add support for DENX M28EVK board Marek Vasut
@ 2011-09-13 22:29   ` Marek Vasut
  2011-09-14  2:48     ` Mike Frysinger
  2011-09-20  2:15     ` [U-Boot] [PATCH 13/15 V3] " Marek Vasut
  0 siblings, 2 replies; 116+ messages in thread
From: Marek Vasut @ 2011-09-13 22:29 UTC (permalink / raw)
  To: u-boot

This contains support for the following components:
- DUART
- MMC
- Both FEC interfaces
- NAND
- I2C (RTC, EEPROM)
- SPI (FLASH)

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 MAINTAINERS                |    1 +
 board/denx/m28evk/Makefile |   49 ++++++++
 board/denx/m28evk/m28evk.c |  195 ++++++++++++++++++++++++++++++
 boards.cfg                 |    1 +
 include/configs/m28evk.h   |  281 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 527 insertions(+), 0 deletions(-)
 create mode 100644 board/denx/m28evk/Makefile
 create mode 100644 board/denx/m28evk/m28evk.c
 create mode 100644 include/configs/m28evk.h

V2: Use scrub -y instead of scrub.quiet in the scripts.

diff --git a/MAINTAINERS b/MAINTAINERS
index 2f60a60..61a55a8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -847,6 +847,7 @@ Marek Vasut <marek.vasut@gmail.com>
 	palmtc		xscale/pxa
 	vpac270		xscale/pxa
 	zipitz2		xscale/pxa
+	m28evk		i.MX28
  	efikamx		i.MX51
 
 Hugo Villeneuve <hugo.villeneuve@lyrtech.com>
diff --git a/board/denx/m28evk/Makefile b/board/denx/m28evk/Makefile
new file mode 100644
index 0000000..4037199
--- /dev/null
+++ b/board/denx/m28evk/Makefile
@@ -0,0 +1,49 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(BOARD).o
+
+COBJS	:= m28evk.o
+
+SRCS	:= $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+clean:
+	rm -f $(OBJS)
+
+distclean:	clean
+	rm -f $(LIB) core *.bak .depend
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/denx/m28evk/m28evk.c b/board/denx/m28evk/m28evk.c
new file mode 100644
index 0000000..118e222
--- /dev/null
+++ b/board/denx/m28evk/m28evk.c
@@ -0,0 +1,195 @@
+/*
+ * DENX M28 module
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/iomux-mx28.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sys_proto.h>
+#include <linux/mii.h>
+#include <miiphy.h>
+#include <netdev.h>
+#include <errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Functions
+ */
+int board_early_init_f(void)
+{
+	/* IO0 clock at 480MHz */
+	mx28_set_ioclk(MXC_IOCLK0, 480000);
+	/* IO1 clock at 480MHz */
+	mx28_set_ioclk(MXC_IOCLK1, 480000);
+
+	/* SSP0 clock at 96MHz */
+	mx28_set_sspclk(MXC_SSPCLK0, 96000, 0);
+	/* SSP2 clock at 96MHz */
+	mx28_set_sspclk(MXC_SSPCLK2, 96000, 0);
+
+	return 0;
+}
+
+int board_init(void)
+{
+	/* Adress of boot parameters */
+	gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
+
+	return 0;
+}
+
+int dram_init(void)
+{
+	/* dram_init must store complete ramsize in gd->ram_size */
+	gd->ram_size = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE);
+	return 0;
+}
+
+#ifdef	CONFIG_CMD_MMC
+static int m28_mmc_wp(int id)
+{
+	if (id != 0) {
+		printf("MXS MMC: Invalid card selected (card id = %d)\n", id);
+		return 1;
+	}
+
+	return gpio_get_value(MX28_PAD_AUART2_CTS__GPIO_3_10);
+}
+
+int board_mmc_init(bd_t *bis)
+{
+	/* Configure WP as output */
+	gpio_direction_input(MX28_PAD_AUART2_CTS__GPIO_3_10);
+
+	return mxsmmc_initialize(bis, 0, m28_mmc_wp);
+}
+#endif
+
+#ifdef	CONFIG_CMD_NET
+
+#define	MII_OPMODE_STRAP_OVERRIDE	0x16
+#define	MII_PHY_CTRL1			0x1e
+#define	MII_PHY_CTRL2			0x1f
+
+int fecmxc_mii_postcall(int phy)
+{
+	miiphy_write("FEC1", phy, MII_BMCR, 0x9000);
+	miiphy_write("FEC1", phy, MII_OPMODE_STRAP_OVERRIDE, 0x0202);
+	if (phy == 3)
+		miiphy_write("FEC1", 3, MII_PHY_CTRL2, 0x8180);
+	return 0;
+}
+
+int board_eth_init(bd_t *bis)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	struct eth_device *dev;
+	int ret;
+
+	ret = cpu_eth_init(bis);
+
+	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_enet,
+		CLKCTRL_ENET_TIME_SEL_MASK | CLKCTRL_ENET_CLK_OUT_EN,
+		CLKCTRL_ENET_TIME_SEL_RMII_CLK);
+
+	ret = fecmxc_initialize_multi(bis, 0, 0, MXS_ENET0_BASE);
+	if (ret) {
+		printf("FEC MXS: Unable to init FEC0\n");
+		return ret;
+	}
+
+	ret = fecmxc_initialize_multi(bis, 1, 3, MXS_ENET1_BASE);
+	if (ret) {
+		printf("FEC MXS: Unable to init FEC1\n");
+		return ret;
+	}
+
+	dev = eth_get_dev_by_name("FEC0");
+	if (!dev) {
+		printf("FEC MXS: Unable to get FEC0 device entry\n");
+		return -EINVAL;
+	}
+
+	ret = fecmxc_register_mii_postcall(dev, fecmxc_mii_postcall);
+	if (ret) {
+		printf("FEC MXS: Unable to register FEC0 mii postcall\n");
+		return ret;
+	}
+
+	dev = eth_get_dev_by_name("FEC1");
+	if (!dev) {
+		printf("FEC MXS: Unable to get FEC1 device entry\n");
+		return -EINVAL;
+	}
+
+	ret = fecmxc_register_mii_postcall(dev, fecmxc_mii_postcall);
+	if (ret) {
+		printf("FEC MXS: Unable to register FEC1 mii postcall\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+#ifdef	CONFIG_M28_FEC_MAC_IN_OCOTP
+
+#define	MXS_OCOTP_MAX_TIMEOUT	1000000
+void imx_get_mac_from_fuse(char *mac)
+{
+	struct mx28_ocotp_regs *ocotp_regs =
+		(struct mx28_ocotp_regs *)MXS_OCOTP_BASE;
+	uint32_t data;
+
+	memset(mac, 0, 6);
+
+	writel(OCOTP_CTRL_RD_BANK_OPEN, &ocotp_regs->hw_ocotp_ctrl_set);
+
+	if (mx28_wait_mask_clr(&ocotp_regs->hw_ocotp_ctrl_reg, OCOTP_CTRL_BUSY,
+				MXS_OCOTP_MAX_TIMEOUT)) {
+		printf("MXS FEC: Can't get MAC from OCOTP\n");
+		return;
+	}
+
+	data = readl(&ocotp_regs->hw_ocotp_cust0);
+
+	mac[0] = 0x00;
+	mac[1] = 0x04;
+	mac[2] = (data >> 24) & 0xff;
+	mac[3] = (data >> 16) & 0xff;
+	mac[4] = (data >> 8) & 0xff;
+	mac[5] = data & 0xff;
+}
+#else
+void imx_get_mac_from_fuse(char *mac)
+{
+	memset(mac, 0, 6);
+}
+#endif
+
+#endif
diff --git a/boards.cfg b/boards.cfg
index 8a5bfc1..c5d8a90 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -147,6 +147,7 @@ jadecpu                      arm         arm926ejs   jadecpu             syteco
 zmx25                        arm         arm926ejs   zmx25               syteco         mx25
 imx27lite                    arm         arm926ejs   imx27lite           logicpd        mx27
 magnesium                    arm         arm926ejs   imx27lite           logicpd        mx27
+m28evk                       arm         arm926ejs   -                   denx           mx28
 nhk8815                      arm         arm926ejs   nhk8815             st             nomadik
 nhk8815_onenand              arm         arm926ejs   nhk8815             st             nomadik       nhk8815:BOOT_ONENAND
 omap5912osk                  arm         arm926ejs   -                   ti             omap
diff --git a/include/configs/m28evk.h b/include/configs/m28evk.h
new file mode 100644
index 0000000..f61af41
--- /dev/null
+++ b/include/configs/m28evk.h
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef __M28_H__
+#define __M28_H__
+
+#include <asm/arch/regs-base.h>
+
+/*
+ * SoC configurations
+ */
+#define	CONFIG_MX28				/* i.MX28 SoC */
+#define	CONFIG_MXS_GPIO				/* GPIO control */
+#define	CONFIG_SYS_HZ		1000		/* Ticks per second */
+
+/*
+ * Define M28EVK machine type by hand until it lands in mach-types
+ */
+#define	MACH_TYPE_M28EVK	3613
+
+#define	CONFIG_MACH_TYPE	MACH_TYPE_M28EVK
+
+#define	CONFIG_SYS_NO_FLASH
+#define	CONFIG_SYS_ICACHE_OFF
+#define	CONFIG_SYS_DCACHE_OFF
+#define	CONFIG_BOARD_EARLY_INIT_F
+#define	CONFIG_ARCH_CPU_INIT
+
+/*
+ * U-Boot Commands
+ */
+#include <config_cmd_default.h>
+#define	CONFIG_DISPLAY_CPUINFO
+#define	CONFIG_DOS_PARTITION
+
+#define	CONFIG_CMD_CACHE
+#define	CONFIG_CMD_DATE
+#define	CONFIG_CMD_DHCP
+#define	CONFIG_CMD_EEPROM
+#define	CONFIG_CMD_EXT2
+#define	CONFIG_CMD_FAT
+#define	CONFIG_CMD_GPIO
+#define	CONFIG_CMD_I2C
+#define	CONFIG_CMD_MII
+#define	CONFIG_CMD_MMC
+#define	CONFIG_CMD_NAND
+#define	CONFIG_CMD_NET
+#define	CONFIG_CMD_NFS
+#define	CONFIG_CMD_PING
+#define	CONFIG_CMD_SETEXPR
+#define	CONFIG_CMD_SF
+#define	CONFIG_CMD_SPI
+
+/*
+ * Memory configurations
+ */
+#define	CONFIG_NR_DRAM_BANKS		1		/* 2 banks of DRAM */
+#define	PHYS_SDRAM_1			0x40000000	/* Base address */
+#define	PHYS_SDRAM_1_SIZE		0x10000000	/* 256 MB */
+#define	CONFIG_STACKSIZE		0x00010000	/* 128 KB stack */
+#define	CONFIG_SYS_MALLOC_LEN		0x00400000	/* 4 MB for malloc */
+#define	CONFIG_SYS_GBL_DATA_SIZE	128		/* Initial data */
+#define	CONFIG_SYS_MEMTEST_START	0x40000000	/* Memtest start adr */
+#define	CONFIG_SYS_MEMTEST_END		0x40400000	/* 4 MB RAM test */
+#define	CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM_1
+/* Point initial SP in SRAM so SPL can use it too. */
+#define	CONFIG_SYS_INIT_SP_ADDR		0x00002000
+/*
+ * We need to sacrifice first 4 bytes of RAM here to avoid triggering some
+ * strange BUG in ROM corrupting first 4 bytes of RAM when loading U-Boot
+ * binary. In case there was more of this mess, 0x100 bytes are skipped.
+ */
+#define	CONFIG_SYS_TEXT_BASE		0x40000100
+
+/*
+ * U-Boot general configurations
+ */
+#define	CONFIG_SYS_LONGHELP
+#define	CONFIG_SYS_PROMPT	"=> "
+#define	CONFIG_SYS_CBSIZE	1024		/* Console I/O buffer size */
+#define	CONFIG_SYS_PBSIZE	\
+	(CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+						/* Print buffer size */
+#define	CONFIG_SYS_MAXARGS	32		/* Max number of command args */
+#define	CONFIG_SYS_BARGSIZE	CONFIG_SYS_CBSIZE
+						/* Boot argument buffer size */
+#define	CONFIG_VERSION_VARIABLE			/* U-BOOT version */
+#define	CONFIG_AUTO_COMPLETE			/* Command auto complete */
+#define	CONFIG_CMDLINE_EDITING			/* Command history etc */
+#define	CONFIG_SYS_HUSH_PARSER
+#define	CONFIG_SYS_PROMPT_HUSH_PS2	"> "
+
+/*
+ * Serial Driver
+ */
+#define	CONFIG_PL011_SERIAL
+#define	CONFIG_PL011_CLOCK		24000000
+#define	CONFIG_PL01x_PORTS		{ (void *)MXS_UARTDBG_BASE }
+#define	CONFIG_CONS_INDEX		0
+#define	CONFIG_BAUDRATE			115200	/* Default baud rate */
+#define	CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 }
+
+/*
+ * MMC Driver
+ */
+#ifdef	CONFIG_CMD_MMC
+#define	CONFIG_MMC
+#define	CONFIG_GENERIC_MMC
+#define	CONFIG_MXS_MMC
+#endif
+
+/*
+ * NAND
+ */
+#ifdef	CONFIG_CMD_NAND
+#define	CONFIG_NAND_MXS
+#define CONFIG_APBH_DMA
+#define	CONFIG_SYS_MAX_NAND_DEVICE	1
+#define	CONFIG_SYS_NAND_BASE		0x60000000
+#define	CONFIG_SYS_NAND_5_ADDR_CYCLE
+#define	NAND_MAX_CHIPS			8
+
+/* Environment is in NAND */
+#define	CONFIG_ENV_IS_IN_NAND		1
+#define	CONFIG_ENV_SECT_SIZE		(128 * 1024)
+#define	CONFIG_ENV_SIZE			(16 * 1024)
+#define	CONFIG_ENV_SIZE_REDUND		CONFIG_ENV_SIZE
+#define	CONFIG_ENV_OFFSET		0x300000
+#define	CONFIG_ENV_OFFSET_REDUND	\
+		(CONFIG_ENV_OFFSET + CONFIG_ENV_SECT_SIZE)
+
+#define	CONFIG_CMD_UBI
+#define	CONFIG_CMD_UBIFS
+#define	CONFIG_CMD_MTDPARTS
+#define	CONFIG_RBTREE
+#define	CONFIG_LZO
+#define	CONFIG_MTD_DEVICE
+#define	CONFIG_MTD_PARTITIONS
+#define	MTDIDS_DEFAULT			"nand0=gpmi-nand.0"
+#define	MTDPARTS_DEFAULT			\
+	"mtdparts=gpmi-nand.0:"			\
+		"3m(bootloader)ro,"		\
+		"128k(environment),"		\
+		"128k(redundant-environment),"	\
+		"4m(kernel),"			\
+		"-(filesystem)"
+#endif
+
+/*
+ * Ethernet on SOC (FEC)
+ */
+#ifdef	CONFIG_CMD_NET
+#define	CONFIG_NET_MULTI
+#define	CONFIG_ETHPRIME			"FEC0"
+#define	CONFIG_FEC_MXC
+#define	CONFIG_FEC_MXC_MULTI
+#define	CONFIG_MII
+#define	CONFIG_DISCOVER_PHY
+#define	CONFIG_FEC_XCV_TYPE		RMII
+#endif
+
+/*
+ * I2C
+ */
+#ifdef	CONFIG_CMD_I2C
+#define	CONFIG_I2C_MXS
+#define	CONFIG_HARD_I2C
+#define	CONFIG_SYS_I2C_SPEED		400000
+#endif
+
+/*
+ * EEPROM
+ */
+#ifdef	CONFIG_CMD_EEPROM
+#define	CONFIG_SYS_I2C_MULTI_EEPROMS
+#define	CONFIG_SYS_I2C_EEPROM_ADDR_LEN	2
+#endif
+
+/*
+ * RTC
+ */
+#ifdef	CONFIG_CMD_DATE
+/* Use the internal RTC in the MXS chip */
+#define	CONFIG_RTC_INTERNAL
+#ifdef	CONFIG_RTC_INTERNAL
+#define	CONFIG_RTC_MXS
+#else
+#define	CONFIG_RTC_M41T62
+#define	CONFIG_SYS_I2C_RTC_ADDR		0x68
+#define	CONFIG_SYS_M41T11_BASE_YEAR	2000
+#endif
+#endif
+
+/*
+ * SPI
+ */
+#ifdef	CONFIG_CMD_SPI
+#define	CONFIG_HARD_SPI
+#define	CONFIG_MXS_SPI
+#define	CONFIG_SPI_HALF_DUPLEX
+#define	CONFIG_DEFAULT_SPI_BUS		2
+#define	CONFIG_DEFAULT_SPI_MODE		SPI_MODE_0
+
+/* SPI FLASH */
+#ifdef	CONFIG_CMD_SF
+#define	CONFIG_SPI_FLASH
+#define	CONFIG_SPI_FLASH_STMICRO
+#define	CONFIG_SPI_FLASH_CS		2
+#define	CONFIG_SF_DEFAULT_MODE		SPI_MODE_0
+#define	CONFIG_SF_DEFAULT_SPEED		24000000
+
+#define	CONFIG_ENV_SPI_CS		0
+#define	CONFIG_ENV_SPI_BUS		2
+#define	CONFIG_ENV_SPI_MAX_HZ		24000000
+#define	CONFIG_ENV_SPI_MODE		SPI_MODE_0
+#endif
+#endif
+
+/*
+ * Boot Linux
+ */
+#define	CONFIG_CMDLINE_TAG
+#define	CONFIG_SETUP_MEMORY_TAGS
+#define	CONFIG_BOOTDELAY	3
+#define	CONFIG_BOOTFILE		"uImage"
+#define	CONFIG_BOOTARGS		"console=ttyAM0,115200n8 "
+#define	CONFIG_BOOTCOMMAND	"run bootcmd_net"
+#define	CONFIG_LOADADDR		0x42000000
+#define	CONFIG_SYS_LOAD_ADDR	CONFIG_LOADADDR
+
+/*
+ * Extra Environments
+ */
+#define	CONFIG_EXTRA_ENV_SETTINGS					\
+	"update_nand_full_filename=u-boot.nand\0"			\
+	"update_nand_firmware_filename=u-boot.sb\0"			\
+	"update_nand_firmware_maxsz=0x100000\0"				\
+	"update_nand_stride=0x40\0"	/* MX28 datasheet ch. 12.12 */	\
+	"update_nand_count=0x4\0"	/* MX28 datasheet ch. 12.12 */	\
+	"update_nand_get_fcb_size="	/* Get size of FCB blocks */	\
+		"nand device 0 ; "					\
+		"nand info ; "						\
+		"setexpr fcb_sz ${update_nand_stride} * ${update_nand_count};" \
+		"setexpr update_nand_fcb ${fcb_sz} * ${nand_writesize}\0" \
+	"update_nand_full="		/* Update FCB, DBBT and FW */	\
+		"if tftp ${update_nand_full_filename} ; then "		\
+		"run update_nand_get_fcb_size ; "			\
+		"nand scrub -y 0x0 ${filesize} ; "			\
+		"nand write.raw ${loadaddr} 0x0 ${update_nand_fcb} ; "	\
+		"setexpr update_off ${loadaddr} + ${update_nand_fcb} ; " \
+		"setexpr update_sz ${filesize} - ${update_nand_fcb} ; " \
+		"nand write ${update_off} ${update_nand_fcb} ${update_sz} ; " \
+		"fi\0"							\
+	"update_nand_firmware="		/* Update only firmware */	\
+		"if tftp ${update_nand_firmware_filename} ; then "	\
+		"run update_nand_get_fcb_size ; "			\
+		"setexpr fcb_sz ${update_nand_fcb} * 2 ; " /* FCB + DBBT */ \
+		"setexpr fw_sz ${update_nand_firmware_maxsz} * 2 ; "	\
+		"setexpr fw_off ${fcb_sz} + ${update_nand_firmware_maxsz};" \
+		"nand erase ${fcb_sz} ${fw_sz} ; "			\
+		"nand write ${loadaddr} ${fcb_sz} ${filesize} ; "	\
+		"nand write ${loadaddr} ${fw_off} ${filesize} ; "	\
+		"fi\0"
+
+#endif /* __M28_H__ */
-- 
1.7.5.4

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

* [U-Boot] [PATCH 13/15 V2] iMX28: Add support for DENX M28EVK board
  2011-09-13 22:29   ` [U-Boot] [PATCH 13/15 V2] " Marek Vasut
@ 2011-09-14  2:48     ` Mike Frysinger
  2011-09-14  3:17       ` Marek Vasut
  2011-09-20  2:15     ` [U-Boot] [PATCH 13/15 V3] " Marek Vasut
  1 sibling, 1 reply; 116+ messages in thread
From: Mike Frysinger @ 2011-09-14  2:48 UTC (permalink / raw)
  To: u-boot

On Tuesday, September 13, 2011 18:29:38 Marek Vasut wrote:
> --- /dev/null
> +++ b/board/denx/m28evk/Makefile
> 
> +clean:
> +	rm -f $(OBJS)
> +
> +distclean:	clean
> +	rm -f $(LIB) core *.bak .depend

pretty sure these dont get used anywhere
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20110913/f5505875/attachment.pgp 

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

* [U-Boot] [PATCH 07/15 V2] iMX28: Add SPI driver
  2011-09-13 22:26   ` [U-Boot] [PATCH 07/15 V2] " Marek Vasut
@ 2011-09-14  2:50     ` Mike Frysinger
  2011-09-14  3:14       ` Marek Vasut
  0 siblings, 1 reply; 116+ messages in thread
From: Mike Frysinger @ 2011-09-14  2:50 UTC (permalink / raw)
  To: u-boot

On Tuesday, September 13, 2011 18:26:19 Marek Vasut wrote:
> +int spi_claim_bus(struct spi_slave *slave)
> +{
> +	struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave);
> +	struct mx28_ssp_regs *ssp_regs = mxs_slave->regs;
> +	uint32_t reg = 0;
> +
> +	mx28_reset_block(&ssp_regs->hw_ssp_ctrl0_reg);
> +
> +	writel(SSP_CTRL0_BUS_WIDTH_ONE_BIT, &ssp_regs->hw_ssp_ctrl0);
> +
> +	reg = SSP_CTRL1_SSP_MODE_SPI | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS;
> +	reg |= (mxs_slave->mode & SPI_CPOL) ? SSP_CTRL1_POLARITY : 0;
> +	reg |= (mxs_slave->mode & SPI_CPHA) ? SSP_CTRL1_PHASE : 0;
> +	writel(reg, &ssp_regs->hw_ssp_ctrl1);
> +
> +	writel(0, &ssp_regs->hw_ssp_cmd0);
> +
> +	mx28_set_ssp_busclock(slave->bus, mxs_slave->max_khz);

this turns on the hardware ...

> +void spi_release_bus(struct spi_slave *slave)
> +{
> +}

... so shouldn't this turn it off ?

i dont have the datasheet for the controller, so i have no idea :)
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20110913/310bfd73/attachment.pgp 

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

* [U-Boot] [PATCH 07/15 V2] iMX28: Add SPI driver
  2011-09-14  2:50     ` Mike Frysinger
@ 2011-09-14  3:14       ` Marek Vasut
  0 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-09-14  3:14 UTC (permalink / raw)
  To: u-boot

On Wednesday, September 14, 2011 04:50:09 AM Mike Frysinger wrote:
> On Tuesday, September 13, 2011 18:26:19 Marek Vasut wrote:
> > +int spi_claim_bus(struct spi_slave *slave)
> > +{
> > +	struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave);
> > +	struct mx28_ssp_regs *ssp_regs = mxs_slave->regs;
> > +	uint32_t reg = 0;
> > +
> > +	mx28_reset_block(&ssp_regs->hw_ssp_ctrl0_reg);
> > +
> > +	writel(SSP_CTRL0_BUS_WIDTH_ONE_BIT, &ssp_regs->hw_ssp_ctrl0);
> > +
> > +	reg = SSP_CTRL1_SSP_MODE_SPI | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS;
> > +	reg |= (mxs_slave->mode & SPI_CPOL) ? SSP_CTRL1_POLARITY : 0;
> > +	reg |= (mxs_slave->mode & SPI_CPHA) ? SSP_CTRL1_PHASE : 0;
> > +	writel(reg, &ssp_regs->hw_ssp_ctrl1);
> > +
> > +	writel(0, &ssp_regs->hw_ssp_cmd0);
> > +
> > +	mx28_set_ssp_busclock(slave->bus, mxs_slave->max_khz);
> 
> this turns on the hardware ...

This only sets up the clock to a correct frequency, the hardware is running all 
the time.
> 
> > +void spi_release_bus(struct spi_slave *slave)
> > +{
> > +}
> 
> ... so shouldn't this turn it off ?
> 
> i dont have the datasheet for the controller, so i have no idea :)
> -mike

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

* [U-Boot] [PATCH 13/15 V2] iMX28: Add support for DENX M28EVK board
  2011-09-14  2:48     ` Mike Frysinger
@ 2011-09-14  3:17       ` Marek Vasut
  2011-09-14  3:33         ` Mike Frysinger
  0 siblings, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-09-14  3:17 UTC (permalink / raw)
  To: u-boot

On Wednesday, September 14, 2011 04:48:03 AM Mike Frysinger wrote:
> On Tuesday, September 13, 2011 18:29:38 Marek Vasut wrote:
> > --- /dev/null
> > +++ b/board/denx/m28evk/Makefile
> > 
> > +clean:
> > +	rm -f $(OBJS)
> > +
> > +distclean:	clean
> > +	rm -f $(LIB) core *.bak .depend
> 
> pretty sure these dont get used anywhere

I suppose make clean would be the thing ?

> -mike

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

* [U-Boot] [PATCH 13/15 V2] iMX28: Add support for DENX M28EVK board
  2011-09-14  3:17       ` Marek Vasut
@ 2011-09-14  3:33         ` Mike Frysinger
  2011-09-14  4:24           ` Marek Vasut
  0 siblings, 1 reply; 116+ messages in thread
From: Mike Frysinger @ 2011-09-14  3:33 UTC (permalink / raw)
  To: u-boot

On Tuesday, September 13, 2011 23:17:48 Marek Vasut wrote:
> On Wednesday, September 14, 2011 04:48:03 AM Mike Frysinger wrote:
> > On Tuesday, September 13, 2011 18:29:38 Marek Vasut wrote:
> > > --- /dev/null
> > > +++ b/board/denx/m28evk/Makefile
> > > 
> > > +clean:
> > > +	rm -f $(OBJS)
> > > +
> > > +distclean:	clean
> > > +	rm -f $(LIB) core *.bak .depend
> > 
> > pretty sure these dont get used anywhere
> 
> I suppose make clean would be the thing ?

if you read the top level Makefile, you'll see that there is no recursion for 
clean or distclean targets
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20110913/60493ef8/attachment.pgp 

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

* [U-Boot] [PATCH 13/15 V2] iMX28: Add support for DENX M28EVK board
  2011-09-14  3:33         ` Mike Frysinger
@ 2011-09-14  4:24           ` Marek Vasut
  2011-09-14  5:01             ` Mike Frysinger
  0 siblings, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-09-14  4:24 UTC (permalink / raw)
  To: u-boot

On Wednesday, September 14, 2011 05:33:48 AM Mike Frysinger wrote:
> On Tuesday, September 13, 2011 23:17:48 Marek Vasut wrote:
> > On Wednesday, September 14, 2011 04:48:03 AM Mike Frysinger wrote:
> > > On Tuesday, September 13, 2011 18:29:38 Marek Vasut wrote:
> > > > --- /dev/null
> > > > +++ b/board/denx/m28evk/Makefile
> > > > 
> > > > +clean:
> > > > +	rm -f $(OBJS)
> > > > +
> > > > +distclean:	clean
> > > > +	rm -f $(LIB) core *.bak .depend
> > > 
> > > pretty sure these dont get used anywhere
> > 
> > I suppose make clean would be the thing ?
> 
> if you read the top level Makefile, you'll see that there is no recursion
> for clean or distclean targets
> -mike

It makes sense, but then why does the rest of the boards still define it ? If 
there was some major cleanup on this matter, this should have been removed from 
the board Makefiles too.

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

* [U-Boot] [PATCH 13/15 V2] iMX28: Add support for DENX M28EVK board
  2011-09-14  4:24           ` Marek Vasut
@ 2011-09-14  5:01             ` Mike Frysinger
  2011-09-14  5:10               ` Marek Vasut
  0 siblings, 1 reply; 116+ messages in thread
From: Mike Frysinger @ 2011-09-14  5:01 UTC (permalink / raw)
  To: u-boot

On Wednesday, September 14, 2011 00:24:48 Marek Vasut wrote:
> On Wednesday, September 14, 2011 05:33:48 AM Mike Frysinger wrote:
> > On Tuesday, September 13, 2011 23:17:48 Marek Vasut wrote:
> > > On Wednesday, September 14, 2011 04:48:03 AM Mike Frysinger wrote:
> > > > On Tuesday, September 13, 2011 18:29:38 Marek Vasut wrote:
> > > > > --- /dev/null
> > > > > +++ b/board/denx/m28evk/Makefile
> > > > > 
> > > > > +clean:
> > > > > +	rm -f $(OBJS)
> > > > > +
> > > > > +distclean:	clean
> > > > > +	rm -f $(LIB) core *.bak .depend
> > > > 
> > > > pretty sure these dont get used anywhere
> > > 
> > > I suppose make clean would be the thing ?
> > 
> > if you read the top level Makefile, you'll see that there is no recursion
> > for clean or distclean targets
> 
> It makes sense, but then why does the rest of the boards still define it ?

old cruft

> If there was some major cleanup on this matter, this should have been
> removed from the board Makefiles too.

i dont know the exact sequence of events, but this is the current state of 
things.  feel free to post a big cleanup patch :).
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20110914/48eb7cba/attachment.pgp 

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

* [U-Boot] [PATCH 13/15 V2] iMX28: Add support for DENX M28EVK board
  2011-09-14  5:01             ` Mike Frysinger
@ 2011-09-14  5:10               ` Marek Vasut
  2011-09-14 22:12                 ` Mike Frysinger
  0 siblings, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-09-14  5:10 UTC (permalink / raw)
  To: u-boot

On Wednesday, September 14, 2011 07:01:38 AM Mike Frysinger wrote:
> On Wednesday, September 14, 2011 00:24:48 Marek Vasut wrote:
> > On Wednesday, September 14, 2011 05:33:48 AM Mike Frysinger wrote:
> > > On Tuesday, September 13, 2011 23:17:48 Marek Vasut wrote:
> > > > On Wednesday, September 14, 2011 04:48:03 AM Mike Frysinger wrote:
> > > > > On Tuesday, September 13, 2011 18:29:38 Marek Vasut wrote:
> > > > > > --- /dev/null
> > > > > > +++ b/board/denx/m28evk/Makefile
> > > > > > 
> > > > > > +clean:
> > > > > > +	rm -f $(OBJS)
> > > > > > +
> > > > > > +distclean:	clean
> > > > > > +	rm -f $(LIB) core *.bak .depend
> > > > > 
> > > > > pretty sure these dont get used anywhere
> > > > 
> > > > I suppose make clean would be the thing ?
> > > 
> > > if you read the top level Makefile, you'll see that there is no
> > > recursion for clean or distclean targets
> > 
> > It makes sense, but then why does the rest of the boards still define it
> > ?
> 
> old cruft
> 
> > If there was some major cleanup on this matter, this should have been
> > removed from the board Makefiles too.
> 
> i dont know the exact sequence of events, but this is the current state of
> things.  feel free to post a big cleanup patch :).

Not until I get confirmation from someone involved it really is an old useless 
crap.

> -mike

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

* [U-Boot] [PATCH 01/15] iMX28: Initial support for iMX28 CPU
  2011-09-12  4:06 ` [U-Boot] [PATCH 01/15] iMX28: Initial support for iMX28 CPU Marek Vasut
@ 2011-09-14  7:10   ` Stefano Babic
  2011-09-27 13:45   ` [U-Boot] [PATCH 01/15 V2] " Marek Vasut
  1 sibling, 0 replies; 116+ messages in thread
From: Stefano Babic @ 2011-09-14  7:10 UTC (permalink / raw)
  To: u-boot

On 09/12/2011 06:06 AM, Marek Vasut wrote:
> This patch supports:
> - Timers
> - Debug UART
> - Clock
> 
> Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
> Cc: Stefano Babic <sbabic@denx.de>
> Cc: Wolfgang Denk <wd@denx.de>
> Cc: Detlev Zundel <dzu@denx.de>
> ---

Hi Marek,

it seems ok to me.

Acked-by: Stefano Babic <sbabic@denx.de>

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de
=====================================================================

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

* [U-Boot] [PATCH 03/15] FEC: Add support for iMX28 quirks
  2011-09-12  4:06 ` [U-Boot] [PATCH 03/15] FEC: Add support for iMX28 quirks Marek Vasut
@ 2011-09-14  7:17   ` Stefano Babic
  2011-09-14 12:11     ` Marek Vasut
  0 siblings, 1 reply; 116+ messages in thread
From: Stefano Babic @ 2011-09-14  7:17 UTC (permalink / raw)
  To: u-boot

On 09/12/2011 06:06 AM, Marek Vasut wrote:
> Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
> Cc: Ben Warren <biggerbadderben@gmail.com>
> Cc: Stefano Babic <sbabic@denx.de>
> Cc: Wolfgang Denk <wd@denx.de>
> Cc: Detlev Zundel <dzu@denx.de>
> ---

Hi Marek,

only a small question:

>  drivers/net/fec_mxc.c |   44 ++++++++++++++++++++++++++++++++++++++++++--
>  1 files changed, 42 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
> index cfe2176..f50433dd 100644
> --- a/drivers/net/fec_mxc.c
> +++ b/drivers/net/fec_mxc.c
> @@ -42,6 +42,14 @@ DECLARE_GLOBAL_DATA_PTR;
>  #define	CONFIG_FEC_XCV_TYPE	MII100
>  #endif
>  
> +/*
> + * The i.MX28 operates with packets in big endian. We need to swap them before
> + * sending and after receiving.
> + */
> +#ifdef	CONFIG_MX28
> +#define	CONFIG_FEC_MXC_SWAP_PACKET
> +#endif
> +

Do we really need two defines ? If the MX28 has the oddity to swap
packets and this must be always done for this SOC, we could protect the
code only with CONFIG_MX28. I think in the code it is already clear that
in case of MX28 the packets are swapped.

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de
=====================================================================

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

* [U-Boot] [PATCH 06/15] iMX28: Add GPIO control
  2011-09-12  4:06 ` [U-Boot] [PATCH 06/15] iMX28: Add GPIO control Marek Vasut
@ 2011-09-14  7:25   ` Stefano Babic
  0 siblings, 0 replies; 116+ messages in thread
From: Stefano Babic @ 2011-09-14  7:25 UTC (permalink / raw)
  To: u-boot

On 09/12/2011 06:06 AM, Marek Vasut wrote:
> Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
> Cc: Stefano Babic <sbabic@denx.de>
> Cc: Wolfgang Denk <wd@denx.de>
> Cc: Detlev Zundel <dzu@denx.de>
> ---

Hi Marek,

> +
> +#include <common.h>
> +#include <netdev.h>
> +#include <asm/errno.h>
> +#include <asm/io.h>
> +#include <asm/arch/iomux.h>
> +#include <asm/arch/imx-regs.h>
> +
> +#if	defined(CONFIG_MX23)
> +#define	PINCTRL_BANKS		3
> +#define	PINCTRL_DOUT(n)		(0x0500 + ((n) * 0x10))
> +#define	PINCTRL_DIN(n)		(0x0600 + ((n) * 0x10))
> +#define	PINCTRL_DOE(n)		(0x0700 + ((n) * 0x10))
> +#define	PINCTRL_PIN2IRQ(n)	(0x0800 + ((n) * 0x10))
> +#define	PINCTRL_IRQEN(n)	(0x0900 + ((n) * 0x10))
> +#define	PINCTRL_IRQSTAT(n)	(0x0c00 + ((n) * 0x10))
> +#elif	defined(CONFIG_MX28)
> +#define	PINCTRL_BANKS		5
> +#define	PINCTRL_DOUT(n)		(0x0700 + ((n) * 0x10))
> +#define	PINCTRL_DIN(n)		(0x0900 + ((n) * 0x10))
> +#define	PINCTRL_DOE(n)		(0x0b00 + ((n) * 0x10))
> +#define	PINCTRL_PIN2IRQ(n)	(0x1000 + ((n) * 0x10))
> +#define	PINCTRL_IRQEN(n)	(0x1100 + ((n) * 0x10))
> +#define	PINCTRL_IRQSTAT(n)	(0x1400 + ((n) * 0x10))
> +#else
> +#error "Please select CONFIG_MX23 or CONFIG_MX28"
> +#endif

Only to remark: I know that at the moment we have not CONFIG_MX23 in
u-boot and the MX23 part is dead code. However, the added part is very
small and clear visible, and I agree to let it in code even if it breaks
this u-boot rule.

Acked-by: Stefano Babic <sbabic@denx.de>

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de
=====================================================================

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

* [U-Boot] [PATCH 03/15] FEC: Add support for iMX28 quirks
  2011-09-14  7:17   ` Stefano Babic
@ 2011-09-14 12:11     ` Marek Vasut
  2011-09-14 15:38       ` Mike Frysinger
  0 siblings, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-09-14 12:11 UTC (permalink / raw)
  To: u-boot

On Wednesday, September 14, 2011 09:17:37 AM Stefano Babic wrote:
> On 09/12/2011 06:06 AM, Marek Vasut wrote:
> > Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
> > Cc: Ben Warren <biggerbadderben@gmail.com>
> > Cc: Stefano Babic <sbabic@denx.de>
> > Cc: Wolfgang Denk <wd@denx.de>
> > Cc: Detlev Zundel <dzu@denx.de>
> > ---
> 
> Hi Marek,
> 
> only a small question:
> >  drivers/net/fec_mxc.c |   44
> >  ++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 42
> >  insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
> > index cfe2176..f50433dd 100644
> > --- a/drivers/net/fec_mxc.c
> > +++ b/drivers/net/fec_mxc.c
> > @@ -42,6 +42,14 @@ DECLARE_GLOBAL_DATA_PTR;
> > 
> >  #define	CONFIG_FEC_XCV_TYPE	MII100
> >  #endif
> > 
> > +/*
> > + * The i.MX28 operates with packets in big endian. We need to swap them
> > before + * sending and after receiving.
> > + */
> > +#ifdef	CONFIG_MX28
> > +#define	CONFIG_FEC_MXC_SWAP_PACKET
> > +#endif
> > +
> 
> Do we really need two defines ? If the MX28 has the oddity to swap
> packets and this must be always done for this SOC, we could protect the
> code only with CONFIG_MX28. I think in the code it is already clear that
> in case of MX28 the packets are swapped.

Well if any other CPU with this problem pops up on the market, we should be 
ready.

> 
> Best regards,
> Stefano Babic

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

* [U-Boot] [PATCH 03/15] FEC: Add support for iMX28 quirks
  2011-09-14 12:11     ` Marek Vasut
@ 2011-09-14 15:38       ` Mike Frysinger
  0 siblings, 0 replies; 116+ messages in thread
From: Mike Frysinger @ 2011-09-14 15:38 UTC (permalink / raw)
  To: u-boot

On Wed, Sep 14, 2011 at 08:11, Marek Vasut wrote:
> On Wednesday, September 14, 2011 09:17:37 AM Stefano Babic wrote:
>> On 09/12/2011 06:06 AM, Marek Vasut wrote:
>> > --- a/drivers/net/fec_mxc.c
>> > +++ b/drivers/net/fec_mxc.c
>> >
>> > +/*
>> > + * The i.MX28 operates with packets in big endian. We need to swap them
>> > before + * sending and after receiving.
>> > + */
>> > +#ifdef ? ? CONFIG_MX28
>> > +#define ? ?CONFIG_FEC_MXC_SWAP_PACKET
>> > +#endif
>>
>> Do we really need two defines ? If the MX28 has the oddity to swap
>> packets and this must be always done for this SOC, we could protect the
>> code only with CONFIG_MX28. I think in the code it is already clear that
>> in case of MX28 the packets are swapped.
>
> Well if any other CPU with this problem pops up on the market, we should be
> ready.

makes sense
-mike

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

* [U-Boot] [PATCH 13/15 V2] iMX28: Add support for DENX M28EVK board
  2011-09-14  5:10               ` Marek Vasut
@ 2011-09-14 22:12                 ` Mike Frysinger
  2011-09-14 23:13                   ` Marek Vasut
  0 siblings, 1 reply; 116+ messages in thread
From: Mike Frysinger @ 2011-09-14 22:12 UTC (permalink / raw)
  To: u-boot

2011/9/14 Marek Vasut:
> On Wednesday, September 14, 2011 07:01:38 AM Mike Frysinger wrote:
>> On Wednesday, September 14, 2011 00:24:48 Marek Vasut wrote:
>> > On Wednesday, September 14, 2011 05:33:48 AM Mike Frysinger wrote:
>> > > On Tuesday, September 13, 2011 23:17:48 Marek Vasut wrote:
>> > > > On Wednesday, September 14, 2011 04:48:03 AM Mike Frysinger wrote:
>> > > > > On Tuesday, September 13, 2011 18:29:38 Marek Vasut wrote:
>> > > > > > --- /dev/null
>> > > > > > +++ b/board/denx/m28evk/Makefile
>> > > > > >
>> > > > > > +clean:
>> > > > > > + ? rm -f $(OBJS)
>> > > > > > +
>> > > > > > +distclean: clean
>> > > > > > + ? rm -f $(LIB) core *.bak .depend
>> > > > >
>> > > > > pretty sure these dont get used anywhere
>> > > >
>> > > > I suppose make clean would be the thing ?
>> > >
>> > > if you read the top level Makefile, you'll see that there is no
>> > > recursion for clean or distclean targets
>> >
>> > It makes sense, but then why does the rest of the boards still define it
>> > ?
>>
>> old cruft
>>
>> > If there was some major cleanup on this matter, this should have been
>> > removed from the board Makefiles too.
>>
>> i dont know the exact sequence of events, but this is the current state of
>> things. ?feel free to post a big cleanup patch :).
>
> Not until I get confirmation from someone involved it really is an old useless
> crap.

lazy :P.  i'll send a patch then.

(when i said "sequence of events", i meant change history which turned
this into unused cruft)
-mike

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

* [U-Boot] [PATCH 13/15 V2] iMX28: Add support for DENX M28EVK board
  2011-09-14 22:12                 ` Mike Frysinger
@ 2011-09-14 23:13                   ` Marek Vasut
  0 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-09-14 23:13 UTC (permalink / raw)
  To: u-boot

On Thursday, September 15, 2011 12:12:52 AM Mike Frysinger wrote:
> 2011/9/14 Marek Vasut:
> > On Wednesday, September 14, 2011 07:01:38 AM Mike Frysinger wrote:
> >> On Wednesday, September 14, 2011 00:24:48 Marek Vasut wrote:
> >> > On Wednesday, September 14, 2011 05:33:48 AM Mike Frysinger wrote:
> >> > > On Tuesday, September 13, 2011 23:17:48 Marek Vasut wrote:
> >> > > > On Wednesday, September 14, 2011 04:48:03 AM Mike Frysinger wrote:
> >> > > > > On Tuesday, September 13, 2011 18:29:38 Marek Vasut wrote:
> >> > > > > > --- /dev/null
> >> > > > > > +++ b/board/denx/m28evk/Makefile
> >> > > > > > 
> >> > > > > > +clean:
> >> > > > > > +   rm -f $(OBJS)
> >> > > > > > +
> >> > > > > > +distclean: clean
> >> > > > > > +   rm -f $(LIB) core *.bak .depend
> >> > > > > 
> >> > > > > pretty sure these dont get used anywhere
> >> > > > 
> >> > > > I suppose make clean would be the thing ?
> >> > > 
> >> > > if you read the top level Makefile, you'll see that there is no
> >> > > recursion for clean or distclean targets
> >> > 
> >> > It makes sense, but then why does the rest of the boards still define
> >> > it ?
> >> 
> >> old cruft
> >> 
> >> > If there was some major cleanup on this matter, this should have been
> >> > removed from the board Makefiles too.
> >> 
> >> i dont know the exact sequence of events, but this is the current state
> >> of things.  feel free to post a big cleanup patch :).
> > 
> > Not until I get confirmation from someone involved it really is an old
> > useless crap.
> 
> lazy :P.

Don't get me started ;-D

> i'll send a patch then.

Be sure to run it through makeall for all and every platform if necessary.
> 
> (when i said "sequence of events", i meant change history which turned
> this into unused cruft)

Sure, I got your point.

> -mike

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

* [U-Boot] [PATCH 13/15 V3] iMX28: Add support for DENX M28EVK board
  2011-09-13 22:29   ` [U-Boot] [PATCH 13/15 V2] " Marek Vasut
  2011-09-14  2:48     ` Mike Frysinger
@ 2011-09-20  2:15     ` Marek Vasut
  1 sibling, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-09-20  2:15 UTC (permalink / raw)
  To: u-boot

This contains support for the following components:
- DUART
- MMC
- Both FEC interfaces
- NAND
- I2C (RTC, EEPROM)
- SPI (FLASH)

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
Cc: Scott Wood <scottwood@freescale.com>
---
 MAINTAINERS                |    1 +
 board/denx/m28evk/Makefile |   49 ++++++++
 board/denx/m28evk/m28evk.c |  195 ++++++++++++++++++++++++++++++
 boards.cfg                 |    1 +
 include/configs/m28evk.h   |  282 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 528 insertions(+), 0 deletions(-)
 create mode 100644 board/denx/m28evk/Makefile
 create mode 100644 board/denx/m28evk/m28evk.c
 create mode 100644 include/configs/m28evk.h

V2: Use scrub -y instead of scrub.quiet in the scripts.

V3: Use CONFIG_ENV_RANGE

diff --git a/MAINTAINERS b/MAINTAINERS
index 2f60a60..61a55a8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -847,6 +847,7 @@ Marek Vasut <marek.vasut@gmail.com>
 	palmtc		xscale/pxa
 	vpac270		xscale/pxa
 	zipitz2		xscale/pxa
+	m28evk		i.MX28
  	efikamx		i.MX51
 
 Hugo Villeneuve <hugo.villeneuve@lyrtech.com>
diff --git a/board/denx/m28evk/Makefile b/board/denx/m28evk/Makefile
new file mode 100644
index 0000000..4037199
--- /dev/null
+++ b/board/denx/m28evk/Makefile
@@ -0,0 +1,49 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(BOARD).o
+
+COBJS	:= m28evk.o
+
+SRCS	:= $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+clean:
+	rm -f $(OBJS)
+
+distclean:	clean
+	rm -f $(LIB) core *.bak .depend
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/denx/m28evk/m28evk.c b/board/denx/m28evk/m28evk.c
new file mode 100644
index 0000000..118e222
--- /dev/null
+++ b/board/denx/m28evk/m28evk.c
@@ -0,0 +1,195 @@
+/*
+ * DENX M28 module
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/iomux-mx28.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sys_proto.h>
+#include <linux/mii.h>
+#include <miiphy.h>
+#include <netdev.h>
+#include <errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Functions
+ */
+int board_early_init_f(void)
+{
+	/* IO0 clock at 480MHz */
+	mx28_set_ioclk(MXC_IOCLK0, 480000);
+	/* IO1 clock at 480MHz */
+	mx28_set_ioclk(MXC_IOCLK1, 480000);
+
+	/* SSP0 clock at 96MHz */
+	mx28_set_sspclk(MXC_SSPCLK0, 96000, 0);
+	/* SSP2 clock at 96MHz */
+	mx28_set_sspclk(MXC_SSPCLK2, 96000, 0);
+
+	return 0;
+}
+
+int board_init(void)
+{
+	/* Adress of boot parameters */
+	gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
+
+	return 0;
+}
+
+int dram_init(void)
+{
+	/* dram_init must store complete ramsize in gd->ram_size */
+	gd->ram_size = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE);
+	return 0;
+}
+
+#ifdef	CONFIG_CMD_MMC
+static int m28_mmc_wp(int id)
+{
+	if (id != 0) {
+		printf("MXS MMC: Invalid card selected (card id = %d)\n", id);
+		return 1;
+	}
+
+	return gpio_get_value(MX28_PAD_AUART2_CTS__GPIO_3_10);
+}
+
+int board_mmc_init(bd_t *bis)
+{
+	/* Configure WP as output */
+	gpio_direction_input(MX28_PAD_AUART2_CTS__GPIO_3_10);
+
+	return mxsmmc_initialize(bis, 0, m28_mmc_wp);
+}
+#endif
+
+#ifdef	CONFIG_CMD_NET
+
+#define	MII_OPMODE_STRAP_OVERRIDE	0x16
+#define	MII_PHY_CTRL1			0x1e
+#define	MII_PHY_CTRL2			0x1f
+
+int fecmxc_mii_postcall(int phy)
+{
+	miiphy_write("FEC1", phy, MII_BMCR, 0x9000);
+	miiphy_write("FEC1", phy, MII_OPMODE_STRAP_OVERRIDE, 0x0202);
+	if (phy == 3)
+		miiphy_write("FEC1", 3, MII_PHY_CTRL2, 0x8180);
+	return 0;
+}
+
+int board_eth_init(bd_t *bis)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	struct eth_device *dev;
+	int ret;
+
+	ret = cpu_eth_init(bis);
+
+	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_enet,
+		CLKCTRL_ENET_TIME_SEL_MASK | CLKCTRL_ENET_CLK_OUT_EN,
+		CLKCTRL_ENET_TIME_SEL_RMII_CLK);
+
+	ret = fecmxc_initialize_multi(bis, 0, 0, MXS_ENET0_BASE);
+	if (ret) {
+		printf("FEC MXS: Unable to init FEC0\n");
+		return ret;
+	}
+
+	ret = fecmxc_initialize_multi(bis, 1, 3, MXS_ENET1_BASE);
+	if (ret) {
+		printf("FEC MXS: Unable to init FEC1\n");
+		return ret;
+	}
+
+	dev = eth_get_dev_by_name("FEC0");
+	if (!dev) {
+		printf("FEC MXS: Unable to get FEC0 device entry\n");
+		return -EINVAL;
+	}
+
+	ret = fecmxc_register_mii_postcall(dev, fecmxc_mii_postcall);
+	if (ret) {
+		printf("FEC MXS: Unable to register FEC0 mii postcall\n");
+		return ret;
+	}
+
+	dev = eth_get_dev_by_name("FEC1");
+	if (!dev) {
+		printf("FEC MXS: Unable to get FEC1 device entry\n");
+		return -EINVAL;
+	}
+
+	ret = fecmxc_register_mii_postcall(dev, fecmxc_mii_postcall);
+	if (ret) {
+		printf("FEC MXS: Unable to register FEC1 mii postcall\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+#ifdef	CONFIG_M28_FEC_MAC_IN_OCOTP
+
+#define	MXS_OCOTP_MAX_TIMEOUT	1000000
+void imx_get_mac_from_fuse(char *mac)
+{
+	struct mx28_ocotp_regs *ocotp_regs =
+		(struct mx28_ocotp_regs *)MXS_OCOTP_BASE;
+	uint32_t data;
+
+	memset(mac, 0, 6);
+
+	writel(OCOTP_CTRL_RD_BANK_OPEN, &ocotp_regs->hw_ocotp_ctrl_set);
+
+	if (mx28_wait_mask_clr(&ocotp_regs->hw_ocotp_ctrl_reg, OCOTP_CTRL_BUSY,
+				MXS_OCOTP_MAX_TIMEOUT)) {
+		printf("MXS FEC: Can't get MAC from OCOTP\n");
+		return;
+	}
+
+	data = readl(&ocotp_regs->hw_ocotp_cust0);
+
+	mac[0] = 0x00;
+	mac[1] = 0x04;
+	mac[2] = (data >> 24) & 0xff;
+	mac[3] = (data >> 16) & 0xff;
+	mac[4] = (data >> 8) & 0xff;
+	mac[5] = data & 0xff;
+}
+#else
+void imx_get_mac_from_fuse(char *mac)
+{
+	memset(mac, 0, 6);
+}
+#endif
+
+#endif
diff --git a/boards.cfg b/boards.cfg
index 8a5bfc1..c5d8a90 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -147,6 +147,7 @@ jadecpu                      arm         arm926ejs   jadecpu             syteco
 zmx25                        arm         arm926ejs   zmx25               syteco         mx25
 imx27lite                    arm         arm926ejs   imx27lite           logicpd        mx27
 magnesium                    arm         arm926ejs   imx27lite           logicpd        mx27
+m28evk                       arm         arm926ejs   -                   denx           mx28
 nhk8815                      arm         arm926ejs   nhk8815             st             nomadik
 nhk8815_onenand              arm         arm926ejs   nhk8815             st             nomadik       nhk8815:BOOT_ONENAND
 omap5912osk                  arm         arm926ejs   -                   ti             omap
diff --git a/include/configs/m28evk.h b/include/configs/m28evk.h
new file mode 100644
index 0000000..44a09a0
--- /dev/null
+++ b/include/configs/m28evk.h
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef __M28_H__
+#define __M28_H__
+
+#include <asm/arch/regs-base.h>
+
+/*
+ * SoC configurations
+ */
+#define	CONFIG_MX28				/* i.MX28 SoC */
+#define	CONFIG_MXS_GPIO				/* GPIO control */
+#define	CONFIG_SYS_HZ		1000		/* Ticks per second */
+
+/*
+ * Define M28EVK machine type by hand until it lands in mach-types
+ */
+#define	MACH_TYPE_M28EVK	3613
+
+#define	CONFIG_MACH_TYPE	MACH_TYPE_M28EVK
+
+#define	CONFIG_SYS_NO_FLASH
+#define	CONFIG_SYS_ICACHE_OFF
+#define	CONFIG_SYS_DCACHE_OFF
+#define	CONFIG_BOARD_EARLY_INIT_F
+#define	CONFIG_ARCH_CPU_INIT
+
+/*
+ * U-Boot Commands
+ */
+#include <config_cmd_default.h>
+#define	CONFIG_DISPLAY_CPUINFO
+#define	CONFIG_DOS_PARTITION
+
+#define	CONFIG_CMD_CACHE
+#define	CONFIG_CMD_DATE
+#define	CONFIG_CMD_DHCP
+#define	CONFIG_CMD_EEPROM
+#define	CONFIG_CMD_EXT2
+#define	CONFIG_CMD_FAT
+#define	CONFIG_CMD_GPIO
+#define	CONFIG_CMD_I2C
+#define	CONFIG_CMD_MII
+#define	CONFIG_CMD_MMC
+#define	CONFIG_CMD_NAND
+#define	CONFIG_CMD_NET
+#define	CONFIG_CMD_NFS
+#define	CONFIG_CMD_PING
+#define	CONFIG_CMD_SETEXPR
+#define	CONFIG_CMD_SF
+#define	CONFIG_CMD_SPI
+
+/*
+ * Memory configurations
+ */
+#define	CONFIG_NR_DRAM_BANKS		1		/* 2 banks of DRAM */
+#define	PHYS_SDRAM_1			0x40000000	/* Base address */
+#define	PHYS_SDRAM_1_SIZE		0x10000000	/* 256 MB */
+#define	CONFIG_STACKSIZE		0x00010000	/* 128 KB stack */
+#define	CONFIG_SYS_MALLOC_LEN		0x00400000	/* 4 MB for malloc */
+#define	CONFIG_SYS_GBL_DATA_SIZE	128		/* Initial data */
+#define	CONFIG_SYS_MEMTEST_START	0x40000000	/* Memtest start adr */
+#define	CONFIG_SYS_MEMTEST_END		0x40400000	/* 4 MB RAM test */
+#define	CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM_1
+/* Point initial SP in SRAM so SPL can use it too. */
+#define	CONFIG_SYS_INIT_SP_ADDR		0x00002000
+/*
+ * We need to sacrifice first 4 bytes of RAM here to avoid triggering some
+ * strange BUG in ROM corrupting first 4 bytes of RAM when loading U-Boot
+ * binary. In case there was more of this mess, 0x100 bytes are skipped.
+ */
+#define	CONFIG_SYS_TEXT_BASE		0x40000100
+
+/*
+ * U-Boot general configurations
+ */
+#define	CONFIG_SYS_LONGHELP
+#define	CONFIG_SYS_PROMPT	"=> "
+#define	CONFIG_SYS_CBSIZE	1024		/* Console I/O buffer size */
+#define	CONFIG_SYS_PBSIZE	\
+	(CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+						/* Print buffer size */
+#define	CONFIG_SYS_MAXARGS	32		/* Max number of command args */
+#define	CONFIG_SYS_BARGSIZE	CONFIG_SYS_CBSIZE
+						/* Boot argument buffer size */
+#define	CONFIG_VERSION_VARIABLE			/* U-BOOT version */
+#define	CONFIG_AUTO_COMPLETE			/* Command auto complete */
+#define	CONFIG_CMDLINE_EDITING			/* Command history etc */
+#define	CONFIG_SYS_HUSH_PARSER
+#define	CONFIG_SYS_PROMPT_HUSH_PS2	"> "
+
+/*
+ * Serial Driver
+ */
+#define	CONFIG_PL011_SERIAL
+#define	CONFIG_PL011_CLOCK		24000000
+#define	CONFIG_PL01x_PORTS		{ (void *)MXS_UARTDBG_BASE }
+#define	CONFIG_CONS_INDEX		0
+#define	CONFIG_BAUDRATE			115200	/* Default baud rate */
+#define	CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 }
+
+/*
+ * MMC Driver
+ */
+#ifdef	CONFIG_CMD_MMC
+#define	CONFIG_MMC
+#define	CONFIG_GENERIC_MMC
+#define	CONFIG_MXS_MMC
+#endif
+
+/*
+ * NAND
+ */
+#ifdef	CONFIG_CMD_NAND
+#define	CONFIG_NAND_MXS
+#define CONFIG_APBH_DMA
+#define	CONFIG_SYS_MAX_NAND_DEVICE	1
+#define	CONFIG_SYS_NAND_BASE		0x60000000
+#define	CONFIG_SYS_NAND_5_ADDR_CYCLE
+#define	NAND_MAX_CHIPS			8
+
+/* Environment is in NAND */
+#define	CONFIG_ENV_IS_IN_NAND
+#define	CONFIG_ENV_SIZE			(16 * 1024)
+#define	CONFIG_ENV_SIZE_REDUND		CONFIG_ENV_SIZE
+#define	CONFIG_ENV_SECT_SIZE		(128 * 1024)
+#define	CONFIG_ENV_RANGE		(512 * 1024)
+#define	CONFIG_ENV_OFFSET		0x300000
+#define	CONFIG_ENV_OFFSET_REDUND	\
+		(CONFIG_ENV_OFFSET + CONFIG_ENV_RANGE)
+
+#define	CONFIG_CMD_UBI
+#define	CONFIG_CMD_UBIFS
+#define	CONFIG_CMD_MTDPARTS
+#define	CONFIG_RBTREE
+#define	CONFIG_LZO
+#define	CONFIG_MTD_DEVICE
+#define	CONFIG_MTD_PARTITIONS
+#define	MTDIDS_DEFAULT			"nand0=gpmi-nand.0"
+#define	MTDPARTS_DEFAULT			\
+	"mtdparts=gpmi-nand.0:"			\
+		"3m(bootloader)ro,"		\
+		"512k(environment),"		\
+		"512k(redundant-environment),"	\
+		"4m(kernel),"			\
+		"-(filesystem)"
+#endif
+
+/*
+ * Ethernet on SOC (FEC)
+ */
+#ifdef	CONFIG_CMD_NET
+#define	CONFIG_NET_MULTI
+#define	CONFIG_ETHPRIME			"FEC0"
+#define	CONFIG_FEC_MXC
+#define	CONFIG_FEC_MXC_MULTI
+#define	CONFIG_MII
+#define	CONFIG_DISCOVER_PHY
+#define	CONFIG_FEC_XCV_TYPE		RMII
+#endif
+
+/*
+ * I2C
+ */
+#ifdef	CONFIG_CMD_I2C
+#define	CONFIG_I2C_MXS
+#define	CONFIG_HARD_I2C
+#define	CONFIG_SYS_I2C_SPEED		400000
+#endif
+
+/*
+ * EEPROM
+ */
+#ifdef	CONFIG_CMD_EEPROM
+#define	CONFIG_SYS_I2C_MULTI_EEPROMS
+#define	CONFIG_SYS_I2C_EEPROM_ADDR_LEN	2
+#endif
+
+/*
+ * RTC
+ */
+#ifdef	CONFIG_CMD_DATE
+/* Use the internal RTC in the MXS chip */
+#define	CONFIG_RTC_INTERNAL
+#ifdef	CONFIG_RTC_INTERNAL
+#define	CONFIG_RTC_MXS
+#else
+#define	CONFIG_RTC_M41T62
+#define	CONFIG_SYS_I2C_RTC_ADDR		0x68
+#define	CONFIG_SYS_M41T11_BASE_YEAR	2000
+#endif
+#endif
+
+/*
+ * SPI
+ */
+#ifdef	CONFIG_CMD_SPI
+#define	CONFIG_HARD_SPI
+#define	CONFIG_MXS_SPI
+#define	CONFIG_SPI_HALF_DUPLEX
+#define	CONFIG_DEFAULT_SPI_BUS		2
+#define	CONFIG_DEFAULT_SPI_MODE		SPI_MODE_0
+
+/* SPI FLASH */
+#ifdef	CONFIG_CMD_SF
+#define	CONFIG_SPI_FLASH
+#define	CONFIG_SPI_FLASH_STMICRO
+#define	CONFIG_SPI_FLASH_CS		2
+#define	CONFIG_SF_DEFAULT_MODE		SPI_MODE_0
+#define	CONFIG_SF_DEFAULT_SPEED		24000000
+
+#define	CONFIG_ENV_SPI_CS		0
+#define	CONFIG_ENV_SPI_BUS		2
+#define	CONFIG_ENV_SPI_MAX_HZ		24000000
+#define	CONFIG_ENV_SPI_MODE		SPI_MODE_0
+#endif
+#endif
+
+/*
+ * Boot Linux
+ */
+#define	CONFIG_CMDLINE_TAG
+#define	CONFIG_SETUP_MEMORY_TAGS
+#define	CONFIG_BOOTDELAY	3
+#define	CONFIG_BOOTFILE		"uImage"
+#define	CONFIG_BOOTARGS		"console=ttyAM0,115200n8 "
+#define	CONFIG_BOOTCOMMAND	"run bootcmd_net"
+#define	CONFIG_LOADADDR		0x42000000
+#define	CONFIG_SYS_LOAD_ADDR	CONFIG_LOADADDR
+
+/*
+ * Extra Environments
+ */
+#define	CONFIG_EXTRA_ENV_SETTINGS					\
+	"update_nand_full_filename=u-boot.nand\0"			\
+	"update_nand_firmware_filename=u-boot.sb\0"			\
+	"update_nand_firmware_maxsz=0x100000\0"				\
+	"update_nand_stride=0x40\0"	/* MX28 datasheet ch. 12.12 */	\
+	"update_nand_count=0x4\0"	/* MX28 datasheet ch. 12.12 */	\
+	"update_nand_get_fcb_size="	/* Get size of FCB blocks */	\
+		"nand device 0 ; "					\
+		"nand info ; "						\
+		"setexpr fcb_sz ${update_nand_stride} * ${update_nand_count};" \
+		"setexpr update_nand_fcb ${fcb_sz} * ${nand_writesize}\0" \
+	"update_nand_full="		/* Update FCB, DBBT and FW */	\
+		"if tftp ${update_nand_full_filename} ; then "		\
+		"run update_nand_get_fcb_size ; "			\
+		"nand scrub -y 0x0 ${filesize} ; "			\
+		"nand write.raw ${loadaddr} 0x0 ${update_nand_fcb} ; "	\
+		"setexpr update_off ${loadaddr} + ${update_nand_fcb} ; " \
+		"setexpr update_sz ${filesize} - ${update_nand_fcb} ; " \
+		"nand write ${update_off} ${update_nand_fcb} ${update_sz} ; " \
+		"fi\0"							\
+	"update_nand_firmware="		/* Update only firmware */	\
+		"if tftp ${update_nand_firmware_filename} ; then "	\
+		"run update_nand_get_fcb_size ; "			\
+		"setexpr fcb_sz ${update_nand_fcb} * 2 ; " /* FCB + DBBT */ \
+		"setexpr fw_sz ${update_nand_firmware_maxsz} * 2 ; "	\
+		"setexpr fw_off ${fcb_sz} + ${update_nand_firmware_maxsz};" \
+		"nand erase ${fcb_sz} ${fw_sz} ; "			\
+		"nand write ${loadaddr} ${fcb_sz} ${filesize} ; "	\
+		"nand write ${loadaddr} ${fw_off} ${filesize} ; "	\
+		"fi\0"
+
+#endif /* __M28_H__ */
-- 
1.7.5.4

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

* [U-Boot] [PATCH 01/15 V2] iMX28: Initial support for iMX28 CPU
  2011-09-12  4:06 ` [U-Boot] [PATCH 01/15] iMX28: Initial support for iMX28 CPU Marek Vasut
  2011-09-14  7:10   ` Stefano Babic
@ 2011-09-27 13:45   ` Marek Vasut
  2011-09-30  9:42     ` [U-Boot] [PATCH 01/15 V3] " Marek Vasut
  1 sibling, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-09-27 13:45 UTC (permalink / raw)
  To: u-boot

This patch supports:
- Timers
- Debug UART
- Clock

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 arch/arm/cpu/arm926ejs/mx28/Makefile          |   46 +
 arch/arm/cpu/arm926ejs/mx28/clock.c           |  355 +++++++
 arch/arm/cpu/arm926ejs/mx28/mx28.c            |  196 ++++
 arch/arm/cpu/arm926ejs/mx28/timer.c           |  141 +++
 arch/arm/include/asm/arch-mx28/clock.h        |   61 ++
 arch/arm/include/asm/arch-mx28/imx-regs.h     |   38 +
 arch/arm/include/asm/arch-mx28/regs-base.h    |   88 ++
 arch/arm/include/asm/arch-mx28/regs-bch.h     |  230 +++++
 arch/arm/include/asm/arch-mx28/regs-clkctrl.h |  312 ++++++
 arch/arm/include/asm/arch-mx28/regs-common.h  |   66 ++
 arch/arm/include/asm/arch-mx28/regs-gpmi.h    |  222 +++++
 arch/arm/include/asm/arch-mx28/regs-i2c.h     |  207 ++++
 arch/arm/include/asm/arch-mx28/regs-ocotp.h   |  173 ++++
 arch/arm/include/asm/arch-mx28/regs-pinctrl.h | 1284 +++++++++++++++++++++++++
 arch/arm/include/asm/arch-mx28/regs-power.h   |  413 ++++++++
 arch/arm/include/asm/arch-mx28/regs-rtc.h     |  147 +++
 arch/arm/include/asm/arch-mx28/regs-ssp.h     |  349 +++++++
 arch/arm/include/asm/arch-mx28/regs-timrot.h  |  171 ++++
 arch/arm/include/asm/arch-mx28/sys_proto.h    |   30 +
 19 files changed, 4529 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/Makefile
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/clock.c
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/mx28.c
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/timer.c
 create mode 100644 arch/arm/include/asm/arch-mx28/clock.h
 create mode 100644 arch/arm/include/asm/arch-mx28/imx-regs.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-base.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-bch.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-clkctrl.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-common.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-gpmi.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-i2c.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-ocotp.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-pinctrl.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-power.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-rtc.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-ssp.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-timrot.h
 create mode 100644 arch/arm/include/asm/arch-mx28/sys_proto.h

V2: Use watchdog for reset

diff --git a/arch/arm/cpu/arm926ejs/mx28/Makefile b/arch/arm/cpu/arm926ejs/mx28/Makefile
new file mode 100644
index 0000000..98504f9
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/Makefile
@@ -0,0 +1,46 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(SOC).o
+
+COBJS	= clock.o mx28.o timer.o
+
+SRCS	:= $(START:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+START	:= $(addprefix $(obj),$(START))
+
+all:	$(obj).depend $(LIB)
+
+$(LIB):	$(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/arm/cpu/arm926ejs/mx28/clock.c b/arch/arm/cpu/arm926ejs/mx28/clock.c
new file mode 100644
index 0000000..f698506
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/clock.c
@@ -0,0 +1,355 @@
+/*
+ * Freescale i.MX28 clock setup code
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+
+/* The PLL frequency is always 480MHz, see section 10.2 in iMX28 datasheet. */
+#define	PLL_FREQ_KHZ	480000
+#define	PLL_FREQ_COEF	18
+/* The XTAL frequency is always 24MHz, see section 10.2 in iMX28 datasheet. */
+#define	XTAL_FREQ_KHZ	24000
+
+#define	PLL_FREQ_MHZ	(PLL_FREQ_KHZ / 1000)
+#define	XTAL_FREQ_MHZ	(XTAL_FREQ_KHZ / 1000)
+
+static uint32_t mx28_get_pclk(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	uint32_t clkctrl, clkseq, clkfrac;
+	uint32_t frac, div;
+
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_cpu);
+
+	/* No support of fractional divider calculation */
+	if (clkctrl &
+		(CLKCTRL_CPU_DIV_XTAL_FRAC_EN | CLKCTRL_CPU_DIV_CPU_FRAC_EN)) {
+		return 0;
+	}
+
+	clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+
+	/* XTAL Path */
+	if (clkseq & CLKCTRL_CLKSEQ_BYPASS_CPU) {
+		div = (clkctrl & CLKCTRL_CPU_DIV_XTAL_MASK) >>
+			CLKCTRL_CPU_DIV_XTAL_OFFSET;
+		return XTAL_FREQ_MHZ / div;
+	}
+
+	/* REF Path */
+	clkfrac = readl(&clkctrl_regs->hw_clkctrl_frac0);
+	frac = clkfrac & CLKCTRL_FRAC0_CPUFRAC_MASK;
+	div = clkctrl & CLKCTRL_CPU_DIV_CPU_MASK;
+	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
+}
+
+static uint32_t mx28_get_hclk(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	uint32_t div;
+	uint32_t clkctrl;
+
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_hbus);
+
+	/* No support of fractional divider calculation */
+	if (clkctrl & CLKCTRL_HBUS_DIV_FRAC_EN)
+		return 0;
+
+	div = clkctrl & CLKCTRL_HBUS_DIV_MASK;
+	return mx28_get_pclk() / div;
+}
+
+static uint32_t mx28_get_emiclk(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	uint32_t frac, div;
+	uint32_t clkctrl, clkseq, clkfrac;
+
+	clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_emi);
+
+	/* XTAL Path */
+	if (clkseq & CLKCTRL_CLKSEQ_BYPASS_EMI) {
+		div = (clkctrl & CLKCTRL_EMI_DIV_XTAL_MASK) >>
+			CLKCTRL_EMI_DIV_XTAL_OFFSET;
+		return XTAL_FREQ_MHZ / div;
+	}
+
+	clkfrac = readl(&clkctrl_regs->hw_clkctrl_frac0);
+
+	/* REF Path */
+	frac = (clkfrac & CLKCTRL_FRAC0_EMIFRAC_MASK) >>
+		CLKCTRL_FRAC0_EMIFRAC_OFFSET;
+	div = clkctrl & CLKCTRL_EMI_DIV_EMI_MASK;
+	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
+}
+
+static uint32_t mx28_get_gpmiclk(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	uint32_t frac, div;
+	uint32_t clkctrl, clkseq, clkfrac;
+
+	clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_gpmi);
+
+	/* XTAL Path */
+	if (clkseq & CLKCTRL_CLKSEQ_BYPASS_GPMI) {
+		div = clkctrl & CLKCTRL_GPMI_DIV_MASK;
+		return XTAL_FREQ_MHZ / div;
+	}
+
+	clkfrac = readl(&clkctrl_regs->hw_clkctrl_frac1);
+
+	/* REF Path */
+	frac = (clkfrac & CLKCTRL_FRAC1_GPMIFRAC_MASK) >>
+		CLKCTRL_FRAC1_GPMIFRAC_OFFSET;
+	div = clkctrl & CLKCTRL_GPMI_DIV_MASK;
+	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
+}
+
+/*
+ * Set IO clock frequency, in kHz
+ */
+void mx28_set_ioclk(enum mxs_ioclock io, uint32_t freq)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t div;
+
+	if (freq == 0)
+		return;
+
+	if (io > MXC_IOCLK1)
+		return;
+
+	div = (PLL_FREQ_KHZ * PLL_FREQ_COEF) / freq;
+
+	if (div < 18)
+		div = 18;
+
+	if (div > 35)
+		div = 35;
+
+	if (io == MXC_IOCLK0) {
+		writel(CLKCTRL_FRAC0_CLKGATEIO0,
+			&clkctrl_regs->hw_clkctrl_frac0_set);
+		clrsetbits_le32(&clkctrl_regs->hw_clkctrl_frac0,
+				CLKCTRL_FRAC0_IO0FRAC_MASK,
+				div << CLKCTRL_FRAC0_IO0FRAC_OFFSET);
+		writel(CLKCTRL_FRAC0_CLKGATEIO0,
+			&clkctrl_regs->hw_clkctrl_frac0_clr);
+	} else {
+		writel(CLKCTRL_FRAC0_CLKGATEIO1,
+			&clkctrl_regs->hw_clkctrl_frac0_set);
+		clrsetbits_le32(&clkctrl_regs->hw_clkctrl_frac0,
+				CLKCTRL_FRAC0_IO1FRAC_MASK,
+				div << CLKCTRL_FRAC0_IO1FRAC_OFFSET);
+		writel(CLKCTRL_FRAC0_CLKGATEIO1,
+			&clkctrl_regs->hw_clkctrl_frac0_clr);
+	}
+}
+
+/*
+ * Get IO clock, returns IO clock in kHz
+ */
+static uint32_t mx28_get_ioclk(enum mxs_ioclock io)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t tmp, ret;
+
+	if (io > MXC_IOCLK1)
+		return 0;
+
+	tmp = readl(&clkctrl_regs->hw_clkctrl_frac0);
+
+	if (io == MXC_IOCLK0)
+		ret = (tmp & CLKCTRL_FRAC0_IO0FRAC_MASK) >>
+			CLKCTRL_FRAC0_IO0FRAC_OFFSET;
+	else
+		ret = (tmp & CLKCTRL_FRAC0_IO1FRAC_MASK) >>
+			CLKCTRL_FRAC0_IO1FRAC_OFFSET;
+
+	return (PLL_FREQ_KHZ * PLL_FREQ_COEF) / ret;
+}
+
+/*
+ * Configure SSP clock frequency, in kHz
+ */
+void mx28_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t clk, clkreg;
+
+	if (ssp > MXC_SSPCLK3)
+		return;
+
+	clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) +
+			(ssp * sizeof(struct mx28_register));
+
+	clrbits_le32(clkreg, CLKCTRL_SSP_CLKGATE);
+	while (readl(clkreg) & CLKCTRL_SSP_CLKGATE)
+		;
+
+	if (xtal)
+		clk = XTAL_FREQ_KHZ;
+	else
+		clk = mx28_get_ioclk(ssp >> 1);
+
+	if (freq > clk)
+		return;
+
+	/* Calculate the divider and cap it if necessary */
+	clk /= freq;
+	if (clk > CLKCTRL_SSP_DIV_MASK)
+		clk = CLKCTRL_SSP_DIV_MASK;
+
+	clrsetbits_le32(clkreg, CLKCTRL_SSP_DIV_MASK, clk);
+	while (readl(clkreg) & CLKCTRL_SSP_BUSY)
+		;
+
+	if (xtal)
+		writel(CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp,
+			&clkctrl_regs->hw_clkctrl_clkseq_set);
+	else
+		writel(CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp,
+			&clkctrl_regs->hw_clkctrl_clkseq_clr);
+}
+
+/*
+ * Return SSP frequency, in kHz
+ */
+static uint32_t mx28_get_sspclk(enum mxs_sspclock ssp)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t clkreg;
+	uint32_t clk, tmp;
+
+	if (ssp > MXC_SSPCLK3)
+		return 0;
+
+	tmp = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+	if (tmp & (CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp))
+		return XTAL_FREQ_KHZ;
+
+	clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) +
+			(ssp * sizeof(struct mx28_register));
+
+	tmp = readl(clkreg) & CLKCTRL_SSP_DIV_MASK;
+
+	if (tmp == 0)
+		return 0;
+
+	clk = mx28_get_ioclk(ssp >> 1);
+
+	return clk / tmp;
+}
+
+/*
+ * Set SSP/MMC bus frequency, in kHz)
+ */
+void mx28_set_ssp_busclock(unsigned int bus, uint32_t freq)
+{
+	struct mx28_ssp_regs *ssp_regs;
+	const uint32_t sspclk = mx28_get_sspclk(bus);
+	uint32_t reg;
+	uint32_t divide, rate, tgtclk;
+
+	ssp_regs = (struct mx28_ssp_regs *)(MXS_SSP0_BASE + (bus * 0x2000));
+
+	/*
+	 * SSP bit rate = SSPCLK / (CLOCK_DIVIDE * (1 + CLOCK_RATE)),
+	 * CLOCK_DIVIDE has to be an even value from 2 to 254, and
+	 * CLOCK_RATE could be any integer from 0 to 255.
+	 */
+	for (divide = 2; divide < 254; divide += 2) {
+		rate = sspclk / freq / divide;
+		if (rate <= 256)
+			break;
+	}
+
+	tgtclk = sspclk / divide / rate;
+	while (tgtclk > freq) {
+		rate++;
+		tgtclk = sspclk / divide / rate;
+	}
+	if (rate > 256)
+		rate = 256;
+
+	/* Always set timeout the maximum */
+	reg = SSP_TIMING_TIMEOUT_MASK |
+		(divide << SSP_TIMING_CLOCK_DIVIDE_OFFSET) |
+		((rate - 1) << SSP_TIMING_CLOCK_RATE_OFFSET);
+	writel(reg, &ssp_regs->hw_ssp_timing);
+
+	debug("SPI%d: Set freq rate to %d KHz (requested %d KHz)\n",
+		bus, tgtclk, freq);
+}
+
+uint32_t mxc_get_clock(enum mxc_clock clk)
+{
+	switch (clk) {
+	case MXC_ARM_CLK:
+		return mx28_get_pclk() * 1000000;
+	case MXC_GPMI_CLK:
+		return mx28_get_gpmiclk() * 1000000;
+	case MXC_AHB_CLK:
+	case MXC_IPG_CLK:
+		return mx28_get_hclk() * 1000000;
+	case MXC_EMI_CLK:
+		return mx28_get_emiclk();
+	case MXC_IO0_CLK:
+		return mx28_get_ioclk(MXC_IOCLK0);
+	case MXC_IO1_CLK:
+		return mx28_get_ioclk(MXC_IOCLK1);
+	case MXC_SSP0_CLK:
+		return mx28_get_sspclk(MXC_SSPCLK0);
+	case MXC_SSP1_CLK:
+		return mx28_get_sspclk(MXC_SSPCLK1);
+	case MXC_SSP2_CLK:
+		return mx28_get_sspclk(MXC_SSPCLK2);
+	case MXC_SSP3_CLK:
+		return mx28_get_sspclk(MXC_SSPCLK3);
+	}
+
+	return 0;
+}
diff --git a/arch/arm/cpu/arm926ejs/mx28/mx28.c b/arch/arm/cpu/arm926ejs/mx28/mx28.c
new file mode 100644
index 0000000..b29d4a9
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/mx28.c
@@ -0,0 +1,196 @@
+/*
+ * Freescale i.MX28 common code
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/iomux-mx28.h>
+
+/* 1 second delay should be plenty of time for block reset. */
+#define	RESET_MAX_TIMEOUT	1000000
+
+#define	MX28_BLOCK_SFTRST	(1 << 31)
+#define	MX28_BLOCK_CLKGATE	(1 << 30)
+
+/* Lowlevel init isn't used on i.MX28, so just have a dummy here */
+inline void lowlevel_init(void) {}
+
+void reset_cpu(ulong ignored) __attribute__((noreturn));
+
+void reset_cpu(ulong ignored)
+{
+
+	struct mx28_rtc_regs *rtc_regs =
+		(struct mx28_rtc_regs *)MXS_RTC_BASE;
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/* Wait 1 uS before doing the actual watchdog reset */
+	writel(1, &rtc_regs->hw_rtc_watchdog);
+	writel(RTC_CTRL_WATCHDOGEN, &rtc_regs->hw_rtc_ctrl_set);
+
+	/* Endless loop, reset will exit from here */
+	for (;;)
+		;
+}
+
+int mx28_wait_mask_set(struct mx28_register *reg, uint32_t mask, int timeout)
+{
+	while (--timeout) {
+		if ((readl(&reg->reg) & mask) == mask)
+			break;
+		udelay(1);
+	}
+
+	return !timeout;
+}
+
+int mx28_wait_mask_clr(struct mx28_register *reg, uint32_t mask, int timeout)
+{
+	while (--timeout) {
+		if ((readl(&reg->reg) & mask) == 0)
+			break;
+		udelay(1);
+	}
+
+	return !timeout;
+}
+
+int mx28_reset_block(struct mx28_register *reg)
+{
+	/* Clear SFTRST */
+	writel(MX28_BLOCK_SFTRST, &reg->reg_clr);
+
+	if (mx28_wait_mask_clr(reg, MX28_BLOCK_SFTRST, RESET_MAX_TIMEOUT))
+		return 1;
+
+	/* Clear CLKGATE */
+	writel(MX28_BLOCK_CLKGATE, &reg->reg_clr);
+
+	/* Set SFTRST */
+	writel(MX28_BLOCK_SFTRST, &reg->reg_set);
+
+	/* Wait for CLKGATE being set */
+	if (mx28_wait_mask_set(reg, MX28_BLOCK_CLKGATE, RESET_MAX_TIMEOUT))
+		return 1;
+
+	/* Clear SFTRST */
+	writel(MX28_BLOCK_SFTRST, &reg->reg_clr);
+
+	if (mx28_wait_mask_clr(reg, MX28_BLOCK_SFTRST, RESET_MAX_TIMEOUT))
+		return 1;
+
+	/* Clear CLKGATE */
+	writel(MX28_BLOCK_CLKGATE, &reg->reg_clr);
+
+	if (mx28_wait_mask_clr(reg, MX28_BLOCK_CLKGATE, RESET_MAX_TIMEOUT))
+		return 1;
+
+	return 0;
+}
+
+#ifdef	CONFIG_ARCH_CPU_INIT
+int arch_cpu_init(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/*
+	 * Enable NAND clock
+	 */
+	/* Clear bypass bit */
+	writel(CLKCTRL_CLKSEQ_BYPASS_GPMI,
+		&clkctrl_regs->hw_clkctrl_clkseq_set);
+
+	/* Set GPMI clock to ref_gpmi / 12 */
+	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_gpmi,
+		CLKCTRL_GPMI_CLKGATE | CLKCTRL_GPMI_DIV_MASK, 1);
+
+	udelay(1000);
+
+	return 0;
+}
+#endif
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+int print_cpuinfo(void)
+{
+	printf("Freescale i.MX28 family\n");
+	return 0;
+}
+#endif
+
+int do_mx28_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	printf("CPU:   %3d MHz\n", mxc_get_clock(MXC_ARM_CLK) / 1000000);
+	printf("BUS:   %3d MHz\n", mxc_get_clock(MXC_AHB_CLK) / 1000000);
+	printf("EMI:   %3d MHz\n", mxc_get_clock(MXC_EMI_CLK));
+	printf("GPMI:  %3d MHz\n", mxc_get_clock(MXC_GPMI_CLK) / 1000000);
+	return 0;
+}
+
+/*
+ * Initializes on-chip ethernet controllers.
+ */
+#ifdef	CONFIG_CMD_NET
+int cpu_eth_init(bd_t *bis)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/* Turn on ENET clocks */
+	clrbits_le32(&clkctrl_regs->hw_clkctrl_enet,
+		CLKCTRL_ENET_SLEEP | CLKCTRL_ENET_DISABLE);
+
+	/* Set up ENET PLL for 50 MHz */
+	/* Power on ENET PLL */
+	writel(CLKCTRL_PLL2CTRL0_POWER,
+		&clkctrl_regs->hw_clkctrl_pll2ctrl0_set);
+
+	udelay(10);
+
+	/* Gate on ENET PLL */
+	writel(CLKCTRL_PLL2CTRL0_CLKGATE,
+		&clkctrl_regs->hw_clkctrl_pll2ctrl0_clr);
+
+	/* Enable pad output */
+	setbits_le32(&clkctrl_regs->hw_clkctrl_enet, CLKCTRL_ENET_CLK_OUT_EN);
+
+	return 0;
+}
+#endif
+
+U_BOOT_CMD(
+	clocks,	CONFIG_SYS_MAXARGS, 1, do_mx28_showclocks,
+	"display clocks",
+	""
+);
diff --git a/arch/arm/cpu/arm926ejs/mx28/timer.c b/arch/arm/cpu/arm926ejs/mx28/timer.c
new file mode 100644
index 0000000..dbc904d
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/timer.c
@@ -0,0 +1,141 @@
+/*
+ * Freescale i.MX28 timer driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * (C) Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+
+/* Maximum fixed count */
+#define TIMER_LOAD_VAL	0xffffffff
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define timestamp (gd->tbl)
+#define lastdec (gd->lastinc)
+
+/*
+ * This driver uses 1kHz clock source.
+ */
+#define	MX28_INCREMENTER_HZ		1000
+
+static inline unsigned long tick_to_time(unsigned long tick)
+{
+	return tick / (MX28_INCREMENTER_HZ / CONFIG_SYS_HZ);
+}
+
+static inline unsigned long time_to_tick(unsigned long time)
+{
+	return time * (MX28_INCREMENTER_HZ / CONFIG_SYS_HZ);
+}
+
+/* Calculate how many ticks happen in "us" microseconds */
+static inline unsigned long us_to_tick(unsigned long us)
+{
+	return (us * MX28_INCREMENTER_HZ) / 1000000;
+}
+
+int timer_init(void)
+{
+	struct mx28_timrot_regs *timrot_regs =
+		(struct mx28_timrot_regs *)MXS_TIMROT_BASE;
+
+	/* Reset Timers and Rotary Encoder module */
+	mx28_reset_block(&timrot_regs->hw_timrot_rotctrl_reg);
+
+	/* Set fixed_count to 0 */
+	writel(0, &timrot_regs->hw_timrot_fixed_count0);
+
+	/* Set UPDATE bit and 1Khz frequency */
+	writel(TIMROT_TIMCTRLn_UPDATE | TIMROT_TIMCTRLn_RELOAD |
+		TIMROT_TIMCTRLn_SELECT_1KHZ_XTAL,
+		&timrot_regs->hw_timrot_timctrl0);
+
+	/* Set fixed_count to maximal value */
+	writel(TIMER_LOAD_VAL, &timrot_regs->hw_timrot_fixed_count0);
+
+	return 0;
+}
+
+ulong get_timer(ulong base)
+{
+	struct mx28_timrot_regs *timrot_regs =
+		(struct mx28_timrot_regs *)MXS_TIMROT_BASE;
+
+	/* Current tick value */
+	uint32_t now = readl(&timrot_regs->hw_timrot_running_count0);
+
+	if (lastdec >= now) {
+		/*
+		 * normal mode (non roll)
+		 * move stamp forward with absolut diff ticks
+		 */
+		timestamp += (lastdec - now);
+	} else {
+		/* we have rollover of decrementer */
+		timestamp += (TIMER_LOAD_VAL - now) + lastdec;
+
+	}
+	lastdec = now;
+
+	return tick_to_time(timestamp) - base;
+}
+
+/* We use the HW_DIGCTL_MICROSECONDS register for sub-millisecond timer. */
+#define	MX28_HW_DIGCTL_MICROSECONDS	0x8001c0c0
+
+void __udelay(unsigned long usec)
+{
+	uint32_t old, new, incr;
+	uint32_t counter = 0;
+
+	old = readl(MX28_HW_DIGCTL_MICROSECONDS);
+
+	while (counter < usec) {
+		new = readl(MX28_HW_DIGCTL_MICROSECONDS);
+
+		/* Check if the timer wrapped. */
+		if (new < old) {
+			incr = 0xffffffff - old;
+			incr += new;
+		} else {
+			incr = new - old;
+		}
+
+		/*
+		 * Check if we are close to the maximum time and the counter
+		 * would wrap if incremented. If that's the case, break out
+		 * from the loop as the requested delay time passed.
+		 */
+		if (counter + incr < counter)
+			break;
+
+		counter += incr;
+		old = new;
+	}
+}
diff --git a/arch/arm/include/asm/arch-mx28/clock.h b/arch/arm/include/asm/arch-mx28/clock.h
new file mode 100644
index 0000000..1700fe3
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/clock.h
@@ -0,0 +1,61 @@
+/*
+ * Freescale i.MX28 Clock
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __CLOCK_H__
+#define __CLOCK_H__
+
+enum mxc_clock {
+	MXC_ARM_CLK = 0,
+	MXC_AHB_CLK,
+	MXC_IPG_CLK,
+	MXC_EMI_CLK,
+	MXC_GPMI_CLK,
+	MXC_IO0_CLK,
+	MXC_IO1_CLK,
+	MXC_SSP0_CLK,
+	MXC_SSP1_CLK,
+	MXC_SSP2_CLK,
+	MXC_SSP3_CLK,
+};
+
+enum mxs_ioclock {
+	MXC_IOCLK0 = 0,
+	MXC_IOCLK1,
+};
+
+enum mxs_sspclock {
+	MXC_SSPCLK0 = 0,
+	MXC_SSPCLK1,
+	MXC_SSPCLK2,
+	MXC_SSPCLK3,
+};
+
+uint32_t mxc_get_clock(enum mxc_clock clk);
+
+void mx28_set_ioclk(enum mxs_ioclock io, uint32_t freq);
+void mx28_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal);
+void mx28_set_ssp_busclock(unsigned int bus, uint32_t freq);
+
+/* Compatibility with the FEC Ethernet driver */
+#define	imx_get_fecclk()	mxc_get_clock(MXC_AHB_CLK)
+
+#endif	/* __CLOCK_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/imx-regs.h b/arch/arm/include/asm/arch-mx28/imx-regs.h
new file mode 100644
index 0000000..32bfd7e
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/imx-regs.h
@@ -0,0 +1,38 @@
+/*
+ * Freescale i.MX28 Registers
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __IMX_REGS_H__
+#define __IMX_REGS_H__
+
+#include <asm/arch/regs-base.h>
+#include <asm/arch/regs-bch.h>
+#include <asm/arch/regs-clkctrl.h>
+#include <asm/arch/regs-gpmi.h>
+#include <asm/arch/regs-i2c.h>
+#include <asm/arch/regs-ocotp.h>
+#include <asm/arch/regs-pinctrl.h>
+#include <asm/arch/regs-power.h>
+#include <asm/arch/regs-rtc.h>
+#include <asm/arch/regs-ssp.h>
+#include <asm/arch/regs-timrot.h>
+
+#endif	/* __IMX_REGS_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-base.h b/arch/arm/include/asm/arch-mx28/regs-base.h
new file mode 100644
index 0000000..dbdcc2b
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-base.h
@@ -0,0 +1,88 @@
+/*
+ * Freescale i.MX28 Peripheral Base Addresses
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright (C) 2008 Embedded Alley Solutions Inc.
+ *
+ * (C) Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __MX28_REGS_BASE_H__
+#define __MX28_REGS_BASE_H__
+
+/*
+ * Register base address
+ */
+#define	MXS_ICOL_BASE		0x80000000
+#define	MXS_HSADC_BASE		0x80002000
+#define	MXS_APBH_BASE		0x80004000
+#define	MXS_PERFMON_BASE	0x80006000
+#define	MXS_BCH_BASE		0x8000A000
+#define	MXS_GPMI_BASE		0x8000C000
+#define	MXS_SSP0_BASE		0x80010000
+#define	MXS_SSP1_BASE		0x80012000
+#define	MXS_SSP2_BASE		0x80014000
+#define	MXS_SSP3_BASE		0x80016000
+#define	MXS_PINCTRL_BASE	0x80018000
+#define	MXS_DIGCTL_BASE		0x8001C000
+#define	MXS_ETM_BASE		0x80022000
+#define	MXS_APBX_BASE		0x80024000
+#define	MXS_DCP_BASE		0x80028000
+#define	MXS_PXP_BASE		0x8002A000
+#define	MXS_OCOTP_BASE		0x8002C000
+#define	MXS_AXI_AHB0_BASE	0x8002E000
+#define	MXS_LCDIF_BASE		0x80030000
+#define	MXS_CAN0_BASE		0x80032000
+#define	MXS_CAN1_BASE		0x80034000
+#define	MXS_SIMDBG_BASE		0x8003C000
+#define	MXS_SIMGPMISEL_BASE	0x8003C200
+#define	MXS_SIMSSPSEL_BASE	0x8003C300
+#define	MXS_SIMMEMSEL_BASE	0x8003C400
+#define	MXS_GPIOMON_BASE	0x8003C500
+#define	MXS_SIMENET_BASE	0x8003C700
+#define	MXS_ARMJTAG_BASE	0x8003C800
+#define	MXS_CLKCTRL_BASE	0x80040000
+#define	MXS_SAIF0_BASE		0x80042000
+#define	MXS_POWER_BASE		0x80044000
+#define	MXS_SAIF1_BASE		0x80046000
+#define	MXS_LRADC_BASE		0x80050000
+#define	MXS_SPDIF_BASE		0x80054000
+#define	MXS_RTC_BASE		0x80056000
+#define	MXS_I2C0_BASE		0x80058000
+#define	MXS_I2C1_BASE		0x8005A000
+#define	MXS_PWM_BASE		0x80064000
+#define	MXS_TIMROT_BASE		0x80068000
+#define	MXS_UARTAPP0_BASE	0x8006A000
+#define	MXS_UARTAPP1_BASE	0x8006C000
+#define	MXS_UARTAPP2_BASE	0x8006E000
+#define	MXS_UARTAPP3_BASE	0x80070000
+#define	MXS_UARTAPP4_BASE	0x80072000
+#define	MXS_UARTDBG_BASE	0x80074000
+#define	MXS_USBPHY0_BASE	0x8007C000
+#define	MXS_USBPHY1_BASE	0x8007E000
+#define	MXS_USBCTRL0_BASE	0x80080000
+#define	MXS_USBCTRL1_BASE	0x80090000
+#define	MXS_DFLPT_BASE		0x800C0000
+#define	MXS_DRAM_BASE		0x800E0000
+#define	MXS_ENET0_BASE		0x800F0000
+#define	MXS_ENET1_BASE		0x800F4000
+
+#endif /* __MX28_REGS_BASE_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-bch.h b/arch/arm/include/asm/arch-mx28/regs-bch.h
new file mode 100644
index 0000000..cac0470
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-bch.h
@@ -0,0 +1,230 @@
+/*
+ * Freescale i.MX28 BCH Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_BCH_H__
+#define __MX28_REGS_BCH_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_bch_regs {
+	mx28_reg(hw_bch_ctrl)
+	mx28_reg(hw_bch_status0)
+	mx28_reg(hw_bch_mode)
+	mx28_reg(hw_bch_encodeptr)
+	mx28_reg(hw_bch_dataptr)
+	mx28_reg(hw_bch_metaptr)
+
+	uint32_t	reserved[4];
+
+	mx28_reg(hw_bch_layoutselect)
+	mx28_reg(hw_bch_flash0layout0)
+	mx28_reg(hw_bch_flash0layout1)
+	mx28_reg(hw_bch_flash1layout0)
+	mx28_reg(hw_bch_flash1layout1)
+	mx28_reg(hw_bch_flash2layout0)
+	mx28_reg(hw_bch_flash2layout1)
+	mx28_reg(hw_bch_flash3layout0)
+	mx28_reg(hw_bch_flash3layout1)
+	mx28_reg(hw_bch_dbgkesread)
+	mx28_reg(hw_bch_dbgcsferead)
+	mx28_reg(hw_bch_dbgsyndegread)
+	mx28_reg(hw_bch_dbgahbmread)
+	mx28_reg(hw_bch_blockname)
+	mx28_reg(hw_bch_version)
+};
+#endif
+
+#define	BCH_CTRL_SFTRST					(1 << 31)
+#define	BCH_CTRL_CLKGATE				(1 << 30)
+#define	BCH_CTRL_DEBUGSYNDROME				(1 << 22)
+#define	BCH_CTRL_M2M_LAYOUT_MASK			(0x3 << 18)
+#define	BCH_CTRL_M2M_LAYOUT_OFFSET			18
+#define	BCH_CTRL_M2M_ENCODE				(1 << 17)
+#define	BCH_CTRL_M2M_ENABLE				(1 << 16)
+#define	BCH_CTRL_DEBUG_STALL_IRQ_EN			(1 << 10)
+#define	BCH_CTRL_COMPLETE_IRQ_EN			(1 << 8)
+#define	BCH_CTRL_BM_ERROR_IRQ				(1 << 3)
+#define	BCH_CTRL_DEBUG_STALL_IRQ			(1 << 2)
+#define	BCH_CTRL_COMPLETE_IRQ				(1 << 0)
+
+#define	BCH_STATUS0_HANDLE_MASK				(0xfff << 20)
+#define	BCH_STATUS0_HANDLE_OFFSET			20
+#define	BCH_STATUS0_COMPLETED_CE_MASK			(0xf << 16)
+#define	BCH_STATUS0_COMPLETED_CE_OFFSET			16
+#define	BCH_STATUS0_STATUS_BLK0_MASK			(0xff << 8)
+#define	BCH_STATUS0_STATUS_BLK0_OFFSET			8
+#define	BCH_STATUS0_STATUS_BLK0_ZERO			(0x00 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERROR1			(0x01 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERROR2			(0x02 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERROR3			(0x03 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERROR4			(0x04 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_UNCORRECTABLE		(0xfe << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERASED			(0xff << 8)
+#define	BCH_STATUS0_ALLONES				(1 << 4)
+#define	BCH_STATUS0_CORRECTED				(1 << 3)
+#define	BCH_STATUS0_UNCORRECTABLE			(1 << 2)
+
+#define	BCH_MODE_ERASE_THRESHOLD_MASK			0xff
+#define	BCH_MODE_ERASE_THRESHOLD_OFFSET			0
+
+#define	BCH_ENCODEPTR_ADDR_MASK				0xffffffff
+#define	BCH_ENCODEPTR_ADDR_OFFSET			0
+
+#define	BCH_DATAPTR_ADDR_MASK				0xffffffff
+#define	BCH_DATAPTR_ADDR_OFFSET				0
+
+#define	BCH_METAPTR_ADDR_MASK				0xffffffff
+#define	BCH_METAPTR_ADDR_OFFSET				0
+
+#define	BCH_LAYOUTSELECT_CS15_SELECT_MASK		(0x3 << 30)
+#define	BCH_LAYOUTSELECT_CS15_SELECT_OFFSET		30
+#define	BCH_LAYOUTSELECT_CS14_SELECT_MASK		(0x3 << 28)
+#define	BCH_LAYOUTSELECT_CS14_SELECT_OFFSET		28
+#define	BCH_LAYOUTSELECT_CS13_SELECT_MASK		(0x3 << 26)
+#define	BCH_LAYOUTSELECT_CS13_SELECT_OFFSET		26
+#define	BCH_LAYOUTSELECT_CS12_SELECT_MASK		(0x3 << 24)
+#define	BCH_LAYOUTSELECT_CS12_SELECT_OFFSET		24
+#define	BCH_LAYOUTSELECT_CS11_SELECT_MASK		(0x3 << 22)
+#define	BCH_LAYOUTSELECT_CS11_SELECT_OFFSET		22
+#define	BCH_LAYOUTSELECT_CS10_SELECT_MASK		(0x3 << 20)
+#define	BCH_LAYOUTSELECT_CS10_SELECT_OFFSET		20
+#define	BCH_LAYOUTSELECT_CS9_SELECT_MASK		(0x3 << 18)
+#define	BCH_LAYOUTSELECT_CS9_SELECT_OFFSET		18
+#define	BCH_LAYOUTSELECT_CS8_SELECT_MASK		(0x3 << 16)
+#define	BCH_LAYOUTSELECT_CS8_SELECT_OFFSET		16
+#define	BCH_LAYOUTSELECT_CS7_SELECT_MASK		(0x3 << 14)
+#define	BCH_LAYOUTSELECT_CS7_SELECT_OFFSET		14
+#define	BCH_LAYOUTSELECT_CS6_SELECT_MASK		(0x3 << 12)
+#define	BCH_LAYOUTSELECT_CS6_SELECT_OFFSET		12
+#define	BCH_LAYOUTSELECT_CS5_SELECT_MASK		(0x3 << 10)
+#define	BCH_LAYOUTSELECT_CS5_SELECT_OFFSET		10
+#define	BCH_LAYOUTSELECT_CS4_SELECT_MASK		(0x3 << 8)
+#define	BCH_LAYOUTSELECT_CS4_SELECT_OFFSET		8
+#define	BCH_LAYOUTSELECT_CS3_SELECT_MASK		(0x3 << 6)
+#define	BCH_LAYOUTSELECT_CS3_SELECT_OFFSET		6
+#define	BCH_LAYOUTSELECT_CS2_SELECT_MASK		(0x3 << 4)
+#define	BCH_LAYOUTSELECT_CS2_SELECT_OFFSET		4
+#define	BCH_LAYOUTSELECT_CS1_SELECT_MASK		(0x3 << 2)
+#define	BCH_LAYOUTSELECT_CS1_SELECT_OFFSET		2
+#define	BCH_LAYOUTSELECT_CS0_SELECT_MASK		(0x3 << 0)
+#define	BCH_LAYOUTSELECT_CS0_SELECT_OFFSET		0
+
+#define	BCH_FLASHLAYOUT0_NBLOCKS_MASK			(0xff << 24)
+#define	BCH_FLASHLAYOUT0_NBLOCKS_OFFSET			24
+#define	BCH_FLASHLAYOUT0_META_SIZE_MASK			(0xff << 16)
+#define	BCH_FLASHLAYOUT0_META_SIZE_OFFSET		16
+#define	BCH_FLASHLAYOUT0_ECC0_MASK			(0xf << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_OFFSET			12
+#define	BCH_FLASHLAYOUT0_ECC0_NONE			(0x0 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC2			(0x1 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC4			(0x2 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC6			(0x3 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC8			(0x4 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC10			(0x5 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC12			(0x6 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC14			(0x7 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC16			(0x8 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC18			(0x9 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC20			(0xa << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC22			(0xb << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC24			(0xc << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC26			(0xd << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC28			(0xe << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC30			(0xf << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC32			(0x10 << 12)
+#define	BCH_FLASHLAYOUT0_GF13_0_GF14_1			(1 << 10)
+#define	BCH_FLASHLAYOUT0_DATA0_SIZE_MASK		0xfff
+#define	BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET		0
+
+#define	BCH_FLASHLAYOUT1_PAGE_SIZE_MASK			(0xffff << 16)
+#define	BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET		16
+#define	BCH_FLASHLAYOUT1_ECCN_MASK			(0xf << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_OFFSET			12
+#define	BCH_FLASHLAYOUT1_ECCN_NONE			(0x0 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC2			(0x1 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC4			(0x2 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC6			(0x3 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC8			(0x4 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC10			(0x5 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC12			(0x6 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC14			(0x7 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC16			(0x8 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC18			(0x9 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC20			(0xa << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC22			(0xb << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC24			(0xc << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC26			(0xd << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC28			(0xe << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC30			(0xf << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC32			(0x10 << 12)
+#define	BCH_FLASHLAYOUT1_GF13_0_GF14_1			(1 << 10)
+#define	BCH_FLASHLAYOUT1_DATAN_SIZE_MASK		0xfff
+#define	BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET		0
+
+#define	BCH_DEBUG0_RSVD1_MASK				(0x1f << 27)
+#define	BCH_DEBUG0_RSVD1_OFFSET				27
+#define	BCH_DEBUG0_ROM_BIST_ENABLE			(1 << 26)
+#define	BCH_DEBUG0_ROM_BIST_COMPLETE			(1 << 25)
+#define	BCH_DEBUG0_KES_DEBUG_SYNDROME_SYMBOL_MASK	(0x1ff << 16)
+#define	BCH_DEBUG0_KES_DEBUG_SYNDROME_SYMBOL_OFFSET	16
+#define	BCH_DEBUG0_KES_DEBUG_SYNDROME_SYMBOL_NORMAL	(0x0 << 16)
+#define	BCH_DEBUG0_KES_DEBUG_SYNDROME_SYMBOL_TEST_MODE	(0x1 << 16)
+#define	BCH_DEBUG0_KES_DEBUG_SHIFT_SYND			(1 << 15)
+#define	BCH_DEBUG0_KES_DEBUG_PAYLOAD_FLAG		(1 << 14)
+#define	BCH_DEBUG0_KES_DEBUG_MODE4K			(1 << 13)
+#define	BCH_DEBUG0_KES_DEBUG_KICK			(1 << 12)
+#define	BCH_DEBUG0_KES_STANDALONE			(1 << 11)
+#define	BCH_DEBUG0_KES_DEBUG_STEP			(1 << 10)
+#define	BCH_DEBUG0_KES_DEBUG_STALL			(1 << 9)
+#define	BCH_DEBUG0_BM_KES_TEST_BYPASS			(1 << 8)
+#define	BCH_DEBUG0_RSVD0_MASK				(0x3 << 6)
+#define	BCH_DEBUG0_RSVD0_OFFSET				6
+#define	BCH_DEBUG0_DEBUG_REG_SELECT_MASK		0x3f
+#define	BCH_DEBUG0_DEBUG_REG_SELECT_OFFSET		0
+
+#define	BCH_DBGKESREAD_VALUES_MASK			0xffffffff
+#define	BCH_DBGKESREAD_VALUES_OFFSET			0
+
+#define	BCH_DBGCSFEREAD_VALUES_MASK			0xffffffff
+#define	BCH_DBGCSFEREAD_VALUES_OFFSET			0
+
+#define	BCH_DBGSYNDGENREAD_VALUES_MASK			0xffffffff
+#define	BCH_DBGSYNDGENREAD_VALUES_OFFSET		0
+
+#define	BCH_DBGAHBMREAD_VALUES_MASK			0xffffffff
+#define	BCH_DBGAHBMREAD_VALUES_OFFSET			0
+
+#define	BCH_BLOCKNAME_NAME_MASK				0xffffffff
+#define	BCH_BLOCKNAME_NAME_OFFSET			0
+
+#define	BCH_VERSION_MAJOR_MASK				(0xff << 24)
+#define	BCH_VERSION_MAJOR_OFFSET			24
+#define	BCH_VERSION_MINOR_MASK				(0xff << 16)
+#define	BCH_VERSION_MINOR_OFFSET			16
+#define	BCH_VERSION_STEP_MASK				0xffff
+#define	BCH_VERSION_STEP_OFFSET				0
+
+#endif	/* __MX28_REGS_BCH_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-clkctrl.h b/arch/arm/include/asm/arch-mx28/regs-clkctrl.h
new file mode 100644
index 0000000..93d0397
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-clkctrl.h
@@ -0,0 +1,312 @@
+/*
+ * Freescale i.MX28 CLKCTRL Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_CLKCTRL_H__
+#define __MX28_REGS_CLKCTRL_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_clkctrl_regs {
+	mx28_reg(hw_clkctrl_pll0ctrl0)		/* 0x00 */
+	mx28_reg(hw_clkctrl_pll0ctrl1)		/* 0x10 */
+	mx28_reg(hw_clkctrl_pll1ctrl0)		/* 0x20 */
+	mx28_reg(hw_clkctrl_pll1ctrl1)		/* 0x30 */
+	mx28_reg(hw_clkctrl_pll2ctrl0)		/* 0x40 */
+	mx28_reg(hw_clkctrl_cpu)		/* 0x50 */
+	mx28_reg(hw_clkctrl_hbus)		/* 0x60 */
+	mx28_reg(hw_clkctrl_xbus)		/* 0x70 */
+	mx28_reg(hw_clkctrl_xtal)		/* 0x80 */
+	mx28_reg(hw_clkctrl_ssp0)		/* 0x90 */
+	mx28_reg(hw_clkctrl_ssp1)		/* 0xa0 */
+	mx28_reg(hw_clkctrl_ssp2)		/* 0xb0 */
+	mx28_reg(hw_clkctrl_ssp3)		/* 0xc0 */
+	mx28_reg(hw_clkctrl_gpmi)		/* 0xd0 */
+	mx28_reg(hw_clkctrl_spdif)		/* 0xe0 */
+	mx28_reg(hw_clkctrl_emi)		/* 0xf0 */
+	mx28_reg(hw_clkctrl_saif0)		/* 0x100 */
+	mx28_reg(hw_clkctrl_saif1)		/* 0x110 */
+	mx28_reg(hw_clkctrl_lcdif)		/* 0x120 */
+	mx28_reg(hw_clkctrl_etm)		/* 0x130 */
+	mx28_reg(hw_clkctrl_enet)		/* 0x140 */
+	mx28_reg(hw_clkctrl_hsadc)		/* 0x150 */
+	mx28_reg(hw_clkctrl_flexcan)		/* 0x160 */
+
+	uint32_t	reserved[16];
+
+	mx28_reg(hw_clkctrl_frac0)		/* 0x1b0 */
+	mx28_reg(hw_clkctrl_frac1)		/* 0x1c0 */
+	mx28_reg(hw_clkctrl_clkseq)		/* 0x1d0 */
+	mx28_reg(hw_clkctrl_reset)		/* 0x1e0 */
+	mx28_reg(hw_clkctrl_status)		/* 0x1f0 */
+	mx28_reg(hw_clkctrl_version)		/* 0x200 */
+};
+#endif
+
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_MASK		(0x3 << 28)
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_OFFSET	28
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_DEFAULT	(0x0 << 28)
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_TIMES_2	(0x1 << 28)
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_TIMES_05	(0x2 << 28)
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_UNDEFINED	(0x3 << 28)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_MASK		(0x3 << 24)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_OFFSET		24
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_DEFAULT	(0x0 << 24)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_TIMES_2	(0x1 << 24)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_TIMES_05	(0x2 << 24)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_UNDEFINED	(0x3 << 24)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_MASK		(0x3 << 20)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_OFFSET	20
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_DEFAULT	(0x0 << 20)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_LOWER		(0x1 << 20)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_LOWEST	(0x2 << 20)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_UNDEFINED	(0x3 << 20)
+#define	CLKCTRL_PLL0CTRL0_EN_USB_CLKS		(1 << 18)
+#define	CLKCTRL_PLL0CTRL0_POWER			(1 << 17)
+
+#define	CLKCTRL_PLL0CTRL1_LOCK			(1 << 31)
+#define	CLKCTRL_PLL0CTRL1_FORCE_LOCK		(1 << 30)
+#define	CLKCTRL_PLL0CTRL1_LOCK_COUNT_MASK	0xffff
+#define	CLKCTRL_PLL0CTRL1_LOCK_COUNT_OFFSET	0
+
+#define	CLKCTRL_PLL1CTRL0_CLKGATEEMI		(1 << 31)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_MASK		(0x3 << 28)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_OFFSET	28
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_DEFAULT	(0x0 << 28)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_TIMES_2	(0x1 << 28)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_TIMES_05	(0x2 << 28)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_UNDEFINED	(0x3 << 28)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_MASK		(0x3 << 24)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_OFFSET		24
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_DEFAULT	(0x0 << 24)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_TIMES_2	(0x1 << 24)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_TIMES_05	(0x2 << 24)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_UNDEFINED	(0x3 << 24)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_MASK		(0x3 << 20)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_OFFSET	20
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_DEFAULT	(0x0 << 20)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_LOWER		(0x1 << 20)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_LOWEST	(0x2 << 20)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_UNDEFINED	(0x3 << 20)
+#define	CLKCTRL_PLL1CTRL0_EN_USB_CLKS		(1 << 18)
+#define	CLKCTRL_PLL1CTRL0_POWER			(1 << 17)
+
+#define	CLKCTRL_PLL1CTRL1_LOCK			(1 << 31)
+#define	CLKCTRL_PLL1CTRL1_FORCE_LOCK		(1 << 30)
+#define	CLKCTRL_PLL1CTRL1_LOCK_COUNT_MASK	0xffff
+#define	CLKCTRL_PLL1CTRL1_LOCK_COUNT_OFFSET	0
+
+#define	CLKCTRL_PLL2CTRL0_CLKGATE		(1 << 31)
+#define	CLKCTRL_PLL2CTRL0_LFR_SEL_MASK		(0x3 << 28)
+#define	CLKCTRL_PLL2CTRL0_LFR_SEL_OFFSET	28
+#define	CLKCTRL_PLL2CTRL0_HOLD_RING_OFF_B	(1 << 26)
+#define	CLKCTRL_PLL2CTRL0_CP_SEL_MASK		(0x3 << 24)
+#define	CLKCTRL_PLL2CTRL0_CP_SEL_OFFSET		24
+#define	CLKCTRL_PLL2CTRL0_POWER			(1 << 23)
+
+#define	CLKCTRL_CPU_BUSY_REF_XTAL		(1 << 29)
+#define	CLKCTRL_CPU_BUSY_REF_CPU		(1 << 28)
+#define	CLKCTRL_CPU_DIV_XTAL_FRAC_EN		(1 << 26)
+#define	CLKCTRL_CPU_DIV_XTAL_MASK		(0x3ff << 16)
+#define	CLKCTRL_CPU_DIV_XTAL_OFFSET		16
+#define	CLKCTRL_CPU_INTERRUPT_WAIT		(1 << 12)
+#define	CLKCTRL_CPU_DIV_CPU_FRAC_EN		(1 << 10)
+#define	CLKCTRL_CPU_DIV_CPU_MASK		0x3f
+#define	CLKCTRL_CPU_DIV_CPU_OFFSET		0
+
+#define	CLKCTRL_HBUS_ASM_BUSY			(1 << 31)
+#define	CLKCTRL_HBUS_DCP_AS_ENABLE		(1 << 30)
+#define	CLKCTRL_HBUS_PXP_AS_ENABLE		(1 << 29)
+#define	CLKCTRL_HBUS_ASM_EMIPORT_AS_ENABLE	(1 << 27)
+#define	CLKCTRL_HBUS_APBHDMA_AS_ENABLE		(1 << 26)
+#define	CLKCTRL_HBUS_APBXDMA_AS_ENABLE		(1 << 25)
+#define	CLKCTRL_HBUS_TRAFFIC_JAM_AS_ENABLE	(1 << 24)
+#define	CLKCTRL_HBUS_TRAFFIC_AS_ENABLE		(1 << 23)
+#define	CLKCTRL_HBUS_CPU_DATA_AS_ENABLE		(1 << 22)
+#define	CLKCTRL_HBUS_CPU_INSTR_AS_ENABLE	(1 << 21)
+#define	CLKCTRL_HBUS_ASM_ENABLE			(1 << 20)
+#define	CLKCTRL_HBUS_AUTO_CLEAR_DIV_ENABLE	(1 << 19)
+#define	CLKCTRL_HBUS_SLOW_DIV_MASK		(0x7 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_OFFSET		16
+#define	CLKCTRL_HBUS_SLOW_DIV_BY1		(0x0 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY2		(0x1 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY4		(0x2 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY8		(0x3 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY16		(0x4 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY32		(0x5 << 16)
+#define	CLKCTRL_HBUS_DIV_FRAC_EN		(1 << 5)
+#define	CLKCTRL_HBUS_DIV_MASK			0x1f
+#define	CLKCTRL_HBUS_DIV_OFFSET			0
+
+#define	CLKCTRL_XBUS_BUSY			(1 << 31)
+#define	CLKCTRL_XBUS_AUTO_CLEAR_DIV_ENABLE	(1 << 11)
+#define	CLKCTRL_XBUS_DIV_FRAC_EN		(1 << 10)
+#define	CLKCTRL_XBUS_DIV_MASK			0x3ff
+#define	CLKCTRL_XBUS_DIV_OFFSET			0
+
+#define	CLKCTRL_XTAL_UART_CLK_GATE		(1 << 31)
+#define	CLKCTRL_XTAL_PWM_CLK24M_GATE		(1 << 29)
+#define	CLKCTRL_XTAL_TIMROT_CLK32K_GATE		(1 << 26)
+#define	CLKCTRL_XTAL_DIV_UART_MASK		0x3
+#define	CLKCTRL_XTAL_DIV_UART_OFFSET		0
+
+#define	CLKCTRL_SSP_CLKGATE			(1 << 31)
+#define	CLKCTRL_SSP_BUSY			(1 << 29)
+#define	CLKCTRL_SSP_DIV_FRAC_EN			(1 << 9)
+#define	CLKCTRL_SSP_DIV_MASK			0x1ff
+#define	CLKCTRL_SSP_DIV_OFFSET			0
+
+#define	CLKCTRL_GPMI_CLKGATE			(1 << 31)
+#define	CLKCTRL_GPMI_BUSY			(1 << 29)
+#define	CLKCTRL_GPMI_DIV_FRAC_EN		(1 << 10)
+#define	CLKCTRL_GPMI_DIV_MASK			0x3ff
+#define	CLKCTRL_GPMI_DIV_OFFSET			0
+
+#define	CLKCTRL_SPDIF_CLKGATE			(1 << 31)
+
+#define	CLKCTRL_EMI_CLKGATE			(1 << 31)
+#define	CLKCTRL_EMI_SYNC_MODE_EN		(1 << 30)
+#define	CLKCTRL_EMI_BUSY_REF_XTAL		(1 << 29)
+#define	CLKCTRL_EMI_BUSY_REF_EMI		(1 << 28)
+#define	CLKCTRL_EMI_BUSY_REF_CPU		(1 << 27)
+#define	CLKCTRL_EMI_BUSY_SYNC_MODE		(1 << 26)
+#define	CLKCTRL_EMI_BUSY_DCC_RESYNC		(1 << 17)
+#define	CLKCTRL_EMI_DCC_RESYNC_ENABLE		(1 << 16)
+#define	CLKCTRL_EMI_DIV_XTAL_MASK		(0xf << 8)
+#define	CLKCTRL_EMI_DIV_XTAL_OFFSET		8
+#define	CLKCTRL_EMI_DIV_EMI_MASK		0x3f
+#define	CLKCTRL_EMI_DIV_EMI_OFFSET		0
+
+#define	CLKCTRL_SAIF0_CLKGATE			(1 << 31)
+#define	CLKCTRL_SAIF0_BUSY			(1 << 29)
+#define	CLKCTRL_SAIF0_DIV_FRAC_EN		(1 << 16)
+#define	CLKCTRL_SAIF0_DIV_MASK			0xffff
+#define	CLKCTRL_SAIF0_DIV_OFFSET		0
+
+#define	CLKCTRL_SAIF1_CLKGATE			(1 << 31)
+#define	CLKCTRL_SAIF1_BUSY			(1 << 29)
+#define	CLKCTRL_SAIF1_DIV_FRAC_EN		(1 << 16)
+#define	CLKCTRL_SAIF1_DIV_MASK			0xffff
+#define	CLKCTRL_SAIF1_DIV_OFFSET		0
+
+#define	CLKCTRL_DIS_LCDIF_CLKGATE		(1 << 31)
+#define	CLKCTRL_DIS_LCDIF_BUSY			(1 << 29)
+#define	CLKCTRL_DIS_LCDIF_DIV_FRAC_EN		(1 << 13)
+#define	CLKCTRL_DIS_LCDIF_DIV_MASK		0x1fff
+#define	CLKCTRL_DIS_LCDIF_DIV_OFFSET		0
+
+#define	CLKCTRL_ETM_CLKGATE			(1 << 31)
+#define	CLKCTRL_ETM_BUSY			(1 << 29)
+#define	CLKCTRL_ETM_DIV_FRAC_EN			(1 << 7)
+#define	CLKCTRL_ETM_DIV_MASK			0x7f
+#define	CLKCTRL_ETM_DIV_OFFSET			0
+
+#define	CLKCTRL_ENET_SLEEP			(1 << 31)
+#define	CLKCTRL_ENET_DISABLE			(1 << 30)
+#define	CLKCTRL_ENET_STATUS			(1 << 29)
+#define	CLKCTRL_ENET_BUSY_TIME			(1 << 27)
+#define	CLKCTRL_ENET_DIV_TIME_MASK		(0x3f << 21)
+#define	CLKCTRL_ENET_DIV_TIME_OFFSET		21
+#define	CLKCTRL_ENET_TIME_SEL_MASK		(0x3 << 19)
+#define	CLKCTRL_ENET_TIME_SEL_OFFSET		19
+#define	CLKCTRL_ENET_TIME_SEL_XTAL		(0x0 << 19)
+#define	CLKCTRL_ENET_TIME_SEL_PLL		(0x1 << 19)
+#define	CLKCTRL_ENET_TIME_SEL_RMII_CLK		(0x2 << 19)
+#define	CLKCTRL_ENET_TIME_SEL_UNDEFINED		(0x3 << 19)
+#define	CLKCTRL_ENET_CLK_OUT_EN			(1 << 18)
+#define	CLKCTRL_ENET_RESET_BY_SW_CHIP		(1 << 17)
+#define	CLKCTRL_ENET_RESET_BY_SW		(1 << 16)
+
+#define	CLKCTRL_HSADC_RESETB			(1 << 30)
+#define	CLKCTRL_HSADC_FREQDIV_MASK		(0x3 << 28)
+#define	CLKCTRL_HSADC_FREQDIV_OFFSET		28
+
+#define	CLKCTRL_FLEXCAN_STOP_CAN0		(1 << 30)
+#define	CLKCTRL_FLEXCAN_CAN0_STATUS		(1 << 29)
+#define	CLKCTRL_FLEXCAN_STOP_CAN1		(1 << 28)
+#define	CLKCTRL_FLEXCAN_CAN1_STATUS		(1 << 27)
+
+#define	CLKCTRL_FRAC0_CLKGATEIO0		(1 << 31)
+#define	CLKCTRL_FRAC0_IO0_STABLE		(1 << 30)
+#define	CLKCTRL_FRAC0_IO0FRAC_MASK		(0x3f << 24)
+#define	CLKCTRL_FRAC0_IO0FRAC_OFFSET		24
+#define	CLKCTRL_FRAC0_CLKGATEIO1		(1 << 23)
+#define	CLKCTRL_FRAC0_IO1_STABLE		(1 << 22)
+#define	CLKCTRL_FRAC0_IO1FRAC_MASK		(0x3f << 16)
+#define	CLKCTRL_FRAC0_IO1FRAC_OFFSET		16
+#define	CLKCTRL_FRAC0_CLKGATEEMI		(1 << 15)
+#define	CLKCTRL_FRAC0_EMI_STABLE		(1 << 14)
+#define	CLKCTRL_FRAC0_EMIFRAC_MASK		(0x3f << 8)
+#define	CLKCTRL_FRAC0_EMIFRAC_OFFSET		8
+#define	CLKCTRL_FRAC0_CLKGATECPU		(1 << 7)
+#define	CLKCTRL_FRAC0_CPU_STABLE		(1 << 6)
+#define	CLKCTRL_FRAC0_CPUFRAC_MASK		0x3f
+#define	CLKCTRL_FRAC0_CPUFRAC_OFFSET		0
+
+#define	CLKCTRL_FRAC1_CLKGATEGPMI		(1 << 23)
+#define	CLKCTRL_FRAC1_GPMI_STABLE		(1 << 22)
+#define	CLKCTRL_FRAC1_GPMIFRAC_MASK		(0x3f << 16)
+#define	CLKCTRL_FRAC1_GPMIFRAC_OFFSET		16
+#define	CLKCTRL_FRAC1_CLKGATEHSADC		(1 << 15)
+#define	CLKCTRL_FRAC1_HSADC_STABLE		(1 << 14)
+#define	CLKCTRL_FRAC1_HSADCFRAC_MASK		(0x3f << 8)
+#define	CLKCTRL_FRAC1_HSADCFRAC_OFFSET		8
+#define	CLKCTRL_FRAC1_CLKGATEPIX		(1 << 7)
+#define	CLKCTRL_FRAC1_PIX_STABLE		(1 << 6)
+#define	CLKCTRL_FRAC1_PIXFRAC_MASK		0x3f
+#define	CLKCTRL_FRAC1_PIXFRAC_OFFSET		0
+
+#define	CLKCTRL_CLKSEQ_BYPASS_CPU		(1 << 18)
+#define	CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF		(1 << 14)
+#define	CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF_BYPASS	(0x1 << 14)
+#define	CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF_PFD	(0x0 << 14)
+#define	CLKCTRL_CLKSEQ_BYPASS_ETM		(1 << 8)
+#define	CLKCTRL_CLKSEQ_BYPASS_EMI		(1 << 7)
+#define	CLKCTRL_CLKSEQ_BYPASS_SSP3		(1 << 6)
+#define	CLKCTRL_CLKSEQ_BYPASS_SSP2		(1 << 5)
+#define	CLKCTRL_CLKSEQ_BYPASS_SSP1		(1 << 4)
+#define	CLKCTRL_CLKSEQ_BYPASS_SSP0		(1 << 3)
+#define	CLKCTRL_CLKSEQ_BYPASS_GPMI		(1 << 2)
+#define	CLKCTRL_CLKSEQ_BYPASS_SAIF1		(1 << 1)
+#define	CLKCTRL_CLKSEQ_BYPASS_SAIF0		(1 << 0)
+
+#define	CLKCTRL_RESET_WDOG_POR_DISABLE		(1 << 5)
+#define	CLKCTRL_RESET_EXTERNAL_RESET_ENABLE	(1 << 4)
+#define	CLKCTRL_RESET_THERMAL_RESET_ENABLE	(1 << 3)
+#define	CLKCTRL_RESET_THERMAL_RESET_DEFAULT	(1 << 2)
+#define	CLKCTRL_RESET_CHIP			(1 << 1)
+#define	CLKCTRL_RESET_DIG			(1 << 0)
+
+#define	CLKCTRL_STATUS_CPU_LIMIT_MASK		(0x3 << 30)
+#define	CLKCTRL_STATUS_CPU_LIMIT_OFFSET		30
+
+#define	CLKCTRL_VERSION_MAJOR_MASK		(0xff << 24)
+#define	CLKCTRL_VERSION_MAJOR_OFFSET		24
+#define	CLKCTRL_VERSION_MINOR_MASK		(0xff << 16)
+#define	CLKCTRL_VERSION_MINOR_OFFSET		16
+#define	CLKCTRL_VERSION_STEP_MASK		0xffff
+#define	CLKCTRL_VERSION_STEP_OFFSET		0
+
+#endif /* __MX28_REGS_CLKCTRL_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-common.h b/arch/arm/include/asm/arch-mx28/regs-common.h
new file mode 100644
index 0000000..efe975b
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-common.h
@@ -0,0 +1,66 @@
+/*
+ * Freescale i.MX28 Register Accessors
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_COMMON_H__
+#define __MX28_REGS_COMMON_H__
+
+/*
+ * The i.MX28 has interesting feature when it comes to register access. There
+ * are four kinds of access to one particular register. Those are:
+ *
+ * 1) Common read/write access. To use this mode, just write to the address of
+ *    the register.
+ * 2) Set bits only access. To set bits, write which bits you want to set to the
+ *    address of the register + 0x4.
+ * 3) Clear bits only access. To clear bits, write which bits you want to clear
+ *    to the address of the register + 0x8.
+ * 4) Toggle bits only access. To toggle bits, write which bits you want to
+ *    toggle to the address of the register + 0xc.
+ *
+ * IMPORTANT NOTE: Not all registers support accesses 2-4! Also, not all bits
+ * can be set/cleared by pure write as in access type 1, some need to be
+ * explicitly set/cleared by using access type 2-3.
+ *
+ * The following macros and structures allow the user to either access the
+ * register in all aforementioned modes (by accessing reg_name, reg_name_set,
+ * reg_name_clr, reg_name_tog) or pass the register structure further into
+ * various functions with correct type information (by accessing reg_name_reg).
+ *
+ */
+
+#define	__mx28_reg(name)		\
+	uint32_t name;			\
+	uint32_t name##_set;		\
+	uint32_t name##_clr;		\
+	uint32_t name##_tog;
+
+struct mx28_register {
+	__mx28_reg(reg)
+};
+
+#define	mx28_reg(name)					\
+	union {						\
+		struct { __mx28_reg(name) };		\
+		struct mx28_register name##_reg;	\
+	};
+
+#endif	/* __MX28_REGS_COMMON_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-gpmi.h b/arch/arm/include/asm/arch-mx28/regs-gpmi.h
new file mode 100644
index 0000000..0096793
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-gpmi.h
@@ -0,0 +1,222 @@
+/*
+ * Freescale i.MX28 GPMI Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_GPMI_H__
+#define __MX28_REGS_GPMI_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_gpmi_regs {
+	mx28_reg(hw_gpmi_ctrl0)
+	mx28_reg(hw_gpmi_compare)
+	mx28_reg(hw_gpmi_eccctrl)
+	mx28_reg(hw_gpmi_ecccount)
+	mx28_reg(hw_gpmi_payload)
+	mx28_reg(hw_gpmi_auxiliary)
+	mx28_reg(hw_gpmi_ctrl1)
+	mx28_reg(hw_gpmi_timing0)
+	mx28_reg(hw_gpmi_timing1)
+
+	uint32_t	reserved[4];
+
+	mx28_reg(hw_gpmi_data)
+	mx28_reg(hw_gpmi_stat)
+	mx28_reg(hw_gpmi_debug)
+	mx28_reg(hw_gpmi_version)
+};
+#endif
+
+#define	GPMI_CTRL0_SFTRST				(1 << 31)
+#define	GPMI_CTRL0_CLKGATE				(1 << 30)
+#define	GPMI_CTRL0_RUN					(1 << 29)
+#define	GPMI_CTRL0_DEV_IRQ_EN				(1 << 28)
+#define	GPMI_CTRL0_LOCK_CS				(1 << 27)
+#define	GPMI_CTRL0_UDMA					(1 << 26)
+#define	GPMI_CTRL0_COMMAND_MODE_MASK			(0x3 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_OFFSET			24
+#define	GPMI_CTRL0_COMMAND_MODE_WRITE			(0x0 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_READ			(0x1 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_READ_AND_COMPARE	(0x2 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY		(0x3 << 24)
+#define	GPMI_CTRL0_WORD_LENGTH				(1 << 23)
+#define	GPMI_CTRL0_CS_MASK				(0x7 << 20)
+#define	GPMI_CTRL0_CS_OFFSET				20
+#define	GPMI_CTRL0_ADDRESS_MASK				(0x7 << 17)
+#define	GPMI_CTRL0_ADDRESS_OFFSET			17
+#define	GPMI_CTRL0_ADDRESS_NAND_DATA			(0x0 << 17)
+#define	GPMI_CTRL0_ADDRESS_NAND_CLE			(0x1 << 17)
+#define	GPMI_CTRL0_ADDRESS_NAND_ALE			(0x2 << 17)
+#define	GPMI_CTRL0_ADDRESS_INCREMENT			(1 << 16)
+#define	GPMI_CTRL0_XFER_COUNT_MASK			0xffff
+#define	GPMI_CTRL0_XFER_COUNT_OFFSET			0
+
+#define	GPMI_COMPARE_MASK_MASK				(0xffff << 16)
+#define	GPMI_COMPARE_MASK_OFFSET			16
+#define	GPMI_COMPARE_REFERENCE_MASK			0xffff
+#define	GPMI_COMPARE_REFERENCE_OFFSET			0
+
+#define	GPMI_ECCCTRL_HANDLE_MASK			(0xffff << 16)
+#define	GPMI_ECCCTRL_HANDLE_OFFSET			16
+#define	GPMI_ECCCTRL_ECC_CMD_MASK			(0x3 << 13)
+#define	GPMI_ECCCTRL_ECC_CMD_OFFSET			13
+#define	GPMI_ECCCTRL_ECC_CMD_DECODE			(0x0 << 13)
+#define	GPMI_ECCCTRL_ECC_CMD_ENCODE			(0x1 << 13)
+#define	GPMI_ECCCTRL_ENABLE_ECC				(1 << 12)
+#define	GPMI_ECCCTRL_BUFFER_MASK_MASK			0x1ff
+#define	GPMI_ECCCTRL_BUFFER_MASK_OFFSET			0
+#define	GPMI_ECCCTRL_BUFFER_MASK_BCH_AUXONLY		0x100
+#define	GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE		0x1ff
+
+#define	GPMI_ECCCOUNT_COUNT_MASK			0xffff
+#define	GPMI_ECCCOUNT_COUNT_OFFSET			0
+
+#define	GPMI_PAYLOAD_ADDRESS_MASK			(0x3fffffff << 2)
+#define	GPMI_PAYLOAD_ADDRESS_OFFSET			2
+
+#define	GPMI_AUXILIARY_ADDRESS_MASK			(0x3fffffff << 2)
+#define	GPMI_AUXILIARY_ADDRESS_OFFSET			2
+
+#define	GPMI_CTRL1_DECOUPLE_CS				(1 << 24)
+#define	GPMI_CTRL1_WRN_DLY_SEL_MASK			(0x3 << 22)
+#define	GPMI_CTRL1_WRN_DLY_SEL_OFFSET			22
+#define	GPMI_CTRL1_TIMEOUT_IRQ_EN			(1 << 20)
+#define	GPMI_CTRL1_GANGED_RDYBUSY			(1 << 19)
+#define	GPMI_CTRL1_BCH_MODE				(1 << 18)
+#define	GPMI_CTRL1_DLL_ENABLE				(1 << 17)
+#define	GPMI_CTRL1_HALF_PERIOD				(1 << 16)
+#define	GPMI_CTRL1_RDN_DELAY_MASK			(0xf << 12)
+#define	GPMI_CTRL1_RDN_DELAY_OFFSET			12
+#define	GPMI_CTRL1_DMA2ECC_MODE				(1 << 11)
+#define	GPMI_CTRL1_DEV_IRQ				(1 << 10)
+#define	GPMI_CTRL1_TIMEOUT_IRQ				(1 << 9)
+#define	GPMI_CTRL1_BURST_EN				(1 << 8)
+#define	GPMI_CTRL1_ABORT_WAIT_REQUEST			(1 << 7)
+#define	GPMI_CTRL1_ABORT_WAIT_FOR_READY_CHANNEL_MASK	(0x7 << 4)
+#define	GPMI_CTRL1_ABORT_WAIT_FOR_READY_CHANNEL_OFFSET	4
+#define	GPMI_CTRL1_DEV_RESET				(1 << 3)
+#define	GPMI_CTRL1_ATA_IRQRDY_POLARITY			(1 << 2)
+#define	GPMI_CTRL1_CAMERA_MODE				(1 << 1)
+#define	GPMI_CTRL1_GPMI_MODE				(1 << 0)
+
+#define	GPMI_TIMING0_ADDRESS_SETUP_MASK			(0xff << 16)
+#define	GPMI_TIMING0_ADDRESS_SETUP_OFFSET		16
+#define	GPMI_TIMING0_DATA_HOLD_MASK			(0xff << 8)
+#define	GPMI_TIMING0_DATA_HOLD_OFFSET			8
+#define	GPMI_TIMING0_DATA_SETUP_MASK			0xff
+#define	GPMI_TIMING0_DATA_SETUP_OFFSET			0
+
+#define	GPMI_TIMING1_DEVICE_BUSY_TIMEOUT_MASK		(0xffff << 16)
+#define	GPMI_TIMING1_DEVICE_BUSY_TIMEOUT_OFFSET		16
+
+#define	GPMI_TIMING2_UDMA_TRP_MASK			(0xff << 24)
+#define	GPMI_TIMING2_UDMA_TRP_OFFSET			24
+#define	GPMI_TIMING2_UDMA_ENV_MASK			(0xff << 16)
+#define	GPMI_TIMING2_UDMA_ENV_OFFSET			16
+#define	GPMI_TIMING2_UDMA_HOLD_MASK			(0xff << 8)
+#define	GPMI_TIMING2_UDMA_HOLD_OFFSET			8
+#define	GPMI_TIMING2_UDMA_SETUP_MASK			0xff
+#define	GPMI_TIMING2_UDMA_SETUP_OFFSET			0
+
+#define	GPMI_DATA_DATA_MASK				0xffffffff
+#define	GPMI_DATA_DATA_OFFSET				0
+
+#define	GPMI_STAT_READY_BUSY_MASK			(0xff << 24)
+#define	GPMI_STAT_READY_BUSY_OFFSET			24
+#define	GPMI_STAT_RDY_TIMEOUT_MASK			(0xff << 16)
+#define	GPMI_STAT_RDY_TIMEOUT_OFFSET			16
+#define	GPMI_STAT_DEV7_ERROR				(1 << 15)
+#define	GPMI_STAT_DEV6_ERROR				(1 << 14)
+#define	GPMI_STAT_DEV5_ERROR				(1 << 13)
+#define	GPMI_STAT_DEV4_ERROR				(1 << 12)
+#define	GPMI_STAT_DEV3_ERROR				(1 << 11)
+#define	GPMI_STAT_DEV2_ERROR				(1 << 10)
+#define	GPMI_STAT_DEV1_ERROR				(1 << 9)
+#define	GPMI_STAT_DEV0_ERROR				(1 << 8)
+#define	GPMI_STAT_ATA_IRQ				(1 << 4)
+#define	GPMI_STAT_INVALID_BUFFER_MASK			(1 << 3)
+#define	GPMI_STAT_FIFO_EMPTY				(1 << 2)
+#define	GPMI_STAT_FIFO_FULL				(1 << 1)
+#define	GPMI_STAT_PRESENT				(1 << 0)
+
+#define	GPMI_DEBUG_WAIT_FOR_READY_END_MASK		(0xff << 24)
+#define	GPMI_DEBUG_WAIT_FOR_READY_END_OFFSET		24
+#define	GPMI_DEBUG_DMA_SENSE_MASK			(0xff << 16)
+#define	GPMI_DEBUG_DMA_SENSE_OFFSET			16
+#define	GPMI_DEBUG_DMAREQ_MASK				(0xff << 8)
+#define	GPMI_DEBUG_DMAREQ_OFFSET			8
+#define	GPMI_DEBUG_CMD_END_MASK				0xff
+#define	GPMI_DEBUG_CMD_END_OFFSET			0
+
+#define	GPMI_VERSION_MAJOR_MASK				(0xff << 24)
+#define	GPMI_VERSION_MAJOR_OFFSET			24
+#define	GPMI_VERSION_MINOR_MASK				(0xff << 16)
+#define	GPMI_VERSION_MINOR_OFFSET			16
+#define	GPMI_VERSION_STEP_MASK				0xffff
+#define	GPMI_VERSION_STEP_OFFSET			0
+
+#define	GPMI_DEBUG2_UDMA_STATE_MASK			(0xf << 24)
+#define	GPMI_DEBUG2_UDMA_STATE_OFFSET			24
+#define	GPMI_DEBUG2_BUSY				(1 << 23)
+#define	GPMI_DEBUG2_PIN_STATE_MASK			(0x7 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_OFFSET			20
+#define	GPMI_DEBUG2_PIN_STATE_PSM_IDLE			(0x0 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_BYTCNT		(0x1 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_ADDR			(0x2 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_STALL			(0x3 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_STROBE		(0x4 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_ATARDY		(0x5 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_DHOLD			(0x6 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_DONE			(0x7 << 20)
+#define	GPMI_DEBUG2_MAIN_STATE_MASK			(0xf << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_OFFSET			16
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_IDLE			(0x0 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_BYTCNT		(0x1 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_WAITFE		(0x2 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_WAITFR		(0x3 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_DMAREQ		(0x4 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_DMAACK		(0x5 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_WAITFF		(0x6 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_LDFIFO		(0x7 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_LDDMAR		(0x8 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_RDCMP		(0x9 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_DONE			(0xa << 16)
+#define	GPMI_DEBUG2_SYND2GPMI_BE_MASK			(0xf << 12)
+#define	GPMI_DEBUG2_SYND2GPMI_BE_OFFSET			12
+#define	GPMI_DEBUG2_GPMI2SYND_VALID			(1 << 11)
+#define	GPMI_DEBUG2_GPMI2SYND_READY			(1 << 10)
+#define	GPMI_DEBUG2_SYND2GPMI_VALID			(1 << 9)
+#define	GPMI_DEBUG2_SYND2GPMI_READY			(1 << 8)
+#define	GPMI_DEBUG2_VIEW_DELAYED_RDN			(1 << 7)
+#define	GPMI_DEBUG2_UPDATE_WINDOW			(1 << 6)
+#define	GPMI_DEBUG2_RDN_TAP_MASK			0x3f
+#define	GPMI_DEBUG2_RDN_TAP_OFFSET			0
+
+#define	GPMI_DEBUG3_APB_WORD_CNTR_MASK			(0xffff << 16)
+#define	GPMI_DEBUG3_APB_WORD_CNTR_OFFSET		16
+#define	GPMI_DEBUG3_DEV_WORD_CNTR_MASK			0xffff
+#define	GPMI_DEBUG3_DEV_WORD_CNTR_OFFSET		0
+
+#endif	/* __MX28_REGS_GPMI_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-i2c.h b/arch/arm/include/asm/arch-mx28/regs-i2c.h
new file mode 100644
index 0000000..30e0ed7
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-i2c.h
@@ -0,0 +1,207 @@
+/*
+ * Freescale i.MX28 I2C Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_I2C_H__
+#define __MX28_REGS_I2C_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_i2c_regs {
+	mx28_reg(hw_i2c_ctrl0)
+	mx28_reg(hw_i2c_timing0)
+	mx28_reg(hw_i2c_timing1)
+	mx28_reg(hw_i2c_timing2)
+	mx28_reg(hw_i2c_ctrl1)
+	mx28_reg(hw_i2c_stat)
+	mx28_reg(hw_i2c_queuectrl)
+	mx28_reg(hw_i2c_queuestat)
+	mx28_reg(hw_i2c_queuecmd)
+	mx28_reg(hw_i2c_queuedata)
+	mx28_reg(hw_i2c_data)
+	mx28_reg(hw_i2c_debug0)
+	mx28_reg(hw_i2c_debug1)
+	mx28_reg(hw_i2c_version)
+};
+#endif
+
+#define	I2C_CTRL_SFTRST				(1 << 31)
+#define	I2C_CTRL_CLKGATE			(1 << 30)
+#define	I2C_CTRL_RUN				(1 << 29)
+#define	I2C_CTRL_PREACK				(1 << 27)
+#define	I2C_CTRL_ACKNOWLEDGE			(1 << 26)
+#define	I2C_CTRL_SEND_NAK_ON_LAST		(1 << 25)
+#define	I2C_CTRL_MULTI_MASTER			(1 << 23)
+#define	I2C_CTRL_CLOCK_HELD			(1 << 22)
+#define	I2C_CTRL_RETAIN_CLOCK			(1 << 21)
+#define	I2C_CTRL_POST_SEND_STOP			(1 << 20)
+#define	I2C_CTRL_PRE_SEND_START			(1 << 19)
+#define	I2C_CTRL_SLAVE_ADDRESS_ENABLE		(1 << 18)
+#define	I2C_CTRL_MASTER_MODE			(1 << 17)
+#define	I2C_CTRL_DIRECTION			(1 << 16)
+#define	I2C_CTRL_XFER_COUNT_MASK		0xffff
+#define	I2C_CTRL_XFER_COUNT_OFFSET		0
+
+#define	I2C_TIMING0_HIGH_COUNT_MASK		(0x3ff << 16)
+#define	I2C_TIMING0_HIGH_COUNT_OFFSET		16
+#define	I2C_TIMING0_RCV_COUNT_MASK		0x3ff
+#define	I2C_TIMING0_RCV_COUNT_OFFSET		0
+
+#define	I2C_TIMING1_LOW_COUNT_MASK		(0x3ff << 16)
+#define	I2C_TIMING1_LOW_COUNT_OFFSET		16
+#define	I2C_TIMING1_XMIT_COUNT_MASK		0x3ff
+#define	I2C_TIMING1_XMIT_COUNT_OFFSET		0
+
+#define	I2C_TIMING2_BUS_FREE_MASK		(0x3ff << 16)
+#define	I2C_TIMING2_BUS_FREE_OFFSET		16
+#define	I2C_TIMING2_LEADIN_COUNT_MASK		0x3ff
+#define	I2C_TIMING2_LEADIN_COUNT_OFFSET		0
+
+#define	I2C_CTRL1_RD_QUEUE_IRQ			(1 << 30)
+#define	I2C_CTRL1_WR_QUEUE_IRQ			(1 << 29)
+#define	I2C_CTRL1_CLR_GOT_A_NAK			(1 << 28)
+#define	I2C_CTRL1_ACK_MODE			(1 << 27)
+#define	I2C_CTRL1_FORCE_DATA_IDLE		(1 << 26)
+#define	I2C_CTRL1_FORCE_CLK_IDLE		(1 << 25)
+#define	I2C_CTRL1_BCAST_SLAVE_EN		(1 << 24)
+#define	I2C_CTRL1_SLAVE_ADDRESS_BYTE_MASK	(0xff << 16)
+#define	I2C_CTRL1_SLAVE_ADDRESS_BYTE_OFFSET	16
+#define	I2C_CTRL1_BUS_FREE_IRQ_EN		(1 << 15)
+#define	I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ_EN	(1 << 14)
+#define	I2C_CTRL1_NO_SLAVE_ACK_IRQ_EN		(1 << 13)
+#define	I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ_EN	(1 << 12)
+#define	I2C_CTRL1_EARLY_TERM_IRQ_EN		(1 << 11)
+#define	I2C_CTRL1_MASTER_LOSS_IRQ_EN		(1 << 10)
+#define	I2C_CTRL1_SLAVE_STOP_IRQ_EN		(1 << 9)
+#define	I2C_CTRL1_SLAVE_IRQ_EN			(1 << 8)
+#define	I2C_CTRL1_BUS_FREE_IRQ			(1 << 7)
+#define	I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ		(1 << 6)
+#define	I2C_CTRL1_NO_SLAVE_ACK_IRQ		(1 << 5)
+#define	I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ	(1 << 4)
+#define	I2C_CTRL1_EARLY_TERM_IRQ		(1 << 3)
+#define	I2C_CTRL1_MASTER_LOSS_IRQ		(1 << 2)
+#define	I2C_CTRL1_SLAVE_STOP_IRQ		(1 << 1)
+#define	I2C_CTRL1_SLAVE_IRQ			(1 << 0)
+
+#define	I2C_STAT_MASTER_PRESENT			(1 << 31)
+#define	I2C_STAT_SLAVE_PRESENT			(1 << 30)
+#define	I2C_STAT_ANY_ENABLED_IRQ		(1 << 29)
+#define	I2C_STAT_GOT_A_NAK			(1 << 28)
+#define	I2C_STAT_RCVD_SLAVE_ADDR_MASK		(0xff << 16)
+#define	I2C_STAT_RCVD_SLAVE_ADDR_OFFSET		16
+#define	I2C_STAT_SLAVE_ADDR_EQ_ZERO		(1 << 15)
+#define	I2C_STAT_SLAVE_FOUND			(1 << 14)
+#define	I2C_STAT_SLAVE_SEARCHING		(1 << 13)
+#define	I2C_STAT_DATA_ENGING_DMA_WAIT		(1 << 12)
+#define	I2C_STAT_BUS_BUSY			(1 << 11)
+#define	I2C_STAT_CLK_GEN_BUSY			(1 << 10)
+#define	I2C_STAT_DATA_ENGINE_BUSY		(1 << 9)
+#define	I2C_STAT_SLAVE_BUSY			(1 << 8)
+#define	I2C_STAT_BUS_FREE_IRQ_SUMMARY		(1 << 7)
+#define	I2C_STAT_DATA_ENGINE_CMPLT_IRQ_SUMMARY	(1 << 6)
+#define	I2C_STAT_NO_SLAVE_ACK_IRQ_SUMMARY	(1 << 5)
+#define	I2C_STAT_OVERSIZE_XFER_TERM_IRQ_SUMMARY	(1 << 4)
+#define	I2C_STAT_EARLY_TERM_IRQ_SUMMARY		(1 << 3)
+#define	I2C_STAT_MASTER_LOSS_IRQ_SUMMARY	(1 << 2)
+#define	I2C_STAT_SLAVE_STOP_IRQ_SUMMARY		(1 << 1)
+#define	I2C_STAT_SLAVE_IRQ_SUMMARY		(1 << 0)
+
+#define	I2C_QUEUECTRL_RD_THRESH_MASK		(0x1f << 16)
+#define	I2C_QUEUECTRL_RD_THRESH_OFFSET		16
+#define	I2C_QUEUECTRL_WR_THRESH_MASK		(0x1f << 8)
+#define	I2C_QUEUECTRL_WR_THRESH_OFFSET		8
+#define	I2C_QUEUECTRL_QUEUE_RUN			(1 << 5)
+#define	I2C_QUEUECTRL_RD_CLEAR			(1 << 4)
+#define	I2C_QUEUECTRL_WR_CLEAR			(1 << 3)
+#define	I2C_QUEUECTRL_PIO_QUEUE_MODE		(1 << 2)
+#define	I2C_QUEUECTRL_RD_QUEUE_IRQ_EN		(1 << 1)
+#define	I2C_QUEUECTRL_WR_QUEUE_IRQ_EN		(1 << 0)
+
+#define	I2C_QUEUESTAT_RD_QUEUE_FULL		(1 << 14)
+#define	I2C_QUEUESTAT_RD_QUEUE_EMPTY		(1 << 13)
+#define	I2C_QUEUESTAT_RD_QUEUE_CNT_MASK		(0x1f << 8)
+#define	I2C_QUEUESTAT_RD_QUEUE_CNT_OFFSET	8
+#define	I2C_QUEUESTAT_WR_QUEUE_FULL		(1 << 6)
+#define	I2C_QUEUESTAT_WR_QUEUE_EMPTY		(1 << 5)
+#define	I2C_QUEUESTAT_WR_QUEUE_CNT_MASK		0x1f
+#define	I2C_QUEUESTAT_WR_QUEUE_CNT_OFFSET	0
+
+#define	I2C_QUEUECMD_PREACK			(1 << 27)
+#define	I2C_QUEUECMD_ACKNOWLEDGE		(1 << 26)
+#define	I2C_QUEUECMD_SEND_NAK_ON_LAST		(1 << 25)
+#define	I2C_QUEUECMD_MULTI_MASTER		(1 << 23)
+#define	I2C_QUEUECMD_CLOCK_HELD			(1 << 22)
+#define	I2C_QUEUECMD_RETAIN_CLOCK		(1 << 21)
+#define	I2C_QUEUECMD_POST_SEND_STOP		(1 << 20)
+#define	I2C_QUEUECMD_PRE_SEND_START		(1 << 19)
+#define	I2C_QUEUECMD_SLAVE_ADDRESS_ENABLE	(1 << 18)
+#define	I2C_QUEUECMD_MASTER_MODE		(1 << 17)
+#define	I2C_QUEUECMD_DIRECTION			(1 << 16)
+#define	I2C_QUEUECMD_XFER_COUNT_MASK		0xffff
+#define	I2C_QUEUECMD_XFER_COUNT_OFFSET		0
+
+#define	I2C_QUEUEDATA_DATA_MASK			0xffffffff
+#define	I2C_QUEUEDATA_DATA_OFFSET		0
+
+#define	I2C_DATA_DATA_MASK			0xffffffff
+#define	I2C_DATA_DATA_OFFSET			0
+
+#define	I2C_DEBUG0_DMAREQ			(1 << 31)
+#define	I2C_DEBUG0_DMAENDCMD			(1 << 30)
+#define	I2C_DEBUG0_DMAKICK			(1 << 29)
+#define	I2C_DEBUG0_DMATERMINATE			(1 << 28)
+#define	I2C_DEBUG0_STATE_VALUE_MASK		(0x3 << 26)
+#define	I2C_DEBUG0_STATE_VALUE_OFFSET		26
+#define	I2C_DEBUG0_DMA_STATE_MASK		(0x3ff << 16)
+#define	I2C_DEBUG0_DMA_STATE_OFFSET		16
+#define	I2C_DEBUG0_START_TOGGLE			(1 << 15)
+#define	I2C_DEBUG0_STOP_TOGGLE			(1 << 14)
+#define	I2C_DEBUG0_GRAB_TOGGLE			(1 << 13)
+#define	I2C_DEBUG0_CHANGE_TOGGLE		(1 << 12)
+#define	I2C_DEBUG0_STATE_LATCH			(1 << 11)
+#define	I2C_DEBUG0_SLAVE_HOLD_CLK		(1 << 10)
+#define	I2C_DEBUG0_STATE_STATE_MASK		0x3ff
+#define	I2C_DEBUG0_STATE_STATE_OFFSET		0
+
+#define	I2C_DEBUG1_I2C_CLK_IN			(1 << 31)
+#define	I2C_DEBUG1_I2C_DATA_IN			(1 << 30)
+#define	I2C_DEBUG1_DMA_BYTE_ENABLES_MASK	(0xf << 24)
+#define	I2C_DEBUG1_DMA_BYTE_ENABLES_OFFSET	24
+#define	I2C_DEBUG1_CLK_GEN_STATE_MASK		(0xff << 16)
+#define	I2C_DEBUG1_CLK_GEN_STATE_OFFSET		16
+#define	I2C_DEBUG1_LST_MODE_MASK		(0x3 << 9)
+#define	I2C_DEBUG1_LST_MODE_OFFSET		9
+#define	I2C_DEBUG1_LOCAL_SLAVE_TEST		(1 << 8)
+#define	I2C_DEBUG1_FORCE_CLK_ON			(1 << 4)
+#define	I2C_DEBUG1_FORCE_ABR_LOSS		(1 << 3)
+#define	I2C_DEBUG1_FORCE_RCV_ACK		(1 << 2)
+#define	I2C_DEBUG1_FORCE_I2C_DATA_OE		(1 << 1)
+#define	I2C_DEBUG1_FORCE_I2C_CLK_OE		(1 << 0)
+
+#define	I2C_VERSION_MAJOR_MASK			(0xff << 24)
+#define	I2C_VERSION_MAJOR_OFFSET		24
+#define	I2C_VERSION_MINOR_MASK			(0xff << 16)
+#define	I2C_VERSION_MINOR_OFFSET		16
+#define	I2C_VERSION_STEP_MASK			0xffff
+#define	I2C_VERSION_STEP_OFFSET			0
+
+#endif	/* __MX28_REGS_I2C_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-ocotp.h b/arch/arm/include/asm/arch-mx28/regs-ocotp.h
new file mode 100644
index 0000000..ea2fd7b
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-ocotp.h
@@ -0,0 +1,173 @@
+/*
+ * Freescale i.MX28 OCOTP Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_OCOTP_H__
+#define __MX28_REGS_OCOTP_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_ocotp_regs {
+	mx28_reg(hw_ocotp_ctrl)		/* 0x0 */
+	mx28_reg(hw_ocotp_data)		/* 0x10 */
+	mx28_reg(hw_ocotp_cust0)	/* 0x20 */
+	mx28_reg(hw_ocotp_cust1)	/* 0x30 */
+	mx28_reg(hw_ocotp_cust2)	/* 0x40 */
+	mx28_reg(hw_ocotp_cust3)	/* 0x50 */
+	mx28_reg(hw_ocotp_crypto0)	/* 0x60 */
+	mx28_reg(hw_ocotp_crypto1)	/* 0x70 */
+	mx28_reg(hw_ocotp_crypto2)	/* 0x80 */
+	mx28_reg(hw_ocotp_crypto3)	/* 0x90 */
+	mx28_reg(hw_ocotp_hwcap0)	/* 0xa0 */
+	mx28_reg(hw_ocotp_hwcap1)	/* 0xb0 */
+	mx28_reg(hw_ocotp_hwcap2)	/* 0xc0 */
+	mx28_reg(hw_ocotp_hwcap3)	/* 0xd0 */
+	mx28_reg(hw_ocotp_hwcap4)	/* 0xe0 */
+	mx28_reg(hw_ocotp_hwcap5)	/* 0xf0 */
+	mx28_reg(hw_ocotp_swcap)	/* 0x100 */
+	mx28_reg(hw_ocotp_custcap)	/* 0x110 */
+	mx28_reg(hw_ocotp_lock)		/* 0x120 */
+	mx28_reg(hw_ocotp_ops0)		/* 0x130 */
+	mx28_reg(hw_ocotp_ops1)		/* 0x140 */
+	mx28_reg(hw_ocotp_ops2)		/* 0x150 */
+	mx28_reg(hw_ocotp_ops3)		/* 0x160 */
+	mx28_reg(hw_ocotp_un0)		/* 0x170 */
+	mx28_reg(hw_ocotp_un1)		/* 0x180 */
+	mx28_reg(hw_ocotp_un2)		/* 0x190 */
+	mx28_reg(hw_ocotp_rom0)		/* 0x1a0 */
+	mx28_reg(hw_ocotp_rom1)		/* 0x1b0 */
+	mx28_reg(hw_ocotp_rom2)		/* 0x1c0 */
+	mx28_reg(hw_ocotp_rom3)		/* 0x1d0 */
+	mx28_reg(hw_ocotp_rom4)		/* 0x1e0 */
+	mx28_reg(hw_ocotp_rom5)		/* 0x1f0 */
+	mx28_reg(hw_ocotp_rom6)		/* 0x200 */
+	mx28_reg(hw_ocotp_rom7)		/* 0x210 */
+	mx28_reg(hw_ocotp_srk0)		/* 0x220 */
+	mx28_reg(hw_ocotp_srk1)		/* 0x230 */
+	mx28_reg(hw_ocotp_srk2)		/* 0x240 */
+	mx28_reg(hw_ocotp_srk3)		/* 0x250 */
+	mx28_reg(hw_ocotp_srk4)		/* 0x260 */
+	mx28_reg(hw_ocotp_srk5)		/* 0x270 */
+	mx28_reg(hw_ocotp_srk6)		/* 0x280 */
+	mx28_reg(hw_ocotp_srk7)		/* 0x290 */
+	mx28_reg(hw_ocotp_version)	/* 0x2a0 */
+};
+#endif
+
+#define	OCOTP_CTRL_WR_UNLOCK_MASK		(0xffff << 16)
+#define	OCOTP_CTRL_WR_UNLOCK_OFFSET		16
+#define	OCOTP_CTRL_WR_UNLOCK_KEY		(0x3e77 << 16)
+#define	OCOTP_CTRL_RELOAD_SHADOWS		(1 << 13)
+#define	OCOTP_CTRL_RD_BANK_OPEN			(1 << 12)
+#define	OCOTP_CTRL_ERROR			(1 << 9)
+#define	OCOTP_CTRL_BUSY				(1 << 8)
+#define	OCOTP_CTRL_ADDR_MASK			0x3f
+#define	OCOTP_CTRL_ADDR_OFFSET			0
+
+#define	OCOTP_DATA_DATA_MASK			0xffffffff
+#define	OCOTP_DATA_DATA_OFFSET			0
+
+#define	OCOTP_CUST_BITS_MASK			0xffffffff
+#define	OCOTP_CUST_BITS_OFFSET			0
+
+#define	OCOTP_CRYPTO_BITS_MASK			0xffffffff
+#define	OCOTP_CRYPTO_BITS_OFFSET		0
+
+#define	OCOTP_HWCAP_BITS_MASK			0xffffffff
+#define	OCOTP_HWCAP_BITS_OFFSET			0
+
+#define	OCOTP_SWCAP_BITS_MASK			0xffffffff
+#define	OCOTP_SWCAP_BITS_OFFSET			0
+
+#define	OCOTP_CUSTCAP_RTC_XTAL_32768_PRESENT	(1 << 2)
+#define	OCOTP_CUSTCAP_RTC_XTAL_32000_PRESENT	(1 << 1)
+
+#define	OCOTP_LOCK_ROM7				(1 << 31)
+#define	OCOTP_LOCK_ROM6				(1 << 30)
+#define	OCOTP_LOCK_ROM5				(1 << 29)
+#define	OCOTP_LOCK_ROM4				(1 << 28)
+#define	OCOTP_LOCK_ROM3				(1 << 27)
+#define	OCOTP_LOCK_ROM2				(1 << 26)
+#define	OCOTP_LOCK_ROM1				(1 << 25)
+#define	OCOTP_LOCK_ROM0				(1 << 24)
+#define	OCOTP_LOCK_HWSW_SHADOW_ALT		(1 << 23)
+#define	OCOTP_LOCK_CRYPTODCP_ALT		(1 << 22)
+#define	OCOTP_LOCK_CRYPTOKEY_ALT		(1 << 21)
+#define	OCOTP_LOCK_PIN				(1 << 20)
+#define	OCOTP_LOCK_OPS				(1 << 19)
+#define	OCOTP_LOCK_UN2				(1 << 18)
+#define	OCOTP_LOCK_UN1				(1 << 17)
+#define	OCOTP_LOCK_UN0				(1 << 16)
+#define	OCOTP_LOCK_SRK				(1 << 15)
+#define	OCOTP_LOCK_UNALLOCATED_MASK		(0x7 << 12)
+#define	OCOTP_LOCK_UNALLOCATED_OFFSET		12
+#define	OCOTP_LOCK_SRK_SHADOW			(1 << 11)
+#define	OCOTP_LOCK_ROM_SHADOW			(1 << 10)
+#define	OCOTP_LOCK_CUSTCAP			(1 << 9)
+#define	OCOTP_LOCK_HWSW				(1 << 8)
+#define	OCOTP_LOCK_CUSTCAP_SHADOW		(1 << 7)
+#define	OCOTP_LOCK_HWSW_SHADOW			(1 << 6)
+#define	OCOTP_LOCK_CRYPTODCP			(1 << 5)
+#define	OCOTP_LOCK_CRYPTOKEY			(1 << 4)
+#define	OCOTP_LOCK_CUST3			(1 << 3)
+#define	OCOTP_LOCK_CUST2			(1 << 2)
+#define	OCOTP_LOCK_CUST1			(1 << 1)
+#define	OCOTP_LOCK_CUST0			(1 << 0)
+
+#define	OCOTP_OPS_BITS_MASK			0xffffffff
+#define	OCOTP_OPS_BITS_OFFSET			0
+
+#define	OCOTP_UN_BITS_MASK			0xffffffff
+#define	OCOTP_UN_BITS_OFFSET			0
+
+#define	OCOTP_ROM_BOOT_MODE_MASK		(0xff << 24)
+#define	OCOTP_ROM_BOOT_MODE_OFFSET		24
+#define	OCOTP_ROM_SD_MMC_MODE_MASK		(0x3 << 22)
+#define	OCOTP_ROM_SD_MMC_MODE_OFFSET		22
+#define	OCOTP_ROM_SD_POWER_GATE_GPIO_MASK	(0x3 << 20)
+#define	OCOTP_ROM_SD_POWER_GATE_GPIO_OFFSET	20
+#define	OCOTP_ROM_SD_POWER_UP_DELAY_MASK	(0x3f << 14)
+#define	OCOTP_ROM_SD_POWER_UP_DELAY_OFFSET	14
+#define	OCOTP_ROM_SD_BUS_WIDTH_MASK		(0x3 << 12)
+#define	OCOTP_ROM_SD_BUS_WIDTH_OFFSET		12
+#define	OCOTP_ROM_SSP_SCK_INDEX_MASK		(0xf << 8)
+#define	OCOTP_ROM_SSP_SCK_INDEX_OFFSET		8
+#define	OCOTP_ROM_EMMC_USE_DDR			(1 << 7)
+#define	OCOTP_ROM_DISABLE_SPI_NOR_FAST_READ	(1 << 6)
+#define	OCOTP_ROM_ENABLE_USB_BOOT_SERIAL_NUM	(1 << 5)
+#define	OCOTP_ROM_ENABLE_UNENCRYPTED_BOOT	(1 << 4)
+#define	OCOTP_ROM_SD_MBR_BOOT			(1 << 3)
+
+#define	OCOTP_SRK_BITS_MASK			0xffffffff
+#define	OCOTP_SRK_BITS_OFFSET			0
+
+#define	OCOTP_VERSION_MAJOR_MASK		(0xff << 24)
+#define	OCOTP_VERSION_MAJOR_OFFSET		24
+#define	OCOTP_VERSION_MINOR_MASK		(0xff << 16)
+#define	OCOTP_VERSION_MINOR_OFFSET		16
+#define	OCOTP_VERSION_STEP_MASK			0xffff
+#define	OCOTP_VERSION_STEP_OFFSET		0
+
+#endif /* __MX28_REGS_OCOTP_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-pinctrl.h b/arch/arm/include/asm/arch-mx28/regs-pinctrl.h
new file mode 100644
index 0000000..73739ca
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-pinctrl.h
@@ -0,0 +1,1284 @@
+/*
+ * Freescale i.MX28 PINCTRL Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_PINCTRL_H__
+#define __MX28_REGS_PINCTRL_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_pinctrl_regs {
+	mx28_reg(hw_pinctrl_ctrl)		/* 0x0 */
+
+	uint32_t	reserved1[60];
+
+	mx28_reg(hw_pinctrl_muxsel0)		/* 0x100 */
+	mx28_reg(hw_pinctrl_muxsel1)		/* 0x110 */
+	mx28_reg(hw_pinctrl_muxsel2)		/* 0x120 */
+	mx28_reg(hw_pinctrl_muxsel3)		/* 0x130 */
+	mx28_reg(hw_pinctrl_muxsel4)		/* 0x140 */
+	mx28_reg(hw_pinctrl_muxsel5)		/* 0x150 */
+	mx28_reg(hw_pinctrl_muxsel6)		/* 0x160 */
+	mx28_reg(hw_pinctrl_muxsel7)		/* 0x170 */
+	mx28_reg(hw_pinctrl_muxsel8)		/* 0x180 */
+	mx28_reg(hw_pinctrl_muxsel9)		/* 0x190 */
+	mx28_reg(hw_pinctrl_muxsel10)		/* 0x1a0 */
+	mx28_reg(hw_pinctrl_muxsel11)		/* 0x1b0 */
+	mx28_reg(hw_pinctrl_muxsel12)		/* 0x1c0 */
+	mx28_reg(hw_pinctrl_muxsel13)		/* 0x1d0 */
+
+	uint32_t	reserved2[72];
+
+	mx28_reg(hw_pinctrl_drive0)		/* 0x300 */
+	mx28_reg(hw_pinctrl_drive1)		/* 0x310 */
+	mx28_reg(hw_pinctrl_drive2)		/* 0x320 */
+	mx28_reg(hw_pinctrl_drive3)		/* 0x330 */
+	mx28_reg(hw_pinctrl_drive4)		/* 0x340 */
+	mx28_reg(hw_pinctrl_drive5)		/* 0x350 */
+	mx28_reg(hw_pinctrl_drive6)		/* 0x360 */
+	mx28_reg(hw_pinctrl_drive7)		/* 0x370 */
+	mx28_reg(hw_pinctrl_drive8)		/* 0x380 */
+	mx28_reg(hw_pinctrl_drive9)		/* 0x390 */
+	mx28_reg(hw_pinctrl_drive10)		/* 0x3a0 */
+	mx28_reg(hw_pinctrl_drive11)		/* 0x3b0 */
+	mx28_reg(hw_pinctrl_drive12)		/* 0x3c0 */
+	mx28_reg(hw_pinctrl_drive13)		/* 0x3d0 */
+	mx28_reg(hw_pinctrl_drive14)		/* 0x3e0 */
+	mx28_reg(hw_pinctrl_drive15)		/* 0x3f0 */
+	mx28_reg(hw_pinctrl_drive16)		/* 0x400 */
+	mx28_reg(hw_pinctrl_drive17)		/* 0x410 */
+	mx28_reg(hw_pinctrl_drive18)		/* 0x420 */
+	mx28_reg(hw_pinctrl_drive19)		/* 0x430 */
+
+	uint32_t	reserved3[112];
+
+	mx28_reg(hw_pinctrl_pull0)		/* 0x600 */
+	mx28_reg(hw_pinctrl_pull1)		/* 0x610 */
+	mx28_reg(hw_pinctrl_pull2)		/* 0x620 */
+	mx28_reg(hw_pinctrl_pull3)		/* 0x630 */
+	mx28_reg(hw_pinctrl_pull4)		/* 0x640 */
+	mx28_reg(hw_pinctrl_pull5)		/* 0x650 */
+	mx28_reg(hw_pinctrl_pull6)		/* 0x660 */
+
+	uint32_t	reserved4[36];
+
+	mx28_reg(hw_pinctrl_dout0)		/* 0x700 */
+	mx28_reg(hw_pinctrl_dout1)		/* 0x710 */
+	mx28_reg(hw_pinctrl_dout2)		/* 0x720 */
+	mx28_reg(hw_pinctrl_dout3)		/* 0x730 */
+	mx28_reg(hw_pinctrl_dout4)		/* 0x740 */
+
+	uint32_t	reserved5[108];
+
+	mx28_reg(hw_pinctrl_din0)		/* 0x900 */
+	mx28_reg(hw_pinctrl_din1)		/* 0x910 */
+	mx28_reg(hw_pinctrl_din2)		/* 0x920 */
+	mx28_reg(hw_pinctrl_din3)		/* 0x930 */
+	mx28_reg(hw_pinctrl_din4)		/* 0x940 */
+
+	uint32_t	reserved6[108];
+
+	mx28_reg(hw_pinctrl_doe0)		/* 0xb00 */
+	mx28_reg(hw_pinctrl_doe1)		/* 0xb10 */
+	mx28_reg(hw_pinctrl_doe2)		/* 0xb20 */
+	mx28_reg(hw_pinctrl_doe3)		/* 0xb30 */
+	mx28_reg(hw_pinctrl_doe4)		/* 0xb40 */
+
+	uint32_t	reserved7[300];
+
+	mx28_reg(hw_pinctrl_pin2irq0)		/* 0x1000 */
+	mx28_reg(hw_pinctrl_pin2irq1)		/* 0x1010 */
+	mx28_reg(hw_pinctrl_pin2irq2)		/* 0x1020 */
+	mx28_reg(hw_pinctrl_pin2irq3)		/* 0x1030 */
+	mx28_reg(hw_pinctrl_pin2irq4)		/* 0x1040 */
+
+	uint32_t	reserved8[44];
+
+	mx28_reg(hw_pinctrl_irqen0)		/* 0x1100 */
+	mx28_reg(hw_pinctrl_irqen1)		/* 0x1110 */
+	mx28_reg(hw_pinctrl_irqen2)		/* 0x1120 */
+	mx28_reg(hw_pinctrl_irqen3)		/* 0x1130 */
+	mx28_reg(hw_pinctrl_irqen4)		/* 0x1140 */
+
+	uint32_t	reserved9[44];
+
+	mx28_reg(hw_pinctrl_irqlevel0)		/* 0x1200 */
+	mx28_reg(hw_pinctrl_irqlevel1)		/* 0x1210 */
+	mx28_reg(hw_pinctrl_irqlevel2)		/* 0x1220 */
+	mx28_reg(hw_pinctrl_irqlevel3)		/* 0x1230 */
+	mx28_reg(hw_pinctrl_irqlevel4)		/* 0x1240 */
+
+	uint32_t	reserved10[44];
+
+	mx28_reg(hw_pinctrl_irqpol0)		/* 0x1300 */
+	mx28_reg(hw_pinctrl_irqpol1)		/* 0x1310 */
+	mx28_reg(hw_pinctrl_irqpol2)		/* 0x1320 */
+	mx28_reg(hw_pinctrl_irqpol3)		/* 0x1330 */
+	mx28_reg(hw_pinctrl_irqpol4)		/* 0x1340 */
+
+	uint32_t	reserved11[44];
+
+	mx28_reg(hw_pinctrl_irqstat0)		/* 0x1400 */
+	mx28_reg(hw_pinctrl_irqstat1)		/* 0x1410 */
+	mx28_reg(hw_pinctrl_irqstat2)		/* 0x1420 */
+	mx28_reg(hw_pinctrl_irqstat3)		/* 0x1430 */
+	mx28_reg(hw_pinctrl_irqstat4)		/* 0x1440 */
+
+	uint32_t	reserved12[380];
+
+	mx28_reg(hw_pinctrl_emi_odt_ctrl)	/* 0x1a40 */
+
+	uint32_t	reserved13[76];
+
+	mx28_reg(hw_pinctrl_emi_ds_ctrl)	/* 0x1b80 */
+};
+#endif
+
+#define	PINCTRL_CTRL_SFTRST				(1 << 31)
+#define	PINCTRL_CTRL_CLKGATE				(1 << 30)
+#define	PINCTRL_CTRL_PRESENT4				(1 << 24)
+#define	PINCTRL_CTRL_PRESENT3				(1 << 23)
+#define	PINCTRL_CTRL_PRESENT2				(1 << 22)
+#define	PINCTRL_CTRL_PRESENT1				(1 << 21)
+#define	PINCTRL_CTRL_PRESENT0				(1 << 20)
+#define	PINCTRL_CTRL_IRQOUT4				(1 << 4)
+#define	PINCTRL_CTRL_IRQOUT3				(1 << 3)
+#define	PINCTRL_CTRL_IRQOUT2				(1 << 2)
+#define	PINCTRL_CTRL_IRQOUT1				(1 << 1)
+#define	PINCTRL_CTRL_IRQOUT0				(1 << 0)
+
+#define	PINCTRL_MUXSEL0_BANK0_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL0_BANK0_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL0_BANK0_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL0_BANK0_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL0_BANK0_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL0_BANK0_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL0_BANK0_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL0_BANK0_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL0_BANK0_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL0_BANK0_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL0_BANK0_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL0_BANK0_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL0_BANK0_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL0_BANK0_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL0_BANK0_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL0_BANK0_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL1_BANK0_PIN28_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL1_BANK0_PIN28_OFFSET		24
+#define	PINCTRL_MUXSEL1_BANK0_PIN27_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL1_BANK0_PIN27_OFFSET		22
+#define	PINCTRL_MUXSEL1_BANK0_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL1_BANK0_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL1_BANK0_PIN25_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL1_BANK0_PIN25_OFFSET		18
+#define	PINCTRL_MUXSEL1_BANK0_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL1_BANK0_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL1_BANK0_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL1_BANK0_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL1_BANK0_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL1_BANK0_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL1_BANK0_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL1_BANK0_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL1_BANK0_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL1_BANK0_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL1_BANK0_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL1_BANK0_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL1_BANK0_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL1_BANK0_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL1_BANK0_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL1_BANK0_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL1_BANK0_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL1_BANK0_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL2_BANK1_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL2_BANK1_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL2_BANK1_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL2_BANK1_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL2_BANK1_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL2_BANK1_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL2_BANK1_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL2_BANK1_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL2_BANK1_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL2_BANK1_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL2_BANK1_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL2_BANK1_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL2_BANK1_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL2_BANK1_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL2_BANK1_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL2_BANK1_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL2_BANK1_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL2_BANK1_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL2_BANK1_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL2_BANK1_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL2_BANK1_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL2_BANK1_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL2_BANK1_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL2_BANK1_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL2_BANK1_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL2_BANK1_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL2_BANK1_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL2_BANK1_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL2_BANK1_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL2_BANK1_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL2_BANK1_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL2_BANK1_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL3_BANK1_PIN31_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL3_BANK1_PIN31_OFFSET		30
+#define	PINCTRL_MUXSEL3_BANK1_PIN30_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL3_BANK1_PIN30_OFFSET		28
+#define	PINCTRL_MUXSEL3_BANK1_PIN29_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL3_BANK1_PIN29_OFFSET		26
+#define	PINCTRL_MUXSEL3_BANK1_PIN28_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL3_BANK1_PIN28_OFFSET		24
+#define	PINCTRL_MUXSEL3_BANK1_PIN27_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL3_BANK1_PIN27_OFFSET		22
+#define	PINCTRL_MUXSEL3_BANK1_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL3_BANK1_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL3_BANK1_PIN25_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL3_BANK1_PIN25_OFFSET		18
+#define	PINCTRL_MUXSEL3_BANK1_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL3_BANK1_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL3_BANK1_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL3_BANK1_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL3_BANK1_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL3_BANK1_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL3_BANK1_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL3_BANK1_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL3_BANK1_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL3_BANK1_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL3_BANK1_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL3_BANK1_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL3_BANK1_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL3_BANK1_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL3_BANK1_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL3_BANK1_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL3_BANK1_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL3_BANK1_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL4_BANK2_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL4_BANK2_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL4_BANK2_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL4_BANK2_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL4_BANK2_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL4_BANK2_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL4_BANK2_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL4_BANK2_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL4_BANK2_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL4_BANK2_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL4_BANK2_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL4_BANK2_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL4_BANK2_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL4_BANK2_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL4_BANK2_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL4_BANK2_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL4_BANK2_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL4_BANK2_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL4_BANK2_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL4_BANK2_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL4_BANK2_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL4_BANK2_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL4_BANK2_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL4_BANK2_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL4_BANK2_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL4_BANK2_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL4_BANK2_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL4_BANK2_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL4_BANK2_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL4_BANK2_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL5_BANK2_PIN27_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL5_BANK2_PIN27_OFFSET		22
+#define	PINCTRL_MUXSEL5_BANK2_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL5_BANK2_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL5_BANK2_PIN25_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL5_BANK2_PIN25_OFFSET		18
+#define	PINCTRL_MUXSEL5_BANK2_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL5_BANK2_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL5_BANK2_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL5_BANK2_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL5_BANK2_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL5_BANK2_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL5_BANK2_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL5_BANK2_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL5_BANK2_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL5_BANK2_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL5_BANK2_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL5_BANK2_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL5_BANK2_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL5_BANK2_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL6_BANK3_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL6_BANK3_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL6_BANK3_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL6_BANK3_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL6_BANK3_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL6_BANK3_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL6_BANK3_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL6_BANK3_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL6_BANK3_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL6_BANK3_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL6_BANK3_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL6_BANK3_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL6_BANK3_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL6_BANK3_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL6_BANK3_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL6_BANK3_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL6_BANK3_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL6_BANK3_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL6_BANK3_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL6_BANK3_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL6_BANK3_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL6_BANK3_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL6_BANK3_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL6_BANK3_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL6_BANK3_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL6_BANK3_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL6_BANK3_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL6_BANK3_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL6_BANK3_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL6_BANK3_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL6_BANK3_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL6_BANK3_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL7_BANK3_PIN30_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL7_BANK3_PIN30_OFFSET		28
+#define	PINCTRL_MUXSEL7_BANK3_PIN29_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL7_BANK3_PIN29_OFFSET		26
+#define	PINCTRL_MUXSEL7_BANK3_PIN28_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL7_BANK3_PIN28_OFFSET		24
+#define	PINCTRL_MUXSEL7_BANK3_PIN27_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL7_BANK3_PIN27_OFFSET		22
+#define	PINCTRL_MUXSEL7_BANK3_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL7_BANK3_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL7_BANK3_PIN25_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL7_BANK3_PIN25_OFFSET		18
+#define	PINCTRL_MUXSEL7_BANK3_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL7_BANK3_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL7_BANK3_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL7_BANK3_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL7_BANK3_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL7_BANK3_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL7_BANK3_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL7_BANK3_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL7_BANK3_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL7_BANK3_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL7_BANK3_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL7_BANK3_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL7_BANK3_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL7_BANK3_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL7_BANK3_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL7_BANK3_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL8_BANK4_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL8_BANK4_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL8_BANK4_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL8_BANK4_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL8_BANK4_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL8_BANK4_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL8_BANK4_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL8_BANK4_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL8_BANK4_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL8_BANK4_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL8_BANK4_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL8_BANK4_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL8_BANK4_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL8_BANK4_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL8_BANK4_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL8_BANK4_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL8_BANK4_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL8_BANK4_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL8_BANK4_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL8_BANK4_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL8_BANK4_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL8_BANK4_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL8_BANK4_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL8_BANK4_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL8_BANK4_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL8_BANK4_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL8_BANK4_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL8_BANK4_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL8_BANK4_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL8_BANK4_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL8_BANK4_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL8_BANK4_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL9_BANK4_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL9_BANK4_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL9_BANK4_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL9_BANK4_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL10_BANK5_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL10_BANK5_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL10_BANK5_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL10_BANK5_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL10_BANK5_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL10_BANK5_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL10_BANK5_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL10_BANK5_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL10_BANK5_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL10_BANK5_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL10_BANK5_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL10_BANK5_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL10_BANK5_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL10_BANK5_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL10_BANK5_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL10_BANK5_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL10_BANK5_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL10_BANK5_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL10_BANK5_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL10_BANK5_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL10_BANK5_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL10_BANK5_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL10_BANK5_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL10_BANK5_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL10_BANK5_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL10_BANK5_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL10_BANK5_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL10_BANK5_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL10_BANK5_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL10_BANK5_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL10_BANK5_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL10_BANK5_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL11_BANK5_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL11_BANK5_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL11_BANK5_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL11_BANK5_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL11_BANK5_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL11_BANK5_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL11_BANK5_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL11_BANK5_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL11_BANK5_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL11_BANK5_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL11_BANK5_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL11_BANK5_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL11_BANK5_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL11_BANK5_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL11_BANK5_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL11_BANK5_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL11_BANK5_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL11_BANK5_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL12_BANK6_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL12_BANK6_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL12_BANK6_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL12_BANK6_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL12_BANK6_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL12_BANK6_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL12_BANK6_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL12_BANK6_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL12_BANK6_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL12_BANK6_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL12_BANK6_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL12_BANK6_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL12_BANK6_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL12_BANK6_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL12_BANK6_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL12_BANK6_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL12_BANK6_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL12_BANK6_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL12_BANK6_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL12_BANK6_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL12_BANK6_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL12_BANK6_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL12_BANK6_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL12_BANK6_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL12_BANK6_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL12_BANK6_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL12_BANK6_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL12_BANK6_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL12_BANK6_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL12_BANK6_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL13_BANK6_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL13_BANK6_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL13_BANK6_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL13_BANK6_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL13_BANK6_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL13_BANK6_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL13_BANK6_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL13_BANK6_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL13_BANK6_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL13_BANK6_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL13_BANK6_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL13_BANK6_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL13_BANK6_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL13_BANK6_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL13_BANK6_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL13_BANK6_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL13_BANK6_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL13_BANK6_PIN16_OFFSET		0
+
+#define	PINCTRL_DRIVE0_BANK0_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE0_BANK0_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE0_BANK0_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE0_BANK0_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE0_BANK0_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE0_BANK0_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE0_BANK0_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE0_BANK0_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE0_BANK0_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE0_BANK0_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE0_BANK0_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE0_BANK0_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE0_BANK0_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE0_BANK0_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE0_BANK0_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE0_BANK0_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE0_BANK0_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE0_BANK0_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE0_BANK0_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE0_BANK0_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE0_BANK0_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE0_BANK0_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE0_BANK0_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE0_BANK0_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE2_BANK0_PIN23_V			(1 << 30)
+#define	PINCTRL_DRIVE2_BANK0_PIN23_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE2_BANK0_PIN23_MA_OFFSET		28
+#define	PINCTRL_DRIVE2_BANK0_PIN22_V			(1 << 26)
+#define	PINCTRL_DRIVE2_BANK0_PIN22_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE2_BANK0_PIN22_MA_OFFSET		24
+#define	PINCTRL_DRIVE2_BANK0_PIN21_V			(1 << 22)
+#define	PINCTRL_DRIVE2_BANK0_PIN21_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE2_BANK0_PIN21_MA_OFFSET		20
+#define	PINCTRL_DRIVE2_BANK0_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE2_BANK0_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE2_BANK0_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE2_BANK0_PIN19_V			(1 << 14)
+#define	PINCTRL_DRIVE2_BANK0_PIN19_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE2_BANK0_PIN19_MA_OFFSET		12
+#define	PINCTRL_DRIVE2_BANK0_PIN18_V			(1 << 10)
+#define	PINCTRL_DRIVE2_BANK0_PIN18_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE2_BANK0_PIN18_MA_OFFSET		8
+#define	PINCTRL_DRIVE2_BANK0_PIN17_V			(1 << 6)
+#define	PINCTRL_DRIVE2_BANK0_PIN17_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE2_BANK0_PIN17_MA_OFFSET		4
+#define	PINCTRL_DRIVE2_BANK0_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE2_BANK0_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE2_BANK0_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE3_BANK0_PIN28_V			(1 << 18)
+#define	PINCTRL_DRIVE3_BANK0_PIN28_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE3_BANK0_PIN28_MA_OFFSET		16
+#define	PINCTRL_DRIVE3_BANK0_PIN27_V			(1 << 14)
+#define	PINCTRL_DRIVE3_BANK0_PIN27_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE3_BANK0_PIN27_MA_OFFSET		12
+#define	PINCTRL_DRIVE3_BANK0_PIN26_V			(1 << 10)
+#define	PINCTRL_DRIVE3_BANK0_PIN26_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE3_BANK0_PIN26_MA_OFFSET		8
+#define	PINCTRL_DRIVE3_BANK0_PIN25_V			(1 << 6)
+#define	PINCTRL_DRIVE3_BANK0_PIN25_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE3_BANK0_PIN25_MA_OFFSET		4
+#define	PINCTRL_DRIVE3_BANK0_PIN24_V			(1 << 2)
+#define	PINCTRL_DRIVE3_BANK0_PIN24_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE3_BANK0_PIN24_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE4_BANK1_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE4_BANK1_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE4_BANK1_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE4_BANK1_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE4_BANK1_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE4_BANK1_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE4_BANK1_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE4_BANK1_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE4_BANK1_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE4_BANK1_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE4_BANK1_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE4_BANK1_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE4_BANK1_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE4_BANK1_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE4_BANK1_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE4_BANK1_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE4_BANK1_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE4_BANK1_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE4_BANK1_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE4_BANK1_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE4_BANK1_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE4_BANK1_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE4_BANK1_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE4_BANK1_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE5_BANK1_PIN15_V			(1 << 30)
+#define	PINCTRL_DRIVE5_BANK1_PIN15_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE5_BANK1_PIN15_MA_OFFSET		28
+#define	PINCTRL_DRIVE5_BANK1_PIN14_V			(1 << 26)
+#define	PINCTRL_DRIVE5_BANK1_PIN14_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE5_BANK1_PIN14_MA_OFFSET		24
+#define	PINCTRL_DRIVE5_BANK1_PIN13_V			(1 << 22)
+#define	PINCTRL_DRIVE5_BANK1_PIN13_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE5_BANK1_PIN13_MA_OFFSET		20
+#define	PINCTRL_DRIVE5_BANK1_PIN12_V			(1 << 18)
+#define	PINCTRL_DRIVE5_BANK1_PIN12_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE5_BANK1_PIN12_MA_OFFSET		16
+#define	PINCTRL_DRIVE5_BANK1_PIN11_V			(1 << 14)
+#define	PINCTRL_DRIVE5_BANK1_PIN11_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE5_BANK1_PIN11_MA_OFFSET		12
+#define	PINCTRL_DRIVE5_BANK1_PIN10_V			(1 << 10)
+#define	PINCTRL_DRIVE5_BANK1_PIN10_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE5_BANK1_PIN10_MA_OFFSET		8
+#define	PINCTRL_DRIVE5_BANK1_PIN09_V			(1 << 6)
+#define	PINCTRL_DRIVE5_BANK1_PIN09_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE5_BANK1_PIN09_MA_OFFSET		4
+#define	PINCTRL_DRIVE5_BANK1_PIN08_V			(1 << 2)
+#define	PINCTRL_DRIVE5_BANK1_PIN08_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE5_BANK1_PIN08_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE6_BANK1_PIN23_V			(1 << 30)
+#define	PINCTRL_DRIVE6_BANK1_PIN23_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE6_BANK1_PIN23_MA_OFFSET		28
+#define	PINCTRL_DRIVE6_BANK1_PIN22_V			(1 << 26)
+#define	PINCTRL_DRIVE6_BANK1_PIN22_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE6_BANK1_PIN22_MA_OFFSET		24
+#define	PINCTRL_DRIVE6_BANK1_PIN21_V			(1 << 22)
+#define	PINCTRL_DRIVE6_BANK1_PIN21_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE6_BANK1_PIN21_MA_OFFSET		20
+#define	PINCTRL_DRIVE6_BANK1_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE6_BANK1_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE6_BANK1_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE6_BANK1_PIN19_V			(1 << 14)
+#define	PINCTRL_DRIVE6_BANK1_PIN19_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE6_BANK1_PIN19_MA_OFFSET		12
+#define	PINCTRL_DRIVE6_BANK1_PIN18_V			(1 << 10)
+#define	PINCTRL_DRIVE6_BANK1_PIN18_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE6_BANK1_PIN18_MA_OFFSET		8
+#define	PINCTRL_DRIVE6_BANK1_PIN17_V			(1 << 6)
+#define	PINCTRL_DRIVE6_BANK1_PIN17_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE6_BANK1_PIN17_MA_OFFSET		4
+#define	PINCTRL_DRIVE6_BANK1_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE6_BANK1_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE6_BANK1_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE7_BANK1_PIN31_V			(1 << 30)
+#define	PINCTRL_DRIVE7_BANK1_PIN31_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE7_BANK1_PIN31_MA_OFFSET		28
+#define	PINCTRL_DRIVE7_BANK1_PIN30_V			(1 << 26)
+#define	PINCTRL_DRIVE7_BANK1_PIN30_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE7_BANK1_PIN30_MA_OFFSET		24
+#define	PINCTRL_DRIVE7_BANK1_PIN29_V			(1 << 22)
+#define	PINCTRL_DRIVE7_BANK1_PIN29_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE7_BANK1_PIN29_MA_OFFSET		20
+#define	PINCTRL_DRIVE7_BANK1_PIN28_V			(1 << 18)
+#define	PINCTRL_DRIVE7_BANK1_PIN28_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE7_BANK1_PIN28_MA_OFFSET		16
+#define	PINCTRL_DRIVE7_BANK1_PIN27_V			(1 << 14)
+#define	PINCTRL_DRIVE7_BANK1_PIN27_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE7_BANK1_PIN27_MA_OFFSET		12
+#define	PINCTRL_DRIVE7_BANK1_PIN26_V			(1 << 10)
+#define	PINCTRL_DRIVE7_BANK1_PIN26_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE7_BANK1_PIN26_MA_OFFSET		8
+#define	PINCTRL_DRIVE7_BANK1_PIN25_V			(1 << 6)
+#define	PINCTRL_DRIVE7_BANK1_PIN25_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE7_BANK1_PIN25_MA_OFFSET		4
+#define	PINCTRL_DRIVE7_BANK1_PIN24_V			(1 << 2)
+#define	PINCTRL_DRIVE7_BANK1_PIN24_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE7_BANK1_PIN24_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE8_BANK2_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE8_BANK2_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE8_BANK2_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE8_BANK2_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE8_BANK2_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE8_BANK2_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE8_BANK2_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE8_BANK2_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE8_BANK2_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE8_BANK2_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE8_BANK2_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE8_BANK2_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE8_BANK2_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE8_BANK2_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE8_BANK2_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE8_BANK2_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE8_BANK2_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE8_BANK2_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE8_BANK2_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE8_BANK2_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE8_BANK2_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE8_BANK2_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE8_BANK2_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE8_BANK2_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE9_BANK2_PIN15_V			(1 << 30)
+#define	PINCTRL_DRIVE9_BANK2_PIN15_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE9_BANK2_PIN15_MA_OFFSET		28
+#define	PINCTRL_DRIVE9_BANK2_PIN14_V			(1 << 26)
+#define	PINCTRL_DRIVE9_BANK2_PIN14_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE9_BANK2_PIN14_MA_OFFSET		24
+#define	PINCTRL_DRIVE9_BANK2_PIN13_V			(1 << 22)
+#define	PINCTRL_DRIVE9_BANK2_PIN13_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE9_BANK2_PIN13_MA_OFFSET		20
+#define	PINCTRL_DRIVE9_BANK2_PIN12_V			(1 << 18)
+#define	PINCTRL_DRIVE9_BANK2_PIN12_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE9_BANK2_PIN12_MA_OFFSET		16
+#define	PINCTRL_DRIVE9_BANK2_PIN10_V			(1 << 10)
+#define	PINCTRL_DRIVE9_BANK2_PIN10_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE9_BANK2_PIN10_MA_OFFSET		8
+#define	PINCTRL_DRIVE9_BANK2_PIN09_V			(1 << 6)
+#define	PINCTRL_DRIVE9_BANK2_PIN09_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE9_BANK2_PIN09_MA_OFFSET		4
+#define	PINCTRL_DRIVE9_BANK2_PIN08_V			(1 << 2)
+#define	PINCTRL_DRIVE9_BANK2_PIN08_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE9_BANK2_PIN08_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE10_BANK2_PIN21_V			(1 << 22)
+#define	PINCTRL_DRIVE10_BANK2_PIN21_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE10_BANK2_PIN21_MA_OFFSET		20
+#define	PINCTRL_DRIVE10_BANK2_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE10_BANK2_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE10_BANK2_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE10_BANK2_PIN19_V			(1 << 14)
+#define	PINCTRL_DRIVE10_BANK2_PIN19_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE10_BANK2_PIN19_MA_OFFSET		12
+#define	PINCTRL_DRIVE10_BANK2_PIN18_V			(1 << 10)
+#define	PINCTRL_DRIVE10_BANK2_PIN18_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE10_BANK2_PIN18_MA_OFFSET		8
+#define	PINCTRL_DRIVE10_BANK2_PIN17_V			(1 << 6)
+#define	PINCTRL_DRIVE10_BANK2_PIN17_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE10_BANK2_PIN17_MA_OFFSET		4
+#define	PINCTRL_DRIVE10_BANK2_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE10_BANK2_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE10_BANK2_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE11_BANK2_PIN27_V			(1 << 14)
+#define	PINCTRL_DRIVE11_BANK2_PIN27_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE11_BANK2_PIN27_MA_OFFSET		12
+#define	PINCTRL_DRIVE11_BANK2_PIN26_V			(1 << 10)
+#define	PINCTRL_DRIVE11_BANK2_PIN26_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE11_BANK2_PIN26_MA_OFFSET		8
+#define	PINCTRL_DRIVE11_BANK2_PIN25_V			(1 << 6)
+#define	PINCTRL_DRIVE11_BANK2_PIN25_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE11_BANK2_PIN25_MA_OFFSET		4
+#define	PINCTRL_DRIVE11_BANK2_PIN24_V			(1 << 2)
+#define	PINCTRL_DRIVE11_BANK2_PIN24_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE11_BANK2_PIN24_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE12_BANK3_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE12_BANK3_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE12_BANK3_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE12_BANK3_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE12_BANK3_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE12_BANK3_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE12_BANK3_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE12_BANK3_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE12_BANK3_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE12_BANK3_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE12_BANK3_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE12_BANK3_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE12_BANK3_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE12_BANK3_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE12_BANK3_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE12_BANK3_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE12_BANK3_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE12_BANK3_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE12_BANK3_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE12_BANK3_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE12_BANK3_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE12_BANK3_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE12_BANK3_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE12_BANK3_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE13_BANK3_PIN15_V			(1 << 30)
+#define	PINCTRL_DRIVE13_BANK3_PIN15_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE13_BANK3_PIN15_MA_OFFSET		28
+#define	PINCTRL_DRIVE13_BANK3_PIN14_V			(1 << 26)
+#define	PINCTRL_DRIVE13_BANK3_PIN14_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE13_BANK3_PIN14_MA_OFFSET		24
+#define	PINCTRL_DRIVE13_BANK3_PIN13_V			(1 << 22)
+#define	PINCTRL_DRIVE13_BANK3_PIN13_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE13_BANK3_PIN13_MA_OFFSET		20
+#define	PINCTRL_DRIVE13_BANK3_PIN12_V			(1 << 18)
+#define	PINCTRL_DRIVE13_BANK3_PIN12_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE13_BANK3_PIN12_MA_OFFSET		16
+#define	PINCTRL_DRIVE13_BANK3_PIN11_V			(1 << 14)
+#define	PINCTRL_DRIVE13_BANK3_PIN11_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE13_BANK3_PIN11_MA_OFFSET		12
+#define	PINCTRL_DRIVE13_BANK3_PIN10_V			(1 << 10)
+#define	PINCTRL_DRIVE13_BANK3_PIN10_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE13_BANK3_PIN10_MA_OFFSET		8
+#define	PINCTRL_DRIVE13_BANK3_PIN09_V			(1 << 6)
+#define	PINCTRL_DRIVE13_BANK3_PIN09_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE13_BANK3_PIN09_MA_OFFSET		4
+#define	PINCTRL_DRIVE13_BANK3_PIN08_V			(1 << 2)
+#define	PINCTRL_DRIVE13_BANK3_PIN08_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE13_BANK3_PIN08_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE14_BANK3_PIN23_V			(1 << 30)
+#define	PINCTRL_DRIVE14_BANK3_PIN23_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE14_BANK3_PIN23_MA_OFFSET		28
+#define	PINCTRL_DRIVE14_BANK3_PIN22_V			(1 << 26)
+#define	PINCTRL_DRIVE14_BANK3_PIN22_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE14_BANK3_PIN22_MA_OFFSET		24
+#define	PINCTRL_DRIVE14_BANK3_PIN21_V			(1 << 22)
+#define	PINCTRL_DRIVE14_BANK3_PIN21_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE14_BANK3_PIN21_MA_OFFSET		20
+#define	PINCTRL_DRIVE14_BANK3_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE14_BANK3_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE14_BANK3_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE14_BANK3_PIN18_V			(1 << 10)
+#define	PINCTRL_DRIVE14_BANK3_PIN18_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE14_BANK3_PIN18_MA_OFFSET		8
+#define	PINCTRL_DRIVE14_BANK3_PIN17_V			(1 << 6)
+#define	PINCTRL_DRIVE14_BANK3_PIN17_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE14_BANK3_PIN17_MA_OFFSET		4
+#define	PINCTRL_DRIVE14_BANK3_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE14_BANK3_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE14_BANK3_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE15_BANK3_PIN30_V			(1 << 26)
+#define	PINCTRL_DRIVE15_BANK3_PIN30_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE15_BANK3_PIN30_MA_OFFSET		24
+#define	PINCTRL_DRIVE15_BANK3_PIN29_V			(1 << 22)
+#define	PINCTRL_DRIVE15_BANK3_PIN29_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE15_BANK3_PIN29_MA_OFFSET		20
+#define	PINCTRL_DRIVE15_BANK3_PIN28_V			(1 << 18)
+#define	PINCTRL_DRIVE15_BANK3_PIN28_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE15_BANK3_PIN28_MA_OFFSET		16
+#define	PINCTRL_DRIVE15_BANK3_PIN27_V			(1 << 14)
+#define	PINCTRL_DRIVE15_BANK3_PIN27_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE15_BANK3_PIN27_MA_OFFSET		12
+#define	PINCTRL_DRIVE15_BANK3_PIN26_V			(1 << 10)
+#define	PINCTRL_DRIVE15_BANK3_PIN26_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE15_BANK3_PIN26_MA_OFFSET		8
+#define	PINCTRL_DRIVE15_BANK3_PIN25_V			(1 << 6)
+#define	PINCTRL_DRIVE15_BANK3_PIN25_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE15_BANK3_PIN25_MA_OFFSET		4
+#define	PINCTRL_DRIVE15_BANK3_PIN24_V			(1 << 2)
+#define	PINCTRL_DRIVE15_BANK3_PIN24_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE15_BANK3_PIN24_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE16_BANK4_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE16_BANK4_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE16_BANK4_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE16_BANK4_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE16_BANK4_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE16_BANK4_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE16_BANK4_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE16_BANK4_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE16_BANK4_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE16_BANK4_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE16_BANK4_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE16_BANK4_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE16_BANK4_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE16_BANK4_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE16_BANK4_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE16_BANK4_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE16_BANK4_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE16_BANK4_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE16_BANK4_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE16_BANK4_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE16_BANK4_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE16_BANK4_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE16_BANK4_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE16_BANK4_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE17_BANK4_PIN15_V			(1 << 30)
+#define	PINCTRL_DRIVE17_BANK4_PIN15_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE17_BANK4_PIN15_MA_OFFSET		28
+#define	PINCTRL_DRIVE17_BANK4_PIN14_V			(1 << 26)
+#define	PINCTRL_DRIVE17_BANK4_PIN14_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE17_BANK4_PIN14_MA_OFFSET		24
+#define	PINCTRL_DRIVE17_BANK4_PIN13_V			(1 << 22)
+#define	PINCTRL_DRIVE17_BANK4_PIN13_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE17_BANK4_PIN13_MA_OFFSET		20
+#define	PINCTRL_DRIVE17_BANK4_PIN12_V			(1 << 18)
+#define	PINCTRL_DRIVE17_BANK4_PIN12_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE17_BANK4_PIN12_MA_OFFSET		16
+#define	PINCTRL_DRIVE17_BANK4_PIN11_V			(1 << 14)
+#define	PINCTRL_DRIVE17_BANK4_PIN11_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE17_BANK4_PIN11_MA_OFFSET		12
+#define	PINCTRL_DRIVE17_BANK4_PIN10_V			(1 << 10)
+#define	PINCTRL_DRIVE17_BANK4_PIN10_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE17_BANK4_PIN10_MA_OFFSET		8
+#define	PINCTRL_DRIVE17_BANK4_PIN09_V			(1 << 6)
+#define	PINCTRL_DRIVE17_BANK4_PIN09_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE17_BANK4_PIN09_MA_OFFSET		4
+#define	PINCTRL_DRIVE17_BANK4_PIN08_V			(1 << 2)
+#define	PINCTRL_DRIVE17_BANK4_PIN08_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE17_BANK4_PIN08_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE18_BANK4_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE18_BANK4_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE18_BANK4_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE18_BANK4_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE18_BANK4_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE18_BANK4_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_PULL0_BANK0_PIN28			(1 << 28)
+#define	PINCTRL_PULL0_BANK0_PIN27			(1 << 27)
+#define	PINCTRL_PULL0_BANK0_PIN26			(1 << 26)
+#define	PINCTRL_PULL0_BANK0_PIN25			(1 << 25)
+#define	PINCTRL_PULL0_BANK0_PIN24			(1 << 24)
+#define	PINCTRL_PULL0_BANK0_PIN23			(1 << 23)
+#define	PINCTRL_PULL0_BANK0_PIN22			(1 << 22)
+#define	PINCTRL_PULL0_BANK0_PIN21			(1 << 21)
+#define	PINCTRL_PULL0_BANK0_PIN20			(1 << 20)
+#define	PINCTRL_PULL0_BANK0_PIN19			(1 << 19)
+#define	PINCTRL_PULL0_BANK0_PIN18			(1 << 18)
+#define	PINCTRL_PULL0_BANK0_PIN17			(1 << 17)
+#define	PINCTRL_PULL0_BANK0_PIN16			(1 << 16)
+#define	PINCTRL_PULL0_BANK0_PIN07			(1 << 7)
+#define	PINCTRL_PULL0_BANK0_PIN06			(1 << 6)
+#define	PINCTRL_PULL0_BANK0_PIN05			(1 << 5)
+#define	PINCTRL_PULL0_BANK0_PIN04			(1 << 4)
+#define	PINCTRL_PULL0_BANK0_PIN03			(1 << 3)
+#define	PINCTRL_PULL0_BANK0_PIN02			(1 << 2)
+#define	PINCTRL_PULL0_BANK0_PIN01			(1 << 1)
+#define	PINCTRL_PULL0_BANK0_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL1_BANK1_PIN31			(1 << 31)
+#define	PINCTRL_PULL1_BANK1_PIN30			(1 << 30)
+#define	PINCTRL_PULL1_BANK1_PIN29			(1 << 29)
+#define	PINCTRL_PULL1_BANK1_PIN28			(1 << 28)
+#define	PINCTRL_PULL1_BANK1_PIN27			(1 << 27)
+#define	PINCTRL_PULL1_BANK1_PIN26			(1 << 26)
+#define	PINCTRL_PULL1_BANK1_PIN25			(1 << 25)
+#define	PINCTRL_PULL1_BANK1_PIN24			(1 << 24)
+#define	PINCTRL_PULL1_BANK1_PIN23			(1 << 23)
+#define	PINCTRL_PULL1_BANK1_PIN22			(1 << 22)
+#define	PINCTRL_PULL1_BANK1_PIN21			(1 << 21)
+#define	PINCTRL_PULL1_BANK1_PIN20			(1 << 20)
+#define	PINCTRL_PULL1_BANK1_PIN19			(1 << 19)
+#define	PINCTRL_PULL1_BANK1_PIN18			(1 << 18)
+#define	PINCTRL_PULL1_BANK1_PIN17			(1 << 17)
+#define	PINCTRL_PULL1_BANK1_PIN16			(1 << 16)
+#define	PINCTRL_PULL1_BANK1_PIN15			(1 << 15)
+#define	PINCTRL_PULL1_BANK1_PIN14			(1 << 14)
+#define	PINCTRL_PULL1_BANK1_PIN13			(1 << 13)
+#define	PINCTRL_PULL1_BANK1_PIN12			(1 << 12)
+#define	PINCTRL_PULL1_BANK1_PIN11			(1 << 11)
+#define	PINCTRL_PULL1_BANK1_PIN10			(1 << 10)
+#define	PINCTRL_PULL1_BANK1_PIN09			(1 << 9)
+#define	PINCTRL_PULL1_BANK1_PIN08			(1 << 8)
+#define	PINCTRL_PULL1_BANK1_PIN07			(1 << 7)
+#define	PINCTRL_PULL1_BANK1_PIN06			(1 << 6)
+#define	PINCTRL_PULL1_BANK1_PIN05			(1 << 5)
+#define	PINCTRL_PULL1_BANK1_PIN04			(1 << 4)
+#define	PINCTRL_PULL1_BANK1_PIN03			(1 << 3)
+#define	PINCTRL_PULL1_BANK1_PIN02			(1 << 2)
+#define	PINCTRL_PULL1_BANK1_PIN01			(1 << 1)
+#define	PINCTRL_PULL1_BANK1_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL2_BANK2_PIN27			(1 << 27)
+#define	PINCTRL_PULL2_BANK2_PIN26			(1 << 26)
+#define	PINCTRL_PULL2_BANK2_PIN25			(1 << 25)
+#define	PINCTRL_PULL2_BANK2_PIN24			(1 << 24)
+#define	PINCTRL_PULL2_BANK2_PIN21			(1 << 21)
+#define	PINCTRL_PULL2_BANK2_PIN20			(1 << 20)
+#define	PINCTRL_PULL2_BANK2_PIN19			(1 << 19)
+#define	PINCTRL_PULL2_BANK2_PIN18			(1 << 18)
+#define	PINCTRL_PULL2_BANK2_PIN17			(1 << 17)
+#define	PINCTRL_PULL2_BANK2_PIN16			(1 << 16)
+#define	PINCTRL_PULL2_BANK2_PIN15			(1 << 15)
+#define	PINCTRL_PULL2_BANK2_PIN14			(1 << 14)
+#define	PINCTRL_PULL2_BANK2_PIN13			(1 << 13)
+#define	PINCTRL_PULL2_BANK2_PIN12			(1 << 12)
+#define	PINCTRL_PULL2_BANK2_PIN10			(1 << 10)
+#define	PINCTRL_PULL2_BANK2_PIN09			(1 << 9)
+#define	PINCTRL_PULL2_BANK2_PIN08			(1 << 8)
+#define	PINCTRL_PULL2_BANK2_PIN07			(1 << 7)
+#define	PINCTRL_PULL2_BANK2_PIN06			(1 << 6)
+#define	PINCTRL_PULL2_BANK2_PIN05			(1 << 5)
+#define	PINCTRL_PULL2_BANK2_PIN04			(1 << 4)
+#define	PINCTRL_PULL2_BANK2_PIN03			(1 << 3)
+#define	PINCTRL_PULL2_BANK2_PIN02			(1 << 2)
+#define	PINCTRL_PULL2_BANK2_PIN01			(1 << 1)
+#define	PINCTRL_PULL2_BANK2_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL3_BANK3_PIN30			(1 << 30)
+#define	PINCTRL_PULL3_BANK3_PIN29			(1 << 29)
+#define	PINCTRL_PULL3_BANK3_PIN28			(1 << 28)
+#define	PINCTRL_PULL3_BANK3_PIN27			(1 << 27)
+#define	PINCTRL_PULL3_BANK3_PIN26			(1 << 26)
+#define	PINCTRL_PULL3_BANK3_PIN25			(1 << 25)
+#define	PINCTRL_PULL3_BANK3_PIN24			(1 << 24)
+#define	PINCTRL_PULL3_BANK3_PIN23			(1 << 23)
+#define	PINCTRL_PULL3_BANK3_PIN22			(1 << 22)
+#define	PINCTRL_PULL3_BANK3_PIN21			(1 << 21)
+#define	PINCTRL_PULL3_BANK3_PIN20			(1 << 20)
+#define	PINCTRL_PULL3_BANK3_PIN18			(1 << 18)
+#define	PINCTRL_PULL3_BANK3_PIN17			(1 << 17)
+#define	PINCTRL_PULL3_BANK3_PIN16			(1 << 16)
+#define	PINCTRL_PULL3_BANK3_PIN15			(1 << 15)
+#define	PINCTRL_PULL3_BANK3_PIN14			(1 << 14)
+#define	PINCTRL_PULL3_BANK3_PIN13			(1 << 13)
+#define	PINCTRL_PULL3_BANK3_PIN12			(1 << 12)
+#define	PINCTRL_PULL3_BANK3_PIN11			(1 << 11)
+#define	PINCTRL_PULL3_BANK3_PIN10			(1 << 10)
+#define	PINCTRL_PULL3_BANK3_PIN09			(1 << 9)
+#define	PINCTRL_PULL3_BANK3_PIN08			(1 << 8)
+#define	PINCTRL_PULL3_BANK3_PIN07			(1 << 7)
+#define	PINCTRL_PULL3_BANK3_PIN06			(1 << 6)
+#define	PINCTRL_PULL3_BANK3_PIN05			(1 << 5)
+#define	PINCTRL_PULL3_BANK3_PIN04			(1 << 4)
+#define	PINCTRL_PULL3_BANK3_PIN03			(1 << 3)
+#define	PINCTRL_PULL3_BANK3_PIN02			(1 << 2)
+#define	PINCTRL_PULL3_BANK3_PIN01			(1 << 1)
+#define	PINCTRL_PULL3_BANK3_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL4_BANK4_PIN20			(1 << 20)
+#define	PINCTRL_PULL4_BANK4_PIN16			(1 << 16)
+#define	PINCTRL_PULL4_BANK4_PIN15			(1 << 15)
+#define	PINCTRL_PULL4_BANK4_PIN14			(1 << 14)
+#define	PINCTRL_PULL4_BANK4_PIN13			(1 << 13)
+#define	PINCTRL_PULL4_BANK4_PIN12			(1 << 12)
+#define	PINCTRL_PULL4_BANK4_PIN11			(1 << 11)
+#define	PINCTRL_PULL4_BANK4_PIN10			(1 << 10)
+#define	PINCTRL_PULL4_BANK4_PIN09			(1 << 9)
+#define	PINCTRL_PULL4_BANK4_PIN08			(1 << 8)
+#define	PINCTRL_PULL4_BANK4_PIN07			(1 << 7)
+#define	PINCTRL_PULL4_BANK4_PIN06			(1 << 6)
+#define	PINCTRL_PULL4_BANK4_PIN05			(1 << 5)
+#define	PINCTRL_PULL4_BANK4_PIN04			(1 << 4)
+#define	PINCTRL_PULL4_BANK4_PIN03			(1 << 3)
+#define	PINCTRL_PULL4_BANK4_PIN02			(1 << 2)
+#define	PINCTRL_PULL4_BANK4_PIN01			(1 << 1)
+#define	PINCTRL_PULL4_BANK4_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL5_BANK5_PIN26			(1 << 26)
+#define	PINCTRL_PULL5_BANK5_PIN23			(1 << 23)
+#define	PINCTRL_PULL5_BANK5_PIN22			(1 << 22)
+#define	PINCTRL_PULL5_BANK5_PIN21			(1 << 21)
+#define	PINCTRL_PULL5_BANK5_PIN20			(1 << 20)
+#define	PINCTRL_PULL5_BANK5_PIN19			(1 << 19)
+#define	PINCTRL_PULL5_BANK5_PIN18			(1 << 18)
+#define	PINCTRL_PULL5_BANK5_PIN17			(1 << 17)
+#define	PINCTRL_PULL5_BANK5_PIN16			(1 << 16)
+#define	PINCTRL_PULL5_BANK5_PIN15			(1 << 15)
+#define	PINCTRL_PULL5_BANK5_PIN14			(1 << 14)
+#define	PINCTRL_PULL5_BANK5_PIN13			(1 << 13)
+#define	PINCTRL_PULL5_BANK5_PIN12			(1 << 12)
+#define	PINCTRL_PULL5_BANK5_PIN11			(1 << 11)
+#define	PINCTRL_PULL5_BANK5_PIN10			(1 << 10)
+#define	PINCTRL_PULL5_BANK5_PIN09			(1 << 9)
+#define	PINCTRL_PULL5_BANK5_PIN08			(1 << 8)
+#define	PINCTRL_PULL5_BANK5_PIN07			(1 << 7)
+#define	PINCTRL_PULL5_BANK5_PIN06			(1 << 6)
+#define	PINCTRL_PULL5_BANK5_PIN05			(1 << 5)
+#define	PINCTRL_PULL5_BANK5_PIN04			(1 << 4)
+#define	PINCTRL_PULL5_BANK5_PIN03			(1 << 3)
+#define	PINCTRL_PULL5_BANK5_PIN02			(1 << 2)
+#define	PINCTRL_PULL5_BANK5_PIN01			(1 << 1)
+#define	PINCTRL_PULL5_BANK5_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL6_BANK6_PIN24			(1 << 24)
+#define	PINCTRL_PULL6_BANK6_PIN23			(1 << 23)
+#define	PINCTRL_PULL6_BANK6_PIN22			(1 << 22)
+#define	PINCTRL_PULL6_BANK6_PIN21			(1 << 21)
+#define	PINCTRL_PULL6_BANK6_PIN20			(1 << 20)
+#define	PINCTRL_PULL6_BANK6_PIN19			(1 << 19)
+#define	PINCTRL_PULL6_BANK6_PIN18			(1 << 18)
+#define	PINCTRL_PULL6_BANK6_PIN17			(1 << 17)
+#define	PINCTRL_PULL6_BANK6_PIN16			(1 << 16)
+#define	PINCTRL_PULL6_BANK6_PIN14			(1 << 14)
+#define	PINCTRL_PULL6_BANK6_PIN13			(1 << 13)
+#define	PINCTRL_PULL6_BANK6_PIN12			(1 << 12)
+#define	PINCTRL_PULL6_BANK6_PIN11			(1 << 11)
+#define	PINCTRL_PULL6_BANK6_PIN10			(1 << 10)
+#define	PINCTRL_PULL6_BANK6_PIN09			(1 << 9)
+#define	PINCTRL_PULL6_BANK6_PIN08			(1 << 8)
+#define	PINCTRL_PULL6_BANK6_PIN07			(1 << 7)
+#define	PINCTRL_PULL6_BANK6_PIN06			(1 << 6)
+#define	PINCTRL_PULL6_BANK6_PIN05			(1 << 5)
+#define	PINCTRL_PULL6_BANK6_PIN04			(1 << 4)
+#define	PINCTRL_PULL6_BANK6_PIN03			(1 << 3)
+#define	PINCTRL_PULL6_BANK6_PIN02			(1 << 2)
+#define	PINCTRL_PULL6_BANK6_PIN01			(1 << 1)
+#define	PINCTRL_PULL6_BANK6_PIN00			(1 << 0)
+
+#define	PINCTRL_DOUT0_DOUT_MASK				0x1fffffff
+#define	PINCTRL_DOUT0_DOUT_OFFSET			0
+
+#define	PINCTRL_DOUT1_DOUT_MASK				0xffffffff
+#define	PINCTRL_DOUT1_DOUT_OFFSET			0
+
+#define	PINCTRL_DOUT2_DOUT_MASK				0xfffffff
+#define	PINCTRL_DOUT2_DOUT_OFFSET			0
+
+#define	PINCTRL_DOUT3_DOUT_MASK				0x7fffffff
+#define	PINCTRL_DOUT3_DOUT_OFFSET			0
+
+#define	PINCTRL_DOUT4_DOUT_MASK				0x1fffff
+#define	PINCTRL_DOUT4_DOUT_OFFSET			0
+
+#define	PINCTRL_DIN0_DIN_MASK				0x1fffffff
+#define	PINCTRL_DIN0_DIN_OFFSET				0
+
+#define	PINCTRL_DIN1_DIN_MASK				0xffffffff
+#define	PINCTRL_DIN1_DIN_OFFSET				0
+
+#define	PINCTRL_DIN2_DIN_MASK				0xfffffff
+#define	PINCTRL_DIN2_DIN_OFFSET				0
+
+#define	PINCTRL_DIN3_DIN_MASK				0x7fffffff
+#define	PINCTRL_DIN3_DIN_OFFSET				0
+
+#define	PINCTRL_DIN4_DIN_MASK				0x1fffff
+#define	PINCTRL_DIN4_DIN_OFFSET				0
+
+#define	PINCTRL_DOE0_DOE_MASK				0x1fffffff
+#define	PINCTRL_DOE0_DOE_OFFSET				0
+
+#define	PINCTRL_DOE1_DOE_MASK				0xffffffff
+#define	PINCTRL_DOE1_DOE_OFFSET				0
+
+#define	PINCTRL_DOE2_DOE_MASK				0xfffffff
+#define	PINCTRL_DOE2_DOE_OFFSET				0
+
+#define	PINCTRL_DOE3_DOE_MASK				0x7fffffff
+#define	PINCTRL_DOE3_DOE_OFFSET				0
+
+#define	PINCTRL_DOE4_DOE_MASK				0x1fffff
+#define	PINCTRL_DOE4_DOE_OFFSET				0
+
+#define	PINCTRL_PIN2IRQ0_PIN2IRQ_MASK			0x1fffffff
+#define	PINCTRL_PIN2IRQ0_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_PIN2IRQ1_PIN2IRQ_MASK			0xffffffff
+#define	PINCTRL_PIN2IRQ1_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_PIN2IRQ2_PIN2IRQ_MASK			0xfffffff
+#define	PINCTRL_PIN2IRQ2_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_PIN2IRQ3_PIN2IRQ_MASK			0x7fffffff
+#define	PINCTRL_PIN2IRQ3_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_PIN2IRQ4_PIN2IRQ_MASK			0x1fffff
+#define	PINCTRL_PIN2IRQ4_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_IRQEN0_IRQEN_MASK			0x1fffffff
+#define	PINCTRL_IRQEN0_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQEN1_IRQEN_MASK			0xffffffff
+#define	PINCTRL_IRQEN1_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQEN2_IRQEN_MASK			0xfffffff
+#define	PINCTRL_IRQEN2_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQEN3_IRQEN_MASK			0x7fffffff
+#define	PINCTRL_IRQEN3_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQEN4_IRQEN_MASK			0x1fffff
+#define	PINCTRL_IRQEN4_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQLEVEL0_IRQLEVEL_MASK			0x1fffffff
+#define	PINCTRL_IRQLEVEL0_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQLEVEL1_IRQLEVEL_MASK			0xffffffff
+#define	PINCTRL_IRQLEVEL1_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQLEVEL2_IRQLEVEL_MASK			0xfffffff
+#define	PINCTRL_IRQLEVEL2_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQLEVEL3_IRQLEVEL_MASK			0x7fffffff
+#define	PINCTRL_IRQLEVEL3_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQLEVEL4_IRQLEVEL_MASK			0x1fffff
+#define	PINCTRL_IRQLEVEL4_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQPOL0_IRQPOL_MASK			0x1fffffff
+#define	PINCTRL_IRQPOL0_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQPOL1_IRQPOL_MASK			0xffffffff
+#define	PINCTRL_IRQPOL1_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQPOL2_IRQPOL_MASK			0xfffffff
+#define	PINCTRL_IRQPOL2_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQPOL3_IRQPOL_MASK			0x7fffffff
+#define	PINCTRL_IRQPOL3_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQPOL4_IRQPOL_MASK			0x1fffff
+#define	PINCTRL_IRQPOL4_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQSTAT0_IRQSTAT_MASK			0x1fffffff
+#define	PINCTRL_IRQSTAT0_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_IRQSTAT1_IRQSTAT_MASK			0xffffffff
+#define	PINCTRL_IRQSTAT1_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_IRQSTAT2_IRQSTAT_MASK			0xfffffff
+#define	PINCTRL_IRQSTAT2_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_IRQSTAT3_IRQSTAT_MASK			0x7fffffff
+#define	PINCTRL_IRQSTAT3_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_IRQSTAT4_IRQSTAT_MASK			0x1fffff
+#define	PINCTRL_IRQSTAT4_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_EMI_ODT_CTRL_ADDRESS_CALIB_MASK		(0x3 << 26)
+#define	PINCTRL_EMI_ODT_CTRL_ADDRESS_CALIB_OFFSET	26
+#define	PINCTRL_EMI_ODT_CTRL_ADDRESS_TLOAD_MASK		(0x3 << 24)
+#define	PINCTRL_EMI_ODT_CTRL_ADDRESS_TLOAD_OFFSET	24
+#define	PINCTRL_EMI_ODT_CTRL_CONTROL_CALIB_MASK		(0x3 << 22)
+#define	PINCTRL_EMI_ODT_CTRL_CONTROL_CALIB_OFFSET	22
+#define	PINCTRL_EMI_ODT_CTRL_CONTROL_TLOAD_MASK		(0x3 << 20)
+#define	PINCTRL_EMI_ODT_CTRL_CONTROL_TLOAD_OFFSET	20
+#define	PINCTRL_EMI_ODT_CTRL_DUALPAD_CALIB_MASK		(0x3 << 18)
+#define	PINCTRL_EMI_ODT_CTRL_DUALPAD_CALIB_OFFSET	18
+#define	PINCTRL_EMI_ODT_CTRL_DUALPAD_TLOAD_MASK		(0x3 << 16)
+#define	PINCTRL_EMI_ODT_CTRL_DUALPAD_TLOAD_OFFSET	16
+#define	PINCTRL_EMI_ODT_CTRL_SLICE3_CALIB_MASK		(0x3 << 14)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE3_CALIB_OFFSET	14
+#define	PINCTRL_EMI_ODT_CTRL_SLICE3_TLOAD_MASK		(0x3 << 12)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE3_TLOAD_OFFSET	12
+#define	PINCTRL_EMI_ODT_CTRL_SLICE2_CALIB_MASK		(0x3 << 10)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE2_CALIB_OFFSET	10
+#define	PINCTRL_EMI_ODT_CTRL_SLICE2_TLOAD_MASK		(0x3 << 8)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE2_TLOAD_OFFSET	8
+#define	PINCTRL_EMI_ODT_CTRL_SLICE1_CALIB_MASK		(0x3 << 6)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE1_CALIB_OFFSET	6
+#define	PINCTRL_EMI_ODT_CTRL_SLICE1_TLOAD_MASK		(0x3 << 4)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE1_TLOAD_OFFSET	4
+#define	PINCTRL_EMI_ODT_CTRL_SLICE0_CALIB_MASK		(0x3 << 2)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE0_CALIB_OFFSET	2
+#define	PINCTRL_EMI_ODT_CTRL_SLICE0_TLOAD_MASK		(0x3 << 0)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE0_TLOAD_OFFSET	0
+
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_MASK		(0x3 << 16)
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_OFFSET		16
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_mDDR		(0x0 << 16)
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_GPIO		(0x1 << 16)
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_LVDDR2		(0x2 << 16)
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2		(0x3 << 16)
+#define	PINCTRL_EMI_DS_CTRL_ADDRESS_MA_MASK		(0x3 << 12)
+#define	PINCTRL_EMI_DS_CTRL_ADDRESS_MA_OFFSET		12
+#define	PINCTRL_EMI_DS_CTRL_CONTROL_MA_MASK		(0x3 << 10)
+#define	PINCTRL_EMI_DS_CTRL_CONTROL_MA_OFFSET		10
+#define	PINCTRL_EMI_DS_CTRL_DUALPAD_MA_MASK		(0x3 << 8)
+#define	PINCTRL_EMI_DS_CTRL_DUALPAD_MA_OFFSET		8
+#define	PINCTRL_EMI_DS_CTRL_SLICE3_MA_MASK		(0x3 << 6)
+#define	PINCTRL_EMI_DS_CTRL_SLICE3_MA_OFFSET		6
+#define	PINCTRL_EMI_DS_CTRL_SLICE2_MA_MASK		(0x3 << 4)
+#define	PINCTRL_EMI_DS_CTRL_SLICE2_MA_OFFSET		4
+#define	PINCTRL_EMI_DS_CTRL_SLICE1_MA_MASK		(0x3 << 2)
+#define	PINCTRL_EMI_DS_CTRL_SLICE1_MA_OFFSET		2
+#define	PINCTRL_EMI_DS_CTRL_SLICE0_MA_MASK		(0x3 << 0)
+#define	PINCTRL_EMI_DS_CTRL_SLICE0_MA_OFFSET		0
+
+#endif /* __MX28_REGS_PINCTRL_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-power.h b/arch/arm/include/asm/arch-mx28/regs-power.h
new file mode 100644
index 0000000..9da63ad
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-power.h
@@ -0,0 +1,413 @@
+/*
+ * Freescale i.MX28 Power Controller Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_POWER_H__
+#define __MX28_REGS_POWER_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_power_regs {
+	mx28_reg(hw_power_ctrl)
+	mx28_reg(hw_power_5vctrl)
+	mx28_reg(hw_power_minpwr)
+	mx28_reg(hw_power_charge)
+	uint32_t	hw_power_vdddctrl;
+	uint32_t	reserved_vddd[3];
+	uint32_t	hw_power_vddactrl;
+	uint32_t	reserved_vdda[3];
+	uint32_t	hw_power_vddioctrl;
+	uint32_t	reserved_vddio[3];
+	uint32_t	hw_power_vddmemctrl;
+	uint32_t	reserved_vddmem[3];
+	uint32_t	hw_power_dcdc4p2;
+	uint32_t	reserved_dcdc4p2[3];
+	uint32_t	hw_power_misc;
+	uint32_t	reserved_misc[3];
+	uint32_t	hw_power_dclimits;
+	uint32_t	reserved_dclimits[3];
+	mx28_reg(hw_power_loopctrl)
+	uint32_t	hw_power_sts;
+	uint32_t	reserved_sts[3];
+	mx28_reg(hw_power_speed)
+	uint32_t	hw_power_battmonitor;
+	uint32_t	reserved_battmonitor[3];
+
+	uint32_t	reserved[4];
+
+	mx28_reg(hw_power_reset)
+	mx28_reg(hw_power_debug)
+	mx28_reg(hw_power_thermal)
+	mx28_reg(hw_power_usb1ctrl)
+	mx28_reg(hw_power_special)
+	mx28_reg(hw_power_version)
+	mx28_reg(hw_power_anaclkctrl)
+	mx28_reg(hw_power_refctrl)
+};
+#endif
+
+#define	POWER_CTRL_PSWITCH_MID_TRAN			(1 << 27)
+#define	POWER_CTRL_DCDC4P2_BO_IRQ			(1 << 24)
+#define	POWER_CTRL_ENIRQ_DCDC4P2_BO			(1 << 23)
+#define	POWER_CTRL_VDD5V_DROOP_IRQ			(1 << 22)
+#define	POWER_CTRL_ENIRQ_VDD5V_DROOP			(1 << 21)
+#define	POWER_CTRL_PSWITCH_IRQ				(1 << 20)
+#define	POWER_CTRL_PSWITCH_IRQ_SRC			(1 << 19)
+#define	POWER_CTRL_POLARITY_PSWITCH			(1 << 18)
+#define	POWER_CTRL_ENIRQ_PSWITCH			(1 << 17)
+#define	POWER_CTRL_POLARITY_DC_OK			(1 << 16)
+#define	POWER_CTRL_DC_OK_IRQ				(1 << 15)
+#define	POWER_CTRL_ENIRQ_DC_OK				(1 << 14)
+#define	POWER_CTRL_BATT_BO_IRQ				(1 << 13)
+#define	POWER_CTRL_ENIRQ_BATT_BO			(1 << 12)
+#define	POWER_CTRL_VDDIO_BO_IRQ				(1 << 11)
+#define	POWER_CTRL_ENIRQ_VDDIO_BO			(1 << 10)
+#define	POWER_CTRL_VDDA_BO_IRQ				(1 << 9)
+#define	POWER_CTRL_ENIRQ_VDDA_BO			(1 << 8)
+#define	POWER_CTRL_VDDD_BO_IRQ				(1 << 7)
+#define	POWER_CTRL_ENIRQ_VDDD_BO			(1 << 6)
+#define	POWER_CTRL_POLARITY_VBUSVALID			(1 << 5)
+#define	POWER_CTRL_VBUS_VALID_IRQ			(1 << 4)
+#define	POWER_CTRL_ENIRQ_VBUS_VALID			(1 << 3)
+#define	POWER_CTRL_POLARITY_VDD5V_GT_VDDIO		(1 << 2)
+#define	POWER_CTRL_VDD5V_GT_VDDIO_IRQ			(1 << 1)
+#define	POWER_CTRL_ENIRQ_VDD5V_GT_VDDIO			(1 << 0)
+
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_MASK		(0x3 << 30)
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_OFFSET		30
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_4V3			(0x0 << 30)
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_4V4			(0x1 << 30)
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_4V5			(0x2 << 30)
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_4V7			(0x3 << 30)
+#define	POWER_5VCTRL_HEADROOM_ADJ_MASK			(0x7 << 24)
+#define	POWER_5VCTRL_HEADROOM_ADJ_OFFSET		24
+#define	POWER_5VCTRL_PWD_CHARGE_4P2_MASK		(0x3 << 20)
+#define	POWER_5VCTRL_PWD_CHARGE_4P2_OFFSET		20
+#define	POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK		(0x3f << 12)
+#define	POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET		12
+#define	POWER_5VCTRL_VBUSVALID_TRSH_MASK		(0x7 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_OFFSET		8
+#define	POWER_5VCTRL_VBUSVALID_TRSH_2V9			(0x0 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V0			(0x1 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V1			(0x2 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V2			(0x3 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V3			(0x4 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V4			(0x5 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V5			(0x6 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V6			(0x7 << 8)
+#define	POWER_5VCTRL_PWDN_5VBRNOUT			(1 << 7)
+#define	POWER_5VCTRL_ENABLE_LINREG_ILIMIT		(1 << 6)
+#define	POWER_5VCTRL_DCDC_XFER				(1 << 5)
+#define	POWER_5VCTRL_VBUSVALID_5VDETECT			(1 << 4)
+#define	POWER_5VCTRL_VBUSVALID_TO_B			(1 << 3)
+#define	POWER_5VCTRL_ILIMIT_EQ_ZERO			(1 << 2)
+#define	POWER_5VCTRL_PWRUP_VBUS_CMPS			(1 << 1)
+#define	POWER_5VCTRL_ENABLE_DCDC			(1 << 0)
+
+#define	POWER_MINPWR_LOWPWR_4P2				(1 << 14)
+#define	POWER_MINPWR_PWD_BO				(1 << 12)
+#define	POWER_MINPWR_USE_VDDXTAL_VBG			(1 << 11)
+#define	POWER_MINPWR_PWD_ANA_CMPS			(1 << 10)
+#define	POWER_MINPWR_ENABLE_OSC				(1 << 9)
+#define	POWER_MINPWR_SELECT_OSC				(1 << 8)
+#define	POWER_MINPWR_FBG_OFF				(1 << 7)
+#define	POWER_MINPWR_DOUBLE_FETS			(1 << 6)
+#define	POWER_MINPWR_HALFFETS				(1 << 5)
+#define	POWER_MINPWR_LESSANA_I				(1 << 4)
+#define	POWER_MINPWR_PWD_XTAL24				(1 << 3)
+#define	POWER_MINPWR_DC_STOPCLK				(1 << 2)
+#define	POWER_MINPWR_EN_DC_PFM				(1 << 1)
+#define	POWER_MINPWR_DC_HALFCLK				(1 << 0)
+
+#define	POWER_CHARGE_ADJ_VOLT_MASK			(0x7 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_OFFSET			24
+#define	POWER_CHARGE_ADJ_VOLT_M025P			(0x1 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_P050P			(0x2 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_M075P			(0x3 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_P025P			(0x4 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_M050P			(0x5 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_P075P			(0x6 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_M100P			(0x7 << 24)
+#define	POWER_CHARGE_ENABLE_LOAD			(1 << 22)
+#define	POWER_CHARGE_ENABLE_FAULT_DETECT		(1 << 20)
+#define	POWER_CHARGE_CHRG_STS_OFF			(1 << 19)
+#define	POWER_CHARGE_LIION_4P1				(1 << 18)
+#define	POWER_CHARGE_PWD_BATTCHRG			(1 << 16)
+#define	POWER_CHARGE_ENABLE_CHARGER_USB1		(1 << 13)
+#define	POWER_CHARGE_ENABLE_CHARGER_USB0		(1 << 12)
+#define	POWER_CHARGE_STOP_ILIMIT_MASK			(0xf << 8)
+#define	POWER_CHARGE_STOP_ILIMIT_OFFSET			8
+#define	POWER_CHARGE_STOP_ILIMIT_10MA			(0x1 << 8)
+#define	POWER_CHARGE_STOP_ILIMIT_20MA			(0x2 << 8)
+#define	POWER_CHARGE_STOP_ILIMIT_50MA			(0x4 << 8)
+#define	POWER_CHARGE_STOP_ILIMIT_100MA			(0x8 << 8)
+#define	POWER_CHARGE_BATTCHRG_I_MASK			0x3f
+#define	POWER_CHARGE_BATTCHRG_I_OFFSET			0
+#define	POWER_CHARGE_BATTCHRG_I_10MA			0x01
+#define	POWER_CHARGE_BATTCHRG_I_20MA			0x02
+#define	POWER_CHARGE_BATTCHRG_I_50MA			0x04
+#define	POWER_CHARGE_BATTCHRG_I_100MA			0x08
+#define	POWER_CHARGE_BATTCHRG_I_200MA			0x10
+#define	POWER_CHARGE_BATTCHRG_I_400MA			0x20
+
+#define	POWER_VDDDCTRL_ADJTN_MASK			(0xf << 28)
+#define	POWER_VDDDCTRL_ADJTN_OFFSET			28
+#define	POWER_VDDDCTRL_PWDN_BRNOUT			(1 << 23)
+#define	POWER_VDDDCTRL_DISABLE_STEPPING			(1 << 22)
+#define	POWER_VDDDCTRL_ENABLE_LINREG			(1 << 21)
+#define	POWER_VDDDCTRL_DISABLE_FET			(1 << 20)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_MASK		(0x3 << 16)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_OFFSET		16
+#define	POWER_VDDDCTRL_LINREG_OFFSET_0STEPS		(0x0 << 16)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_ABOVE	(0x1 << 16)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW	(0x2 << 16)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_2STEPS_BELOW	(0x3 << 16)
+#define	POWER_VDDDCTRL_BO_OFFSET_MASK			(0x7 << 8)
+#define	POWER_VDDDCTRL_BO_OFFSET_OFFSET			8
+#define	POWER_VDDDCTRL_TRG_MASK				0x1f
+#define	POWER_VDDDCTRL_TRG_OFFSET			0
+
+#define	POWER_VDDACTRL_PWDN_BRNOUT			(1 << 19)
+#define	POWER_VDDACTRL_DISABLE_STEPPING			(1 << 18)
+#define	POWER_VDDACTRL_ENABLE_LINREG			(1 << 17)
+#define	POWER_VDDACTRL_DISABLE_FET			(1 << 16)
+#define	POWER_VDDACTRL_LINREG_OFFSET_MASK		(0x3 << 12)
+#define	POWER_VDDACTRL_LINREG_OFFSET_OFFSET		12
+#define	POWER_VDDACTRL_LINREG_OFFSET_0STEPS		(0x0 << 12)
+#define	POWER_VDDACTRL_LINREG_OFFSET_1STEPS_ABOVE	(0x1 << 12)
+#define	POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW	(0x2 << 12)
+#define	POWER_VDDACTRL_LINREG_OFFSET_2STEPS_BELOW	(0x3 << 12)
+#define	POWER_VDDACTRL_BO_OFFSET_MASK			(0x7 << 8)
+#define	POWER_VDDACTRL_BO_OFFSET_OFFSET			8
+#define	POWER_VDDACTRL_TRG_MASK				0x1f
+#define	POWER_VDDACTRL_TRG_OFFSET			0
+
+#define	POWER_VDDIOCTRL_ADJTN_MASK			(0xf << 20)
+#define	POWER_VDDIOCTRL_ADJTN_OFFSET			20
+#define	POWER_VDDIOCTRL_PWDN_BRNOUT			(1 << 18)
+#define	POWER_VDDIOCTRL_DISABLE_STEPPING		(1 << 17)
+#define	POWER_VDDIOCTRL_DISABLE_FET			(1 << 16)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_MASK		(0x3 << 12)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_OFFSET		12
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_0STEPS		(0x0 << 12)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_ABOVE	(0x1 << 12)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW	(0x2 << 12)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_2STEPS_BELOW	(0x3 << 12)
+#define	POWER_VDDIOCTRL_BO_OFFSET_MASK			(0x7 << 8)
+#define	POWER_VDDIOCTRL_BO_OFFSET_OFFSET		8
+#define	POWER_VDDIOCTRL_TRG_MASK			0x1f
+#define	POWER_VDDIOCTRL_TRG_OFFSET			0
+
+#define	POWER_VDDMEMCTRL_PULLDOWN_ACTIVE		(1 << 10)
+#define	POWER_VDDMEMCTRL_ENABLE_ILIMIT			(1 << 9)
+#define	POWER_VDDMEMCTRL_ENABLE_LINREG			(1 << 8)
+#define	POWER_VDDMEMCTRL_BO_OFFSET_MASK			(0x7 << 5)
+#define	POWER_VDDMEMCTRL_BO_OFFSET_OFFSET		5
+#define	POWER_VDDMEMCTRL_TRG_MASK			0x1f
+#define	POWER_VDDMEMCTRL_TRG_OFFSET			0
+
+#define	POWER_DCDC4P2_DROPOUT_CTRL_MASK			(0xf << 28)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_OFFSET		28
+#define	POWER_DCDC4P2_DROPOUT_CTRL_200MV		(0x3 << 30)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_100MV		(0x2 << 30)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_50MV			(0x1 << 30)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_25MV			(0x0 << 30)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_SRC_4P2		(0x0 << 28)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_SRC_4P2_LT_BATT	(0x1 << 28)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL		(0x2 << 28)
+#define	POWER_DCDC4P2_ISTEAL_THRESH_MASK		(0x3 << 24)
+#define	POWER_DCDC4P2_ISTEAL_THRESH_OFFSET		24
+#define	POWER_DCDC4P2_ENABLE_4P2			(1 << 23)
+#define	POWER_DCDC4P2_ENABLE_DCDC			(1 << 22)
+#define	POWER_DCDC4P2_HYST_DIR				(1 << 21)
+#define	POWER_DCDC4P2_HYST_THRESH			(1 << 20)
+#define	POWER_DCDC4P2_TRG_MASK				(0x7 << 16)
+#define	POWER_DCDC4P2_TRG_OFFSET			16
+#define	POWER_DCDC4P2_TRG_4V2				(0x0 << 16)
+#define	POWER_DCDC4P2_TRG_4V1				(0x1 << 16)
+#define	POWER_DCDC4P2_TRG_4V0				(0x2 << 16)
+#define	POWER_DCDC4P2_TRG_3V9				(0x3 << 16)
+#define	POWER_DCDC4P2_TRG_BATT				(0x4 << 16)
+#define	POWER_DCDC4P2_BO_MASK				(0x1f << 8)
+#define	POWER_DCDC4P2_BO_OFFSET				8
+#define	POWER_DCDC4P2_CMPTRIP_MASK			0x1f
+#define	POWER_DCDC4P2_CMPTRIP_OFFSET			0
+
+#define	POWER_MISC_FREQSEL_MASK				(0x7 << 4)
+#define	POWER_MISC_FREQSEL_OFFSET			4
+#define	POWER_MISC_FREQSEL_20MHZ			(0x1 << 4)
+#define	POWER_MISC_FREQSEL_24MHZ			(0x2 << 4)
+#define	POWER_MISC_FREQSEL_19MHZ			(0x3 << 4)
+#define	POWER_MISC_FREQSEL_14MHZ			(0x4 << 4)
+#define	POWER_MISC_FREQSEL_18MHZ			(0x5 << 4)
+#define	POWER_MISC_FREQSEL_21MHZ			(0x6 << 4)
+#define	POWER_MISC_FREQSEL_17MHZ			(0x7 << 4)
+#define	POWER_MISC_DISABLE_FET_BO_LOGIC			(1 << 3)
+#define	POWER_MISC_DELAY_TIMING				(1 << 2)
+#define	POWER_MISC_TEST					(1 << 1)
+#define	POWER_MISC_SEL_PLLCLK				(1 << 0)
+
+#define	POWER_DCLIMITS_POSLIMIT_BUCK_MASK		(0x7f << 8)
+#define	POWER_DCLIMITS_POSLIMIT_BUCK_OFFSET		8
+#define	POWER_DCLIMITS_NEGLIMIT_MASK			0x7f
+#define	POWER_DCLIMITS_NETLIMIT_OFFSET			0
+
+#define	POWER_LOOPCTRL_TOGGLE_DIF			(1 << 20)
+#define	POWER_LOOPCTRL_HYST_SIGN			(1 << 19)
+#define	POWER_LOOPCTRL_EN_CM_HYST			(1 << 18)
+#define	POWER_LOOPCTRL_EN_DF_HYST			(1 << 17)
+#define	POWER_LOOPCTRL_CM_HYST_THRESH			(1 << 16)
+#define	POWER_LOOPCTRL_DF_HYST_THRESH			(1 << 15)
+#define	POWER_LOOPCTRL_RCSCALE_THRESH			(1 << 14)
+#define	POWER_LOOPCTRL_EN_RCSCALE_MASK			(0x3 << 12)
+#define	POWER_LOOPCTRL_EN_RCSCALE_OFFSET		12
+#define	POWER_LOOPCTRL_EN_RCSCALE_DIS			(0x0 << 12)
+#define	POWER_LOOPCTRL_EN_RCSCALE_2X			(0x1 << 12)
+#define	POWER_LOOPCTRL_EN_RCSCALE_4X			(0x2 << 12)
+#define	POWER_LOOPCTRL_EN_RCSCALE_8X			(0x3 << 12)
+#define	POWER_LOOPCTRL_DC_FF_MASK			(0x7 << 8)
+#define	POWER_LOOPCTRL_DC_FF_OFFSET			8
+#define	POWER_LOOPCTRL_DC_R_MASK			(0xf << 4)
+#define	POWER_LOOPCTRL_DC_R_OFFSET			4
+#define	POWER_LOOPCTRL_DC_C_MASK			0x3
+#define	POWER_LOOPCTRL_DC_C_OFFSET			0
+#define	POWER_LOOPCTRL_DC_C_MAX				0x0
+#define	POWER_LOOPCTRL_DC_C_2X				0x1
+#define	POWER_LOOPCTRL_DC_C_4X				0x2
+#define	POWER_LOOPCTRL_DC_C_MIN				0x3
+
+#define	POWER_STS_PWRUP_SOURCE_MASK			(0x3f << 24)
+#define	POWER_STS_PWRUP_SOURCE_OFFSET			24
+#define	POWER_STS_PWRUP_SOURCE_5V			(0x20 << 24)
+#define	POWER_STS_PWRUP_SOURCE_RTC			(0x10 << 24)
+#define	POWER_STS_PWRUP_SOURCE_PSWITCH_HIGH		(0x02 << 24)
+#define	POWER_STS_PWRUP_SOURCE_PSWITCH_MID		(0x01 << 24)
+#define	POWER_STS_PSWITCH_MASK				(0x3 << 20)
+#define	POWER_STS_PSWITCH_OFFSET			20
+#define	POWER_STS_THERMAL_WARNING			(1 << 19)
+#define	POWER_STS_VDDMEM_BO				(1 << 18)
+#define	POWER_STS_AVALID0_STATUS			(1 << 17)
+#define	POWER_STS_BVALID0_STATUS			(1 << 16)
+#define	POWER_STS_VBUSVALID0_STATUS			(1 << 15)
+#define	POWER_STS_SESSEND0_STATUS			(1 << 14)
+#define	POWER_STS_BATT_BO				(1 << 13)
+#define	POWER_STS_VDD5V_FAULT				(1 << 12)
+#define	POWER_STS_CHRGSTS				(1 << 11)
+#define	POWER_STS_DCDC_4P2_BO				(1 << 10)
+#define	POWER_STS_DC_OK					(1 << 9)
+#define	POWER_STS_VDDIO_BO				(1 << 8)
+#define	POWER_STS_VDDA_BO				(1 << 7)
+#define	POWER_STS_VDDD_BO				(1 << 6)
+#define	POWER_STS_VDD5V_GT_VDDIO			(1 << 5)
+#define	POWER_STS_VDD5V_DROOP				(1 << 4)
+#define	POWER_STS_AVALID0				(1 << 3)
+#define	POWER_STS_BVALID0				(1 << 2)
+#define	POWER_STS_VBUSVALID0				(1 << 1)
+#define	POWER_STS_SESSEND0				(1 << 0)
+
+#define	POWER_SPEED_STATUS_MASK				(0xffff << 8)
+#define	POWER_SPEED_STATUS_OFFSET			8
+#define	POWER_SPEED_STATUS_SEL_MASK			(0x3 << 6)
+#define	POWER_SPEED_STATUS_SEL_OFFSET			6
+#define	POWER_SPEED_STATUS_SEL_DCDC_STAT		(0x0 << 6)
+#define	POWER_SPEED_STATUS_SEL_CORE_STAT		(0x1 << 6)
+#define	POWER_SPEED_STATUS_SEL_ARM_STAT			(0x2 << 6)
+#define	POWER_SPEED_CTRL_MASK				0x3
+#define	POWER_SPEED_CTRL_OFFSET				0
+#define	POWER_SPEED_CTRL_SS_OFF				0x0
+#define	POWER_SPEED_CTRL_SS_ON				0x1
+#define	POWER_SPEED_CTRL_SS_ENABLE			0x3
+
+#define	POWER_BATTMONITOR_BATT_VAL_MASK			(0x3ff << 16)
+#define	POWER_BATTMONITOR_BATT_VAL_OFFSET		16
+#define	POWER_BATTMONITOR_PWDN_BATTBRNOUT_5VDETECT_EN	(1 << 11)
+#define	POWER_BATTMONITOR_EN_BATADJ			(1 << 10)
+#define	POWER_BATTMONITOR_PWDN_BATTBRNOUT		(1 << 9)
+#define	POWER_BATTMONITOR_BRWNOUT_PWD			(1 << 8)
+#define	POWER_BATTMONITOR_BRWNOUT_LVL_MASK		0x1f
+#define	POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET		0
+
+#define	POWER_RESET_UNLOCK_MASK				(0xffff << 16)
+#define	POWER_RESET_UNLOCK_OFFSET			16
+#define	POWER_RESET_UNLOCK_KEY				(0x3e77 << 16)
+#define	POWER_RESET_FASTFALL_PSWITCH_OFF		(1 << 2)
+#define	POWER_RESET_PWD_OFF				(1 << 1)
+#define	POWER_RESET_PWD					(1 << 0)
+
+#define	POWER_DEBUG_VBUSVALIDPIOLOCK			(1 << 3)
+#define	POWER_DEBUG_AVALIDPIOLOCK			(1 << 2)
+#define	POWER_DEBUG_BVALIDPIOLOCK			(1 << 1)
+#define	POWER_DEBUG_SESSENDPIOLOCK			(1 << 0)
+
+#define	POWER_THERMAL_TEST				(1 << 8)
+#define	POWER_THERMAL_PWD				(1 << 7)
+#define	POWER_THERMAL_LOW_POWER				(1 << 6)
+#define	POWER_THERMAL_OFFSET_ADJ_MASK			(0x3 << 4)
+#define	POWER_THERMAL_OFFSET_ADJ_OFFSET			4
+#define	POWER_THERMAL_OFFSET_ADJ_ENABLE			(1 << 3)
+#define	POWER_THERMAL_TEMP_THRESHOLD_MASK		0x7
+#define	POWER_THERMAL_TEMP_THRESHOLD_OFFSET		0
+
+#define	POWER_USB1CTRL_AVALID1				(1 << 3)
+#define	POWER_USB1CTRL_BVALID1				(1 << 2)
+#define	POWER_USB1CTRL_VBUSVALID1			(1 << 1)
+#define	POWER_USB1CTRL_SESSEND1				(1 << 0)
+
+#define	POWER_SPECIAL_TEST_MASK				0xffffffff
+#define	POWER_SPECIAL_TEST_OFFSET			0
+
+#define	POWER_VERSION_MAJOR_MASK			(0xff << 24)
+#define	POWER_VERSION_MAJOR_OFFSET			24
+#define	POWER_VERSION_MINOR_MASK			(0xff << 16)
+#define	POWER_VERSION_MINOR_OFFSET			16
+#define	POWER_VERSION_STEP_MASK				0xffff
+#define	POWER_VERSION_STEP_OFFSET			0
+
+#define	POWER_ANACLKCTRL_CLKGATE_0			(1 << 31)
+#define	POWER_ANACLKCTRL_OUTDIV_MASK			(0x7 << 28)
+#define	POWER_ANACLKCTRL_OUTDIV_OFFSET			28
+#define	POWER_ANACLKCTRL_INVERT_OUTCLK			(1 << 27)
+#define	POWER_ANACLKCTRL_CLKGATE_I			(1 << 26)
+#define	POWER_ANACLKCTRL_DITHER_OFF			(1 << 10)
+#define	POWER_ANACLKCTRL_SLOW_DITHER			(1 << 9)
+#define	POWER_ANACLKCTRL_INVERT_INCLK			(1 << 8)
+#define	POWER_ANACLKCTRL_INCLK_SHIFT_MASK		(0x3 << 4)
+#define	POWER_ANACLKCTRL_INCLK_SHIFT_OFFSET		4
+#define	POWER_ANACLKCTRL_INDIV_MASK			0x7
+#define	POWER_ANACLKCTRL_INDIV_OFFSET			0
+
+#define	POWER_REFCTRL_FASTSETTLING			(1 << 26)
+#define	POWER_REFCTRL_RAISE_REF				(1 << 25)
+#define	POWER_REFCTRL_XTAL_BGR_BIAS			(1 << 24)
+#define	POWER_REFCTRL_VBG_ADJ_MASK			(0x7 << 20)
+#define	POWER_REFCTRL_VBG_ADJ_OFFSET			20
+#define	POWER_REFCTRL_LOW_PWR				(1 << 19)
+#define	POWER_REFCTRL_BIAS_CTRL_MASK			(0x3 << 16)
+#define	POWER_REFCTRL_BIAS_CTRL_OFFSET			16
+#define	POWER_REFCTRL_VDDXTAL_TO_VDDD			(1 << 14)
+#define	POWER_REFCTRL_ADJ_ANA				(1 << 13)
+#define	POWER_REFCTRL_ADJ_VAG				(1 << 12)
+#define	POWER_REFCTRL_ANA_REFVAL_MASK			(0xf << 8)
+#define	POWER_REFCTRL_ANA_REFVAL_OFFSET			8
+#define	POWER_REFCTRL_VAG_VAL_MASK			(0xf << 4)
+#define	POWER_REFCTRL_VAG_VAL_OFFSET			4
+
+#endif	/* __MX28_REGS_POWER_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-rtc.h b/arch/arm/include/asm/arch-mx28/regs-rtc.h
new file mode 100644
index 0000000..fe2fda9
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-rtc.h
@@ -0,0 +1,147 @@
+/*
+ * Freescale i.MX28 RTC Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_RTC_H__
+#define __MX28_REGS_RTC_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_rtc_regs {
+	mx28_reg(hw_rtc_ctrl)
+	mx28_reg(hw_rtc_stat)
+	mx28_reg(hw_rtc_milliseconds)
+	mx28_reg(hw_rtc_seconds)
+	mx28_reg(hw_rtc_rtc_alarm)
+	mx28_reg(hw_rtc_watchdog)
+	mx28_reg(hw_rtc_persistent0)
+	mx28_reg(hw_rtc_persistent1)
+	mx28_reg(hw_rtc_persistent2)
+	mx28_reg(hw_rtc_persistent3)
+	mx28_reg(hw_rtc_persistent4)
+	mx28_reg(hw_rtc_persistent5)
+	mx28_reg(hw_rtc_debug)
+	mx28_reg(hw_rtc_version)
+};
+#endif
+
+#define	RTC_CTRL_SFTRST				(1 << 31)
+#define	RTC_CTRL_CLKGATE			(1 << 30)
+#define	RTC_CTRL_SUPPRESS_COPY2ANALOG		(1 << 6)
+#define	RTC_CTRL_FORCE_UPDATE			(1 << 5)
+#define	RTC_CTRL_WATCHDOGEN			(1 << 4)
+#define	RTC_CTRL_ONEMSEC_IRQ			(1 << 3)
+#define	RTC_CTRL_ALARM_IRQ			(1 << 2)
+#define	RTC_CTRL_ONEMSEC_IRQ_EN			(1 << 1)
+#define	RTC_CTRL_ALARM_IRQ_EN			(1 << 0)
+
+#define	RTC_STAT_RTC_PRESENT			(1 << 31)
+#define	RTC_STAT_ALARM_PRESENT			(1 << 30)
+#define	RTC_STAT_WATCHDOG_PRESENT		(1 << 29)
+#define	RTC_STAT_XTAL32000_PRESENT		(1 << 28)
+#define	RTC_STAT_XTAL32768_PRESENT		(1 << 27)
+#define	RTC_STAT_STALE_REGS_MASK		(0xff << 16)
+#define	RTC_STAT_STALE_REGS_OFFSET		16
+#define	RTC_STAT_NEW_REGS_MASK			(0xff << 8)
+#define	RTC_STAT_NEW_REGS_OFFSET		8
+
+#define	RTC_MILLISECONDS_COUNT_MASK		0xffffffff
+#define	RTC_MILLISECONDS_COUNT_OFFSET		0
+
+#define	RTC_SECONDS_COUNT_MASK			0xffffffff
+#define	RTC_SECONDS_COUNT_OFFSET		0
+
+#define	RTC_ALARM_VALUE_MASK			0xffffffff
+#define	RTC_ALARM_VALUE_OFFSET			0
+
+#define	RTC_WATCHDOG_COUNT_MASK			0xffffffff
+#define	RTC_WATCHDOG_COUNT_OFFSET		0
+
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_MASK	(0xf << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_OFFSET	28
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V83	(0x0 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V78	(0x1 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V73	(0x2 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V68	(0x3 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V62	(0x4 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V57	(0x5 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V52	(0x6 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V48	(0x7 << 28)
+#define	RTC_PERSISTENT0_EXTERNAL_RESET		(1 << 21)
+#define	RTC_PERSISTENT0_THERMAL_RESET		(1 << 20)
+#define	RTC_PERSISTENT0_ENABLE_LRADC_PWRUP	(1 << 18)
+#define	RTC_PERSISTENT0_AUTO_RESTART		(1 << 17)
+#define	RTC_PERSISTENT0_DISABLE_PSWITCH		(1 << 16)
+#define	RTC_PERSISTENT0_LOWERBIAS_MASK		(0xf << 14)
+#define	RTC_PERSISTENT0_LOWERBIAS_OFFSET	14
+#define	RTC_PERSISTENT0_LOWERBIAS_NOMINAL	(0x0 << 14)
+#define	RTC_PERSISTENT0_LOWERBIAS_M25P		(0x1 << 14)
+#define	RTC_PERSISTENT0_LOWERBIAS_M50P		(0x3 << 14)
+#define	RTC_PERSISTENT0_DISABLE_XTALOK		(1 << 13)
+#define	RTC_PERSISTENT0_MSEC_RES_MASK		(0x1f << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_OFFSET		8
+#define	RTC_PERSISTENT0_MSEC_RES_1MS		(0x01 << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_2MS		(0x02 << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_4MS		(0x04 << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_8MS		(0x08 << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_16MS		(0x10 << 8)
+#define	RTC_PERSISTENT0_ALARM_WAKE		(1 << 7)
+#define	RTC_PERSISTENT0_XTAL32_FREQ		(1 << 6)
+#define	RTC_PERSISTENT0_XTAL32KHZ_PWRUP		(1 << 5)
+#define	RTC_PERSISTENT0_XTAL24KHZ_PWRUP		(1 << 4)
+#define	RTC_PERSISTENT0_LCK_SECS		(1 << 3)
+#define	RTC_PERSISTENT0_ALARM_EN		(1 << 2)
+#define	RTC_PERSISTENT0_ALARM_WAKE_EN		(1 << 1)
+#define	RTC_PERSISTENT0_CLOCKSOURCE		(1 << 0)
+
+#define	RTC_PERSISTENT1_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT1_GENERAL_OFFSET		0
+#define	RTC_PERSISTENT1_GENERAL_OTG_ALT_ROLE	0x0080
+#define	RTC_PERSISTENT1_GENERAL_OTG_HNP		0x0100
+#define	RTC_PERSISTENT1_GENERAL_USB_LPM		0x0200
+#define	RTC_PERSISTENT1_GENERAL_SKIP_CHECKDISK	0x0400
+#define	RTC_PERSISTENT1_GENERAL_USB_BOOT_PLAYER	0x0800
+#define	RTC_PERSISTENT1_GENERAL_ENUM_500MA_2X	0x1000
+
+#define	RTC_PERSISTENT2_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT2_GENERAL_OFFSET		0
+
+#define	RTC_PERSISTENT3_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT3_GENERAL_OFFSET		0
+
+#define	RTC_PERSISTENT4_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT4_GENERAL_OFFSET		0
+
+#define	RTC_PERSISTENT5_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT5_GENERAL_OFFSET		0
+
+#define	RTC_DEBUG_WATCHDOG_RESET_MASK		(1 << 1)
+#define	RTC_DEBUG_WATCHDOG_RESET		(1 << 0)
+
+#define	RTC_VERSION_MAJOR_MASK			(0xff << 24)
+#define	RTC_VERSION_MAJOR_OFFSET		24
+#define	RTC_VERSION_MINOR_MASK			(0xff << 16)
+#define	RTC_VERSION_MINOR_OFFSET		16
+#define	RTC_VERSION_STEP_MASK			0xffff
+#define	RTC_VERSION_STEP_OFFSET			0
+
+#endif	/* __MX28_REGS_RTC_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-ssp.h b/arch/arm/include/asm/arch-mx28/regs-ssp.h
new file mode 100644
index 0000000..ab3870c
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-ssp.h
@@ -0,0 +1,349 @@
+/*
+ * Freescale i.MX28 SSP Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_SSP_H__
+#define __MX28_REGS_SSP_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_ssp_regs {
+	mx28_reg(hw_ssp_ctrl0)
+	mx28_reg(hw_ssp_cmd0)
+	mx28_reg(hw_ssp_cmd1)
+	mx28_reg(hw_ssp_xfer_size)
+	mx28_reg(hw_ssp_block_size)
+	mx28_reg(hw_ssp_compref)
+	mx28_reg(hw_ssp_compmask)
+	mx28_reg(hw_ssp_timing)
+	mx28_reg(hw_ssp_ctrl1)
+	mx28_reg(hw_ssp_data)
+	mx28_reg(hw_ssp_sdresp0)
+	mx28_reg(hw_ssp_sdresp1)
+	mx28_reg(hw_ssp_sdresp2)
+	mx28_reg(hw_ssp_sdresp3)
+	mx28_reg(hw_ssp_ddr_ctrl)
+	mx28_reg(hw_ssp_dll_ctrl)
+	mx28_reg(hw_ssp_status)
+	mx28_reg(hw_ssp_dll_sts)
+	mx28_reg(hw_ssp_debug)
+	mx28_reg(hw_ssp_version)
+};
+#endif
+
+#define	SSP_CTRL0_SFTRST			(1 << 31)
+#define	SSP_CTRL0_CLKGATE			(1 << 30)
+#define	SSP_CTRL0_RUN				(1 << 29)
+#define	SSP_CTRL0_SDIO_IRQ_CHECK		(1 << 28)
+#define	SSP_CTRL0_LOCK_CS			(1 << 27)
+#define	SSP_CTRL0_IGNORE_CRC			(1 << 26)
+#define	SSP_CTRL0_READ				(1 << 25)
+#define	SSP_CTRL0_DATA_XFER			(1 << 24)
+#define	SSP_CTRL0_BUS_WIDTH_MASK		(0x3 << 22)
+#define	SSP_CTRL0_BUS_WIDTH_OFFSET		22
+#define	SSP_CTRL0_BUS_WIDTH_ONE_BIT		(0x0 << 22)
+#define	SSP_CTRL0_BUS_WIDTH_FOUR_BIT		(0x1 << 22)
+#define	SSP_CTRL0_BUS_WIDTH_EIGHT_BIT		(0x2 << 22)
+#define	SSP_CTRL0_WAIT_FOR_IRQ			(1 << 21)
+#define	SSP_CTRL0_WAIT_FOR_CMD			(1 << 20)
+#define	SSP_CTRL0_LONG_RESP			(1 << 19)
+#define	SSP_CTRL0_CHECK_RESP			(1 << 18)
+#define	SSP_CTRL0_GET_RESP			(1 << 17)
+#define	SSP_CTRL0_ENABLE			(1 << 16)
+
+#define	SSP_CMD0_SOFT_TERMINATE			(1 << 26)
+#define	SSP_CMD0_DBL_DATA_RATE_EN		(1 << 25)
+#define	SSP_CMD0_PRIM_BOOT_OP_EN		(1 << 24)
+#define	SSP_CMD0_BOOT_ACK_EN			(1 << 23)
+#define	SSP_CMD0_SLOW_CLKING_EN			(1 << 22)
+#define	SSP_CMD0_CONT_CLKING_EN			(1 << 21)
+#define	SSP_CMD0_APPEND_8CYC			(1 << 20)
+#define	SSP_CMD0_CMD_MASK			0xff
+#define	SSP_CMD0_CMD_OFFSET			0
+#define	SSP_CMD0_CMD_MMC_GO_IDLE_STATE		0x00
+#define	SSP_CMD0_CMD_MMC_SEND_OP_COND		0x01
+#define	SSP_CMD0_CMD_MMC_ALL_SEND_CID		0x02
+#define	SSP_CMD0_CMD_MMC_SET_RELATIVE_ADDR	0x03
+#define	SSP_CMD0_CMD_MMC_SET_DSR		0x04
+#define	SSP_CMD0_CMD_MMC_RESERVED_5		0x05
+#define	SSP_CMD0_CMD_MMC_SWITCH			0x06
+#define	SSP_CMD0_CMD_MMC_SELECT_DESELECT_CARD	0x07
+#define	SSP_CMD0_CMD_MMC_SEND_EXT_CSD		0x08
+#define	SSP_CMD0_CMD_MMC_SEND_CSD		0x09
+#define	SSP_CMD0_CMD_MMC_SEND_CID		0x0a
+#define	SSP_CMD0_CMD_MMC_READ_DAT_UNTIL_STOP	0x0b
+#define	SSP_CMD0_CMD_MMC_STOP_TRANSMISSION	0x0c
+#define	SSP_CMD0_CMD_MMC_SEND_STATUS		0x0d
+#define	SSP_CMD0_CMD_MMC_BUSTEST_R		0x0e
+#define	SSP_CMD0_CMD_MMC_GO_INACTIVE_STATE	0x0f
+#define	SSP_CMD0_CMD_MMC_SET_BLOCKLEN		0x10
+#define	SSP_CMD0_CMD_MMC_READ_SINGLE_BLOCK	0x11
+#define	SSP_CMD0_CMD_MMC_READ_MULTIPLE_BLOCK	0x12
+#define	SSP_CMD0_CMD_MMC_BUSTEST_W		0x13
+#define	SSP_CMD0_CMD_MMC_WRITE_DAT_UNTIL_STOP	0x14
+#define	SSP_CMD0_CMD_MMC_SET_BLOCK_COUNT	0x17
+#define	SSP_CMD0_CMD_MMC_WRITE_BLOCK		0x18
+#define	SSP_CMD0_CMD_MMC_WRITE_MULTIPLE_BLOCK	0x19
+#define	SSP_CMD0_CMD_MMC_PROGRAM_CID		0x1a
+#define	SSP_CMD0_CMD_MMC_PROGRAM_CSD		0x1b
+#define	SSP_CMD0_CMD_MMC_SET_WRITE_PROT		0x1c
+#define	SSP_CMD0_CMD_MMC_CLR_WRITE_PROT		0x1d
+#define	SSP_CMD0_CMD_MMC_SEND_WRITE_PROT	0x1e
+#define	SSP_CMD0_CMD_MMC_ERASE_GROUP_START	0x23
+#define	SSP_CMD0_CMD_MMC_ERASE_GROUP_END	0x24
+#define	SSP_CMD0_CMD_MMC_ERASE			0x26
+#define	SSP_CMD0_CMD_MMC_FAST_IO		0x27
+#define	SSP_CMD0_CMD_MMC_GO_IRQ_STATE		0x28
+#define	SSP_CMD0_CMD_MMC_LOCK_UNLOCK		0x2a
+#define	SSP_CMD0_CMD_MMC_APP_CMD		0x37
+#define	SSP_CMD0_CMD_MMC_GEN_CMD		0x38
+#define	SSP_CMD0_CMD_SD_GO_IDLE_STATE		0x00
+#define	SSP_CMD0_CMD_SD_ALL_SEND_CID		0x02
+#define	SSP_CMD0_CMD_SD_SEND_RELATIVE_ADDR	0x03
+#define	SSP_CMD0_CMD_SD_SET_DSR			0x04
+#define	SSP_CMD0_CMD_SD_IO_SEND_OP_COND		0x05
+#define	SSP_CMD0_CMD_SD_SELECT_DESELECT_CARD	0x07
+#define	SSP_CMD0_CMD_SD_SEND_CSD		0x09
+#define	SSP_CMD0_CMD_SD_SEND_CID		0x0a
+#define	SSP_CMD0_CMD_SD_STOP_TRANSMISSION	0x0c
+#define	SSP_CMD0_CMD_SD_SEND_STATUS		0x0d
+#define	SSP_CMD0_CMD_SD_GO_INACTIVE_STATE	0x0f
+#define	SSP_CMD0_CMD_SD_SET_BLOCKLEN		0x10
+#define	SSP_CMD0_CMD_SD_READ_SINGLE_BLOCK	0x11
+#define	SSP_CMD0_CMD_SD_READ_MULTIPLE_BLOCK	0x12
+#define	SSP_CMD0_CMD_SD_WRITE_BLOCK		0x18
+#define	SSP_CMD0_CMD_SD_WRITE_MULTIPLE_BLOCK	0x19
+#define	SSP_CMD0_CMD_SD_PROGRAM_CSD		0x1b
+#define	SSP_CMD0_CMD_SD_SET_WRITE_PROT		0x1c
+#define	SSP_CMD0_CMD_SD_CLR_WRITE_PROT		0x1d
+#define	SSP_CMD0_CMD_SD_SEND_WRITE_PROT		0x1e
+#define	SSP_CMD0_CMD_SD_ERASE_WR_BLK_START	0x20
+#define	SSP_CMD0_CMD_SD_ERASE_WR_BLK_END	0x21
+#define	SSP_CMD0_CMD_SD_ERASE_GROUP_START	0x23
+#define	SSP_CMD0_CMD_SD_ERASE_GROUP_END		0x24
+#define	SSP_CMD0_CMD_SD_ERASE			0x26
+#define	SSP_CMD0_CMD_SD_LOCK_UNLOCK		0x2a
+#define	SSP_CMD0_CMD_SD_IO_RW_DIRECT		0x34
+#define	SSP_CMD0_CMD_SD_IO_RW_EXTENDED		0x35
+#define	SSP_CMD0_CMD_SD_APP_CMD			0x37
+#define	SSP_CMD0_CMD_SD_GEN_CMD			0x38
+
+#define	SSP_CMD1_CMD_ARG_MASK			0xffffffff
+#define	SSP_CMD1_CMD_ARG_OFFSET			0
+
+#define	SSP_XFER_SIZE_XFER_COUNT_MASK		0xffffffff
+#define	SSP_XFER_SIZE_XFER_COUNT_OFFSET		0
+
+#define	SSP_BLOCK_SIZE_BLOCK_COUNT_MASK		(0xffffff << 4)
+#define	SSP_BLOCK_SIZE_BLOCK_COUNT_OFFSET	4
+#define	SSP_BLOCK_SIZE_BLOCK_SIZE_MASK		0xf
+#define	SSP_BLOCK_SIZE_BLOCK_SIZE_OFFSET	0
+
+#define	SSP_COMPREF_REFERENCE_MASK		0xffffffff
+#define	SSP_COMPREF_REFERENCE_OFFSET		0
+
+#define	SSP_COMPMASK_MASK_MASK			0xffffffff
+#define	SSP_COMPMASK_MASK_OFFSET		0
+
+#define	SSP_TIMING_TIMEOUT_MASK			(0xffff << 16)
+#define	SSP_TIMING_TIMEOUT_OFFSET		16
+#define	SSP_TIMING_CLOCK_DIVIDE_MASK		(0xff << 8)
+#define	SSP_TIMING_CLOCK_DIVIDE_OFFSET		8
+#define	SSP_TIMING_CLOCK_RATE_MASK		0xff
+#define	SSP_TIMING_CLOCK_RATE_OFFSET		0
+
+#define	SSP_CTRL1_SDIO_IRQ			(1 << 31)
+#define	SSP_CTRL1_SDIO_IRQ_EN			(1 << 30)
+#define	SSP_CTRL1_RESP_ERR_IRQ			(1 << 29)
+#define	SSP_CTRL1_RESP_ERR_IRQ_EN		(1 << 28)
+#define	SSP_CTRL1_RESP_TIMEOUT_IRQ		(1 << 27)
+#define	SSP_CTRL1_RESP_TIMEOUT_IRQ_EN		(1 << 26)
+#define	SSP_CTRL1_DATA_TIMEOUT_IRQ		(1 << 25)
+#define	SSP_CTRL1_DATA_TIMEOUT_IRQ_EN		(1 << 24)
+#define	SSP_CTRL1_DATA_CRC_IRQ			(1 << 23)
+#define	SSP_CTRL1_DATA_CRC_IRQ_EN		(1 << 22)
+#define	SSP_CTRL1_FIFO_UNDERRUN_IRQ		(1 << 21)
+#define	SSP_CTRL1_FIFO_UNDERRUN_EN		(1 << 20)
+#define	SSP_CTRL1_CEATA_CCS_ERR_IRQ		(1 << 19)
+#define	SSP_CTRL1_CEATA_CCS_ERR_IRQ_EN		(1 << 18)
+#define	SSP_CTRL1_RECV_TIMEOUT_IRQ		(1 << 17)
+#define	SSP_CTRL1_RECV_TIMEOUT_IRQ_EN		(1 << 16)
+#define	SSP_CTRL1_FIFO_OVERRUN_IRQ		(1 << 15)
+#define	SSP_CTRL1_FIFO_OVERRUN_IRQ_EN		(1 << 14)
+#define	SSP_CTRL1_DMA_ENABLE			(1 << 13)
+#define	SSP_CTRL1_CEATA_CCS_ERR_EN		(1 << 12)
+#define	SSP_CTRL1_SLAVE_OUT_DISABLE		(1 << 11)
+#define	SSP_CTRL1_PHASE				(1 << 10)
+#define	SSP_CTRL1_POLARITY			(1 << 9)
+#define	SSP_CTRL1_SLAVE_MODE			(1 << 8)
+#define	SSP_CTRL1_WORD_LENGTH_MASK		(0xf << 4)
+#define	SSP_CTRL1_WORD_LENGTH_OFFSET		4
+#define	SSP_CTRL1_WORD_LENGTH_RESERVED0		(0x0 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_RESERVED1		(0x1 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_RESERVED2		(0x2 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_FOUR_BITS		(0x3 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_EIGHT_BITS	(0x7 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_SIXTEEN_BITS	(0xf << 4)
+#define	SSP_CTRL1_SSP_MODE_MASK			0xf
+#define	SSP_CTRL1_SSP_MODE_OFFSET		0
+#define	SSP_CTRL1_SSP_MODE_SPI			0x0
+#define	SSP_CTRL1_SSP_MODE_SSI			0x1
+#define	SSP_CTRL1_SSP_MODE_SD_MMC		0x3
+#define	SSP_CTRL1_SSP_MODE_MS			0x4
+
+#define	SSP_DATA_DATA_MASK			0xffffffff
+#define	SSP_DATA_DATA_OFFSET			0
+
+#define	SSP_SDRESP0_RESP0_MASK			0xffffffff
+#define	SSP_SDRESP0_RESP0_OFFSET		0
+
+#define	SSP_SDRESP1_RESP1_MASK			0xffffffff
+#define	SSP_SDRESP1_RESP1_OFFSET		0
+
+#define	SSP_SDRESP2_RESP2_MASK			0xffffffff
+#define	SSP_SDRESP2_RESP2_OFFSET		0
+
+#define	SSP_SDRESP3_RESP3_MASK			0xffffffff
+#define	SSP_SDRESP3_RESP3_OFFSET		0
+
+#define	SSP_DDR_CTRL_DMA_BURST_TYPE_MASK	(0x3 << 30)
+#define	SSP_DDR_CTRL_DMA_BURST_TYPE_OFFSET	30
+#define	SSP_DDR_CTRL_NIBBLE_POS			(1 << 1)
+#define	SSP_DDR_CTRL_TXCLK_DELAY_TYPE		(1 << 0)
+
+#define	SSP_DLL_CTRL_REF_UPDATE_INT_MASK	(0xf << 28)
+#define	SSP_DLL_CTRL_REF_UPDATE_INT_OFFSET	28
+#define	SSP_DLL_CTRL_SLV_UPDATE_INT_MASK	(0xff << 20)
+#define	SSP_DLL_CTRL_SLV_UPDATE_INT_OFFSET	20
+#define	SSP_DLL_CTRL_SLV_OVERRIDE_VAL_MASK	(0x3f << 10)
+#define	SSP_DLL_CTRL_SLV_OVERRIDE_VAL_OFFSET	10
+#define	SSP_DLL_CTRL_SLV_OVERRIDE		(1 << 9)
+#define	SSP_DLL_CTRL_GATE_UPDATE		(1 << 7)
+#define	SSP_DLL_CTRL_SLV_DLY_TARGET_MASK	(0xf << 3)
+#define	SSP_DLL_CTRL_SLV_DLY_TARGET_OFFSET	3
+#define	SSP_DLL_CTRL_SLV_FORCE_UPD		(1 << 2)
+#define	SSP_DLL_CTRL_RESET			(1 << 1)
+#define	SSP_DLL_CTRL_ENABLE			(1 << 0)
+
+#define	SSP_STATUS_PRESENT			(1 << 31)
+#define	SSP_STATUS_MS_PRESENT			(1 << 30)
+#define	SSP_STATUS_SD_PRESENT			(1 << 29)
+#define	SSP_STATUS_CARD_DETECT			(1 << 28)
+#define	SSP_STATUS_DMABURST			(1 << 22)
+#define	SSP_STATUS_DMASENSE			(1 << 21)
+#define	SSP_STATUS_DMATERM			(1 << 20)
+#define	SSP_STATUS_DMAREQ			(1 << 19)
+#define	SSP_STATUS_DMAEND			(1 << 18)
+#define	SSP_STATUS_SDIO_IRQ			(1 << 17)
+#define	SSP_STATUS_RESP_CRC_ERR			(1 << 16)
+#define	SSP_STATUS_RESP_ERR			(1 << 15)
+#define	SSP_STATUS_RESP_TIMEOUT			(1 << 14)
+#define	SSP_STATUS_DATA_CRC_ERR			(1 << 13)
+#define	SSP_STATUS_TIMEOUT			(1 << 12)
+#define	SSP_STATUS_RECV_TIMEOUT_STAT		(1 << 11)
+#define	SSP_STATUS_CEATA_CCS_ERR		(1 << 10)
+#define	SSP_STATUS_FIFO_OVRFLW			(1 << 9)
+#define	SSP_STATUS_FIFO_FULL			(1 << 8)
+#define	SSP_STATUS_FIFO_EMPTY			(1 << 5)
+#define	SSP_STATUS_FIFO_UNDRFLW			(1 << 4)
+#define	SSP_STATUS_CMD_BUSY			(1 << 3)
+#define	SSP_STATUS_DATA_BUSY			(1 << 2)
+#define	SSP_STATUS_BUSY				(1 << 0)
+
+#define	SSP_DLL_STS_REF_SEL_MASK		(0x3f << 8)
+#define	SSP_DLL_STS_REF_SEL_OFFSET		8
+#define	SSP_DLL_STS_SLV_SEL_MASK		(0x3f << 2)
+#define	SSP_DLL_STS_SLV_SEL_OFFSET		2
+#define	SSP_DLL_STS_REF_LOCK			(1 << 1)
+#define	SSP_DLL_STS_SLV_LOCK			(1 << 0)
+
+#define	SSP_DEBUG_DATACRC_ERR_MASK		(0xf << 28)
+#define	SSP_DEBUG_DATACRC_ERR_OFFSET		28
+#define	SSP_DEBUG_DATA_STALL			(1 << 27)
+#define	SSP_DEBUG_DAT_SM_MASK			(0x7 << 24)
+#define	SSP_DEBUG_DAT_SM_OFFSET			24
+#define	SSP_DEBUG_DAT_SM_DSM_IDLE		(0x0 << 24)
+#define	SSP_DEBUG_DAT_SM_DSM_WORD		(0x2 << 24)
+#define	SSP_DEBUG_DAT_SM_DSM_CRC1		(0x3 << 24)
+#define	SSP_DEBUG_DAT_SM_DSM_CRC2		(0x4 << 24)
+#define	SSP_DEBUG_DAT_SM_DSM_END		(0x5 << 24)
+#define	SSP_DEBUG_MSTK_SM_MASK			(0xf << 20)
+#define	SSP_DEBUG_MSTK_SM_OFFSET		20
+#define	SSP_DEBUG_MSTK_SM_MSTK_IDLE		(0x0 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_CKON		(0x1 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_BS1		(0x2 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_TPC		(0x3 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_BS2		(0x4 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_HDSHK		(0x5 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_BS3		(0x6 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_RW		(0x7 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_CRC1		(0x8 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_CRC2		(0x9 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_BS0		(0xa << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_END1		(0xb << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_END2W		(0xc << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_END2R		(0xd << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_DONE		(0xe << 20)
+#define	SSP_DEBUG_CMD_OE			(1 << 19)
+#define	SSP_DEBUG_DMA_SM_MASK			(0x7 << 16)
+#define	SSP_DEBUG_DMA_SM_OFFSET			16
+#define	SSP_DEBUG_DMA_SM_DMA_IDLE		(0x0 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_DMAREQ		(0x1 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_DMAACK		(0x2 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_STALL		(0x3 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_BUSY		(0x4 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_DONE		(0x5 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_COUNT		(0x6 << 16)
+#define	SSP_DEBUG_MMC_SM_MASK			(0xf << 12)
+#define	SSP_DEBUG_MMC_SM_OFFSET			12
+#define	SSP_DEBUG_MMC_SM_MMC_IDLE		(0x0 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_CMD		(0x1 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_TRC		(0x2 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_RESP		(0x3 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_RPRX		(0x4 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_TX			(0x5 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_CTOK		(0x6 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_RX			(0x7 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_CCS		(0x8 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_PUP		(0x9 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_WAIT		(0xa << 12)
+#define	SSP_DEBUG_CMD_SM_MASK			(0x3 << 10)
+#define	SSP_DEBUG_CMD_SM_OFFSET			10
+#define	SSP_DEBUG_CMD_SM_CSM_IDLE		(0x0 << 10)
+#define	SSP_DEBUG_CMD_SM_CSM_INDEX		(0x1 << 10)
+#define	SSP_DEBUG_CMD_SM_CSM_ARG		(0x2 << 10)
+#define	SSP_DEBUG_CMD_SM_CSM_CRC		(0x3 << 10)
+#define	SSP_DEBUG_SSP_CMD			(1 << 9)
+#define	SSP_DEBUG_SSP_RESP			(1 << 8)
+#define	SSP_DEBUG_SSP_RXD_MASK			0xff
+#define	SSP_DEBUG_SSP_RXD_OFFSET		0
+
+#define	SSP_VERSION_MAJOR_MASK			(0xff << 24)
+#define	SSP_VERSION_MAJOR_OFFSET		24
+#define	SSP_VERSION_MINOR_MASK			(0xff << 16)
+#define	SSP_VERSION_MINOR_OFFSET		16
+#define	SSP_VERSION_STEP_MASK			0xffff
+#define	SSP_VERSION_STEP_OFFSET			0
+
+#endif /* __MX28_REGS_SSP_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-timrot.h b/arch/arm/include/asm/arch-mx28/regs-timrot.h
new file mode 100644
index 0000000..1b941cf
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-timrot.h
@@ -0,0 +1,171 @@
+/*
+ * Freescale i.MX28 TIMROT Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_TIMROT_H__
+#define __MX28_REGS_TIMROT_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_timrot_regs {
+	mx28_reg(hw_timrot_rotctrl)
+	mx28_reg(hw_timrot_rotcount)
+	mx28_reg(hw_timrot_timctrl0)
+	mx28_reg(hw_timrot_running_count0)
+	mx28_reg(hw_timrot_fixed_count0)
+	mx28_reg(hw_timrot_match_count0)
+	mx28_reg(hw_timrot_timctrl1)
+	mx28_reg(hw_timrot_running_count1)
+	mx28_reg(hw_timrot_fixed_count1)
+	mx28_reg(hw_timrot_match_count1)
+	mx28_reg(hw_timrot_timctrl2)
+	mx28_reg(hw_timrot_running_count2)
+	mx28_reg(hw_timrot_fixed_count2)
+	mx28_reg(hw_timrot_match_count2)
+	mx28_reg(hw_timrot_timctrl3)
+	mx28_reg(hw_timrot_running_count3)
+	mx28_reg(hw_timrot_fixed_count3)
+	mx28_reg(hw_timrot_match_count3)
+	mx28_reg(hw_timrot_version)
+};
+#endif
+
+#define	TIMROT_ROTCTRL_SFTRST				(1 << 31)
+#define	TIMROT_ROTCTRL_CLKGATE				(1 << 30)
+#define	TIMROT_ROTCTRL_ROTARY_PRESENT			(1 << 29)
+#define	TIMROT_ROTCTRL_TIM3_PRESENT			(1 << 28)
+#define	TIMROT_ROTCTRL_TIM2_PRESENT			(1 << 27)
+#define	TIMROT_ROTCTRL_TIM1_PRESENT			(1 << 26)
+#define	TIMROT_ROTCTRL_TIM0_PRESENT			(1 << 25)
+#define	TIMROT_ROTCTRL_STATE_MASK			(0x7 << 22)
+#define	TIMROT_ROTCTRL_STATE_OFFSET			22
+#define	TIMROT_ROTCTRL_DIVIDER_MASK			(0x3f << 16)
+#define	TIMROT_ROTCTRL_DIVIDER_OFFSET			16
+#define	TIMROT_ROTCTRL_RELATIVE				(1 << 12)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_MASK			(0x3 << 10)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_OFFSET		10
+#define	TIMROT_ROTCTRL_OVERSAMPLE_8X			(0x0 << 10)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_4X			(0x1 << 10)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_2X			(0x2 << 10)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_1X			(0x3 << 10)
+#define	TIMROT_ROTCTRL_POLARITY_B			(1 << 9)
+#define	TIMROT_ROTCTRL_POLARITY_A			(1 << 8)
+#define	TIMROT_ROTCTRL_SELECT_B_MASK			(0xf << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_OFFSET			4
+#define	TIMROT_ROTCTRL_SELECT_B_NEVER_TICK		(0x0 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM0			(0x1 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM1			(0x2 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM2			(0x3 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM3			(0x4 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM4			(0x5 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM5			(0x6 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM6			(0x7 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM7			(0x8 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_ROTARYA			(0x9 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_ROTARYB			(0xa << 4)
+#define	TIMROT_ROTCTRL_SELECT_A_MASK			0xf
+#define	TIMROT_ROTCTRL_SELECT_A_OFFSET			0
+#define	TIMROT_ROTCTRL_SELECT_A_NEVER_TICK		0x0
+#define	TIMROT_ROTCTRL_SELECT_A_PWM0			0x1
+#define	TIMROT_ROTCTRL_SELECT_A_PWM1			0x2
+#define	TIMROT_ROTCTRL_SELECT_A_PWM2			0x3
+#define	TIMROT_ROTCTRL_SELECT_A_PWM3			0x4
+#define	TIMROT_ROTCTRL_SELECT_A_PWM4			0x5
+#define	TIMROT_ROTCTRL_SELECT_A_PWM5			0x6
+#define	TIMROT_ROTCTRL_SELECT_A_PWM6			0x7
+#define	TIMROT_ROTCTRL_SELECT_A_PWM7			0x8
+#define	TIMROT_ROTCTRL_SELECT_A_ROTARYA			0x9
+#define	TIMROT_ROTCTRL_SELECT_A_ROTARYB			0xa
+
+#define	TIMROT_ROTCOUNT_UPDOWN_MASK			0xffff
+#define	TIMROT_ROTCOUNT_UPDOWN_OFFSET			0
+
+#define	TIMROT_TIMCTRLn_IRQ				(1 << 15)
+#define	TIMROT_TIMCTRLn_IRQ_EN				(1 << 14)
+#define	TIMROT_TIMCTRLn_MATCH_MODE			(1 << 11)
+#define	TIMROT_TIMCTRLn_POLARITY			(1 << 8)
+#define	TIMROT_TIMCTRLn_UPDATE				(1 << 7)
+#define	TIMROT_TIMCTRLn_RELOAD				(1 << 6)
+#define	TIMROT_TIMCTRLn_PRESCALE_MASK			(0x3 << 4)
+#define	TIMROT_TIMCTRLn_PRESCALE_OFFSET			4
+#define	TIMROT_TIMCTRLn_PRESCALE_DIV_BY_1		(0x0 << 4)
+#define	TIMROT_TIMCTRLn_PRESCALE_DIV_BY_2		(0x1 << 4)
+#define	TIMROT_TIMCTRLn_PRESCALE_DIV_BY_4		(0x2 << 4)
+#define	TIMROT_TIMCTRLn_PRESCALE_DIV_BY_8		(0x3 << 4)
+#define	TIMROT_TIMCTRLn_SELECT_MASK			0xf
+#define	TIMROT_TIMCTRLn_SELECT_OFFSET			0
+#define	TIMROT_TIMCTRLn_SELECT_NEVER_TICK		0x0
+#define	TIMROT_TIMCTRLn_SELECT_PWM0			0x1
+#define	TIMROT_TIMCTRLn_SELECT_PWM1			0x2
+#define	TIMROT_TIMCTRLn_SELECT_PWM2			0x3
+#define	TIMROT_TIMCTRLn_SELECT_PWM3			0x4
+#define	TIMROT_TIMCTRLn_SELECT_PWM4			0x5
+#define	TIMROT_TIMCTRLn_SELECT_PWM5			0x6
+#define	TIMROT_TIMCTRLn_SELECT_PWM6			0x7
+#define	TIMROT_TIMCTRLn_SELECT_PWM7			0x8
+#define	TIMROT_TIMCTRLn_SELECT_ROTARYA			0x9
+#define	TIMROT_TIMCTRLn_SELECT_ROTARYB			0xa
+#define	TIMROT_TIMCTRLn_SELECT_32KHZ_XTAL		0xb
+#define	TIMROT_TIMCTRLn_SELECT_8KHZ_XTAL		0xc
+#define	TIMROT_TIMCTRLn_SELECT_4KHZ_XTAL		0xd
+#define	TIMROT_TIMCTRLn_SELECT_1KHZ_XTAL		0xe
+#define	TIMROT_TIMCTRLn_SELECT_TICK_ALWAYS		0xf
+
+#define	TIMROT_RUNNING_COUNTn_RUNNING_COUNT_MASK	0xffffffff
+#define	TIMROT_RUNNING_COUNTn_RUNNING_COUNT_OFFSET	0
+
+#define	TIMROT_FIXED_COUNTn_FIXED_COUNT_MASK		0xffffffff
+#define	TIMROT_FIXED_COUNTn_FIXED_COUNT_OFFSET		0
+
+#define	TIMROT_MATCH_COUNTn_MATCH_COUNT_MASK		0xffffffff
+#define	TIMROT_MATCH_COUNTn_MATCH_COUNT_OFFSET		0
+
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_MASK		(0xf << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_OFFSET		16
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_NEVER_TICK		(0x0 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM0		(0x1 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM1		(0x2 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM2		(0x3 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM3		(0x4 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM4		(0x5 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM5		(0x6 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM6		(0x7 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM7		(0x8 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_ROTARYA		(0x9 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_ROTARYB		(0xa << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_32KHZ_XTAL		(0xb << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_8KHZ_XTAL		(0xc << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_4KHZ_XTAL		(0xd << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_1KHZ_XTAL		(0xe << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_TICK_ALWAYS		(0xf << 16)
+#define	TIMROT_TIMCTRL3_DUTY_CYCLE			(1 << 9)
+
+#define	TIMROT_VERSION_MAJOR_MASK			(0xff << 24)
+#define	TIMROT_VERSION_MAJOR_OFFSET			24
+#define	TIMROT_VERSION_MINOR_MASK			(0xff << 16)
+#define	TIMROT_VERSION_MINOR_OFFSET			16
+#define	TIMROT_VERSION_STEP_MASK			0xffff
+#define	TIMROT_VERSION_STEP_OFFSET			0
+
+#endif /* __MX28_REGS_TIMROT_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/sys_proto.h b/arch/arm/include/asm/arch-mx28/sys_proto.h
new file mode 100644
index 0000000..a262c05
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/sys_proto.h
@@ -0,0 +1,30 @@
+/*
+ * Freescale i.MX28 MX28 specific functions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __MX28_H__
+#define __MX28_H__
+
+int mx28_reset_block(struct mx28_register *reg);
+int mx28_wait_mask_set(struct mx28_register *reg, uint32_t mask, int timeout);
+int mx28_wait_mask_clr(struct mx28_register *reg, uint32_t mask, int timeout);
+
+#endif	/* __MX28_H__ */
-- 
1.7.5.4

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

* [U-Boot] [PATCH 09/15] iMX28: Add GPMI NAND driver
  2011-09-12  4:06 ` [U-Boot] [PATCH 09/15] iMX28: Add GPMI NAND driver Marek Vasut
@ 2011-09-28 21:26   ` Scott Wood
  2011-09-28 21:42     ` Marek Vasut
  2011-09-28 22:12     ` Marek Vasut
  2011-09-28 22:17   ` [U-Boot] [PATCH 09/15 V2] " Marek Vasut
  1 sibling, 2 replies; 116+ messages in thread
From: Scott Wood @ 2011-09-28 21:26 UTC (permalink / raw)
  To: u-boot

On 09/11/2011 11:06 PM, Marek Vasut wrote:
> +static void mxs_nand_return_dma_descs(struct mxs_nand_info *info)
> +{
> +	int i = info->desc_index;
> +	struct mxs_dma_desc *desc;
> +
> +	for (--i; i >= 0; i--) {

This is an awkward construct.

Why not just the usual:

for (i = 0; i < info->desc_index; i++)

> +		desc = info->desc[i];
> +		memset(desc, 0, sizeof(struct mxs_dma_desc));
> +		desc->address = (dma_addr_t)desc;
> +	}
> +
> +	info->desc_index = 0;
> +}
> +
> +static inline uint32_t mxs_nand_ecc_chunk_cnt(uint32_t page_data_size)
> +{
> +	return page_data_size / MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
> +}

No need for inline in .c files, GCC should take care of this automatically.

> +/*
> + * There are several places in this driver where we have to handle the OOB and
> + * block marks. This is the function where things are the most complicated, so
> + * this is where we try to explain it all. All the other places refer back to
> + * here.
> + *
> + * These are the rules, in order of decreasing importance:
> + *
> + * 1) Nothing the caller does can be allowed to imperil the block mark, so all
> + *    write operations take measures to protect it.
> + *
> + * 2) In read operations, the first byte of the OOB we return must reflect the
> + *    true state of the block mark, no matter where that block mark appears in
> + *    the physical page.
> + *
> + * 3) ECC-based read operations return an OOB full of set bits (since we never
> + *    allow ECC-based writes to the OOB, it doesn't matter what ECC-based reads
> + *    return).
> + *
> + * 4) "Raw" read operations return a direct view of the physical bytes in the
> + *    page, using the conventional definition of which bytes are data and which
> + *    are OOB. This gives the caller a way to see the actual, physical bytes
> + *    in the page, without the distortions applied by our ECC engine.

Hmm, I thought raw was just supposed to disable ECC, not change the
layout from what is used in normal operation.

> + * It turns out that knowing whether we want an "ECC-based" or "raw" read is not
> + * easy. When reading a page, for example, the NAND Flash MTD code calls our
> + * ecc.read_page or ecc.read_page_raw function. Thus, the fact that MTD wants an
> + * ECC-based or raw view of the page is implicit in which function it calls
> + * (there is a similar pair of ECC-based/raw functions for writing).

This is an issue for the eLBC driver as well -- we need to know whether
to enable or disable ECC before we begin the operation (in cmdfunc), not
just at the time the buffer is accessed.  Currently we just always have
ECC on, and raw accesses aren't raw.  It would be nice to fix this more
generally (starting in Linux, so we don't diverge).

It's too bad we can't rely on chip->ops being used... maybe we could
copy the data into there?  Or just have a separate mtd_oob_mode_t in
nand_chip.

> +/*
> + * Write OOB data to NAND.
> + */
> +static int mxs_nand_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *nand,
> +					int page)
> +{
> +	struct mxs_nand_info *nand_info = nand->priv;
> +	uint8_t block_mark = 0;
> +
> +	/*
> +	 * There are fundamental incompatibilities between the i.MX GPMI NFC and
> +	 * the NAND Flash MTD model that make it essentially impossible to write
> +	 * the out-of-band bytes.
> +	 *
> +	 * We permit *ONE* exception. If the *intent* of writing the OOB is to
> +	 * mark a block bad, we can do that.
> +	 */

Is this just an issue with writing OOB separately from the main data
(which would also be an issue on MLC chips that don't allow multiple
partial programming), or can you not even write user OOB bytes as part
of a full page write?

Based on fake_ecc_layout I'm guessing the latter.

> +	if (nand_info->marking_block_bad) {
> +		printf("NXS NAND: Writing OOB isn't supported\n");
> +		return -EIO;
> +	}

Shouldn't this be if (!nand_info->marking_block_bad)?

> +/*
> + * Claims all blocks are good.
> + *
> + * In principle, this function is *only* called when the NAND Flash MTD system
> + * isn't allowed to keep an in-memory bad block table, so it is forced to ask
> + * the driver for bad block information.
> + *
> + * In fact, we permit the NAND Flash MTD system to have an in-memory BBT, so
> + * this function is *only* called when we take it away.
> + *
> + * We take away the in-memory BBT when the user sets the "ignorebad" parameter,
> + * which indicates that all blocks should be reported good.
> + *
> + * Thus, this function is only called when we want *all* blocks to look good,
> + * so it *always* return success.
> + */
> +static int mxs_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
> +{
> +	return 0;
> +}

What/where is the "ignorebad" parameter?

Other than when scrubbing (which has its own override), when would you
want to do this?

> +/*
> + * Nominally, the purpose of this function is to look for or create the bad
> + * block table. In fact, since the HIL calls this function at the very end of

HIL?

> + * the initialization process started by nand_scan(), and the HIL doesn't have a
> + * more formal mechanism, everyone "hooks" this function to continue the
> + * initialization process.

Everyone?  I only see diskonchip doing this.

The nand_base.c code actually does have a split here
(nand_scan_ident/nand_scan_tail), but U-Boot's glue code is too
inflexible, and insists on calling nand_scan.  The right fix is to let
drivers call nand_scan_ident/nand_scan_tail themselves.

-Scott

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

* [U-Boot] [PATCH 09/15] iMX28: Add GPMI NAND driver
  2011-09-28 21:26   ` Scott Wood
@ 2011-09-28 21:42     ` Marek Vasut
  2011-09-28 21:57       ` Scott Wood
  2011-09-28 22:12     ` Marek Vasut
  1 sibling, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-09-28 21:42 UTC (permalink / raw)
  To: u-boot

On Wednesday, September 28, 2011 11:26:45 PM Scott Wood wrote:
> On 09/11/2011 11:06 PM, Marek Vasut wrote:
> > +static void mxs_nand_return_dma_descs(struct mxs_nand_info *info)
> > +{
> > +	int i = info->desc_index;
> > +	struct mxs_dma_desc *desc;
> > +
> > +	for (--i; i >= 0; i--) {
> 
> This is an awkward construct.
> 
> Why not just the usual:
> 
> for (i = 0; i < info->desc_index; i++)

Good catch.

> 
> > +		desc = info->desc[i];
> > +		memset(desc, 0, sizeof(struct mxs_dma_desc));
> > +		desc->address = (dma_addr_t)desc;
> > +	}
> > +
> > +	info->desc_index = 0;
> > +}
> > +
> > +static inline uint32_t mxs_nand_ecc_chunk_cnt(uint32_t page_data_size)
> > +{
> > +	return page_data_size / MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
> > +}
> 
> No need for inline in .c files, GCC should take care of this automatically.

Does it really ?
> 
> > +/*
> > + * There are several places in this driver where we have to handle the
> > OOB and + * block marks. This is the function where things are the most
> > complicated, so + * this is where we try to explain it all. All the
> > other places refer back to + * here.
> > + *
> > + * These are the rules, in order of decreasing importance:
> > + *
> > + * 1) Nothing the caller does can be allowed to imperil the block mark,
> > so all + *    write operations take measures to protect it.
> > + *
> > + * 2) In read operations, the first byte of the OOB we return must
> > reflect the + *    true state of the block mark, no matter where that
> > block mark appears in + *    the physical page.
> > + *
> > + * 3) ECC-based read operations return an OOB full of set bits (since we
> > never + *    allow ECC-based writes to the OOB, it doesn't matter what
> > ECC-based reads + *    return).
> > + *
> > + * 4) "Raw" read operations return a direct view of the physical bytes
> > in the + *    page, using the conventional definition of which bytes are
> > data and which + *    are OOB. This gives the caller a way to see the
> > actual, physical bytes + *    in the page, without the distortions
> > applied by our ECC engine.
> 
> Hmm, I thought raw was just supposed to disable ECC, not change the
> layout from what is used in normal operation.

You see the page as is ... I see no problem with this part.
> 
> > + * It turns out that knowing whether we want an "ECC-based" or "raw"
> > read is not + * easy. When reading a page, for example, the NAND Flash
> > MTD code calls our + * ecc.read_page or ecc.read_page_raw function.
> > Thus, the fact that MTD wants an + * ECC-based or raw view of the page
> > is implicit in which function it calls + * (there is a similar pair of
> > ECC-based/raw functions for writing).
> 
> This is an issue for the eLBC driver as well -- we need to know whether
> to enable or disable ECC before we begin the operation (in cmdfunc), not
> just at the time the buffer is accessed.  Currently we just always have
> ECC on, and raw accesses aren't raw.  It would be nice to fix this more
> generally (starting in Linux, so we don't diverge).
> 
> It's too bad we can't rely on chip->ops being used... maybe we could
> copy the data into there?  Or just have a separate mtd_oob_mode_t in
> nand_chip.
> 
> > +/*
> > + * Write OOB data to NAND.
> > + */
> > +static int mxs_nand_ecc_write_oob(struct mtd_info *mtd, struct nand_chip
> > *nand, +					int page)
> > +{
> > +	struct mxs_nand_info *nand_info = nand->priv;
> > +	uint8_t block_mark = 0;
> > +
> > +	/*
> > +	 * There are fundamental incompatibilities between the i.MX GPMI NFC
> > and +	 * the NAND Flash MTD model that make it essentially impossible 
to
> > write +	 * the out-of-band bytes.
> > +	 *
> > +	 * We permit *ONE* exception. If the *intent* of writing the OOB is to
> > +	 * mark a block bad, we can do that.
> > +	 */
> 
> Is this just an issue with writing OOB separately from the main data
> (which would also be an issue on MLC chips that don't allow multiple
> partial programming), or can you not even write user OOB bytes as part
> of a full page write?
> 
> Based on fake_ecc_layout I'm guessing the latter.

My understanding of the original FSL driver is that you should never be allowed 
to access the physical NAND media at all. Only through the driver, which does 
the magic.
> 
> > +	if (nand_info->marking_block_bad) {
> > +		printf("NXS NAND: Writing OOB isn't supported\n");
> > +		return -EIO;
> > +	}
> 
> Shouldn't this be if (!nand_info->marking_block_bad)?
> 
> > +/*
> > + * Claims all blocks are good.
> > + *
> > + * In principle, this function is *only* called when the NAND Flash MTD
> > system + * isn't allowed to keep an in-memory bad block table, so it is
> > forced to ask + * the driver for bad block information.
> > + *
> > + * In fact, we permit the NAND Flash MTD system to have an in-memory
> > BBT, so + * this function is *only* called when we take it away.
> > + *
> > + * We take away the in-memory BBT when the user sets the "ignorebad"
> > parameter, + * which indicates that all blocks should be reported good.
> > + *
> > + * Thus, this function is only called when we want *all* blocks to look
> > good, + * so it *always* return success.
> > + */
> > +static int mxs_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int
> > getchip) +{
> > +	return 0;
> > +}
> 
> What/where is the "ignorebad" parameter?

Remnant from FSL code.
> 
> Other than when scrubbing (which has its own override), when would you
> want to do this?
> 
> > +/*
> > + * Nominally, the purpose of this function is to look for or create the
> > bad + * block table. In fact, since the HIL calls this function at the
> > very end of
> 
> HIL?

DTTO
> 
> > + * the initialization process started by nand_scan(), and the HIL
> > doesn't have a + * more formal mechanism, everyone "hooks" this function
> > to continue the + * initialization process.
> 
> Everyone?  I only see diskonchip doing this.

DTTO
> 
> The nand_base.c code actually does have a split here
> (nand_scan_ident/nand_scan_tail), but U-Boot's glue code is too
> inflexible, and insists on calling nand_scan.  The right fix is to let
> drivers call nand_scan_ident/nand_scan_tail themselves.

I can't test now, so this has to wait. I'd prefer to get this mainline and then 
start poking around fixing this.
> 
> -Scott

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

* [U-Boot] [PATCH 09/15] iMX28: Add GPMI NAND driver
  2011-09-28 21:42     ` Marek Vasut
@ 2011-09-28 21:57       ` Scott Wood
  2011-09-28 22:09         ` Marek Vasut
  0 siblings, 1 reply; 116+ messages in thread
From: Scott Wood @ 2011-09-28 21:57 UTC (permalink / raw)
  To: u-boot

On 09/28/2011 04:42 PM, Marek Vasut wrote:
> On Wednesday, September 28, 2011 11:26:45 PM Scott Wood wrote:
>> On 09/11/2011 11:06 PM, Marek Vasut wrote:
>>> +		desc = info->desc[i];
>>> +		memset(desc, 0, sizeof(struct mxs_dma_desc));
>>> +		desc->address = (dma_addr_t)desc;
>>> +	}
>>> +
>>> +	info->desc_index = 0;
>>> +}
>>> +
>>> +static inline uint32_t mxs_nand_ecc_chunk_cnt(uint32_t page_data_size)
>>> +{
>>> +	return page_data_size / MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
>>> +}
>>
>> No need for inline in .c files, GCC should take care of this automatically.
> 
> Does it really ?

Very small functions (and anything used only once) get inlined
automatically.

It might need the hint if you have a larger function that collapses down
to something small due to constant propagation (and of course if it's a
header or otherwise *must* be inlined), but usually it does a decent job
on its own.

>> Hmm, I thought raw was just supposed to disable ECC, not change the
>> layout from what is used in normal operation.
> 
> You see the page as is ... I see no problem with this part.

What if the raw access is being done to e.g. force bit flips for testing?

There seems to be a difference between U-Boot and Linux here.

Linux has this in mtd.h:
>  * MTD_OOB_RAW:         mode to read oob and data without doing ECC checking

Doesn't say anything about layout.

Whereas U-Boot says:
>  * MTD_OOB_RAW:         mode to read raw data+oob in one chunk. The oob data
>  *                      is inserted into the data. Thats a raw image of the
>  *                      flash contents.

Linux used to say what U-Boot says, but changed in commit
b64d39d8b03fea88417d53715ccbebf71d4dcc9f

This commit message includes the comment "Now MTD_OOB_RAW behaves just
like MTD_OOB_PLACE, but doesn't do ECC validation".

So I think if you need something that changes the layout from normal
operations, it needs to be a new mode.  And it's about time to sync up
U-Boot's NAND code with Linux again...

>>> +	/*
>>> +	 * There are fundamental incompatibilities between the i.MX GPMI NFC
>>> and +	 * the NAND Flash MTD model that make it essentially impossible 
> to
>>> write +	 * the out-of-band bytes.
>>> +	 *
>>> +	 * We permit *ONE* exception. If the *intent* of writing the OOB is to
>>> +	 * mark a block bad, we can do that.
>>> +	 */
>>
>> Is this just an issue with writing OOB separately from the main data
>> (which would also be an issue on MLC chips that don't allow multiple
>> partial programming), or can you not even write user OOB bytes as part
>> of a full page write?
>>
>> Based on fake_ecc_layout I'm guessing the latter.
> 
> My understanding of the original FSL driver is that you should never be allowed 
> to access the physical NAND media at all. Only through the driver, which does 
> the magic.

I'm not talking about circumventing the driver, just accessing some user
OOB bytes through it.

>> The nand_base.c code actually does have a split here
>> (nand_scan_ident/nand_scan_tail), but U-Boot's glue code is too
>> inflexible, and insists on calling nand_scan.  The right fix is to let
>> drivers call nand_scan_ident/nand_scan_tail themselves.
> 
> I can't test now, so this has to wait. I'd prefer to get this mainline and then 
> start poking around fixing this.

OK.  It's been on my TODO list for a while now...

-Scott

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

* [U-Boot] [PATCH 09/15] iMX28: Add GPMI NAND driver
  2011-09-28 21:57       ` Scott Wood
@ 2011-09-28 22:09         ` Marek Vasut
  2011-09-28 22:13           ` Scott Wood
  0 siblings, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-09-28 22:09 UTC (permalink / raw)
  To: u-boot

On Wednesday, September 28, 2011 11:57:49 PM Scott Wood wrote:
> On 09/28/2011 04:42 PM, Marek Vasut wrote:
> > On Wednesday, September 28, 2011 11:26:45 PM Scott Wood wrote:
> >> On 09/11/2011 11:06 PM, Marek Vasut wrote:
> >>> +		desc = info->desc[i];
> >>> +		memset(desc, 0, sizeof(struct mxs_dma_desc));
> >>> +		desc->address = (dma_addr_t)desc;
> >>> +	}
> >>> +
> >>> +	info->desc_index = 0;
> >>> +}
> >>> +
> >>> +static inline uint32_t mxs_nand_ecc_chunk_cnt(uint32_t page_data_size)
> >>> +{
> >>> +	return page_data_size / MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
> >>> +}
> >> 
> >> No need for inline in .c files, GCC should take care of this
> >> automatically.
> > 
> > Does it really ?
> 
> Very small functions (and anything used only once) get inlined
> automatically.
> 
> It might need the hint if you have a larger function that collapses down
> to something small due to constant propagation (and of course if it's a
> header or otherwise *must* be inlined), but usually it does a decent job
> on its own.
> 
> >> Hmm, I thought raw was just supposed to disable ECC, not change the
> >> layout from what is used in normal operation.
> > 
> > You see the page as is ... I see no problem with this part.
> 
> What if the raw access is being done to e.g. force bit flips for testing?
> 
> There seems to be a difference between U-Boot and Linux here.
> 
> Linux has this in mtd.h:
> >  * MTD_OOB_RAW:         mode to read oob and data without doing ECC
> >  checking
> 
> Doesn't say anything about layout.
> 
> Whereas U-Boot says:
> >  * MTD_OOB_RAW:         mode to read raw data+oob in one chunk. The oob
> >  data *                      is inserted into the data. Thats a raw
> >  image of the *                      flash contents.
> 
> Linux used to say what U-Boot says, but changed in commit
> b64d39d8b03fea88417d53715ccbebf71d4dcc9f
> 
> This commit message includes the comment "Now MTD_OOB_RAW behaves just
> like MTD_OOB_PLACE, but doesn't do ECC validation".
> 
> So I think if you need something that changes the layout from normal
> operations, it needs to be a new mode.  And it's about time to sync up
> U-Boot's NAND code with Linux again...

Well aren't you the maintainer that should take care of it ? ;-)
> 
> >>> +	/*
> >>> +	 * There are fundamental incompatibilities between the i.MX GPMI NFC
> >>> and +	 * the NAND Flash MTD model that make it essentially impossible
> > 
> > to
> > 
> >>> write +	 * the out-of-band bytes.
> >>> +	 *
> >>> +	 * We permit *ONE* exception. If the *intent* of writing the OOB is
> >>> to +	 * mark a block bad, we can do that.
> >>> +	 */
> >> 
> >> Is this just an issue with writing OOB separately from the main data
> >> (which would also be an issue on MLC chips that don't allow multiple
> >> partial programming), or can you not even write user OOB bytes as part
> >> of a full page write?
> >> 
> >> Based on fake_ecc_layout I'm guessing the latter.
> > 
> > My understanding of the original FSL driver is that you should never be
> > allowed to access the physical NAND media at all. Only through the
> > driver, which does the magic.
> 
> I'm not talking about circumventing the driver, just accessing some user
> OOB bytes through it.

There are no user OOB bytes, the driver does the ECC so user has no need to 
write any OOB.

> 
> >> The nand_base.c code actually does have a split here
> >> (nand_scan_ident/nand_scan_tail), but U-Boot's glue code is too
> >> inflexible, and insists on calling nand_scan.  The right fix is to let
> >> drivers call nand_scan_ident/nand_scan_tail themselves.
> > 
> > I can't test now, so this has to wait. I'd prefer to get this mainline
> > and then start poking around fixing this.
> 
> OK.  It's been on my TODO list for a while now...
> 
> -Scott

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

* [U-Boot] [PATCH 09/15] iMX28: Add GPMI NAND driver
  2011-09-28 21:26   ` Scott Wood
  2011-09-28 21:42     ` Marek Vasut
@ 2011-09-28 22:12     ` Marek Vasut
  2011-09-28 22:23       ` Scott Wood
  1 sibling, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-09-28 22:12 UTC (permalink / raw)
  To: u-boot

On Wednesday, September 28, 2011 11:26:45 PM Scott Wood wrote:
> On 09/11/2011 11:06 PM, Marek Vasut wrote:
> > +static void mxs_nand_return_dma_descs(struct mxs_nand_info *info)
> > +{
> > +	int i = info->desc_index;
> > +	struct mxs_dma_desc *desc;
> > +
> > +	for (--i; i >= 0; i--) {
> 
> This is an awkward construct.
> 
> Why not just the usual:
> 
> for (i = 0; i < info->desc_index; i++)
> 

Checking the driver, this modifies the global data so this is ok

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

* [U-Boot] [PATCH 09/15] iMX28: Add GPMI NAND driver
  2011-09-28 22:09         ` Marek Vasut
@ 2011-09-28 22:13           ` Scott Wood
  2011-09-28 22:34             ` Marek Vasut
  0 siblings, 1 reply; 116+ messages in thread
From: Scott Wood @ 2011-09-28 22:13 UTC (permalink / raw)
  To: u-boot

On 09/28/2011 05:09 PM, Marek Vasut wrote:
> On Wednesday, September 28, 2011 11:57:49 PM Scott Wood wrote:
>> So I think if you need something that changes the layout from normal
>> operations, it needs to be a new mode.  And it's about time to sync up
>> U-Boot's NAND code with Linux again...
> 
> Well aren't you the maintainer that should take care of it ? ;-)

Yes, that note was me adding something to my todo list. :-)

>> I'm not talking about circumventing the driver, just accessing some user
>> OOB bytes through it.
> 
> There are no user OOB bytes, the driver does the ECC so user has no need to 
> write any OOB.

By "user OOB bytes" I meant things other than the ECC and the bad-block
marker -- the space described by oobavail in ecclayout.  This is getting
less useful with partial-page restrictions and large ECC that fills up
most of the OOB, though, and thus there's a trend away from making use
of it.  So if it's a pain to provide access to any spare OOB bytes, it's
not that big of a deal.

-Scott

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

* [U-Boot] [PATCH 09/15 V2] iMX28: Add GPMI NAND driver
  2011-09-12  4:06 ` [U-Boot] [PATCH 09/15] iMX28: Add GPMI NAND driver Marek Vasut
  2011-09-28 21:26   ` Scott Wood
@ 2011-09-28 22:17   ` Marek Vasut
  2011-09-28 22:32     ` [U-Boot] [PATCH 09/15 V3] " Marek Vasut
  1 sibling, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-09-28 22:17 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Scott Wood <scottwood@freescale.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 drivers/mtd/nand/Makefile   |    1 +
 drivers/mtd/nand/mxs_nand.c | 1158 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1159 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/nand/mxs_nand.c

V2: Update comments, drop inlines

diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index b6a7886..aef0d56 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -49,6 +49,7 @@ COBJS-$(CONFIG_NAND_KIRKWOOD) += kirkwood_nand.o
 COBJS-$(CONFIG_NAND_KMETER1) += kmeter1_nand.o
 COBJS-$(CONFIG_NAND_MPC5121_NFC) += mpc5121_nfc.o
 COBJS-$(CONFIG_NAND_MXC) += mxc_nand.o
+COBJS-$(CONFIG_NAND_MXS) += mxs_nand.o
 COBJS-$(CONFIG_NAND_NDFC) += ndfc.o
 COBJS-$(CONFIG_NAND_NOMADIK) += nomadik.o
 COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o
diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c
new file mode 100644
index 0000000..09667a9
--- /dev/null
+++ b/drivers/mtd/nand/mxs_nand.c
@@ -0,0 +1,1158 @@
+/*
+ * Freescale i.MX28 NAND flash driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Freescale GPMI NFC NAND Flash Driver
+ *
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ * Copyright (C) 2008 Embedded Alley Solutions, Inc.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/types.h>
+#include <common.h>
+#include <malloc.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/dma.h>
+
+#define	MXS_NAND_DMA_DESCRIPTOR_COUNT		4
+
+#define	MXS_NAND_CHUNK_DATA_CHUNK_SIZE		512
+#define	MXS_NAND_METADATA_SIZE			10
+
+#define	MXS_NAND_COMMAND_BUFFER_SIZE		32
+
+#define	MXS_NAND_BCH_TIMEOUT			10000
+
+struct mxs_nand_info {
+	int		cur_chip;
+
+	uint32_t	cmd_queue_len;
+
+	uint8_t		*cmd_buf;
+	uint8_t		*data_buf;
+	uint8_t		*oob_buf;
+
+	uint8_t		marking_block_bad;
+	uint8_t		raw_oob_mode;
+
+	/* Functions with altered behaviour */
+	int		(*hooked_read_oob)(struct mtd_info *mtd,
+				loff_t from, struct mtd_oob_ops *ops);
+	int		(*hooked_write_oob)(struct mtd_info *mtd,
+				loff_t to, struct mtd_oob_ops *ops);
+	int		(*hooked_block_markbad)(struct mtd_info *mtd,
+				loff_t ofs);
+
+	/* DMA descriptors */
+	struct mxs_dma_desc	**desc;
+	uint32_t		desc_index;
+};
+
+struct nand_ecclayout fake_ecc_layout;
+
+static struct mxs_dma_desc *mxs_nand_get_dma_desc(struct mxs_nand_info *info)
+{
+	struct mxs_dma_desc *desc;
+
+	if (info->desc_index >= MXS_NAND_DMA_DESCRIPTOR_COUNT) {
+		printf("MXS NAND: Too many DMA descriptors requested\n");
+		return NULL;
+	}
+
+	desc = info->desc[info->desc_index];
+	info->desc_index++;
+
+	return desc;
+}
+
+static void mxs_nand_return_dma_descs(struct mxs_nand_info *info)
+{
+	int i = info->desc_index;
+	struct mxs_dma_desc *desc;
+
+	for (--i; i >= 0; i--) {
+		desc = info->desc[i];
+		memset(desc, 0, sizeof(struct mxs_dma_desc));
+		desc->address = (dma_addr_t)desc;
+	}
+
+	info->desc_index = 0;
+}
+
+static uint32_t mxs_nand_ecc_chunk_cnt(uint32_t page_data_size)
+{
+	return page_data_size / MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
+}
+
+static uint32_t mxs_nand_ecc_size_in_bits(uint32_t ecc_strength)
+{
+	return ecc_strength * 13;
+}
+
+static uint32_t mxs_nand_aux_status_offset(void)
+{
+	return (MXS_NAND_METADATA_SIZE + 0x3) & ~0x3;
+}
+
+static uint32_t mxs_nand_aux_size(uint32_t page_size)
+{
+	uint32_t aux_status_off = mxs_nand_aux_status_offset();
+	uint32_t ecc_chunk_cnt =
+		(mxs_nand_ecc_chunk_cnt(page_size) + 0x3) & ~0x3;
+
+	return ecc_chunk_cnt + aux_status_off;
+}
+
+static inline uint32_t mxs_nand_get_ecc_strength(uint32_t page_data_size,
+						uint32_t page_oob_size)
+{
+	if (page_data_size == 2048)
+		return 8;
+
+	if (page_data_size == 4096) {
+		if (page_oob_size == 128)
+			return 8;
+
+		if (page_oob_size == 218)
+			return 16;
+	}
+
+	return 0;
+}
+
+static inline uint32_t mxs_nand_get_mark_offset(uint32_t page_data_size,
+						uint32_t ecc_strength)
+{
+	uint32_t chunk_data_size_in_bits;
+	uint32_t chunk_ecc_size_in_bits;
+	uint32_t chunk_total_size_in_bits;
+	uint32_t block_mark_chunk_number;
+	uint32_t block_mark_chunk_bit_offset;
+	uint32_t block_mark_bit_offset;
+
+	chunk_data_size_in_bits = MXS_NAND_CHUNK_DATA_CHUNK_SIZE * 8;
+	chunk_ecc_size_in_bits  = mxs_nand_ecc_size_in_bits(ecc_strength);
+
+	chunk_total_size_in_bits =
+			chunk_data_size_in_bits + chunk_ecc_size_in_bits;
+
+	/* Compute the bit offset of the block mark within the physical page. */
+	block_mark_bit_offset = page_data_size * 8;
+
+	/* Subtract the metadata bits. */
+	block_mark_bit_offset -= MXS_NAND_METADATA_SIZE * 8;
+
+	/*
+	 * Compute the chunk number (starting at zero) in which the block mark
+	 * appears.
+	 */
+	block_mark_chunk_number =
+			block_mark_bit_offset / chunk_total_size_in_bits;
+
+	/*
+	 * Compute the bit offset of the block mark within its chunk, and
+	 * validate it.
+	 */
+	block_mark_chunk_bit_offset = block_mark_bit_offset -
+			(block_mark_chunk_number * chunk_total_size_in_bits);
+
+	if (block_mark_chunk_bit_offset > chunk_data_size_in_bits)
+		return 1;
+
+	/*
+	 * Now that we know the chunk number in which the block mark appears,
+	 * we can subtract all the ECC bits that appear before it.
+	 */
+	block_mark_bit_offset -=
+		block_mark_chunk_number * chunk_ecc_size_in_bits;
+
+	return block_mark_bit_offset;
+}
+
+static uint32_t mxs_nand_mark_byte_offset(struct mtd_info *mtd)
+{
+	uint32_t ecc_strength;
+	ecc_strength = mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize);
+	return mxs_nand_get_mark_offset(mtd->writesize, ecc_strength) >> 3;
+}
+
+static uint32_t mxs_nand_mark_bit_offset(struct mtd_info *mtd)
+{
+	uint32_t ecc_strength;
+	ecc_strength = mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize);
+	return mxs_nand_get_mark_offset(mtd->writesize, ecc_strength) & 0x7;
+}
+
+/*
+ * Wait for BCH complete IRQ and clear the IRQ
+ */
+static int mxs_nand_wait_for_bch_complete(void)
+{
+	struct mx28_bch_regs *bch_regs = (struct mx28_bch_regs *)MXS_BCH_BASE;
+	int timeout = MXS_NAND_BCH_TIMEOUT;
+	int ret;
+
+	ret = mx28_wait_mask_set(&bch_regs->hw_bch_ctrl_reg,
+		BCH_CTRL_COMPLETE_IRQ, timeout);
+
+	writel(BCH_CTRL_COMPLETE_IRQ, &bch_regs->hw_bch_ctrl_clr);
+
+	return ret;
+}
+
+/*
+ * This is the function that we install in the cmd_ctrl function pointer of the
+ * owning struct nand_chip. The only functions in the reference implementation
+ * that use these functions pointers are cmdfunc and select_chip.
+ *
+ * In this driver, we implement our own select_chip, so this function will only
+ * be called by the reference implementation's cmdfunc. For this reason, we can
+ * ignore the chip enable bit and concentrate only on sending bytes to the
+ * NAND Flash.
+ */
+static void mxs_nand_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	int ret;
+
+	/*
+	 * If this condition is true, something is _VERY_ wrong in MTD
+	 * subsystem!
+	 */
+	if (nand_info->cmd_queue_len == MXS_NAND_COMMAND_BUFFER_SIZE) {
+		printf("MXS NAND: Command queue too long\n");
+		return;
+	}
+
+	/*
+	 * Every operation begins with a command byte and a series of zero or
+	 * more address bytes. These are distinguished by either the Address
+	 * Latch Enable (ALE) or Command Latch Enable (CLE) signals being
+	 * asserted. When MTD is ready to execute the command, it will
+	 * deasert both latch enables.
+	 *
+	 * Rather than run a separate DMA operation for every single byte, we
+	 * queue them up and run a single DMA operation for the entire series
+	 * of command and data bytes.
+	 */
+	if (ctrl & (NAND_ALE | NAND_CLE)) {
+		if (data != NAND_CMD_NONE)
+			nand_info->cmd_buf[nand_info->cmd_queue_len++] = data;
+		return;
+	}
+
+	/*
+	 * If control arrives here, MTD has deasserted both the ALE and CLE,
+	 * which means it's ready to run an operation. Check if we have any
+	 * bytes to send.
+	 */
+	if (nand_info->cmd_queue_len == 0)
+		return;
+
+	/* Compile the DMA descriptor -- a descriptor that sends command. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_DMA_READ | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_CHAIN | MXS_DMA_DESC_DEC_SEM |
+		MXS_DMA_DESC_WAIT4END | (3 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
+		(nand_info->cmd_queue_len << MXS_DMA_DESC_BYTES_OFFSET);
+
+	d->cmd.address = (dma_addr_t)nand_info->cmd_buf;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_CLE |
+		GPMI_CTRL0_ADDRESS_INCREMENT |
+		nand_info->cmd_queue_len;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret)
+		printf("MXS NAND: Error sending command\n");
+
+	mxs_nand_return_dma_descs(nand_info);
+
+	/* Reset the command queue. */
+	nand_info->cmd_queue_len = 0;
+}
+
+/*
+ * Test if the NAND flash is ready.
+ */
+static int mxs_nand_device_ready(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mxs_nand_info *nand_info = chip->priv;
+	struct mx28_gpmi_regs *gpmi_regs =
+		(struct mx28_gpmi_regs *)MXS_GPMI_BASE;
+	uint32_t tmp;
+
+	tmp = readl(&gpmi_regs->hw_gpmi_stat);
+	tmp >>= (GPMI_STAT_READY_BUSY_OFFSET + nand_info->cur_chip);
+
+	return tmp & 1;
+}
+
+/*
+ * Select the NAND chip.
+ */
+static void mxs_nand_select_chip(struct mtd_info *mtd, int chip)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+
+	nand_info->cur_chip = chip;
+}
+
+/*
+ * Handle block mark swapping.
+ *
+ * Note that, when this function is called, it doesn't know whether it's
+ * swapping the block mark, or swapping it *back* -- but it doesn't matter
+ * because the the operation is the same.
+ */
+static void mxs_nand_swap_block_mark(struct mtd_info *mtd,
+					uint8_t *data_buf, uint8_t *oob_buf)
+{
+	uint32_t bit_offset;
+	uint32_t buf_offset;
+
+	uint32_t src;
+	uint32_t dst;
+
+	bit_offset = mxs_nand_mark_bit_offset(mtd);
+	buf_offset = mxs_nand_mark_byte_offset(mtd);
+
+	/*
+	 * Get the byte from the data area that overlays the block mark. Since
+	 * the ECC engine applies its own view to the bits in the page, the
+	 * physical block mark won't (in general) appear on a byte boundary in
+	 * the data.
+	 */
+	src = data_buf[buf_offset] >> bit_offset;
+	src |= data_buf[buf_offset + 1] << (8 - bit_offset);
+
+	dst = oob_buf[0];
+
+	oob_buf[0] = src;
+
+	data_buf[buf_offset] &= ~(0xff << bit_offset);
+	data_buf[buf_offset + 1] &= 0xff << bit_offset;
+
+	data_buf[buf_offset] |= dst << bit_offset;
+	data_buf[buf_offset + 1] |= dst >> (8 - bit_offset);
+}
+
+/*
+ * Read data from NAND.
+ */
+static void mxs_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int length)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	int ret;
+
+	if (length > NAND_MAX_PAGESIZE) {
+		printf("MXS NAND: DMA buffer too big\n");
+		return;
+	}
+
+	if (!buf) {
+		printf("MXS NAND: DMA buffer is NULL\n");
+		return;
+	}
+
+	/* Compile the DMA descriptor - a descriptor that reads data. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_DMA_WRITE | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
+		(1 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
+		(length << MXS_DMA_DESC_BYTES_OFFSET);
+
+	d->cmd.address = (dma_addr_t)nand_info->data_buf;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_READ |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		length;
+
+	mxs_dma_desc_append(channel, d);
+
+	/*
+	 * A DMA descriptor that waits for the command to end and the chip to
+	 * become ready.
+	 *
+	 * I think we actually should *not* be waiting for the chip to become
+	 * ready because, after all, we don't care. I think the original code
+	 * did that and no one has re-thought it yet.
+	 */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_DEC_SEM |
+		MXS_DMA_DESC_WAIT4END | (4 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret) {
+		printf("MXS NAND: DMA read error\n");
+		goto rtn;
+	}
+
+	memcpy(buf, nand_info->data_buf, length);
+
+rtn:
+	mxs_nand_return_dma_descs(nand_info);
+}
+
+/*
+ * Write data to NAND.
+ */
+static void mxs_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf,
+				int length)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	int ret;
+
+	if (length > NAND_MAX_PAGESIZE) {
+		printf("MXS NAND: DMA buffer too big\n");
+		return;
+	}
+
+	if (!buf) {
+		printf("MXS NAND: DMA buffer is NULL\n");
+		return;
+	}
+
+	memcpy(nand_info->data_buf, buf, length);
+
+	/* Compile the DMA descriptor - a descriptor that writes data. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_DMA_READ | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
+		(4 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
+		(length << MXS_DMA_DESC_BYTES_OFFSET);
+
+	d->cmd.address = (dma_addr_t)nand_info->data_buf;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		length;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret)
+		printf("MXS NAND: DMA write error\n");
+
+	mxs_nand_return_dma_descs(nand_info);
+}
+
+/*
+ * Read a single byte from NAND.
+ */
+static uint8_t mxs_nand_read_byte(struct mtd_info *mtd)
+{
+	uint8_t buf;
+	mxs_nand_read_buf(mtd, &buf, 1);
+	return buf;
+}
+
+/*
+ * Read a page from NAND.
+ */
+static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
+					uint8_t *buf, int page)
+{
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	uint32_t corrected = 0, failed = 0;
+	uint8_t	*status;
+	int i, ret;
+
+	/* Compile the DMA descriptor - wait for ready. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
+		MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_WAIT4END |
+		(1 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Compile the DMA descriptor - enable the BCH block and read. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
+		MXS_DMA_DESC_WAIT4END |	(6 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_READ |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		(mtd->writesize + mtd->oobsize);
+	d->cmd.pio_words[1] = 0;
+	d->cmd.pio_words[2] =
+		GPMI_ECCCTRL_ENABLE_ECC |
+		GPMI_ECCCTRL_ECC_CMD_DECODE |
+		GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE;
+	d->cmd.pio_words[3] = mtd->writesize + mtd->oobsize;
+	d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf;
+	d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Compile the DMA descriptor - disable the BCH block. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
+		MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_WAIT4END |
+		(3 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		(mtd->writesize + mtd->oobsize);
+	d->cmd.pio_words[1] = 0;
+	d->cmd.pio_words[2] = 0;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Compile the DMA descriptor - deassert the NAND lock and interrupt. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_DEC_SEM;
+
+	d->cmd.address = 0;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret) {
+		printf("MXS NAND: DMA read error\n");
+		goto rtn;
+	}
+
+	ret = mxs_nand_wait_for_bch_complete();
+	if (ret) {
+		printf("MXS NAND: BCH read timeout\n");
+		goto rtn;
+	}
+
+	/* Read DMA completed, now do the mark swapping. */
+	mxs_nand_swap_block_mark(mtd, nand_info->data_buf, nand_info->oob_buf);
+
+	/* Loop over status bytes, accumulating ECC status. */
+	status = nand_info->oob_buf + mxs_nand_aux_status_offset();
+	for (i = 0; i < mxs_nand_ecc_chunk_cnt(mtd->writesize); i++) {
+		if (status[i] == 0x00)
+			continue;
+
+		if (status[i] == 0xff)
+			continue;
+
+		if (status[i] == 0xfe) {
+			failed++;
+			continue;
+		}
+
+		corrected += status[i];
+	}
+
+	/* Propagate ECC status to the owning MTD. */
+	mtd->ecc_stats.failed += failed;
+	mtd->ecc_stats.corrected += corrected;
+
+	/*
+	 * It's time to deliver the OOB bytes. See mxs_nand_ecc_read_oob() for
+	 * details about our policy for delivering the OOB.
+	 *
+	 * We fill the caller's buffer with set bits, and then copy the block
+	 * mark to th caller's buffer. Note that, if block mark swapping was
+	 * necessary, it has already been done, so we can rely on the first
+	 * byte of the auxiliary buffer to contain the block mark.
+	 */
+	memset(nand->oob_poi, 0xff, mtd->oobsize);
+
+	nand->oob_poi[0] = nand_info->oob_buf[0];
+
+	memcpy(buf, nand_info->data_buf, mtd->writesize);
+
+rtn:
+	mxs_nand_return_dma_descs(nand_info);
+
+	return ret;
+}
+
+/*
+ * Write a page to NAND.
+ */
+static void mxs_nand_ecc_write_page(struct mtd_info *mtd,
+				struct nand_chip *nand, const uint8_t *buf)
+{
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	int ret;
+
+	memcpy(nand_info->data_buf, buf, mtd->writesize);
+	memcpy(nand_info->oob_buf, nand->oob_poi, mtd->oobsize);
+
+	/* Handle block mark swapping. */
+	mxs_nand_swap_block_mark(mtd, nand_info->data_buf, nand_info->oob_buf);
+
+	/* Compile the DMA descriptor - write data. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
+		(6 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA;
+	d->cmd.pio_words[1] = 0;
+	d->cmd.pio_words[2] =
+		GPMI_ECCCTRL_ENABLE_ECC |
+		GPMI_ECCCTRL_ECC_CMD_ENCODE |
+		GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE;
+	d->cmd.pio_words[3] = (mtd->writesize + mtd->oobsize);
+	d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf;
+	d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret) {
+		printf("MXS NAND: DMA write error\n");
+		goto rtn;
+	}
+
+	ret = mxs_nand_wait_for_bch_complete();
+	if (ret) {
+		printf("MXS NAND: BCH write timeout\n");
+		goto rtn;
+	}
+
+rtn:
+	mxs_nand_return_dma_descs(nand_info);
+}
+
+/*
+ * Read OOB from NAND.
+ *
+ * This function is a veneer that replaces the function originally installed by
+ * the NAND Flash MTD code.
+ */
+static int mxs_nand_hook_read_oob(struct mtd_info *mtd, loff_t from,
+					struct mtd_oob_ops *ops)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mxs_nand_info *nand_info = chip->priv;
+	int ret;
+
+	if (ops->mode == MTD_OOB_RAW)
+		nand_info->raw_oob_mode = 1;
+	else
+		nand_info->raw_oob_mode = 0;
+
+	ret = nand_info->hooked_read_oob(mtd, from, ops);
+
+	nand_info->raw_oob_mode = 0;
+
+	return ret;
+}
+
+/*
+ * Write OOB to NAND.
+ *
+ * This function is a veneer that replaces the function originally installed by
+ * the NAND Flash MTD code.
+ */
+static int mxs_nand_hook_write_oob(struct mtd_info *mtd, loff_t to,
+					struct mtd_oob_ops *ops)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mxs_nand_info *nand_info = chip->priv;
+	int ret;
+
+	if (ops->mode == MTD_OOB_RAW)
+		nand_info->raw_oob_mode = 1;
+	else
+		nand_info->raw_oob_mode = 0;
+
+	ret = nand_info->hooked_write_oob(mtd, to, ops);
+
+	nand_info->raw_oob_mode = 0;
+
+	return ret;
+}
+
+/*
+ * Mark a block bad in NAND.
+ *
+ * This function is a veneer that replaces the function originally installed by
+ * the NAND Flash MTD code.
+ */
+static int mxs_nand_hook_block_markbad(struct mtd_info *mtd, loff_t ofs)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mxs_nand_info *nand_info = chip->priv;
+	int ret;
+
+	nand_info->marking_block_bad = 1;
+
+	ret = nand_info->hooked_block_markbad(mtd, ofs);
+
+	nand_info->marking_block_bad = 0;
+
+	return ret;
+}
+
+/*
+ * There are several places in this driver where we have to handle the OOB and
+ * block marks. This is the function where things are the most complicated, so
+ * this is where we try to explain it all. All the other places refer back to
+ * here.
+ *
+ * These are the rules, in order of decreasing importance:
+ *
+ * 1) Nothing the caller does can be allowed to imperil the block mark, so all
+ *    write operations take measures to protect it.
+ *
+ * 2) In read operations, the first byte of the OOB we return must reflect the
+ *    true state of the block mark, no matter where that block mark appears in
+ *    the physical page.
+ *
+ * 3) ECC-based read operations return an OOB full of set bits (since we never
+ *    allow ECC-based writes to the OOB, it doesn't matter what ECC-based reads
+ *    return).
+ *
+ * 4) "Raw" read operations return a direct view of the physical bytes in the
+ *    page, using the conventional definition of which bytes are data and which
+ *    are OOB. This gives the caller a way to see the actual, physical bytes
+ *    in the page, without the distortions applied by our ECC engine.
+ *
+ *
+ * What we do for this specific read operation depends on two questions:
+ *
+ * 1) Are we doing a "raw" read, or an ECC-based read?
+ *
+ * 2) Are we using block mark swapping or transcription?
+ *
+ * There are four cases, illustrated by the following Karnaugh map:
+ *
+ *                    |           Raw           |         ECC-based       |
+ *       -------------+-------------------------+-------------------------+
+ *                    | Read the conventional   |                         |
+ *                    | OOB at the end of the   |                         |
+ *       Swapping     | page and return it. It  |                         |
+ *                    | contains exactly what   |                         |
+ *                    | we want.                | Read the block mark and |
+ *       -------------+-------------------------+ return it in a buffer   |
+ *                    | Read the conventional   | full of set bits.       |
+ *                    | OOB at the end of the   |                         |
+ *                    | page and also the block |                         |
+ *       Transcribing | mark in the metadata.   |                         |
+ *                    | Copy the block mark     |                         |
+ *                    | into the first byte of  |                         |
+ *                    | the OOB.                |                         |
+ *       -------------+-------------------------+-------------------------+
+ *
+ * Note that we break rule #4 in the Transcribing/Raw case because we're not
+ * giving an accurate view of the actual, physical bytes in the page (we're
+ * overwriting the block mark). That's OK because it's more important to follow
+ * rule #2.
+ *
+ * It turns out that knowing whether we want an "ECC-based" or "raw" read is not
+ * easy. When reading a page, for example, the NAND Flash MTD code calls our
+ * ecc.read_page or ecc.read_page_raw function. Thus, the fact that MTD wants an
+ * ECC-based or raw view of the page is implicit in which function it calls
+ * (there is a similar pair of ECC-based/raw functions for writing).
+ *
+ * Since MTD assumes the OOB is not covered by ECC, there is no pair of
+ * ECC-based/raw functions for reading or or writing the OOB. The fact that the
+ * caller wants an ECC-based or raw view of the page is not propagated down to
+ * this driver.
+ *
+ * Since our OOB *is* covered by ECC, we need this information. So, we hook the
+ * ecc.read_oob and ecc.write_oob function pointers in the owning
+ * struct mtd_info with our own functions. These hook functions set the
+ * raw_oob_mode field so that, when control finally arrives here, we'll know
+ * what to do.
+ */
+static int mxs_nand_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *nand,
+				int page, int cmd)
+{
+	struct mxs_nand_info *nand_info = nand->priv;
+
+	/*
+	 * First, fill in the OOB buffer. If we're doing a raw read, we need to
+	 * get the bytes from the physical page. If we're not doing a raw read,
+	 * we need to fill the buffer with set bits.
+	 */
+	if (nand_info->raw_oob_mode) {
+		/*
+		 * If control arrives here, we're doing a "raw" read. Send the
+		 * command to read the conventional OOB and read it.
+		 */
+		nand->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page);
+		nand->read_buf(mtd, nand->oob_poi, mtd->oobsize);
+	} else {
+		/*
+		 * If control arrives here, we're not doing a "raw" read. Fill
+		 * the OOB buffer with set bits and correct the block mark.
+		 */
+		memset(nand->oob_poi, 0xff, mtd->oobsize);
+
+		nand->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page);
+		mxs_nand_read_buf(mtd, nand->oob_poi, 1);
+	}
+
+	return 0;
+
+}
+
+/*
+ * Write OOB data to NAND.
+ */
+static int mxs_nand_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *nand,
+					int page)
+{
+	struct mxs_nand_info *nand_info = nand->priv;
+	uint8_t block_mark = 0;
+
+	/*
+	 * There are fundamental incompatibilities between the i.MX GPMI NFC and
+	 * the NAND Flash MTD model that make it essentially impossible to write
+	 * the out-of-band bytes.
+	 *
+	 * We permit *ONE* exception. If the *intent* of writing the OOB is to
+	 * mark a block bad, we can do that.
+	 */
+
+	if (!nand_info->marking_block_bad) {
+		printf("NXS NAND: Writing OOB isn't supported\n");
+		return -EIO;
+	}
+
+	/* Write the block mark. */
+	nand->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
+	nand->write_buf(mtd, &block_mark, 1);
+	nand->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+
+	/* Check if it worked. */
+	if (nand->waitfunc(mtd, nand) & NAND_STATUS_FAIL)
+		return -EIO;
+
+	return 0;
+}
+
+/*
+ * Claims all blocks are good.
+ *
+ * In principle, this function is *only* called when the NAND Flash MTD system
+ * isn't allowed to keep an in-memory bad block table, so it is forced to ask
+ * the driver for bad block information.
+ *
+ * In fact, we permit the NAND Flash MTD system to have an in-memory BBT, so
+ * this function is *only* called when we take it away.
+ *
+ * We take away the in-memory BBT when the user sets the "ignorebad" parameter,
+ * which indicates that all blocks should be reported good.
+ *
+ * Thus, this function is only called when we want *all* blocks to look good,
+ * so it *always* return success.
+ */
+static int mxs_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
+{
+	return 0;
+}
+
+/*
+ * Nominally, the purpose of this function is to look for or create the bad
+ * block table. In fact, since the we call this function at the very end of
+ * the initialization process started by nand_scan(), and we doesn't have a
+ * more formal mechanism, we "hook" this function to continue init process.
+ *
+ * At this point, the physical NAND Flash chips have been identified and
+ * counted, so we know the physical geometry. This enables us to make some
+ * important configuration decisions.
+ *
+ * The return value of this function propogates directly back to this driver's
+ * call to nand_scan(). Anything other than zero will cause this driver to
+ * tear everything down and declare failure.
+ */
+static int mxs_nand_scan_bbt(struct mtd_info *mtd)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mx28_bch_regs *bch_regs = (struct mx28_bch_regs *)MXS_BCH_BASE;
+	uint32_t tmp;
+
+	/* Configure BCH and set NFC geometry */
+	mx28_reset_block(&bch_regs->hw_bch_ctrl_reg);
+
+	/* Configure layout 0 */
+	tmp = (mxs_nand_ecc_chunk_cnt(mtd->writesize) - 1)
+		<< BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
+	tmp |= MXS_NAND_METADATA_SIZE << BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
+	tmp |= (mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1)
+		<< BCH_FLASHLAYOUT0_ECC0_OFFSET;
+	tmp |= MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
+	writel(tmp, &bch_regs->hw_bch_flash0layout0);
+
+	tmp = (mtd->writesize + mtd->oobsize)
+		<< BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
+	tmp |= (mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1)
+		<< BCH_FLASHLAYOUT1_ECCN_OFFSET;
+	tmp |= MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
+	writel(tmp, &bch_regs->hw_bch_flash0layout1);
+
+	/* Set *all* chip selects to use layout 0 */
+	writel(0, &bch_regs->hw_bch_layoutselect);
+
+	/* Enable BCH complete interrupt */
+	writel(BCH_CTRL_COMPLETE_IRQ_EN, &bch_regs->hw_bch_ctrl_set);
+
+	/* Hook some operations at the MTD level. */
+	if (mtd->read_oob != mxs_nand_hook_read_oob) {
+		nand_info->hooked_read_oob = mtd->read_oob;
+		mtd->read_oob = mxs_nand_hook_read_oob;
+	}
+
+	if (mtd->write_oob != mxs_nand_hook_write_oob) {
+		nand_info->hooked_write_oob = mtd->write_oob;
+		mtd->write_oob = mxs_nand_hook_write_oob;
+	}
+
+	if (mtd->block_markbad != mxs_nand_hook_block_markbad) {
+		nand_info->hooked_block_markbad = mtd->block_markbad;
+		mtd->block_markbad = mxs_nand_hook_block_markbad;
+	}
+
+	/* We use the reference implementation for bad block management. */
+	return nand_default_bbt(mtd);
+}
+
+/*
+ * Allocate DMA buffers
+ */
+int mxs_nand_alloc_buffers(struct mxs_nand_info *nand_info)
+{
+	uint8_t *buf;
+	const int size = NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE;
+
+	/* DMA buffers */
+	buf = memalign(MXS_DMA_ALIGNMENT, size);
+	if (!buf) {
+		printf("MXS NAND: Error allocating DMA buffers\n");
+		return -ENOMEM;
+	}
+
+	memset(buf, 0, size);
+
+	nand_info->data_buf = buf;
+	nand_info->oob_buf = buf + NAND_MAX_PAGESIZE;
+
+	/* Command buffers */
+	nand_info->cmd_buf = memalign(MXS_DMA_ALIGNMENT,
+				MXS_NAND_COMMAND_BUFFER_SIZE);
+	if (!nand_info->cmd_buf) {
+		free(buf);
+		printf("MXS NAND: Error allocating command buffers\n");
+		return -ENOMEM;
+	}
+	memset(nand_info->cmd_buf, 0, MXS_NAND_COMMAND_BUFFER_SIZE);
+	nand_info->cmd_queue_len = 0;
+
+	return 0;
+}
+
+/*
+ * Initializes the NFC hardware.
+ */
+int mxs_nand_init(struct mxs_nand_info *info)
+{
+	struct mx28_gpmi_regs *gpmi_regs =
+		(struct mx28_gpmi_regs *)MXS_GPMI_BASE;
+	int i = 0;
+
+	info->desc = malloc(sizeof(struct mxs_dma_desc *) *
+				MXS_NAND_DMA_DESCRIPTOR_COUNT);
+	if (!info->desc)
+		goto err1;
+
+	/* Allocate the DMA descriptors. */
+	for (i = 0; i < MXS_NAND_DMA_DESCRIPTOR_COUNT; i++) {
+		info->desc[i] = mxs_dma_desc_alloc();
+		if (!info->desc[i])
+			goto err2;
+	}
+
+	/* Init the DMA controller. */
+	mxs_dma_init();
+
+	/* Reset the GPMI block. */
+	mx28_reset_block(&gpmi_regs->hw_gpmi_ctrl0_reg);
+
+	/*
+	 * Choose NAND mode, set IRQ polarity, disable write protection and
+	 * select BCH ECC.
+	 */
+	clrsetbits_le32(&gpmi_regs->hw_gpmi_ctrl1,
+			GPMI_CTRL1_GPMI_MODE,
+			GPMI_CTRL1_ATA_IRQRDY_POLARITY | GPMI_CTRL1_DEV_RESET |
+			GPMI_CTRL1_BCH_MODE);
+
+	return 0;
+
+err2:
+	free(info->desc);
+err1:
+	for (--i; i >= 0; i--)
+		mxs_dma_desc_free(info->desc[i]);
+	printf("MXS NAND: Unable to allocate DMA descriptors\n");
+	return -ENOMEM;
+}
+
+/*!
+ * This function is called during the driver binding process.
+ *
+ * @param   pdev  the device structure used to store device specific
+ *                information that is used by the suspend, resume and
+ *                remove functions
+ *
+ * @return  The function always returns 0.
+ */
+int board_nand_init(struct nand_chip *nand)
+{
+	struct mxs_nand_info *nand_info;
+	int err;
+
+	nand_info = malloc(sizeof(struct mxs_nand_info));
+	if (!nand_info) {
+		printf("MXS NAND: Failed to allocate private data\n");
+		return -ENOMEM;
+	}
+	memset(nand_info, 0, sizeof(struct mxs_nand_info));
+
+	err = mxs_nand_alloc_buffers(nand_info);
+	if (err)
+		goto err1;
+
+	err = mxs_nand_init(nand_info);
+	if (err)
+		goto err2;
+
+	memset(&fake_ecc_layout, 0, sizeof(fake_ecc_layout));
+
+	nand->priv = nand_info;
+	nand->options |= NAND_NO_SUBPAGE_WRITE;
+
+	nand->cmd_ctrl		= mxs_nand_cmd_ctrl;
+
+	nand->dev_ready		= mxs_nand_device_ready;
+	nand->select_chip	= mxs_nand_select_chip;
+	nand->block_bad		= mxs_nand_block_bad;
+	nand->scan_bbt		= mxs_nand_scan_bbt;
+
+	nand->read_byte		= mxs_nand_read_byte;
+
+	nand->read_buf		= mxs_nand_read_buf;
+	nand->write_buf		= mxs_nand_write_buf;
+
+	nand->ecc.read_page	= mxs_nand_ecc_read_page;
+	nand->ecc.write_page	= mxs_nand_ecc_write_page;
+	nand->ecc.read_oob	= mxs_nand_ecc_read_oob;
+	nand->ecc.write_oob	= mxs_nand_ecc_write_oob;
+
+	nand->ecc.layout	= &fake_ecc_layout;
+	nand->ecc.mode		= NAND_ECC_HW;
+	nand->ecc.bytes		= 9;
+	nand->ecc.size		= 512;
+
+	return 0;
+
+err2:
+	free(nand_info->data_buf);
+	free(nand_info->cmd_buf);
+err1:
+	free(nand_info);
+	return err;
+}
-- 
1.7.5.4

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

* [U-Boot] [PATCH 09/15] iMX28: Add GPMI NAND driver
  2011-09-28 22:12     ` Marek Vasut
@ 2011-09-28 22:23       ` Scott Wood
  0 siblings, 0 replies; 116+ messages in thread
From: Scott Wood @ 2011-09-28 22:23 UTC (permalink / raw)
  To: u-boot

On 09/28/2011 05:12 PM, Marek Vasut wrote:
> On Wednesday, September 28, 2011 11:26:45 PM Scott Wood wrote:
>> On 09/11/2011 11:06 PM, Marek Vasut wrote:
>>> +static void mxs_nand_return_dma_descs(struct mxs_nand_info *info)
>>> +{
>>> +	int i = info->desc_index;
>>> +	struct mxs_dma_desc *desc;
>>> +
>>> +	for (--i; i >= 0; i--) {
>>
>> This is an awkward construct.
>>
>> Why not just the usual:
>>
>> for (i = 0; i < info->desc_index; i++)
>>
> 
> Checking the driver, this modifies the global data so this is ok

I don't follow... I'm assuming by "this" you mean the original code
since you didn't change it, so are you saying that the global data has
to be modified in descending order?

If that's really a requirement, put in a comment saying so (and ideally
why), and you could still just do:

for (i = info->desc_index - 1; i >= 0; i--)

or

while (--i >= 0)

-Scott

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

* [U-Boot] [PATCH 09/15 V3] iMX28: Add GPMI NAND driver
  2011-09-28 22:17   ` [U-Boot] [PATCH 09/15 V2] " Marek Vasut
@ 2011-09-28 22:32     ` Marek Vasut
  2011-09-29  0:07       ` [U-Boot] [PATCH 09/15 V4] " Marek Vasut
  0 siblings, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-09-28 22:32 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Scott Wood <scottwood@freescale.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 drivers/mtd/nand/Makefile   |    1 +
 drivers/mtd/nand/mxs_nand.c | 1158 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1159 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/nand/mxs_nand.c

V2: Update comments, drop inlines
V3: Fix descriptor reclamation loop

diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index b6a7886..aef0d56 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -49,6 +49,7 @@ COBJS-$(CONFIG_NAND_KIRKWOOD) += kirkwood_nand.o
 COBJS-$(CONFIG_NAND_KMETER1) += kmeter1_nand.o
 COBJS-$(CONFIG_NAND_MPC5121_NFC) += mpc5121_nfc.o
 COBJS-$(CONFIG_NAND_MXC) += mxc_nand.o
+COBJS-$(CONFIG_NAND_MXS) += mxs_nand.o
 COBJS-$(CONFIG_NAND_NDFC) += ndfc.o
 COBJS-$(CONFIG_NAND_NOMADIK) += nomadik.o
 COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o
diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c
new file mode 100644
index 0000000..601f11b
--- /dev/null
+++ b/drivers/mtd/nand/mxs_nand.c
@@ -0,0 +1,1158 @@
+/*
+ * Freescale i.MX28 NAND flash driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Freescale GPMI NFC NAND Flash Driver
+ *
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ * Copyright (C) 2008 Embedded Alley Solutions, Inc.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/types.h>
+#include <common.h>
+#include <malloc.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/dma.h>
+
+#define	MXS_NAND_DMA_DESCRIPTOR_COUNT		4
+
+#define	MXS_NAND_CHUNK_DATA_CHUNK_SIZE		512
+#define	MXS_NAND_METADATA_SIZE			10
+
+#define	MXS_NAND_COMMAND_BUFFER_SIZE		32
+
+#define	MXS_NAND_BCH_TIMEOUT			10000
+
+struct mxs_nand_info {
+	int		cur_chip;
+
+	uint32_t	cmd_queue_len;
+
+	uint8_t		*cmd_buf;
+	uint8_t		*data_buf;
+	uint8_t		*oob_buf;
+
+	uint8_t		marking_block_bad;
+	uint8_t		raw_oob_mode;
+
+	/* Functions with altered behaviour */
+	int		(*hooked_read_oob)(struct mtd_info *mtd,
+				loff_t from, struct mtd_oob_ops *ops);
+	int		(*hooked_write_oob)(struct mtd_info *mtd,
+				loff_t to, struct mtd_oob_ops *ops);
+	int		(*hooked_block_markbad)(struct mtd_info *mtd,
+				loff_t ofs);
+
+	/* DMA descriptors */
+	struct mxs_dma_desc	**desc;
+	uint32_t		desc_index;
+};
+
+struct nand_ecclayout fake_ecc_layout;
+
+static struct mxs_dma_desc *mxs_nand_get_dma_desc(struct mxs_nand_info *info)
+{
+	struct mxs_dma_desc *desc;
+
+	if (info->desc_index >= MXS_NAND_DMA_DESCRIPTOR_COUNT) {
+		printf("MXS NAND: Too many DMA descriptors requested\n");
+		return NULL;
+	}
+
+	desc = info->desc[info->desc_index];
+	info->desc_index++;
+
+	return desc;
+}
+
+static void mxs_nand_return_dma_descs(struct mxs_nand_info *info)
+{
+	int i;
+	struct mxs_dma_desc *desc;
+
+	for (i = 0; i < info->desc_index; i++) {
+		desc = info->desc[i];
+		memset(desc, 0, sizeof(struct mxs_dma_desc));
+		desc->address = (dma_addr_t)desc;
+	}
+
+	info->desc_index = 0;
+}
+
+static uint32_t mxs_nand_ecc_chunk_cnt(uint32_t page_data_size)
+{
+	return page_data_size / MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
+}
+
+static uint32_t mxs_nand_ecc_size_in_bits(uint32_t ecc_strength)
+{
+	return ecc_strength * 13;
+}
+
+static uint32_t mxs_nand_aux_status_offset(void)
+{
+	return (MXS_NAND_METADATA_SIZE + 0x3) & ~0x3;
+}
+
+static uint32_t mxs_nand_aux_size(uint32_t page_size)
+{
+	uint32_t aux_status_off = mxs_nand_aux_status_offset();
+	uint32_t ecc_chunk_cnt =
+		(mxs_nand_ecc_chunk_cnt(page_size) + 0x3) & ~0x3;
+
+	return ecc_chunk_cnt + aux_status_off;
+}
+
+static inline uint32_t mxs_nand_get_ecc_strength(uint32_t page_data_size,
+						uint32_t page_oob_size)
+{
+	if (page_data_size == 2048)
+		return 8;
+
+	if (page_data_size == 4096) {
+		if (page_oob_size == 128)
+			return 8;
+
+		if (page_oob_size == 218)
+			return 16;
+	}
+
+	return 0;
+}
+
+static inline uint32_t mxs_nand_get_mark_offset(uint32_t page_data_size,
+						uint32_t ecc_strength)
+{
+	uint32_t chunk_data_size_in_bits;
+	uint32_t chunk_ecc_size_in_bits;
+	uint32_t chunk_total_size_in_bits;
+	uint32_t block_mark_chunk_number;
+	uint32_t block_mark_chunk_bit_offset;
+	uint32_t block_mark_bit_offset;
+
+	chunk_data_size_in_bits = MXS_NAND_CHUNK_DATA_CHUNK_SIZE * 8;
+	chunk_ecc_size_in_bits  = mxs_nand_ecc_size_in_bits(ecc_strength);
+
+	chunk_total_size_in_bits =
+			chunk_data_size_in_bits + chunk_ecc_size_in_bits;
+
+	/* Compute the bit offset of the block mark within the physical page. */
+	block_mark_bit_offset = page_data_size * 8;
+
+	/* Subtract the metadata bits. */
+	block_mark_bit_offset -= MXS_NAND_METADATA_SIZE * 8;
+
+	/*
+	 * Compute the chunk number (starting at zero) in which the block mark
+	 * appears.
+	 */
+	block_mark_chunk_number =
+			block_mark_bit_offset / chunk_total_size_in_bits;
+
+	/*
+	 * Compute the bit offset of the block mark within its chunk, and
+	 * validate it.
+	 */
+	block_mark_chunk_bit_offset = block_mark_bit_offset -
+			(block_mark_chunk_number * chunk_total_size_in_bits);
+
+	if (block_mark_chunk_bit_offset > chunk_data_size_in_bits)
+		return 1;
+
+	/*
+	 * Now that we know the chunk number in which the block mark appears,
+	 * we can subtract all the ECC bits that appear before it.
+	 */
+	block_mark_bit_offset -=
+		block_mark_chunk_number * chunk_ecc_size_in_bits;
+
+	return block_mark_bit_offset;
+}
+
+static uint32_t mxs_nand_mark_byte_offset(struct mtd_info *mtd)
+{
+	uint32_t ecc_strength;
+	ecc_strength = mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize);
+	return mxs_nand_get_mark_offset(mtd->writesize, ecc_strength) >> 3;
+}
+
+static uint32_t mxs_nand_mark_bit_offset(struct mtd_info *mtd)
+{
+	uint32_t ecc_strength;
+	ecc_strength = mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize);
+	return mxs_nand_get_mark_offset(mtd->writesize, ecc_strength) & 0x7;
+}
+
+/*
+ * Wait for BCH complete IRQ and clear the IRQ
+ */
+static int mxs_nand_wait_for_bch_complete(void)
+{
+	struct mx28_bch_regs *bch_regs = (struct mx28_bch_regs *)MXS_BCH_BASE;
+	int timeout = MXS_NAND_BCH_TIMEOUT;
+	int ret;
+
+	ret = mx28_wait_mask_set(&bch_regs->hw_bch_ctrl_reg,
+		BCH_CTRL_COMPLETE_IRQ, timeout);
+
+	writel(BCH_CTRL_COMPLETE_IRQ, &bch_regs->hw_bch_ctrl_clr);
+
+	return ret;
+}
+
+/*
+ * This is the function that we install in the cmd_ctrl function pointer of the
+ * owning struct nand_chip. The only functions in the reference implementation
+ * that use these functions pointers are cmdfunc and select_chip.
+ *
+ * In this driver, we implement our own select_chip, so this function will only
+ * be called by the reference implementation's cmdfunc. For this reason, we can
+ * ignore the chip enable bit and concentrate only on sending bytes to the
+ * NAND Flash.
+ */
+static void mxs_nand_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	int ret;
+
+	/*
+	 * If this condition is true, something is _VERY_ wrong in MTD
+	 * subsystem!
+	 */
+	if (nand_info->cmd_queue_len == MXS_NAND_COMMAND_BUFFER_SIZE) {
+		printf("MXS NAND: Command queue too long\n");
+		return;
+	}
+
+	/*
+	 * Every operation begins with a command byte and a series of zero or
+	 * more address bytes. These are distinguished by either the Address
+	 * Latch Enable (ALE) or Command Latch Enable (CLE) signals being
+	 * asserted. When MTD is ready to execute the command, it will
+	 * deasert both latch enables.
+	 *
+	 * Rather than run a separate DMA operation for every single byte, we
+	 * queue them up and run a single DMA operation for the entire series
+	 * of command and data bytes.
+	 */
+	if (ctrl & (NAND_ALE | NAND_CLE)) {
+		if (data != NAND_CMD_NONE)
+			nand_info->cmd_buf[nand_info->cmd_queue_len++] = data;
+		return;
+	}
+
+	/*
+	 * If control arrives here, MTD has deasserted both the ALE and CLE,
+	 * which means it's ready to run an operation. Check if we have any
+	 * bytes to send.
+	 */
+	if (nand_info->cmd_queue_len == 0)
+		return;
+
+	/* Compile the DMA descriptor -- a descriptor that sends command. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_DMA_READ | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_CHAIN | MXS_DMA_DESC_DEC_SEM |
+		MXS_DMA_DESC_WAIT4END | (3 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
+		(nand_info->cmd_queue_len << MXS_DMA_DESC_BYTES_OFFSET);
+
+	d->cmd.address = (dma_addr_t)nand_info->cmd_buf;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_CLE |
+		GPMI_CTRL0_ADDRESS_INCREMENT |
+		nand_info->cmd_queue_len;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret)
+		printf("MXS NAND: Error sending command\n");
+
+	mxs_nand_return_dma_descs(nand_info);
+
+	/* Reset the command queue. */
+	nand_info->cmd_queue_len = 0;
+}
+
+/*
+ * Test if the NAND flash is ready.
+ */
+static int mxs_nand_device_ready(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mxs_nand_info *nand_info = chip->priv;
+	struct mx28_gpmi_regs *gpmi_regs =
+		(struct mx28_gpmi_regs *)MXS_GPMI_BASE;
+	uint32_t tmp;
+
+	tmp = readl(&gpmi_regs->hw_gpmi_stat);
+	tmp >>= (GPMI_STAT_READY_BUSY_OFFSET + nand_info->cur_chip);
+
+	return tmp & 1;
+}
+
+/*
+ * Select the NAND chip.
+ */
+static void mxs_nand_select_chip(struct mtd_info *mtd, int chip)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+
+	nand_info->cur_chip = chip;
+}
+
+/*
+ * Handle block mark swapping.
+ *
+ * Note that, when this function is called, it doesn't know whether it's
+ * swapping the block mark, or swapping it *back* -- but it doesn't matter
+ * because the the operation is the same.
+ */
+static void mxs_nand_swap_block_mark(struct mtd_info *mtd,
+					uint8_t *data_buf, uint8_t *oob_buf)
+{
+	uint32_t bit_offset;
+	uint32_t buf_offset;
+
+	uint32_t src;
+	uint32_t dst;
+
+	bit_offset = mxs_nand_mark_bit_offset(mtd);
+	buf_offset = mxs_nand_mark_byte_offset(mtd);
+
+	/*
+	 * Get the byte from the data area that overlays the block mark. Since
+	 * the ECC engine applies its own view to the bits in the page, the
+	 * physical block mark won't (in general) appear on a byte boundary in
+	 * the data.
+	 */
+	src = data_buf[buf_offset] >> bit_offset;
+	src |= data_buf[buf_offset + 1] << (8 - bit_offset);
+
+	dst = oob_buf[0];
+
+	oob_buf[0] = src;
+
+	data_buf[buf_offset] &= ~(0xff << bit_offset);
+	data_buf[buf_offset + 1] &= 0xff << bit_offset;
+
+	data_buf[buf_offset] |= dst << bit_offset;
+	data_buf[buf_offset + 1] |= dst >> (8 - bit_offset);
+}
+
+/*
+ * Read data from NAND.
+ */
+static void mxs_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int length)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	int ret;
+
+	if (length > NAND_MAX_PAGESIZE) {
+		printf("MXS NAND: DMA buffer too big\n");
+		return;
+	}
+
+	if (!buf) {
+		printf("MXS NAND: DMA buffer is NULL\n");
+		return;
+	}
+
+	/* Compile the DMA descriptor - a descriptor that reads data. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_DMA_WRITE | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
+		(1 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
+		(length << MXS_DMA_DESC_BYTES_OFFSET);
+
+	d->cmd.address = (dma_addr_t)nand_info->data_buf;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_READ |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		length;
+
+	mxs_dma_desc_append(channel, d);
+
+	/*
+	 * A DMA descriptor that waits for the command to end and the chip to
+	 * become ready.
+	 *
+	 * I think we actually should *not* be waiting for the chip to become
+	 * ready because, after all, we don't care. I think the original code
+	 * did that and no one has re-thought it yet.
+	 */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_DEC_SEM |
+		MXS_DMA_DESC_WAIT4END | (4 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret) {
+		printf("MXS NAND: DMA read error\n");
+		goto rtn;
+	}
+
+	memcpy(buf, nand_info->data_buf, length);
+
+rtn:
+	mxs_nand_return_dma_descs(nand_info);
+}
+
+/*
+ * Write data to NAND.
+ */
+static void mxs_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf,
+				int length)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	int ret;
+
+	if (length > NAND_MAX_PAGESIZE) {
+		printf("MXS NAND: DMA buffer too big\n");
+		return;
+	}
+
+	if (!buf) {
+		printf("MXS NAND: DMA buffer is NULL\n");
+		return;
+	}
+
+	memcpy(nand_info->data_buf, buf, length);
+
+	/* Compile the DMA descriptor - a descriptor that writes data. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_DMA_READ | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
+		(4 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
+		(length << MXS_DMA_DESC_BYTES_OFFSET);
+
+	d->cmd.address = (dma_addr_t)nand_info->data_buf;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		length;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret)
+		printf("MXS NAND: DMA write error\n");
+
+	mxs_nand_return_dma_descs(nand_info);
+}
+
+/*
+ * Read a single byte from NAND.
+ */
+static uint8_t mxs_nand_read_byte(struct mtd_info *mtd)
+{
+	uint8_t buf;
+	mxs_nand_read_buf(mtd, &buf, 1);
+	return buf;
+}
+
+/*
+ * Read a page from NAND.
+ */
+static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
+					uint8_t *buf, int page)
+{
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	uint32_t corrected = 0, failed = 0;
+	uint8_t	*status;
+	int i, ret;
+
+	/* Compile the DMA descriptor - wait for ready. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
+		MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_WAIT4END |
+		(1 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Compile the DMA descriptor - enable the BCH block and read. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
+		MXS_DMA_DESC_WAIT4END |	(6 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_READ |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		(mtd->writesize + mtd->oobsize);
+	d->cmd.pio_words[1] = 0;
+	d->cmd.pio_words[2] =
+		GPMI_ECCCTRL_ENABLE_ECC |
+		GPMI_ECCCTRL_ECC_CMD_DECODE |
+		GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE;
+	d->cmd.pio_words[3] = mtd->writesize + mtd->oobsize;
+	d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf;
+	d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Compile the DMA descriptor - disable the BCH block. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
+		MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_WAIT4END |
+		(3 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		(mtd->writesize + mtd->oobsize);
+	d->cmd.pio_words[1] = 0;
+	d->cmd.pio_words[2] = 0;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Compile the DMA descriptor - deassert the NAND lock and interrupt. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_DEC_SEM;
+
+	d->cmd.address = 0;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret) {
+		printf("MXS NAND: DMA read error\n");
+		goto rtn;
+	}
+
+	ret = mxs_nand_wait_for_bch_complete();
+	if (ret) {
+		printf("MXS NAND: BCH read timeout\n");
+		goto rtn;
+	}
+
+	/* Read DMA completed, now do the mark swapping. */
+	mxs_nand_swap_block_mark(mtd, nand_info->data_buf, nand_info->oob_buf);
+
+	/* Loop over status bytes, accumulating ECC status. */
+	status = nand_info->oob_buf + mxs_nand_aux_status_offset();
+	for (i = 0; i < mxs_nand_ecc_chunk_cnt(mtd->writesize); i++) {
+		if (status[i] == 0x00)
+			continue;
+
+		if (status[i] == 0xff)
+			continue;
+
+		if (status[i] == 0xfe) {
+			failed++;
+			continue;
+		}
+
+		corrected += status[i];
+	}
+
+	/* Propagate ECC status to the owning MTD. */
+	mtd->ecc_stats.failed += failed;
+	mtd->ecc_stats.corrected += corrected;
+
+	/*
+	 * It's time to deliver the OOB bytes. See mxs_nand_ecc_read_oob() for
+	 * details about our policy for delivering the OOB.
+	 *
+	 * We fill the caller's buffer with set bits, and then copy the block
+	 * mark to th caller's buffer. Note that, if block mark swapping was
+	 * necessary, it has already been done, so we can rely on the first
+	 * byte of the auxiliary buffer to contain the block mark.
+	 */
+	memset(nand->oob_poi, 0xff, mtd->oobsize);
+
+	nand->oob_poi[0] = nand_info->oob_buf[0];
+
+	memcpy(buf, nand_info->data_buf, mtd->writesize);
+
+rtn:
+	mxs_nand_return_dma_descs(nand_info);
+
+	return ret;
+}
+
+/*
+ * Write a page to NAND.
+ */
+static void mxs_nand_ecc_write_page(struct mtd_info *mtd,
+				struct nand_chip *nand, const uint8_t *buf)
+{
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	int ret;
+
+	memcpy(nand_info->data_buf, buf, mtd->writesize);
+	memcpy(nand_info->oob_buf, nand->oob_poi, mtd->oobsize);
+
+	/* Handle block mark swapping. */
+	mxs_nand_swap_block_mark(mtd, nand_info->data_buf, nand_info->oob_buf);
+
+	/* Compile the DMA descriptor - write data. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
+		(6 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA;
+	d->cmd.pio_words[1] = 0;
+	d->cmd.pio_words[2] =
+		GPMI_ECCCTRL_ENABLE_ECC |
+		GPMI_ECCCTRL_ECC_CMD_ENCODE |
+		GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE;
+	d->cmd.pio_words[3] = (mtd->writesize + mtd->oobsize);
+	d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf;
+	d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret) {
+		printf("MXS NAND: DMA write error\n");
+		goto rtn;
+	}
+
+	ret = mxs_nand_wait_for_bch_complete();
+	if (ret) {
+		printf("MXS NAND: BCH write timeout\n");
+		goto rtn;
+	}
+
+rtn:
+	mxs_nand_return_dma_descs(nand_info);
+}
+
+/*
+ * Read OOB from NAND.
+ *
+ * This function is a veneer that replaces the function originally installed by
+ * the NAND Flash MTD code.
+ */
+static int mxs_nand_hook_read_oob(struct mtd_info *mtd, loff_t from,
+					struct mtd_oob_ops *ops)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mxs_nand_info *nand_info = chip->priv;
+	int ret;
+
+	if (ops->mode == MTD_OOB_RAW)
+		nand_info->raw_oob_mode = 1;
+	else
+		nand_info->raw_oob_mode = 0;
+
+	ret = nand_info->hooked_read_oob(mtd, from, ops);
+
+	nand_info->raw_oob_mode = 0;
+
+	return ret;
+}
+
+/*
+ * Write OOB to NAND.
+ *
+ * This function is a veneer that replaces the function originally installed by
+ * the NAND Flash MTD code.
+ */
+static int mxs_nand_hook_write_oob(struct mtd_info *mtd, loff_t to,
+					struct mtd_oob_ops *ops)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mxs_nand_info *nand_info = chip->priv;
+	int ret;
+
+	if (ops->mode == MTD_OOB_RAW)
+		nand_info->raw_oob_mode = 1;
+	else
+		nand_info->raw_oob_mode = 0;
+
+	ret = nand_info->hooked_write_oob(mtd, to, ops);
+
+	nand_info->raw_oob_mode = 0;
+
+	return ret;
+}
+
+/*
+ * Mark a block bad in NAND.
+ *
+ * This function is a veneer that replaces the function originally installed by
+ * the NAND Flash MTD code.
+ */
+static int mxs_nand_hook_block_markbad(struct mtd_info *mtd, loff_t ofs)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mxs_nand_info *nand_info = chip->priv;
+	int ret;
+
+	nand_info->marking_block_bad = 1;
+
+	ret = nand_info->hooked_block_markbad(mtd, ofs);
+
+	nand_info->marking_block_bad = 0;
+
+	return ret;
+}
+
+/*
+ * There are several places in this driver where we have to handle the OOB and
+ * block marks. This is the function where things are the most complicated, so
+ * this is where we try to explain it all. All the other places refer back to
+ * here.
+ *
+ * These are the rules, in order of decreasing importance:
+ *
+ * 1) Nothing the caller does can be allowed to imperil the block mark, so all
+ *    write operations take measures to protect it.
+ *
+ * 2) In read operations, the first byte of the OOB we return must reflect the
+ *    true state of the block mark, no matter where that block mark appears in
+ *    the physical page.
+ *
+ * 3) ECC-based read operations return an OOB full of set bits (since we never
+ *    allow ECC-based writes to the OOB, it doesn't matter what ECC-based reads
+ *    return).
+ *
+ * 4) "Raw" read operations return a direct view of the physical bytes in the
+ *    page, using the conventional definition of which bytes are data and which
+ *    are OOB. This gives the caller a way to see the actual, physical bytes
+ *    in the page, without the distortions applied by our ECC engine.
+ *
+ *
+ * What we do for this specific read operation depends on two questions:
+ *
+ * 1) Are we doing a "raw" read, or an ECC-based read?
+ *
+ * 2) Are we using block mark swapping or transcription?
+ *
+ * There are four cases, illustrated by the following Karnaugh map:
+ *
+ *                    |           Raw           |         ECC-based       |
+ *       -------------+-------------------------+-------------------------+
+ *                    | Read the conventional   |                         |
+ *                    | OOB at the end of the   |                         |
+ *       Swapping     | page and return it. It  |                         |
+ *                    | contains exactly what   |                         |
+ *                    | we want.                | Read the block mark and |
+ *       -------------+-------------------------+ return it in a buffer   |
+ *                    | Read the conventional   | full of set bits.       |
+ *                    | OOB at the end of the   |                         |
+ *                    | page and also the block |                         |
+ *       Transcribing | mark in the metadata.   |                         |
+ *                    | Copy the block mark     |                         |
+ *                    | into the first byte of  |                         |
+ *                    | the OOB.                |                         |
+ *       -------------+-------------------------+-------------------------+
+ *
+ * Note that we break rule #4 in the Transcribing/Raw case because we're not
+ * giving an accurate view of the actual, physical bytes in the page (we're
+ * overwriting the block mark). That's OK because it's more important to follow
+ * rule #2.
+ *
+ * It turns out that knowing whether we want an "ECC-based" or "raw" read is not
+ * easy. When reading a page, for example, the NAND Flash MTD code calls our
+ * ecc.read_page or ecc.read_page_raw function. Thus, the fact that MTD wants an
+ * ECC-based or raw view of the page is implicit in which function it calls
+ * (there is a similar pair of ECC-based/raw functions for writing).
+ *
+ * Since MTD assumes the OOB is not covered by ECC, there is no pair of
+ * ECC-based/raw functions for reading or or writing the OOB. The fact that the
+ * caller wants an ECC-based or raw view of the page is not propagated down to
+ * this driver.
+ *
+ * Since our OOB *is* covered by ECC, we need this information. So, we hook the
+ * ecc.read_oob and ecc.write_oob function pointers in the owning
+ * struct mtd_info with our own functions. These hook functions set the
+ * raw_oob_mode field so that, when control finally arrives here, we'll know
+ * what to do.
+ */
+static int mxs_nand_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *nand,
+				int page, int cmd)
+{
+	struct mxs_nand_info *nand_info = nand->priv;
+
+	/*
+	 * First, fill in the OOB buffer. If we're doing a raw read, we need to
+	 * get the bytes from the physical page. If we're not doing a raw read,
+	 * we need to fill the buffer with set bits.
+	 */
+	if (nand_info->raw_oob_mode) {
+		/*
+		 * If control arrives here, we're doing a "raw" read. Send the
+		 * command to read the conventional OOB and read it.
+		 */
+		nand->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page);
+		nand->read_buf(mtd, nand->oob_poi, mtd->oobsize);
+	} else {
+		/*
+		 * If control arrives here, we're not doing a "raw" read. Fill
+		 * the OOB buffer with set bits and correct the block mark.
+		 */
+		memset(nand->oob_poi, 0xff, mtd->oobsize);
+
+		nand->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page);
+		mxs_nand_read_buf(mtd, nand->oob_poi, 1);
+	}
+
+	return 0;
+
+}
+
+/*
+ * Write OOB data to NAND.
+ */
+static int mxs_nand_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *nand,
+					int page)
+{
+	struct mxs_nand_info *nand_info = nand->priv;
+	uint8_t block_mark = 0;
+
+	/*
+	 * There are fundamental incompatibilities between the i.MX GPMI NFC and
+	 * the NAND Flash MTD model that make it essentially impossible to write
+	 * the out-of-band bytes.
+	 *
+	 * We permit *ONE* exception. If the *intent* of writing the OOB is to
+	 * mark a block bad, we can do that.
+	 */
+
+	if (!nand_info->marking_block_bad) {
+		printf("NXS NAND: Writing OOB isn't supported\n");
+		return -EIO;
+	}
+
+	/* Write the block mark. */
+	nand->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
+	nand->write_buf(mtd, &block_mark, 1);
+	nand->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+
+	/* Check if it worked. */
+	if (nand->waitfunc(mtd, nand) & NAND_STATUS_FAIL)
+		return -EIO;
+
+	return 0;
+}
+
+/*
+ * Claims all blocks are good.
+ *
+ * In principle, this function is *only* called when the NAND Flash MTD system
+ * isn't allowed to keep an in-memory bad block table, so it is forced to ask
+ * the driver for bad block information.
+ *
+ * In fact, we permit the NAND Flash MTD system to have an in-memory BBT, so
+ * this function is *only* called when we take it away.
+ *
+ * We take away the in-memory BBT when the user sets the "ignorebad" parameter,
+ * which indicates that all blocks should be reported good.
+ *
+ * Thus, this function is only called when we want *all* blocks to look good,
+ * so it *always* return success.
+ */
+static int mxs_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
+{
+	return 0;
+}
+
+/*
+ * Nominally, the purpose of this function is to look for or create the bad
+ * block table. In fact, since the we call this function at the very end of
+ * the initialization process started by nand_scan(), and we doesn't have a
+ * more formal mechanism, we "hook" this function to continue init process.
+ *
+ * At this point, the physical NAND Flash chips have been identified and
+ * counted, so we know the physical geometry. This enables us to make some
+ * important configuration decisions.
+ *
+ * The return value of this function propogates directly back to this driver's
+ * call to nand_scan(). Anything other than zero will cause this driver to
+ * tear everything down and declare failure.
+ */
+static int mxs_nand_scan_bbt(struct mtd_info *mtd)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mx28_bch_regs *bch_regs = (struct mx28_bch_regs *)MXS_BCH_BASE;
+	uint32_t tmp;
+
+	/* Configure BCH and set NFC geometry */
+	mx28_reset_block(&bch_regs->hw_bch_ctrl_reg);
+
+	/* Configure layout 0 */
+	tmp = (mxs_nand_ecc_chunk_cnt(mtd->writesize) - 1)
+		<< BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
+	tmp |= MXS_NAND_METADATA_SIZE << BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
+	tmp |= (mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1)
+		<< BCH_FLASHLAYOUT0_ECC0_OFFSET;
+	tmp |= MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
+	writel(tmp, &bch_regs->hw_bch_flash0layout0);
+
+	tmp = (mtd->writesize + mtd->oobsize)
+		<< BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
+	tmp |= (mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1)
+		<< BCH_FLASHLAYOUT1_ECCN_OFFSET;
+	tmp |= MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
+	writel(tmp, &bch_regs->hw_bch_flash0layout1);
+
+	/* Set *all* chip selects to use layout 0 */
+	writel(0, &bch_regs->hw_bch_layoutselect);
+
+	/* Enable BCH complete interrupt */
+	writel(BCH_CTRL_COMPLETE_IRQ_EN, &bch_regs->hw_bch_ctrl_set);
+
+	/* Hook some operations at the MTD level. */
+	if (mtd->read_oob != mxs_nand_hook_read_oob) {
+		nand_info->hooked_read_oob = mtd->read_oob;
+		mtd->read_oob = mxs_nand_hook_read_oob;
+	}
+
+	if (mtd->write_oob != mxs_nand_hook_write_oob) {
+		nand_info->hooked_write_oob = mtd->write_oob;
+		mtd->write_oob = mxs_nand_hook_write_oob;
+	}
+
+	if (mtd->block_markbad != mxs_nand_hook_block_markbad) {
+		nand_info->hooked_block_markbad = mtd->block_markbad;
+		mtd->block_markbad = mxs_nand_hook_block_markbad;
+	}
+
+	/* We use the reference implementation for bad block management. */
+	return nand_default_bbt(mtd);
+}
+
+/*
+ * Allocate DMA buffers
+ */
+int mxs_nand_alloc_buffers(struct mxs_nand_info *nand_info)
+{
+	uint8_t *buf;
+	const int size = NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE;
+
+	/* DMA buffers */
+	buf = memalign(MXS_DMA_ALIGNMENT, size);
+	if (!buf) {
+		printf("MXS NAND: Error allocating DMA buffers\n");
+		return -ENOMEM;
+	}
+
+	memset(buf, 0, size);
+
+	nand_info->data_buf = buf;
+	nand_info->oob_buf = buf + NAND_MAX_PAGESIZE;
+
+	/* Command buffers */
+	nand_info->cmd_buf = memalign(MXS_DMA_ALIGNMENT,
+				MXS_NAND_COMMAND_BUFFER_SIZE);
+	if (!nand_info->cmd_buf) {
+		free(buf);
+		printf("MXS NAND: Error allocating command buffers\n");
+		return -ENOMEM;
+	}
+	memset(nand_info->cmd_buf, 0, MXS_NAND_COMMAND_BUFFER_SIZE);
+	nand_info->cmd_queue_len = 0;
+
+	return 0;
+}
+
+/*
+ * Initializes the NFC hardware.
+ */
+int mxs_nand_init(struct mxs_nand_info *info)
+{
+	struct mx28_gpmi_regs *gpmi_regs =
+		(struct mx28_gpmi_regs *)MXS_GPMI_BASE;
+	int i = 0;
+
+	info->desc = malloc(sizeof(struct mxs_dma_desc *) *
+				MXS_NAND_DMA_DESCRIPTOR_COUNT);
+	if (!info->desc)
+		goto err1;
+
+	/* Allocate the DMA descriptors. */
+	for (i = 0; i < MXS_NAND_DMA_DESCRIPTOR_COUNT; i++) {
+		info->desc[i] = mxs_dma_desc_alloc();
+		if (!info->desc[i])
+			goto err2;
+	}
+
+	/* Init the DMA controller. */
+	mxs_dma_init();
+
+	/* Reset the GPMI block. */
+	mx28_reset_block(&gpmi_regs->hw_gpmi_ctrl0_reg);
+
+	/*
+	 * Choose NAND mode, set IRQ polarity, disable write protection and
+	 * select BCH ECC.
+	 */
+	clrsetbits_le32(&gpmi_regs->hw_gpmi_ctrl1,
+			GPMI_CTRL1_GPMI_MODE,
+			GPMI_CTRL1_ATA_IRQRDY_POLARITY | GPMI_CTRL1_DEV_RESET |
+			GPMI_CTRL1_BCH_MODE);
+
+	return 0;
+
+err2:
+	free(info->desc);
+err1:
+	for (--i; i >= 0; i--)
+		mxs_dma_desc_free(info->desc[i]);
+	printf("MXS NAND: Unable to allocate DMA descriptors\n");
+	return -ENOMEM;
+}
+
+/*!
+ * This function is called during the driver binding process.
+ *
+ * @param   pdev  the device structure used to store device specific
+ *                information that is used by the suspend, resume and
+ *                remove functions
+ *
+ * @return  The function always returns 0.
+ */
+int board_nand_init(struct nand_chip *nand)
+{
+	struct mxs_nand_info *nand_info;
+	int err;
+
+	nand_info = malloc(sizeof(struct mxs_nand_info));
+	if (!nand_info) {
+		printf("MXS NAND: Failed to allocate private data\n");
+		return -ENOMEM;
+	}
+	memset(nand_info, 0, sizeof(struct mxs_nand_info));
+
+	err = mxs_nand_alloc_buffers(nand_info);
+	if (err)
+		goto err1;
+
+	err = mxs_nand_init(nand_info);
+	if (err)
+		goto err2;
+
+	memset(&fake_ecc_layout, 0, sizeof(fake_ecc_layout));
+
+	nand->priv = nand_info;
+	nand->options |= NAND_NO_SUBPAGE_WRITE;
+
+	nand->cmd_ctrl		= mxs_nand_cmd_ctrl;
+
+	nand->dev_ready		= mxs_nand_device_ready;
+	nand->select_chip	= mxs_nand_select_chip;
+	nand->block_bad		= mxs_nand_block_bad;
+	nand->scan_bbt		= mxs_nand_scan_bbt;
+
+	nand->read_byte		= mxs_nand_read_byte;
+
+	nand->read_buf		= mxs_nand_read_buf;
+	nand->write_buf		= mxs_nand_write_buf;
+
+	nand->ecc.read_page	= mxs_nand_ecc_read_page;
+	nand->ecc.write_page	= mxs_nand_ecc_write_page;
+	nand->ecc.read_oob	= mxs_nand_ecc_read_oob;
+	nand->ecc.write_oob	= mxs_nand_ecc_write_oob;
+
+	nand->ecc.layout	= &fake_ecc_layout;
+	nand->ecc.mode		= NAND_ECC_HW;
+	nand->ecc.bytes		= 9;
+	nand->ecc.size		= 512;
+
+	return 0;
+
+err2:
+	free(nand_info->data_buf);
+	free(nand_info->cmd_buf);
+err1:
+	free(nand_info);
+	return err;
+}
-- 
1.7.5.4

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

* [U-Boot] [PATCH 09/15] iMX28: Add GPMI NAND driver
  2011-09-28 22:13           ` Scott Wood
@ 2011-09-28 22:34             ` Marek Vasut
  0 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-09-28 22:34 UTC (permalink / raw)
  To: u-boot

On Thursday, September 29, 2011 12:13:19 AM Scott Wood wrote:
> On 09/28/2011 05:09 PM, Marek Vasut wrote:
> > On Wednesday, September 28, 2011 11:57:49 PM Scott Wood wrote:
> >> So I think if you need something that changes the layout from normal
> >> operations, it needs to be a new mode.  And it's about time to sync up
> >> U-Boot's NAND code with Linux again...
> > 
> > Well aren't you the maintainer that should take care of it ? ;-)
> 
> Yes, that note was me adding something to my todo list. :-)
> 
> >> I'm not talking about circumventing the driver, just accessing some user
> >> OOB bytes through it.
> > 
> > There are no user OOB bytes, the driver does the ECC so user has no need
> > to write any OOB.
> 
> By "user OOB bytes" I meant things other than the ECC and the bad-block
> marker -- the space described by oobavail in ecclayout.  This is getting
> less useful with partial-page restrictions and large ECC that fills up
> most of the OOB, though, and thus there's a trend away from making use
> of it.  So if it's a pain to provide access to any spare OOB bytes, it's
> not that big of a deal.

But I don't get it, you're still talking about OOB, but the OOB and the actual 
page make no difference here. They are used in the same manner. The OOB is 
spread across the page.

> 
> -Scott

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

* [U-Boot] [PATCH 09/15 V4] iMX28: Add GPMI NAND driver
  2011-09-28 22:32     ` [U-Boot] [PATCH 09/15 V3] " Marek Vasut
@ 2011-09-29  0:07       ` Marek Vasut
  2011-09-30  9:39         ` [U-Boot] [PATCH 09/15 V5] " Marek Vasut
  0 siblings, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-09-29  0:07 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Scott Wood <scottwood@freescale.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 drivers/mtd/nand/Makefile   |    1 +
 drivers/mtd/nand/mxs_nand.c | 1127 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1128 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/nand/mxs_nand.c

V2: Update comments, drop inlines
V3: Fix descriptor reclamation loop
V4: Trim bogus comments

diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index b6a7886..aef0d56 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -49,6 +49,7 @@ COBJS-$(CONFIG_NAND_KIRKWOOD) += kirkwood_nand.o
 COBJS-$(CONFIG_NAND_KMETER1) += kmeter1_nand.o
 COBJS-$(CONFIG_NAND_MPC5121_NFC) += mpc5121_nfc.o
 COBJS-$(CONFIG_NAND_MXC) += mxc_nand.o
+COBJS-$(CONFIG_NAND_MXS) += mxs_nand.o
 COBJS-$(CONFIG_NAND_NDFC) += ndfc.o
 COBJS-$(CONFIG_NAND_NOMADIK) += nomadik.o
 COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o
diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c
new file mode 100644
index 0000000..6ade975
--- /dev/null
+++ b/drivers/mtd/nand/mxs_nand.c
@@ -0,0 +1,1127 @@
+/*
+ * Freescale i.MX28 NAND flash driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Freescale GPMI NFC NAND Flash Driver
+ *
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ * Copyright (C) 2008 Embedded Alley Solutions, Inc.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/types.h>
+#include <common.h>
+#include <malloc.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/dma.h>
+
+#define	MXS_NAND_DMA_DESCRIPTOR_COUNT		4
+
+#define	MXS_NAND_CHUNK_DATA_CHUNK_SIZE		512
+#define	MXS_NAND_METADATA_SIZE			10
+
+#define	MXS_NAND_COMMAND_BUFFER_SIZE		32
+
+#define	MXS_NAND_BCH_TIMEOUT			10000
+
+struct mxs_nand_info {
+	int		cur_chip;
+
+	uint32_t	cmd_queue_len;
+
+	uint8_t		*cmd_buf;
+	uint8_t		*data_buf;
+	uint8_t		*oob_buf;
+
+	uint8_t		marking_block_bad;
+	uint8_t		raw_oob_mode;
+
+	/* Functions with altered behaviour */
+	int		(*hooked_read_oob)(struct mtd_info *mtd,
+				loff_t from, struct mtd_oob_ops *ops);
+	int		(*hooked_write_oob)(struct mtd_info *mtd,
+				loff_t to, struct mtd_oob_ops *ops);
+	int		(*hooked_block_markbad)(struct mtd_info *mtd,
+				loff_t ofs);
+
+	/* DMA descriptors */
+	struct mxs_dma_desc	**desc;
+	uint32_t		desc_index;
+};
+
+struct nand_ecclayout fake_ecc_layout;
+
+static struct mxs_dma_desc *mxs_nand_get_dma_desc(struct mxs_nand_info *info)
+{
+	struct mxs_dma_desc *desc;
+
+	if (info->desc_index >= MXS_NAND_DMA_DESCRIPTOR_COUNT) {
+		printf("MXS NAND: Too many DMA descriptors requested\n");
+		return NULL;
+	}
+
+	desc = info->desc[info->desc_index];
+	info->desc_index++;
+
+	return desc;
+}
+
+static void mxs_nand_return_dma_descs(struct mxs_nand_info *info)
+{
+	int i;
+	struct mxs_dma_desc *desc;
+
+	for (i = 0; i < info->desc_index; i++) {
+		desc = info->desc[i];
+		memset(desc, 0, sizeof(struct mxs_dma_desc));
+		desc->address = (dma_addr_t)desc;
+	}
+
+	info->desc_index = 0;
+}
+
+static uint32_t mxs_nand_ecc_chunk_cnt(uint32_t page_data_size)
+{
+	return page_data_size / MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
+}
+
+static uint32_t mxs_nand_ecc_size_in_bits(uint32_t ecc_strength)
+{
+	return ecc_strength * 13;
+}
+
+static uint32_t mxs_nand_aux_status_offset(void)
+{
+	return (MXS_NAND_METADATA_SIZE + 0x3) & ~0x3;
+}
+
+static uint32_t mxs_nand_aux_size(uint32_t page_size)
+{
+	uint32_t aux_status_off = mxs_nand_aux_status_offset();
+	uint32_t ecc_chunk_cnt =
+		(mxs_nand_ecc_chunk_cnt(page_size) + 0x3) & ~0x3;
+
+	return ecc_chunk_cnt + aux_status_off;
+}
+
+static inline uint32_t mxs_nand_get_ecc_strength(uint32_t page_data_size,
+						uint32_t page_oob_size)
+{
+	if (page_data_size == 2048)
+		return 8;
+
+	if (page_data_size == 4096) {
+		if (page_oob_size == 128)
+			return 8;
+
+		if (page_oob_size == 218)
+			return 16;
+	}
+
+	return 0;
+}
+
+static inline uint32_t mxs_nand_get_mark_offset(uint32_t page_data_size,
+						uint32_t ecc_strength)
+{
+	uint32_t chunk_data_size_in_bits;
+	uint32_t chunk_ecc_size_in_bits;
+	uint32_t chunk_total_size_in_bits;
+	uint32_t block_mark_chunk_number;
+	uint32_t block_mark_chunk_bit_offset;
+	uint32_t block_mark_bit_offset;
+
+	chunk_data_size_in_bits = MXS_NAND_CHUNK_DATA_CHUNK_SIZE * 8;
+	chunk_ecc_size_in_bits  = mxs_nand_ecc_size_in_bits(ecc_strength);
+
+	chunk_total_size_in_bits =
+			chunk_data_size_in_bits + chunk_ecc_size_in_bits;
+
+	/* Compute the bit offset of the block mark within the physical page. */
+	block_mark_bit_offset = page_data_size * 8;
+
+	/* Subtract the metadata bits. */
+	block_mark_bit_offset -= MXS_NAND_METADATA_SIZE * 8;
+
+	/*
+	 * Compute the chunk number (starting at zero) in which the block mark
+	 * appears.
+	 */
+	block_mark_chunk_number =
+			block_mark_bit_offset / chunk_total_size_in_bits;
+
+	/*
+	 * Compute the bit offset of the block mark within its chunk, and
+	 * validate it.
+	 */
+	block_mark_chunk_bit_offset = block_mark_bit_offset -
+			(block_mark_chunk_number * chunk_total_size_in_bits);
+
+	if (block_mark_chunk_bit_offset > chunk_data_size_in_bits)
+		return 1;
+
+	/*
+	 * Now that we know the chunk number in which the block mark appears,
+	 * we can subtract all the ECC bits that appear before it.
+	 */
+	block_mark_bit_offset -=
+		block_mark_chunk_number * chunk_ecc_size_in_bits;
+
+	return block_mark_bit_offset;
+}
+
+static uint32_t mxs_nand_mark_byte_offset(struct mtd_info *mtd)
+{
+	uint32_t ecc_strength;
+	ecc_strength = mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize);
+	return mxs_nand_get_mark_offset(mtd->writesize, ecc_strength) >> 3;
+}
+
+static uint32_t mxs_nand_mark_bit_offset(struct mtd_info *mtd)
+{
+	uint32_t ecc_strength;
+	ecc_strength = mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize);
+	return mxs_nand_get_mark_offset(mtd->writesize, ecc_strength) & 0x7;
+}
+
+/*
+ * Wait for BCH complete IRQ and clear the IRQ
+ */
+static int mxs_nand_wait_for_bch_complete(void)
+{
+	struct mx28_bch_regs *bch_regs = (struct mx28_bch_regs *)MXS_BCH_BASE;
+	int timeout = MXS_NAND_BCH_TIMEOUT;
+	int ret;
+
+	ret = mx28_wait_mask_set(&bch_regs->hw_bch_ctrl_reg,
+		BCH_CTRL_COMPLETE_IRQ, timeout);
+
+	writel(BCH_CTRL_COMPLETE_IRQ, &bch_regs->hw_bch_ctrl_clr);
+
+	return ret;
+}
+
+/*
+ * This is the function that we install in the cmd_ctrl function pointer of the
+ * owning struct nand_chip. The only functions in the reference implementation
+ * that use these functions pointers are cmdfunc and select_chip.
+ *
+ * In this driver, we implement our own select_chip, so this function will only
+ * be called by the reference implementation's cmdfunc. For this reason, we can
+ * ignore the chip enable bit and concentrate only on sending bytes to the NAND
+ * Flash.
+ */
+static void mxs_nand_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	int ret;
+
+	/*
+	 * If this condition is true, something is _VERY_ wrong in MTD
+	 * subsystem!
+	 */
+	if (nand_info->cmd_queue_len == MXS_NAND_COMMAND_BUFFER_SIZE) {
+		printf("MXS NAND: Command queue too long\n");
+		return;
+	}
+
+	/*
+	 * Every operation begins with a command byte and a series of zero or
+	 * more address bytes. These are distinguished by either the Address
+	 * Latch Enable (ALE) or Command Latch Enable (CLE) signals being
+	 * asserted. When MTD is ready to execute the command, it will
+	 * deasert both latch enables.
+	 *
+	 * Rather than run a separate DMA operation for every single byte, we
+	 * queue them up and run a single DMA operation for the entire series
+	 * of command and data bytes.
+	 */
+	if (ctrl & (NAND_ALE | NAND_CLE)) {
+		if (data != NAND_CMD_NONE)
+			nand_info->cmd_buf[nand_info->cmd_queue_len++] = data;
+		return;
+	}
+
+	/*
+	 * If control arrives here, MTD has deasserted both the ALE and CLE,
+	 * which means it's ready to run an operation. Check if we have any
+	 * bytes to send.
+	 */
+	if (nand_info->cmd_queue_len == 0)
+		return;
+
+	/* Compile the DMA descriptor -- a descriptor that sends command. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_DMA_READ | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_CHAIN | MXS_DMA_DESC_DEC_SEM |
+		MXS_DMA_DESC_WAIT4END | (3 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
+		(nand_info->cmd_queue_len << MXS_DMA_DESC_BYTES_OFFSET);
+
+	d->cmd.address = (dma_addr_t)nand_info->cmd_buf;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_CLE |
+		GPMI_CTRL0_ADDRESS_INCREMENT |
+		nand_info->cmd_queue_len;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret)
+		printf("MXS NAND: Error sending command\n");
+
+	mxs_nand_return_dma_descs(nand_info);
+
+	/* Reset the command queue. */
+	nand_info->cmd_queue_len = 0;
+}
+
+/*
+ * Test if the NAND flash is ready.
+ */
+static int mxs_nand_device_ready(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mxs_nand_info *nand_info = chip->priv;
+	struct mx28_gpmi_regs *gpmi_regs =
+		(struct mx28_gpmi_regs *)MXS_GPMI_BASE;
+	uint32_t tmp;
+
+	tmp = readl(&gpmi_regs->hw_gpmi_stat);
+	tmp >>= (GPMI_STAT_READY_BUSY_OFFSET + nand_info->cur_chip);
+
+	return tmp & 1;
+}
+
+/*
+ * Select the NAND chip.
+ */
+static void mxs_nand_select_chip(struct mtd_info *mtd, int chip)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+
+	nand_info->cur_chip = chip;
+}
+
+/*
+ * Handle block mark swapping.
+ *
+ * Note that, when this function is called, it doesn't know whether it's
+ * swapping the block mark, or swapping it *back* -- but it doesn't matter
+ * because the the operation is the same.
+ */
+static void mxs_nand_swap_block_mark(struct mtd_info *mtd,
+					uint8_t *data_buf, uint8_t *oob_buf)
+{
+	uint32_t bit_offset;
+	uint32_t buf_offset;
+
+	uint32_t src;
+	uint32_t dst;
+
+	bit_offset = mxs_nand_mark_bit_offset(mtd);
+	buf_offset = mxs_nand_mark_byte_offset(mtd);
+
+	/*
+	 * Get the byte from the data area that overlays the block mark. Since
+	 * the ECC engine applies its own view to the bits in the page, the
+	 * physical block mark won't (in general) appear on a byte boundary in
+	 * the data.
+	 */
+	src = data_buf[buf_offset] >> bit_offset;
+	src |= data_buf[buf_offset + 1] << (8 - bit_offset);
+
+	dst = oob_buf[0];
+
+	oob_buf[0] = src;
+
+	data_buf[buf_offset] &= ~(0xff << bit_offset);
+	data_buf[buf_offset + 1] &= 0xff << bit_offset;
+
+	data_buf[buf_offset] |= dst << bit_offset;
+	data_buf[buf_offset + 1] |= dst >> (8 - bit_offset);
+}
+
+/*
+ * Read data from NAND.
+ */
+static void mxs_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int length)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	int ret;
+
+	if (length > NAND_MAX_PAGESIZE) {
+		printf("MXS NAND: DMA buffer too big\n");
+		return;
+	}
+
+	if (!buf) {
+		printf("MXS NAND: DMA buffer is NULL\n");
+		return;
+	}
+
+	/* Compile the DMA descriptor - a descriptor that reads data. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_DMA_WRITE | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
+		(1 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
+		(length << MXS_DMA_DESC_BYTES_OFFSET);
+
+	d->cmd.address = (dma_addr_t)nand_info->data_buf;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_READ |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		length;
+
+	mxs_dma_desc_append(channel, d);
+
+	/*
+	 * A DMA descriptor that waits for the command to end and the chip to
+	 * become ready.
+	 *
+	 * I think we actually should *not* be waiting for the chip to become
+	 * ready because, after all, we don't care. I think the original code
+	 * did that and no one has re-thought it yet.
+	 */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_DEC_SEM |
+		MXS_DMA_DESC_WAIT4END | (4 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret) {
+		printf("MXS NAND: DMA read error\n");
+		goto rtn;
+	}
+
+	memcpy(buf, nand_info->data_buf, length);
+
+rtn:
+	mxs_nand_return_dma_descs(nand_info);
+}
+
+/*
+ * Write data to NAND.
+ */
+static void mxs_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf,
+				int length)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	int ret;
+
+	if (length > NAND_MAX_PAGESIZE) {
+		printf("MXS NAND: DMA buffer too big\n");
+		return;
+	}
+
+	if (!buf) {
+		printf("MXS NAND: DMA buffer is NULL\n");
+		return;
+	}
+
+	memcpy(nand_info->data_buf, buf, length);
+
+	/* Compile the DMA descriptor - a descriptor that writes data. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_DMA_READ | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
+		(4 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
+		(length << MXS_DMA_DESC_BYTES_OFFSET);
+
+	d->cmd.address = (dma_addr_t)nand_info->data_buf;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		length;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret)
+		printf("MXS NAND: DMA write error\n");
+
+	mxs_nand_return_dma_descs(nand_info);
+}
+
+/*
+ * Read a single byte from NAND.
+ */
+static uint8_t mxs_nand_read_byte(struct mtd_info *mtd)
+{
+	uint8_t buf;
+	mxs_nand_read_buf(mtd, &buf, 1);
+	return buf;
+}
+
+/*
+ * Read a page from NAND.
+ */
+static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
+					uint8_t *buf, int page)
+{
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	uint32_t corrected = 0, failed = 0;
+	uint8_t	*status;
+	int i, ret;
+
+	/* Compile the DMA descriptor - wait for ready. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
+		MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_WAIT4END |
+		(1 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Compile the DMA descriptor - enable the BCH block and read. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
+		MXS_DMA_DESC_WAIT4END |	(6 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_READ |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		(mtd->writesize + mtd->oobsize);
+	d->cmd.pio_words[1] = 0;
+	d->cmd.pio_words[2] =
+		GPMI_ECCCTRL_ENABLE_ECC |
+		GPMI_ECCCTRL_ECC_CMD_DECODE |
+		GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE;
+	d->cmd.pio_words[3] = mtd->writesize + mtd->oobsize;
+	d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf;
+	d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Compile the DMA descriptor - disable the BCH block. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
+		MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_WAIT4END |
+		(3 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		(mtd->writesize + mtd->oobsize);
+	d->cmd.pio_words[1] = 0;
+	d->cmd.pio_words[2] = 0;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Compile the DMA descriptor - deassert the NAND lock and interrupt. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_DEC_SEM;
+
+	d->cmd.address = 0;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret) {
+		printf("MXS NAND: DMA read error\n");
+		goto rtn;
+	}
+
+	ret = mxs_nand_wait_for_bch_complete();
+	if (ret) {
+		printf("MXS NAND: BCH read timeout\n");
+		goto rtn;
+	}
+
+	/* Read DMA completed, now do the mark swapping. */
+	mxs_nand_swap_block_mark(mtd, nand_info->data_buf, nand_info->oob_buf);
+
+	/* Loop over status bytes, accumulating ECC status. */
+	status = nand_info->oob_buf + mxs_nand_aux_status_offset();
+	for (i = 0; i < mxs_nand_ecc_chunk_cnt(mtd->writesize); i++) {
+		if (status[i] == 0x00)
+			continue;
+
+		if (status[i] == 0xff)
+			continue;
+
+		if (status[i] == 0xfe) {
+			failed++;
+			continue;
+		}
+
+		corrected += status[i];
+	}
+
+	/* Propagate ECC status to the owning MTD. */
+	mtd->ecc_stats.failed += failed;
+	mtd->ecc_stats.corrected += corrected;
+
+	/*
+	 * It's time to deliver the OOB bytes. See mxs_nand_ecc_read_oob() for
+	 * details about our policy for delivering the OOB.
+	 *
+	 * We fill the caller's buffer with set bits, and then copy the block
+	 * mark to the caller's buffer. Note that, if block mark swapping was
+	 * necessary, it has already been done, so we can rely on the first
+	 * byte of the auxiliary buffer to contain the block mark.
+	 */
+	memset(nand->oob_poi, 0xff, mtd->oobsize);
+
+	nand->oob_poi[0] = nand_info->oob_buf[0];
+
+	memcpy(buf, nand_info->data_buf, mtd->writesize);
+
+rtn:
+	mxs_nand_return_dma_descs(nand_info);
+
+	return ret;
+}
+
+/*
+ * Write a page to NAND.
+ */
+static void mxs_nand_ecc_write_page(struct mtd_info *mtd,
+				struct nand_chip *nand, const uint8_t *buf)
+{
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	int ret;
+
+	memcpy(nand_info->data_buf, buf, mtd->writesize);
+	memcpy(nand_info->oob_buf, nand->oob_poi, mtd->oobsize);
+
+	/* Handle block mark swapping. */
+	mxs_nand_swap_block_mark(mtd, nand_info->data_buf, nand_info->oob_buf);
+
+	/* Compile the DMA descriptor - write data. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
+		(6 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA;
+	d->cmd.pio_words[1] = 0;
+	d->cmd.pio_words[2] =
+		GPMI_ECCCTRL_ENABLE_ECC |
+		GPMI_ECCCTRL_ECC_CMD_ENCODE |
+		GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE;
+	d->cmd.pio_words[3] = (mtd->writesize + mtd->oobsize);
+	d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf;
+	d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret) {
+		printf("MXS NAND: DMA write error\n");
+		goto rtn;
+	}
+
+	ret = mxs_nand_wait_for_bch_complete();
+	if (ret) {
+		printf("MXS NAND: BCH write timeout\n");
+		goto rtn;
+	}
+
+rtn:
+	mxs_nand_return_dma_descs(nand_info);
+}
+
+/*
+ * Read OOB from NAND.
+ *
+ * This function is a veneer that replaces the function originally installed by
+ * the NAND Flash MTD code.
+ */
+static int mxs_nand_hook_read_oob(struct mtd_info *mtd, loff_t from,
+					struct mtd_oob_ops *ops)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mxs_nand_info *nand_info = chip->priv;
+	int ret;
+
+	if (ops->mode == MTD_OOB_RAW)
+		nand_info->raw_oob_mode = 1;
+	else
+		nand_info->raw_oob_mode = 0;
+
+	ret = nand_info->hooked_read_oob(mtd, from, ops);
+
+	nand_info->raw_oob_mode = 0;
+
+	return ret;
+}
+
+/*
+ * Write OOB to NAND.
+ *
+ * This function is a veneer that replaces the function originally installed by
+ * the NAND Flash MTD code.
+ */
+static int mxs_nand_hook_write_oob(struct mtd_info *mtd, loff_t to,
+					struct mtd_oob_ops *ops)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mxs_nand_info *nand_info = chip->priv;
+	int ret;
+
+	if (ops->mode == MTD_OOB_RAW)
+		nand_info->raw_oob_mode = 1;
+	else
+		nand_info->raw_oob_mode = 0;
+
+	ret = nand_info->hooked_write_oob(mtd, to, ops);
+
+	nand_info->raw_oob_mode = 0;
+
+	return ret;
+}
+
+/*
+ * Mark a block bad in NAND.
+ *
+ * This function is a veneer that replaces the function originally installed by
+ * the NAND Flash MTD code.
+ */
+static int mxs_nand_hook_block_markbad(struct mtd_info *mtd, loff_t ofs)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mxs_nand_info *nand_info = chip->priv;
+	int ret;
+
+	nand_info->marking_block_bad = 1;
+
+	ret = nand_info->hooked_block_markbad(mtd, ofs);
+
+	nand_info->marking_block_bad = 0;
+
+	return ret;
+}
+
+/*
+ * There are several places in this driver where we have to handle the OOB and
+ * block marks. This is the function where things are the most complicated, so
+ * this is where we try to explain it all. All the other places refer back to
+ * here.
+ *
+ * These are the rules, in order of decreasing importance:
+ *
+ * 1) Nothing the caller does can be allowed to imperil the block mark, so all
+ *    write operations take measures to protect it.
+ *
+ * 2) In read operations, the first byte of the OOB we return must reflect the
+ *    true state of the block mark, no matter where that block mark appears in
+ *    the physical page.
+ *
+ * 3) ECC-based read operations return an OOB full of set bits (since we never
+ *    allow ECC-based writes to the OOB, it doesn't matter what ECC-based reads
+ *    return).
+ *
+ * 4) "Raw" read operations return a direct view of the physical bytes in the
+ *    page, using the conventional definition of which bytes are data and which
+ *    are OOB. This gives the caller a way to see the actual, physical bytes
+ *    in the page, without the distortions applied by our ECC engine.
+ *
+ * What we do for this specific read operation depends on whether we're doing
+ * "raw" read, or an ECC-based read.
+ *
+ * It turns out that knowing whether we want an "ECC-based" or "raw" read is not
+ * easy. When reading a page, for example, the NAND Flash MTD code calls our
+ * ecc.read_page or ecc.read_page_raw function. Thus, the fact that MTD wants an
+ * ECC-based or raw view of the page is implicit in which function it calls
+ * (there is a similar pair of ECC-based/raw functions for writing).
+ *
+ * Since MTD assumes the OOB is not covered by ECC, there is no pair of
+ * ECC-based/raw functions for reading or or writing the OOB. The fact that the
+ * caller wants an ECC-based or raw view of the page is not propagated down to
+ * this driver.
+ *
+ * Since our OOB *is* covered by ECC, we need this information. So, we hook the
+ * ecc.read_oob and ecc.write_oob function pointers in the owning
+ * struct mtd_info with our own functions. These hook functions set the
+ * raw_oob_mode field so that, when control finally arrives here, we'll know
+ * what to do.
+ */
+static int mxs_nand_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *nand,
+				int page, int cmd)
+{
+	struct mxs_nand_info *nand_info = nand->priv;
+
+	/*
+	 * First, fill in the OOB buffer. If we're doing a raw read, we need to
+	 * get the bytes from the physical page. If we're not doing a raw read,
+	 * we need to fill the buffer with set bits.
+	 */
+	if (nand_info->raw_oob_mode) {
+		/*
+		 * If control arrives here, we're doing a "raw" read. Send the
+		 * command to read the conventional OOB and read it.
+		 */
+		nand->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page);
+		nand->read_buf(mtd, nand->oob_poi, mtd->oobsize);
+	} else {
+		/*
+		 * If control arrives here, we're not doing a "raw" read. Fill
+		 * the OOB buffer with set bits and correct the block mark.
+		 */
+		memset(nand->oob_poi, 0xff, mtd->oobsize);
+
+		nand->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page);
+		mxs_nand_read_buf(mtd, nand->oob_poi, 1);
+	}
+
+	return 0;
+
+}
+
+/*
+ * Write OOB data to NAND.
+ */
+static int mxs_nand_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *nand,
+					int page)
+{
+	struct mxs_nand_info *nand_info = nand->priv;
+	uint8_t block_mark = 0;
+
+	/*
+	 * There are fundamental incompatibilities between the i.MX GPMI NFC and
+	 * the NAND Flash MTD model that make it essentially impossible to write
+	 * the out-of-band bytes.
+	 *
+	 * We permit *ONE* exception. If the *intent* of writing the OOB is to
+	 * mark a block bad, we can do that.
+	 */
+
+	if (!nand_info->marking_block_bad) {
+		printf("NXS NAND: Writing OOB isn't supported\n");
+		return -EIO;
+	}
+
+	/* Write the block mark. */
+	nand->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
+	nand->write_buf(mtd, &block_mark, 1);
+	nand->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+
+	/* Check if it worked. */
+	if (nand->waitfunc(mtd, nand) & NAND_STATUS_FAIL)
+		return -EIO;
+
+	return 0;
+}
+
+/*
+ * Claims all blocks are good.
+ *
+ * In principle, this function is *only* called when the NAND Flash MTD system
+ * isn't allowed to keep an in-memory bad block table, so it is forced to ask
+ * the driver for bad block information.
+ *
+ * In fact, we permit the NAND Flash MTD system to have an in-memory BBT, so
+ * this function is *only* called when we take it away.
+ *
+ * Thus, this function is only called when we want *all* blocks to look good,
+ * so it *always* return success.
+ */
+static int mxs_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
+{
+	return 0;
+}
+
+/*
+ * Nominally, the purpose of this function is to look for or create the bad
+ * block table. In fact, since the we call this function at the very end of
+ * the initialization process started by nand_scan(), and we doesn't have a
+ * more formal mechanism, we "hook" this function to continue init process.
+ *
+ * At this point, the physical NAND Flash chips have been identified and
+ * counted, so we know the physical geometry. This enables us to make some
+ * important configuration decisions.
+ *
+ * The return value of this function propogates directly back to this driver's
+ * call to nand_scan(). Anything other than zero will cause this driver to
+ * tear everything down and declare failure.
+ */
+static int mxs_nand_scan_bbt(struct mtd_info *mtd)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mx28_bch_regs *bch_regs = (struct mx28_bch_regs *)MXS_BCH_BASE;
+	uint32_t tmp;
+
+	/* Configure BCH and set NFC geometry */
+	mx28_reset_block(&bch_regs->hw_bch_ctrl_reg);
+
+	/* Configure layout 0 */
+	tmp = (mxs_nand_ecc_chunk_cnt(mtd->writesize) - 1)
+		<< BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
+	tmp |= MXS_NAND_METADATA_SIZE << BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
+	tmp |= (mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1)
+		<< BCH_FLASHLAYOUT0_ECC0_OFFSET;
+	tmp |= MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
+	writel(tmp, &bch_regs->hw_bch_flash0layout0);
+
+	tmp = (mtd->writesize + mtd->oobsize)
+		<< BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
+	tmp |= (mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1)
+		<< BCH_FLASHLAYOUT1_ECCN_OFFSET;
+	tmp |= MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
+	writel(tmp, &bch_regs->hw_bch_flash0layout1);
+
+	/* Set *all* chip selects to use layout 0 */
+	writel(0, &bch_regs->hw_bch_layoutselect);
+
+	/* Enable BCH complete interrupt */
+	writel(BCH_CTRL_COMPLETE_IRQ_EN, &bch_regs->hw_bch_ctrl_set);
+
+	/* Hook some operations at the MTD level. */
+	if (mtd->read_oob != mxs_nand_hook_read_oob) {
+		nand_info->hooked_read_oob = mtd->read_oob;
+		mtd->read_oob = mxs_nand_hook_read_oob;
+	}
+
+	if (mtd->write_oob != mxs_nand_hook_write_oob) {
+		nand_info->hooked_write_oob = mtd->write_oob;
+		mtd->write_oob = mxs_nand_hook_write_oob;
+	}
+
+	if (mtd->block_markbad != mxs_nand_hook_block_markbad) {
+		nand_info->hooked_block_markbad = mtd->block_markbad;
+		mtd->block_markbad = mxs_nand_hook_block_markbad;
+	}
+
+	/* We use the reference implementation for bad block management. */
+	return nand_default_bbt(mtd);
+}
+
+/*
+ * Allocate DMA buffers
+ */
+int mxs_nand_alloc_buffers(struct mxs_nand_info *nand_info)
+{
+	uint8_t *buf;
+	const int size = NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE;
+
+	/* DMA buffers */
+	buf = memalign(MXS_DMA_ALIGNMENT, size);
+	if (!buf) {
+		printf("MXS NAND: Error allocating DMA buffers\n");
+		return -ENOMEM;
+	}
+
+	memset(buf, 0, size);
+
+	nand_info->data_buf = buf;
+	nand_info->oob_buf = buf + NAND_MAX_PAGESIZE;
+
+	/* Command buffers */
+	nand_info->cmd_buf = memalign(MXS_DMA_ALIGNMENT,
+				MXS_NAND_COMMAND_BUFFER_SIZE);
+	if (!nand_info->cmd_buf) {
+		free(buf);
+		printf("MXS NAND: Error allocating command buffers\n");
+		return -ENOMEM;
+	}
+	memset(nand_info->cmd_buf, 0, MXS_NAND_COMMAND_BUFFER_SIZE);
+	nand_info->cmd_queue_len = 0;
+
+	return 0;
+}
+
+/*
+ * Initializes the NFC hardware.
+ */
+int mxs_nand_init(struct mxs_nand_info *info)
+{
+	struct mx28_gpmi_regs *gpmi_regs =
+		(struct mx28_gpmi_regs *)MXS_GPMI_BASE;
+	int i = 0;
+
+	info->desc = malloc(sizeof(struct mxs_dma_desc *) *
+				MXS_NAND_DMA_DESCRIPTOR_COUNT);
+	if (!info->desc)
+		goto err1;
+
+	/* Allocate the DMA descriptors. */
+	for (i = 0; i < MXS_NAND_DMA_DESCRIPTOR_COUNT; i++) {
+		info->desc[i] = mxs_dma_desc_alloc();
+		if (!info->desc[i])
+			goto err2;
+	}
+
+	/* Init the DMA controller. */
+	mxs_dma_init();
+
+	/* Reset the GPMI block. */
+	mx28_reset_block(&gpmi_regs->hw_gpmi_ctrl0_reg);
+
+	/*
+	 * Choose NAND mode, set IRQ polarity, disable write protection and
+	 * select BCH ECC.
+	 */
+	clrsetbits_le32(&gpmi_regs->hw_gpmi_ctrl1,
+			GPMI_CTRL1_GPMI_MODE,
+			GPMI_CTRL1_ATA_IRQRDY_POLARITY | GPMI_CTRL1_DEV_RESET |
+			GPMI_CTRL1_BCH_MODE);
+
+	return 0;
+
+err2:
+	free(info->desc);
+err1:
+	for (--i; i >= 0; i--)
+		mxs_dma_desc_free(info->desc[i]);
+	printf("MXS NAND: Unable to allocate DMA descriptors\n");
+	return -ENOMEM;
+}
+
+/*!
+ * This function is called during the driver binding process.
+ *
+ * @param   pdev  the device structure used to store device specific
+ *                information that is used by the suspend, resume and
+ *                remove functions
+ *
+ * @return  The function always returns 0.
+ */
+int board_nand_init(struct nand_chip *nand)
+{
+	struct mxs_nand_info *nand_info;
+	int err;
+
+	nand_info = malloc(sizeof(struct mxs_nand_info));
+	if (!nand_info) {
+		printf("MXS NAND: Failed to allocate private data\n");
+		return -ENOMEM;
+	}
+	memset(nand_info, 0, sizeof(struct mxs_nand_info));
+
+	err = mxs_nand_alloc_buffers(nand_info);
+	if (err)
+		goto err1;
+
+	err = mxs_nand_init(nand_info);
+	if (err)
+		goto err2;
+
+	memset(&fake_ecc_layout, 0, sizeof(fake_ecc_layout));
+
+	nand->priv = nand_info;
+	nand->options |= NAND_NO_SUBPAGE_WRITE;
+
+	nand->cmd_ctrl		= mxs_nand_cmd_ctrl;
+
+	nand->dev_ready		= mxs_nand_device_ready;
+	nand->select_chip	= mxs_nand_select_chip;
+	nand->block_bad		= mxs_nand_block_bad;
+	nand->scan_bbt		= mxs_nand_scan_bbt;
+
+	nand->read_byte		= mxs_nand_read_byte;
+
+	nand->read_buf		= mxs_nand_read_buf;
+	nand->write_buf		= mxs_nand_write_buf;
+
+	nand->ecc.read_page	= mxs_nand_ecc_read_page;
+	nand->ecc.write_page	= mxs_nand_ecc_write_page;
+	nand->ecc.read_oob	= mxs_nand_ecc_read_oob;
+	nand->ecc.write_oob	= mxs_nand_ecc_write_oob;
+
+	nand->ecc.layout	= &fake_ecc_layout;
+	nand->ecc.mode		= NAND_ECC_HW;
+	nand->ecc.bytes		= 9;
+	nand->ecc.size		= 512;
+
+	return 0;
+
+err2:
+	free(nand_info->data_buf);
+	free(nand_info->cmd_buf);
+err1:
+	free(nand_info);
+	return err;
+}
-- 
1.7.5.4

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

* [U-Boot] [PATCH 09/15 V5] iMX28: Add GPMI NAND driver
  2011-09-29  0:07       ` [U-Boot] [PATCH 09/15 V4] " Marek Vasut
@ 2011-09-30  9:39         ` Marek Vasut
  2011-10-10 21:06           ` Scott Wood
  0 siblings, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-09-30  9:39 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Scott Wood <scottwood@freescale.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 drivers/mtd/nand/Makefile   |    1 +
 drivers/mtd/nand/mxs_nand.c | 1118 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1119 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/nand/mxs_nand.c

V2: Update comments, drop inlines
V3: Fix descriptor reclamation loop
V4: Trim bogus comments
V5: Remove redundant mxs_nand_aux_size() function (gcc 4.6 finding)

diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index b6a7886..aef0d56 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -49,6 +49,7 @@ COBJS-$(CONFIG_NAND_KIRKWOOD) += kirkwood_nand.o
 COBJS-$(CONFIG_NAND_KMETER1) += kmeter1_nand.o
 COBJS-$(CONFIG_NAND_MPC5121_NFC) += mpc5121_nfc.o
 COBJS-$(CONFIG_NAND_MXC) += mxc_nand.o
+COBJS-$(CONFIG_NAND_MXS) += mxs_nand.o
 COBJS-$(CONFIG_NAND_NDFC) += ndfc.o
 COBJS-$(CONFIG_NAND_NOMADIK) += nomadik.o
 COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o
diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c
new file mode 100644
index 0000000..ce2a326
--- /dev/null
+++ b/drivers/mtd/nand/mxs_nand.c
@@ -0,0 +1,1118 @@
+/*
+ * Freescale i.MX28 NAND flash driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Freescale GPMI NFC NAND Flash Driver
+ *
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ * Copyright (C) 2008 Embedded Alley Solutions, Inc.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/types.h>
+#include <common.h>
+#include <malloc.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/dma.h>
+
+#define	MXS_NAND_DMA_DESCRIPTOR_COUNT		4
+
+#define	MXS_NAND_CHUNK_DATA_CHUNK_SIZE		512
+#define	MXS_NAND_METADATA_SIZE			10
+
+#define	MXS_NAND_COMMAND_BUFFER_SIZE		32
+
+#define	MXS_NAND_BCH_TIMEOUT			10000
+
+struct mxs_nand_info {
+	int		cur_chip;
+
+	uint32_t	cmd_queue_len;
+
+	uint8_t		*cmd_buf;
+	uint8_t		*data_buf;
+	uint8_t		*oob_buf;
+
+	uint8_t		marking_block_bad;
+	uint8_t		raw_oob_mode;
+
+	/* Functions with altered behaviour */
+	int		(*hooked_read_oob)(struct mtd_info *mtd,
+				loff_t from, struct mtd_oob_ops *ops);
+	int		(*hooked_write_oob)(struct mtd_info *mtd,
+				loff_t to, struct mtd_oob_ops *ops);
+	int		(*hooked_block_markbad)(struct mtd_info *mtd,
+				loff_t ofs);
+
+	/* DMA descriptors */
+	struct mxs_dma_desc	**desc;
+	uint32_t		desc_index;
+};
+
+struct nand_ecclayout fake_ecc_layout;
+
+static struct mxs_dma_desc *mxs_nand_get_dma_desc(struct mxs_nand_info *info)
+{
+	struct mxs_dma_desc *desc;
+
+	if (info->desc_index >= MXS_NAND_DMA_DESCRIPTOR_COUNT) {
+		printf("MXS NAND: Too many DMA descriptors requested\n");
+		return NULL;
+	}
+
+	desc = info->desc[info->desc_index];
+	info->desc_index++;
+
+	return desc;
+}
+
+static void mxs_nand_return_dma_descs(struct mxs_nand_info *info)
+{
+	int i;
+	struct mxs_dma_desc *desc;
+
+	for (i = 0; i < info->desc_index; i++) {
+		desc = info->desc[i];
+		memset(desc, 0, sizeof(struct mxs_dma_desc));
+		desc->address = (dma_addr_t)desc;
+	}
+
+	info->desc_index = 0;
+}
+
+static uint32_t mxs_nand_ecc_chunk_cnt(uint32_t page_data_size)
+{
+	return page_data_size / MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
+}
+
+static uint32_t mxs_nand_ecc_size_in_bits(uint32_t ecc_strength)
+{
+	return ecc_strength * 13;
+}
+
+static uint32_t mxs_nand_aux_status_offset(void)
+{
+	return (MXS_NAND_METADATA_SIZE + 0x3) & ~0x3;
+}
+
+static inline uint32_t mxs_nand_get_ecc_strength(uint32_t page_data_size,
+						uint32_t page_oob_size)
+{
+	if (page_data_size == 2048)
+		return 8;
+
+	if (page_data_size == 4096) {
+		if (page_oob_size == 128)
+			return 8;
+
+		if (page_oob_size == 218)
+			return 16;
+	}
+
+	return 0;
+}
+
+static inline uint32_t mxs_nand_get_mark_offset(uint32_t page_data_size,
+						uint32_t ecc_strength)
+{
+	uint32_t chunk_data_size_in_bits;
+	uint32_t chunk_ecc_size_in_bits;
+	uint32_t chunk_total_size_in_bits;
+	uint32_t block_mark_chunk_number;
+	uint32_t block_mark_chunk_bit_offset;
+	uint32_t block_mark_bit_offset;
+
+	chunk_data_size_in_bits = MXS_NAND_CHUNK_DATA_CHUNK_SIZE * 8;
+	chunk_ecc_size_in_bits  = mxs_nand_ecc_size_in_bits(ecc_strength);
+
+	chunk_total_size_in_bits =
+			chunk_data_size_in_bits + chunk_ecc_size_in_bits;
+
+	/* Compute the bit offset of the block mark within the physical page. */
+	block_mark_bit_offset = page_data_size * 8;
+
+	/* Subtract the metadata bits. */
+	block_mark_bit_offset -= MXS_NAND_METADATA_SIZE * 8;
+
+	/*
+	 * Compute the chunk number (starting at zero) in which the block mark
+	 * appears.
+	 */
+	block_mark_chunk_number =
+			block_mark_bit_offset / chunk_total_size_in_bits;
+
+	/*
+	 * Compute the bit offset of the block mark within its chunk, and
+	 * validate it.
+	 */
+	block_mark_chunk_bit_offset = block_mark_bit_offset -
+			(block_mark_chunk_number * chunk_total_size_in_bits);
+
+	if (block_mark_chunk_bit_offset > chunk_data_size_in_bits)
+		return 1;
+
+	/*
+	 * Now that we know the chunk number in which the block mark appears,
+	 * we can subtract all the ECC bits that appear before it.
+	 */
+	block_mark_bit_offset -=
+		block_mark_chunk_number * chunk_ecc_size_in_bits;
+
+	return block_mark_bit_offset;
+}
+
+static uint32_t mxs_nand_mark_byte_offset(struct mtd_info *mtd)
+{
+	uint32_t ecc_strength;
+	ecc_strength = mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize);
+	return mxs_nand_get_mark_offset(mtd->writesize, ecc_strength) >> 3;
+}
+
+static uint32_t mxs_nand_mark_bit_offset(struct mtd_info *mtd)
+{
+	uint32_t ecc_strength;
+	ecc_strength = mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize);
+	return mxs_nand_get_mark_offset(mtd->writesize, ecc_strength) & 0x7;
+}
+
+/*
+ * Wait for BCH complete IRQ and clear the IRQ
+ */
+static int mxs_nand_wait_for_bch_complete(void)
+{
+	struct mx28_bch_regs *bch_regs = (struct mx28_bch_regs *)MXS_BCH_BASE;
+	int timeout = MXS_NAND_BCH_TIMEOUT;
+	int ret;
+
+	ret = mx28_wait_mask_set(&bch_regs->hw_bch_ctrl_reg,
+		BCH_CTRL_COMPLETE_IRQ, timeout);
+
+	writel(BCH_CTRL_COMPLETE_IRQ, &bch_regs->hw_bch_ctrl_clr);
+
+	return ret;
+}
+
+/*
+ * This is the function that we install in the cmd_ctrl function pointer of the
+ * owning struct nand_chip. The only functions in the reference implementation
+ * that use these functions pointers are cmdfunc and select_chip.
+ *
+ * In this driver, we implement our own select_chip, so this function will only
+ * be called by the reference implementation's cmdfunc. For this reason, we can
+ * ignore the chip enable bit and concentrate only on sending bytes to the NAND
+ * Flash.
+ */
+static void mxs_nand_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	int ret;
+
+	/*
+	 * If this condition is true, something is _VERY_ wrong in MTD
+	 * subsystem!
+	 */
+	if (nand_info->cmd_queue_len == MXS_NAND_COMMAND_BUFFER_SIZE) {
+		printf("MXS NAND: Command queue too long\n");
+		return;
+	}
+
+	/*
+	 * Every operation begins with a command byte and a series of zero or
+	 * more address bytes. These are distinguished by either the Address
+	 * Latch Enable (ALE) or Command Latch Enable (CLE) signals being
+	 * asserted. When MTD is ready to execute the command, it will
+	 * deasert both latch enables.
+	 *
+	 * Rather than run a separate DMA operation for every single byte, we
+	 * queue them up and run a single DMA operation for the entire series
+	 * of command and data bytes.
+	 */
+	if (ctrl & (NAND_ALE | NAND_CLE)) {
+		if (data != NAND_CMD_NONE)
+			nand_info->cmd_buf[nand_info->cmd_queue_len++] = data;
+		return;
+	}
+
+	/*
+	 * If control arrives here, MTD has deasserted both the ALE and CLE,
+	 * which means it's ready to run an operation. Check if we have any
+	 * bytes to send.
+	 */
+	if (nand_info->cmd_queue_len == 0)
+		return;
+
+	/* Compile the DMA descriptor -- a descriptor that sends command. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_DMA_READ | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_CHAIN | MXS_DMA_DESC_DEC_SEM |
+		MXS_DMA_DESC_WAIT4END | (3 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
+		(nand_info->cmd_queue_len << MXS_DMA_DESC_BYTES_OFFSET);
+
+	d->cmd.address = (dma_addr_t)nand_info->cmd_buf;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_CLE |
+		GPMI_CTRL0_ADDRESS_INCREMENT |
+		nand_info->cmd_queue_len;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret)
+		printf("MXS NAND: Error sending command\n");
+
+	mxs_nand_return_dma_descs(nand_info);
+
+	/* Reset the command queue. */
+	nand_info->cmd_queue_len = 0;
+}
+
+/*
+ * Test if the NAND flash is ready.
+ */
+static int mxs_nand_device_ready(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mxs_nand_info *nand_info = chip->priv;
+	struct mx28_gpmi_regs *gpmi_regs =
+		(struct mx28_gpmi_regs *)MXS_GPMI_BASE;
+	uint32_t tmp;
+
+	tmp = readl(&gpmi_regs->hw_gpmi_stat);
+	tmp >>= (GPMI_STAT_READY_BUSY_OFFSET + nand_info->cur_chip);
+
+	return tmp & 1;
+}
+
+/*
+ * Select the NAND chip.
+ */
+static void mxs_nand_select_chip(struct mtd_info *mtd, int chip)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+
+	nand_info->cur_chip = chip;
+}
+
+/*
+ * Handle block mark swapping.
+ *
+ * Note that, when this function is called, it doesn't know whether it's
+ * swapping the block mark, or swapping it *back* -- but it doesn't matter
+ * because the the operation is the same.
+ */
+static void mxs_nand_swap_block_mark(struct mtd_info *mtd,
+					uint8_t *data_buf, uint8_t *oob_buf)
+{
+	uint32_t bit_offset;
+	uint32_t buf_offset;
+
+	uint32_t src;
+	uint32_t dst;
+
+	bit_offset = mxs_nand_mark_bit_offset(mtd);
+	buf_offset = mxs_nand_mark_byte_offset(mtd);
+
+	/*
+	 * Get the byte from the data area that overlays the block mark. Since
+	 * the ECC engine applies its own view to the bits in the page, the
+	 * physical block mark won't (in general) appear on a byte boundary in
+	 * the data.
+	 */
+	src = data_buf[buf_offset] >> bit_offset;
+	src |= data_buf[buf_offset + 1] << (8 - bit_offset);
+
+	dst = oob_buf[0];
+
+	oob_buf[0] = src;
+
+	data_buf[buf_offset] &= ~(0xff << bit_offset);
+	data_buf[buf_offset + 1] &= 0xff << bit_offset;
+
+	data_buf[buf_offset] |= dst << bit_offset;
+	data_buf[buf_offset + 1] |= dst >> (8 - bit_offset);
+}
+
+/*
+ * Read data from NAND.
+ */
+static void mxs_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int length)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	int ret;
+
+	if (length > NAND_MAX_PAGESIZE) {
+		printf("MXS NAND: DMA buffer too big\n");
+		return;
+	}
+
+	if (!buf) {
+		printf("MXS NAND: DMA buffer is NULL\n");
+		return;
+	}
+
+	/* Compile the DMA descriptor - a descriptor that reads data. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_DMA_WRITE | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
+		(1 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
+		(length << MXS_DMA_DESC_BYTES_OFFSET);
+
+	d->cmd.address = (dma_addr_t)nand_info->data_buf;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_READ |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		length;
+
+	mxs_dma_desc_append(channel, d);
+
+	/*
+	 * A DMA descriptor that waits for the command to end and the chip to
+	 * become ready.
+	 *
+	 * I think we actually should *not* be waiting for the chip to become
+	 * ready because, after all, we don't care. I think the original code
+	 * did that and no one has re-thought it yet.
+	 */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_DEC_SEM |
+		MXS_DMA_DESC_WAIT4END | (4 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret) {
+		printf("MXS NAND: DMA read error\n");
+		goto rtn;
+	}
+
+	memcpy(buf, nand_info->data_buf, length);
+
+rtn:
+	mxs_nand_return_dma_descs(nand_info);
+}
+
+/*
+ * Write data to NAND.
+ */
+static void mxs_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf,
+				int length)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	int ret;
+
+	if (length > NAND_MAX_PAGESIZE) {
+		printf("MXS NAND: DMA buffer too big\n");
+		return;
+	}
+
+	if (!buf) {
+		printf("MXS NAND: DMA buffer is NULL\n");
+		return;
+	}
+
+	memcpy(nand_info->data_buf, buf, length);
+
+	/* Compile the DMA descriptor - a descriptor that writes data. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_DMA_READ | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
+		(4 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
+		(length << MXS_DMA_DESC_BYTES_OFFSET);
+
+	d->cmd.address = (dma_addr_t)nand_info->data_buf;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		length;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret)
+		printf("MXS NAND: DMA write error\n");
+
+	mxs_nand_return_dma_descs(nand_info);
+}
+
+/*
+ * Read a single byte from NAND.
+ */
+static uint8_t mxs_nand_read_byte(struct mtd_info *mtd)
+{
+	uint8_t buf;
+	mxs_nand_read_buf(mtd, &buf, 1);
+	return buf;
+}
+
+/*
+ * Read a page from NAND.
+ */
+static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
+					uint8_t *buf, int page)
+{
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	uint32_t corrected = 0, failed = 0;
+	uint8_t	*status;
+	int i, ret;
+
+	/* Compile the DMA descriptor - wait for ready. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
+		MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_WAIT4END |
+		(1 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Compile the DMA descriptor - enable the BCH block and read. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
+		MXS_DMA_DESC_WAIT4END |	(6 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_READ |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		(mtd->writesize + mtd->oobsize);
+	d->cmd.pio_words[1] = 0;
+	d->cmd.pio_words[2] =
+		GPMI_ECCCTRL_ENABLE_ECC |
+		GPMI_ECCCTRL_ECC_CMD_DECODE |
+		GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE;
+	d->cmd.pio_words[3] = mtd->writesize + mtd->oobsize;
+	d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf;
+	d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Compile the DMA descriptor - disable the BCH block. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
+		MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_WAIT4END |
+		(3 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		(mtd->writesize + mtd->oobsize);
+	d->cmd.pio_words[1] = 0;
+	d->cmd.pio_words[2] = 0;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Compile the DMA descriptor - deassert the NAND lock and interrupt. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_DEC_SEM;
+
+	d->cmd.address = 0;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret) {
+		printf("MXS NAND: DMA read error\n");
+		goto rtn;
+	}
+
+	ret = mxs_nand_wait_for_bch_complete();
+	if (ret) {
+		printf("MXS NAND: BCH read timeout\n");
+		goto rtn;
+	}
+
+	/* Read DMA completed, now do the mark swapping. */
+	mxs_nand_swap_block_mark(mtd, nand_info->data_buf, nand_info->oob_buf);
+
+	/* Loop over status bytes, accumulating ECC status. */
+	status = nand_info->oob_buf + mxs_nand_aux_status_offset();
+	for (i = 0; i < mxs_nand_ecc_chunk_cnt(mtd->writesize); i++) {
+		if (status[i] == 0x00)
+			continue;
+
+		if (status[i] == 0xff)
+			continue;
+
+		if (status[i] == 0xfe) {
+			failed++;
+			continue;
+		}
+
+		corrected += status[i];
+	}
+
+	/* Propagate ECC status to the owning MTD. */
+	mtd->ecc_stats.failed += failed;
+	mtd->ecc_stats.corrected += corrected;
+
+	/*
+	 * It's time to deliver the OOB bytes. See mxs_nand_ecc_read_oob() for
+	 * details about our policy for delivering the OOB.
+	 *
+	 * We fill the caller's buffer with set bits, and then copy the block
+	 * mark to the caller's buffer. Note that, if block mark swapping was
+	 * necessary, it has already been done, so we can rely on the first
+	 * byte of the auxiliary buffer to contain the block mark.
+	 */
+	memset(nand->oob_poi, 0xff, mtd->oobsize);
+
+	nand->oob_poi[0] = nand_info->oob_buf[0];
+
+	memcpy(buf, nand_info->data_buf, mtd->writesize);
+
+rtn:
+	mxs_nand_return_dma_descs(nand_info);
+
+	return ret;
+}
+
+/*
+ * Write a page to NAND.
+ */
+static void mxs_nand_ecc_write_page(struct mtd_info *mtd,
+				struct nand_chip *nand, const uint8_t *buf)
+{
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	int ret;
+
+	memcpy(nand_info->data_buf, buf, mtd->writesize);
+	memcpy(nand_info->oob_buf, nand->oob_poi, mtd->oobsize);
+
+	/* Handle block mark swapping. */
+	mxs_nand_swap_block_mark(mtd, nand_info->data_buf, nand_info->oob_buf);
+
+	/* Compile the DMA descriptor - write data. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
+		(6 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA;
+	d->cmd.pio_words[1] = 0;
+	d->cmd.pio_words[2] =
+		GPMI_ECCCTRL_ENABLE_ECC |
+		GPMI_ECCCTRL_ECC_CMD_ENCODE |
+		GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE;
+	d->cmd.pio_words[3] = (mtd->writesize + mtd->oobsize);
+	d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf;
+	d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret) {
+		printf("MXS NAND: DMA write error\n");
+		goto rtn;
+	}
+
+	ret = mxs_nand_wait_for_bch_complete();
+	if (ret) {
+		printf("MXS NAND: BCH write timeout\n");
+		goto rtn;
+	}
+
+rtn:
+	mxs_nand_return_dma_descs(nand_info);
+}
+
+/*
+ * Read OOB from NAND.
+ *
+ * This function is a veneer that replaces the function originally installed by
+ * the NAND Flash MTD code.
+ */
+static int mxs_nand_hook_read_oob(struct mtd_info *mtd, loff_t from,
+					struct mtd_oob_ops *ops)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mxs_nand_info *nand_info = chip->priv;
+	int ret;
+
+	if (ops->mode == MTD_OOB_RAW)
+		nand_info->raw_oob_mode = 1;
+	else
+		nand_info->raw_oob_mode = 0;
+
+	ret = nand_info->hooked_read_oob(mtd, from, ops);
+
+	nand_info->raw_oob_mode = 0;
+
+	return ret;
+}
+
+/*
+ * Write OOB to NAND.
+ *
+ * This function is a veneer that replaces the function originally installed by
+ * the NAND Flash MTD code.
+ */
+static int mxs_nand_hook_write_oob(struct mtd_info *mtd, loff_t to,
+					struct mtd_oob_ops *ops)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mxs_nand_info *nand_info = chip->priv;
+	int ret;
+
+	if (ops->mode == MTD_OOB_RAW)
+		nand_info->raw_oob_mode = 1;
+	else
+		nand_info->raw_oob_mode = 0;
+
+	ret = nand_info->hooked_write_oob(mtd, to, ops);
+
+	nand_info->raw_oob_mode = 0;
+
+	return ret;
+}
+
+/*
+ * Mark a block bad in NAND.
+ *
+ * This function is a veneer that replaces the function originally installed by
+ * the NAND Flash MTD code.
+ */
+static int mxs_nand_hook_block_markbad(struct mtd_info *mtd, loff_t ofs)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mxs_nand_info *nand_info = chip->priv;
+	int ret;
+
+	nand_info->marking_block_bad = 1;
+
+	ret = nand_info->hooked_block_markbad(mtd, ofs);
+
+	nand_info->marking_block_bad = 0;
+
+	return ret;
+}
+
+/*
+ * There are several places in this driver where we have to handle the OOB and
+ * block marks. This is the function where things are the most complicated, so
+ * this is where we try to explain it all. All the other places refer back to
+ * here.
+ *
+ * These are the rules, in order of decreasing importance:
+ *
+ * 1) Nothing the caller does can be allowed to imperil the block mark, so all
+ *    write operations take measures to protect it.
+ *
+ * 2) In read operations, the first byte of the OOB we return must reflect the
+ *    true state of the block mark, no matter where that block mark appears in
+ *    the physical page.
+ *
+ * 3) ECC-based read operations return an OOB full of set bits (since we never
+ *    allow ECC-based writes to the OOB, it doesn't matter what ECC-based reads
+ *    return).
+ *
+ * 4) "Raw" read operations return a direct view of the physical bytes in the
+ *    page, using the conventional definition of which bytes are data and which
+ *    are OOB. This gives the caller a way to see the actual, physical bytes
+ *    in the page, without the distortions applied by our ECC engine.
+ *
+ * What we do for this specific read operation depends on whether we're doing
+ * "raw" read, or an ECC-based read.
+ *
+ * It turns out that knowing whether we want an "ECC-based" or "raw" read is not
+ * easy. When reading a page, for example, the NAND Flash MTD code calls our
+ * ecc.read_page or ecc.read_page_raw function. Thus, the fact that MTD wants an
+ * ECC-based or raw view of the page is implicit in which function it calls
+ * (there is a similar pair of ECC-based/raw functions for writing).
+ *
+ * Since MTD assumes the OOB is not covered by ECC, there is no pair of
+ * ECC-based/raw functions for reading or or writing the OOB. The fact that the
+ * caller wants an ECC-based or raw view of the page is not propagated down to
+ * this driver.
+ *
+ * Since our OOB *is* covered by ECC, we need this information. So, we hook the
+ * ecc.read_oob and ecc.write_oob function pointers in the owning
+ * struct mtd_info with our own functions. These hook functions set the
+ * raw_oob_mode field so that, when control finally arrives here, we'll know
+ * what to do.
+ */
+static int mxs_nand_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *nand,
+				int page, int cmd)
+{
+	struct mxs_nand_info *nand_info = nand->priv;
+
+	/*
+	 * First, fill in the OOB buffer. If we're doing a raw read, we need to
+	 * get the bytes from the physical page. If we're not doing a raw read,
+	 * we need to fill the buffer with set bits.
+	 */
+	if (nand_info->raw_oob_mode) {
+		/*
+		 * If control arrives here, we're doing a "raw" read. Send the
+		 * command to read the conventional OOB and read it.
+		 */
+		nand->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page);
+		nand->read_buf(mtd, nand->oob_poi, mtd->oobsize);
+	} else {
+		/*
+		 * If control arrives here, we're not doing a "raw" read. Fill
+		 * the OOB buffer with set bits and correct the block mark.
+		 */
+		memset(nand->oob_poi, 0xff, mtd->oobsize);
+
+		nand->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page);
+		mxs_nand_read_buf(mtd, nand->oob_poi, 1);
+	}
+
+	return 0;
+
+}
+
+/*
+ * Write OOB data to NAND.
+ */
+static int mxs_nand_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *nand,
+					int page)
+{
+	struct mxs_nand_info *nand_info = nand->priv;
+	uint8_t block_mark = 0;
+
+	/*
+	 * There are fundamental incompatibilities between the i.MX GPMI NFC and
+	 * the NAND Flash MTD model that make it essentially impossible to write
+	 * the out-of-band bytes.
+	 *
+	 * We permit *ONE* exception. If the *intent* of writing the OOB is to
+	 * mark a block bad, we can do that.
+	 */
+
+	if (!nand_info->marking_block_bad) {
+		printf("NXS NAND: Writing OOB isn't supported\n");
+		return -EIO;
+	}
+
+	/* Write the block mark. */
+	nand->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
+	nand->write_buf(mtd, &block_mark, 1);
+	nand->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+
+	/* Check if it worked. */
+	if (nand->waitfunc(mtd, nand) & NAND_STATUS_FAIL)
+		return -EIO;
+
+	return 0;
+}
+
+/*
+ * Claims all blocks are good.
+ *
+ * In principle, this function is *only* called when the NAND Flash MTD system
+ * isn't allowed to keep an in-memory bad block table, so it is forced to ask
+ * the driver for bad block information.
+ *
+ * In fact, we permit the NAND Flash MTD system to have an in-memory BBT, so
+ * this function is *only* called when we take it away.
+ *
+ * Thus, this function is only called when we want *all* blocks to look good,
+ * so it *always* return success.
+ */
+static int mxs_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
+{
+	return 0;
+}
+
+/*
+ * Nominally, the purpose of this function is to look for or create the bad
+ * block table. In fact, since the we call this function at the very end of
+ * the initialization process started by nand_scan(), and we doesn't have a
+ * more formal mechanism, we "hook" this function to continue init process.
+ *
+ * At this point, the physical NAND Flash chips have been identified and
+ * counted, so we know the physical geometry. This enables us to make some
+ * important configuration decisions.
+ *
+ * The return value of this function propogates directly back to this driver's
+ * call to nand_scan(). Anything other than zero will cause this driver to
+ * tear everything down and declare failure.
+ */
+static int mxs_nand_scan_bbt(struct mtd_info *mtd)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mx28_bch_regs *bch_regs = (struct mx28_bch_regs *)MXS_BCH_BASE;
+	uint32_t tmp;
+
+	/* Configure BCH and set NFC geometry */
+	mx28_reset_block(&bch_regs->hw_bch_ctrl_reg);
+
+	/* Configure layout 0 */
+	tmp = (mxs_nand_ecc_chunk_cnt(mtd->writesize) - 1)
+		<< BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
+	tmp |= MXS_NAND_METADATA_SIZE << BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
+	tmp |= (mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1)
+		<< BCH_FLASHLAYOUT0_ECC0_OFFSET;
+	tmp |= MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
+	writel(tmp, &bch_regs->hw_bch_flash0layout0);
+
+	tmp = (mtd->writesize + mtd->oobsize)
+		<< BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
+	tmp |= (mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1)
+		<< BCH_FLASHLAYOUT1_ECCN_OFFSET;
+	tmp |= MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
+	writel(tmp, &bch_regs->hw_bch_flash0layout1);
+
+	/* Set *all* chip selects to use layout 0 */
+	writel(0, &bch_regs->hw_bch_layoutselect);
+
+	/* Enable BCH complete interrupt */
+	writel(BCH_CTRL_COMPLETE_IRQ_EN, &bch_regs->hw_bch_ctrl_set);
+
+	/* Hook some operations at the MTD level. */
+	if (mtd->read_oob != mxs_nand_hook_read_oob) {
+		nand_info->hooked_read_oob = mtd->read_oob;
+		mtd->read_oob = mxs_nand_hook_read_oob;
+	}
+
+	if (mtd->write_oob != mxs_nand_hook_write_oob) {
+		nand_info->hooked_write_oob = mtd->write_oob;
+		mtd->write_oob = mxs_nand_hook_write_oob;
+	}
+
+	if (mtd->block_markbad != mxs_nand_hook_block_markbad) {
+		nand_info->hooked_block_markbad = mtd->block_markbad;
+		mtd->block_markbad = mxs_nand_hook_block_markbad;
+	}
+
+	/* We use the reference implementation for bad block management. */
+	return nand_default_bbt(mtd);
+}
+
+/*
+ * Allocate DMA buffers
+ */
+int mxs_nand_alloc_buffers(struct mxs_nand_info *nand_info)
+{
+	uint8_t *buf;
+	const int size = NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE;
+
+	/* DMA buffers */
+	buf = memalign(MXS_DMA_ALIGNMENT, size);
+	if (!buf) {
+		printf("MXS NAND: Error allocating DMA buffers\n");
+		return -ENOMEM;
+	}
+
+	memset(buf, 0, size);
+
+	nand_info->data_buf = buf;
+	nand_info->oob_buf = buf + NAND_MAX_PAGESIZE;
+
+	/* Command buffers */
+	nand_info->cmd_buf = memalign(MXS_DMA_ALIGNMENT,
+				MXS_NAND_COMMAND_BUFFER_SIZE);
+	if (!nand_info->cmd_buf) {
+		free(buf);
+		printf("MXS NAND: Error allocating command buffers\n");
+		return -ENOMEM;
+	}
+	memset(nand_info->cmd_buf, 0, MXS_NAND_COMMAND_BUFFER_SIZE);
+	nand_info->cmd_queue_len = 0;
+
+	return 0;
+}
+
+/*
+ * Initializes the NFC hardware.
+ */
+int mxs_nand_init(struct mxs_nand_info *info)
+{
+	struct mx28_gpmi_regs *gpmi_regs =
+		(struct mx28_gpmi_regs *)MXS_GPMI_BASE;
+	int i = 0;
+
+	info->desc = malloc(sizeof(struct mxs_dma_desc *) *
+				MXS_NAND_DMA_DESCRIPTOR_COUNT);
+	if (!info->desc)
+		goto err1;
+
+	/* Allocate the DMA descriptors. */
+	for (i = 0; i < MXS_NAND_DMA_DESCRIPTOR_COUNT; i++) {
+		info->desc[i] = mxs_dma_desc_alloc();
+		if (!info->desc[i])
+			goto err2;
+	}
+
+	/* Init the DMA controller. */
+	mxs_dma_init();
+
+	/* Reset the GPMI block. */
+	mx28_reset_block(&gpmi_regs->hw_gpmi_ctrl0_reg);
+
+	/*
+	 * Choose NAND mode, set IRQ polarity, disable write protection and
+	 * select BCH ECC.
+	 */
+	clrsetbits_le32(&gpmi_regs->hw_gpmi_ctrl1,
+			GPMI_CTRL1_GPMI_MODE,
+			GPMI_CTRL1_ATA_IRQRDY_POLARITY | GPMI_CTRL1_DEV_RESET |
+			GPMI_CTRL1_BCH_MODE);
+
+	return 0;
+
+err2:
+	free(info->desc);
+err1:
+	for (--i; i >= 0; i--)
+		mxs_dma_desc_free(info->desc[i]);
+	printf("MXS NAND: Unable to allocate DMA descriptors\n");
+	return -ENOMEM;
+}
+
+/*!
+ * This function is called during the driver binding process.
+ *
+ * @param   pdev  the device structure used to store device specific
+ *                information that is used by the suspend, resume and
+ *                remove functions
+ *
+ * @return  The function always returns 0.
+ */
+int board_nand_init(struct nand_chip *nand)
+{
+	struct mxs_nand_info *nand_info;
+	int err;
+
+	nand_info = malloc(sizeof(struct mxs_nand_info));
+	if (!nand_info) {
+		printf("MXS NAND: Failed to allocate private data\n");
+		return -ENOMEM;
+	}
+	memset(nand_info, 0, sizeof(struct mxs_nand_info));
+
+	err = mxs_nand_alloc_buffers(nand_info);
+	if (err)
+		goto err1;
+
+	err = mxs_nand_init(nand_info);
+	if (err)
+		goto err2;
+
+	memset(&fake_ecc_layout, 0, sizeof(fake_ecc_layout));
+
+	nand->priv = nand_info;
+	nand->options |= NAND_NO_SUBPAGE_WRITE;
+
+	nand->cmd_ctrl		= mxs_nand_cmd_ctrl;
+
+	nand->dev_ready		= mxs_nand_device_ready;
+	nand->select_chip	= mxs_nand_select_chip;
+	nand->block_bad		= mxs_nand_block_bad;
+	nand->scan_bbt		= mxs_nand_scan_bbt;
+
+	nand->read_byte		= mxs_nand_read_byte;
+
+	nand->read_buf		= mxs_nand_read_buf;
+	nand->write_buf		= mxs_nand_write_buf;
+
+	nand->ecc.read_page	= mxs_nand_ecc_read_page;
+	nand->ecc.write_page	= mxs_nand_ecc_write_page;
+	nand->ecc.read_oob	= mxs_nand_ecc_read_oob;
+	nand->ecc.write_oob	= mxs_nand_ecc_write_oob;
+
+	nand->ecc.layout	= &fake_ecc_layout;
+	nand->ecc.mode		= NAND_ECC_HW;
+	nand->ecc.bytes		= 9;
+	nand->ecc.size		= 512;
+
+	return 0;
+
+err2:
+	free(nand_info->data_buf);
+	free(nand_info->cmd_buf);
+err1:
+	free(nand_info);
+	return err;
+}
-- 
1.7.5.4

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

* [U-Boot] [PATCH 14/15 V2] M28: Add MMC SPL
  2011-09-12  4:06 ` [U-Boot] [PATCH 14/15] M28: Add MMC SPL Marek Vasut
@ 2011-09-30  9:40   ` Marek Vasut
  2011-10-14 12:09     ` [U-Boot] [PATCH 14/15 V3] " Marek Vasut
  0 siblings, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-09-30  9:40 UTC (permalink / raw)
  To: u-boot

This patch adds SPL code for the M28 board.

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Andy Fleming <afleming@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 board/denx/m28evk/Makefile       |    8 +
 board/denx/m28evk/m28_init.h     |   41 ++
 board/denx/m28evk/mem_init.c     |  213 +++++++++
 board/denx/m28evk/mmc_boot.c     |  273 ++++++++++++
 board/denx/m28evk/power_init.c   |  913 ++++++++++++++++++++++++++++++++++++++
 board/denx/m28evk/start.S        |  396 +++++++++++++++++
 board/denx/m28evk/u-boot-spl.lds |   87 ++++
 board/denx/m28evk/u-boot.bd      |   14 +
 include/configs/m28evk.h         |    8 +
 9 files changed, 1953 insertions(+), 0 deletions(-)
 create mode 100644 board/denx/m28evk/m28_init.h
 create mode 100644 board/denx/m28evk/mem_init.c
 create mode 100644 board/denx/m28evk/mmc_boot.c
 create mode 100644 board/denx/m28evk/power_init.c
 create mode 100644 board/denx/m28evk/start.S
 create mode 100644 board/denx/m28evk/u-boot-spl.lds
 create mode 100644 board/denx/m28evk/u-boot.bd

V2: Make waiting for powerswitch to be pressed configurable

diff --git a/board/denx/m28evk/Makefile b/board/denx/m28evk/Makefile
index 4037199..953143a 100644
--- a/board/denx/m28evk/Makefile
+++ b/board/denx/m28evk/Makefile
@@ -25,7 +25,13 @@ include $(TOPDIR)/config.mk
 
 LIB	= $(obj)lib$(BOARD).o
 
+ifndef	CONFIG_SPL_BUILD
 COBJS	:= m28evk.o
+endif
+
+ifdef	CONFIG_SPL_BUILD
+COBJS	:= mem_init.o mmc_boot.o power_init.o
+endif
 
 SRCS	:= $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS))
@@ -33,6 +39,8 @@ OBJS	:= $(addprefix $(obj),$(COBJS))
 $(LIB):	$(obj).depend $(OBJS)
 	$(call cmd_link_o_target, $(OBJS))
 
+all:	$(ALL)
+
 clean:
 	rm -f $(OBJS)
 
diff --git a/board/denx/m28evk/m28_init.h b/board/denx/m28evk/m28_init.h
new file mode 100644
index 0000000..98d3631
--- /dev/null
+++ b/board/denx/m28evk/m28_init.h
@@ -0,0 +1,41 @@
+/*
+ * Freescale i.MX28 SPL functions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef	__M28_INIT_H__
+#define	__M28_INIT_H__
+
+void early_delay(int delay);
+
+void mx28_power_init(void);
+
+#ifdef	CONFIG_SPL_MX28_PSWITCH_WAIT
+void mx28_power_wait_pswitch(void);
+#else
+static inline void mx28_power_wait_pswitch(void) { }
+#endif
+
+void mx28_mem_init(void);
+
+#endif	/* __M28_INIT_H__ */
diff --git a/board/denx/m28evk/mem_init.c b/board/denx/m28evk/mem_init.c
new file mode 100644
index 0000000..066fe0d
--- /dev/null
+++ b/board/denx/m28evk/mem_init.c
@@ -0,0 +1,213 @@
+/*
+ * Freescale i.MX28 RAM init
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/io.h>
+#include <asm/arch/iomux-mx28.h>
+#include <asm/arch/imx-regs.h>
+
+#include "m28_init.h"
+
+uint32_t dram_vals[] = {
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000100, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00010101, 0x01010101, 0x000f0f01, 0x0f02020a,
+	0x00000000, 0x00010101, 0x00000100, 0x00000100, 0x00000000,
+	0x00000002, 0x01010000, 0x05060302, 0x06005003, 0x0a0000c8,
+	0x02009c40, 0x0000030c, 0x0036a609, 0x031a0612, 0x02030202,
+	0x00c8001c, 0x00000000, 0x00000000, 0x00012100, 0xffff0303,
+	0x00012100, 0xffff0303, 0x00012100, 0xffff0303, 0x00012100,
+	0xffff0303, 0x00000003, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000612, 0x01000F02, 0x06120612, 0x00000200,
+	0x00020007, 0xf5014b27, 0xf5014b27, 0xf5014b27, 0xf5014b27,
+	0x07000300, 0x07000300, 0x07000300, 0x07000300, 0x00000006,
+	0x00000000, 0x00000000, 0x01000000, 0x01020408, 0x08040201,
+	0x000f1133, 0x00000000, 0x00001f04, 0x00001f04, 0x00001f04,
+	0x00001f04, 0x00001f04, 0x00001f04, 0x00001f04, 0x00001f04,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00010000, 0x00020304, 0x00000004,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x01010000, 0x01000000, 0x03030000, 0x00010303,
+	0x01020202, 0x00000000, 0x02040303, 0x21002103, 0x00061200,
+	0x06120612, 0x04320432, 0x04320432, 0x00040004, 0x00040004,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00010001
+};
+
+void init_m28_200mhz_ddr2(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dram_vals); i++)
+		writel(dram_vals[i], MXS_DRAM_BASE + (4 * i));
+}
+
+void mx28_mem_init_clock(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/* Gate EMI clock */
+	writel(CLKCTRL_FRAC0_CLKGATEEMI,
+		&clkctrl_regs->hw_clkctrl_frac0_set);
+
+	/* EMI = 205MHz */
+	writel(CLKCTRL_FRAC0_EMIFRAC_MASK,
+		&clkctrl_regs->hw_clkctrl_frac0_set);
+	writel((0x2a << CLKCTRL_FRAC0_EMIFRAC_OFFSET) &
+		CLKCTRL_FRAC0_EMIFRAC_MASK,
+		&clkctrl_regs->hw_clkctrl_frac0_clr);
+
+	/* Ungate EMI clock */
+	writel(CLKCTRL_FRAC0_CLKGATEEMI,
+		&clkctrl_regs->hw_clkctrl_frac0_clr);
+
+	early_delay(11000);
+
+	writel((2 << CLKCTRL_EMI_DIV_EMI_OFFSET) |
+		(1 << CLKCTRL_EMI_DIV_XTAL_OFFSET),
+		&clkctrl_regs->hw_clkctrl_emi);
+
+	/* Unbypass EMI */
+	writel(CLKCTRL_CLKSEQ_BYPASS_EMI,
+		&clkctrl_regs->hw_clkctrl_clkseq_clr);
+
+	early_delay(10000);
+}
+
+void mx28_mem_setup_cpu_and_hbus(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/* CPU = 454MHz and ungate CPU clock */
+	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_frac0,
+		CLKCTRL_FRAC0_CPUFRAC_MASK | CLKCTRL_FRAC0_CLKGATECPU,
+		19 << CLKCTRL_FRAC0_CPUFRAC_OFFSET);
+
+	/* Set CPU bypass */
+	writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
+		&clkctrl_regs->hw_clkctrl_clkseq_set);
+
+	/* HBUS = 151MHz */
+	writel(CLKCTRL_HBUS_DIV_MASK, &clkctrl_regs->hw_clkctrl_hbus_set);
+	writel(((~3) << CLKCTRL_HBUS_DIV_OFFSET) & CLKCTRL_HBUS_DIV_MASK,
+		&clkctrl_regs->hw_clkctrl_hbus_clr);
+
+	early_delay(10000);
+
+	/* CPU clock divider = 1 */
+	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_cpu,
+			CLKCTRL_CPU_DIV_CPU_MASK, 1);
+
+	/* Disable CPU bypass */
+	writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
+		&clkctrl_regs->hw_clkctrl_clkseq_clr);
+}
+
+void mx28_mem_setup_vdda(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	writel((0xc << POWER_VDDACTRL_TRG_OFFSET) |
+		(0x7 << POWER_VDDACTRL_BO_OFFSET_OFFSET) |
+		POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW,
+		&power_regs->hw_power_vddactrl);
+}
+
+void mx28_mem_setup_vddd(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	writel((0x1c << POWER_VDDDCTRL_TRG_OFFSET) |
+		(0x7 << POWER_VDDDCTRL_BO_OFFSET_OFFSET) |
+		POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW,
+		&power_regs->hw_power_vdddctrl);
+}
+
+void mx28_mem_init(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	struct mx28_pinctrl_regs *pinctrl_regs =
+		(struct mx28_pinctrl_regs *)MXS_PINCTRL_BASE;
+
+	/* Set DDR2 mode */
+	writel(PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2,
+		&pinctrl_regs->hw_pinctrl_emi_ds_ctrl_set);
+
+	/* Power up PLL0 */
+	writel(CLKCTRL_PLL0CTRL0_POWER,
+		&clkctrl_regs->hw_clkctrl_pll0ctrl0_set);
+
+	early_delay(11000);
+
+	mx28_mem_init_clock();
+
+	mx28_mem_setup_vdda();
+
+	/*
+	 * Configure the DRAM registers
+	 */
+
+	/* Clear START bit from DRAM_CTL16 */
+	clrbits_le32(MXS_DRAM_BASE + 0x40, 1);
+
+	init_m28_200mhz_ddr2();
+
+	/* Clear SREFRESH bit from DRAM_CTL17 */
+	clrbits_le32(MXS_DRAM_BASE + 0x44, 1);
+
+	/* Set START bit in DRAM_CTL16 */
+	setbits_le32(MXS_DRAM_BASE + 0x40, 1);
+
+	/* Wait for bit 20 (DRAM init complete) in DRAM_CTL58 */
+	while (!(readl(MXS_DRAM_BASE + 0xe8) & (1 << 20)))
+		;
+
+	mx28_mem_setup_vddd();
+
+	early_delay(10000);
+
+	mx28_mem_setup_cpu_and_hbus();
+}
diff --git a/board/denx/m28evk/mmc_boot.c b/board/denx/m28evk/mmc_boot.c
new file mode 100644
index 0000000..07aa65b
--- /dev/null
+++ b/board/denx/m28evk/mmc_boot.c
@@ -0,0 +1,273 @@
+/*
+ * Freescale i.MX28 Boot setup
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/io.h>
+#include <asm/arch/iomux-mx28.h>
+
+#include "m28_init.h"
+
+/*
+ * This delay function is intended to be used only in early stage of boot, where
+ * clock are not set up yet. The timer used here is reset on every boot and
+ * takes a few seconds to roll. The boot doesn't take that long, so to keep the
+ * code simple, it doesn't take rolling into consideration.
+ */
+#define	HW_DIGCTRL_MICROSECONDS	0x8001c0c0
+void early_delay(int delay)
+{
+	uint32_t st = readl(HW_DIGCTRL_MICROSECONDS);
+	st += delay;
+	while (st > readl(HW_DIGCTRL_MICROSECONDS))
+		;
+}
+
+#define	MUX_CONFIG_LED	(MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL)
+#define	MUX_CONFIG_LCD	(MXS_PAD_3V3 | MXS_PAD_4MA)
+#define	MUX_CONFIG_TSC	(MXS_PAD_3V3 | MXS_PAD_8MA | MXS_PAD_PULLUP)
+#define	MUX_CONFIG_SSP0	(MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_PULLUP)
+#define	MUX_CONFIG_SSP2	(MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_PULLUP)
+#define	MUX_CONFIG_GPMI	(MXS_PAD_1V8 | MXS_PAD_4MA | MXS_PAD_NOPULL)
+#define	MUX_CONFIG_ENET	(MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_PULLUP)
+#define	MUX_CONFIG_EMI	(MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_NOPULL)
+
+const iomux_cfg_t iomux_setup[] = {
+	/* LED */
+	MX28_PAD_ENET0_RXD3__GPIO_4_10 | MUX_CONFIG_LED,
+
+	/* framebuffer */
+	MX28_PAD_LCD_D00__LCD_D0 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D01__LCD_D1 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D02__LCD_D2 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D03__LCD_D3 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D04__LCD_D4 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D05__LCD_D5 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D06__LCD_D6 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D07__LCD_D7 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D08__LCD_D8 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D09__LCD_D9 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D10__LCD_D10 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D11__LCD_D11 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D12__LCD_D12 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D13__LCD_D13 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D14__LCD_D14 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D15__LCD_D15 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D16__LCD_D16 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D17__LCD_D17 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D18__LCD_D18 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D19__LCD_D19 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D20__LCD_D20 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D21__LCD_D21 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D22__LCD_D22 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D23__LCD_D23 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_RD_E__LCD_VSYNC | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_WR_RWN__LCD_HSYNC | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_RS__LCD_DOTCLK | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_CS__LCD_CS | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_VSYNC__LCD_VSYNC | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_HSYNC__LCD_HSYNC | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_DOTCLK__LCD_DOTCLK | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_ENABLE__GPIO_1_31 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_RESET__GPIO_3_30 | MUX_CONFIG_LCD,
+	MX28_PAD_PWM0__PWM_0 | MUX_CONFIG_LCD,
+
+	/* UART1 */
+	MX28_PAD_AUART0_CTS__DUART_RX,
+	MX28_PAD_AUART0_RTS__DUART_TX,
+	MX28_PAD_AUART0_TX__DUART_RTS,
+	MX28_PAD_AUART0_RX__DUART_CTS,
+
+	/* UART2 */
+	MX28_PAD_AUART1_RX__AUART1_RX,
+	MX28_PAD_AUART1_TX__AUART1_TX,
+	MX28_PAD_AUART1_RTS__AUART1_RTS,
+	MX28_PAD_AUART1_CTS__AUART1_CTS,
+
+	/* CAN */
+	MX28_PAD_GPMI_RDY2__CAN0_TX,
+	MX28_PAD_GPMI_RDY3__CAN0_RX,
+
+	/* I2C */
+	MX28_PAD_I2C0_SCL__I2C0_SCL,
+	MX28_PAD_I2C0_SDA__I2C0_SDA,
+
+	/* TSC2007 */
+	MX28_PAD_SAIF0_MCLK__GPIO_3_20 | MUX_CONFIG_TSC,
+
+	/* MMC0 */
+	MX28_PAD_SSP0_DATA0__SSP0_D0 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA1__SSP0_D1 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA2__SSP0_D2 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA3__SSP0_D3 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA4__SSP0_D4 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA5__SSP0_D5 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA6__SSP0_D6 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA7__SSP0_D7 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_CMD__SSP0_CMD | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT |
+		(MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_NOPULL),
+	MX28_PAD_SSP0_SCK__SSP0_SCK |
+		(MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_NOPULL),
+	MX28_PAD_PWM3__GPIO_3_28 | MUX_CONFIG_SSP0,	/* Power .. FIXME */
+	MX28_PAD_AUART2_CTS__GPIO_3_10,	/* WP ... FIXME */
+
+	/* GPMI NAND */
+	MX28_PAD_GPMI_D00__GPMI_D0 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D01__GPMI_D1 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D02__GPMI_D2 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D03__GPMI_D3 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D04__GPMI_D4 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D05__GPMI_D5 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D06__GPMI_D6 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D07__GPMI_D7 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_CE0N__GPMI_CE0N | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_RDY0__GPMI_READY0 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_RDN__GPMI_RDN |
+		(MXS_PAD_1V8 | MXS_PAD_8MA | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_WRN__GPMI_WRN | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_ALE__GPMI_ALE | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_CLE__GPMI_CLE | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_RESETN__GPMI_RESETN | MUX_CONFIG_GPMI,
+
+	/* FEC Ethernet */
+	MX28_PAD_ENET0_MDC__ENET0_MDC | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_MDIO__ENET0_MDIO | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_RX_EN__ENET0_RX_EN | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_TX_EN__ENET0_TX_EN | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_RXD0__ENET0_RXD0 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_RXD1__ENET0_RXD1 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_TXD0__ENET0_TXD0 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_TXD1__ENET0_TXD1 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET_CLK__CLKCTRL_ENET | MUX_CONFIG_ENET,
+
+	MX28_PAD_ENET0_COL__ENET1_TX_EN | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_CRS__ENET1_RX_EN | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_RXD2__ENET1_RXD0 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_RXD3__ENET1_RXD1 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_TXD2__ENET1_TXD0 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_TXD3__ENET1_TXD1 | MUX_CONFIG_ENET,
+
+	/* I2C */
+	MX28_PAD_I2C0_SCL__I2C0_SCL,
+	MX28_PAD_I2C0_SDA__I2C0_SDA,
+
+	/* EMI */
+	MX28_PAD_EMI_D00__EMI_DATA0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D01__EMI_DATA1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D02__EMI_DATA2 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D03__EMI_DATA3 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D04__EMI_DATA4 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D05__EMI_DATA5 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D06__EMI_DATA6 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D07__EMI_DATA7 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D08__EMI_DATA8 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D09__EMI_DATA9 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D10__EMI_DATA10 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D11__EMI_DATA11 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D12__EMI_DATA12 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D13__EMI_DATA13 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D14__EMI_DATA14 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D15__EMI_DATA15 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_ODT0__EMI_ODT0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DQM0__EMI_DQM0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_ODT1__EMI_ODT1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DQM1__EMI_DQM1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DDR_OPEN_FB__EMI_DDR_OPEN_FEEDBACK | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_CLK__EMI_CLK | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DQS0__EMI_DQS0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DQS1__EMI_DQS1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DDR_OPEN__EMI_DDR_OPEN | MUX_CONFIG_EMI,
+
+	MX28_PAD_EMI_A00__EMI_ADDR0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A01__EMI_ADDR1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A02__EMI_ADDR2 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A03__EMI_ADDR3 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A04__EMI_ADDR4 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A05__EMI_ADDR5 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A06__EMI_ADDR6 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A07__EMI_ADDR7 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A08__EMI_ADDR8 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A09__EMI_ADDR9 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A10__EMI_ADDR10 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A11__EMI_ADDR11 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A12__EMI_ADDR12 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A13__EMI_ADDR13 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A14__EMI_ADDR14 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_BA0__EMI_BA0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_BA1__EMI_BA1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_BA2__EMI_BA2 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_CASN__EMI_CASN | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_RASN__EMI_RASN | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_WEN__EMI_WEN | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_CE0N__EMI_CE0N | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_CE1N__EMI_CE1N | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_CKE__EMI_CKE | MUX_CONFIG_EMI,
+
+	/* SPI2 (for flash) */
+	MX28_PAD_SSP2_SCK__SSP2_SCK | MUX_CONFIG_SSP2,
+	MX28_PAD_SSP2_MOSI__SSP2_CMD | MUX_CONFIG_SSP2,
+	MX28_PAD_SSP2_MISO__SSP2_D0 | MUX_CONFIG_SSP2,
+	MX28_PAD_SSP2_SS0__SSP2_D3 |
+		(MXS_PAD_3V3 | MXS_PAD_8MA | MXS_PAD_PULLUP),
+};
+
+void board_init_ll(void)
+{
+	mxs_iomux_setup_multiple_pads(iomux_setup, ARRAY_SIZE(iomux_setup));
+	mx28_power_init();
+	mx28_mem_init();
+	mx28_power_wait_pswitch();
+}
+
+/* Support aparatus */
+inline void board_init_f(unsigned long bootflag)
+{
+	for (;;)
+		;
+}
+
+inline void board_init_r(gd_t *id, ulong dest_addr)
+{
+	for (;;)
+		;
+}
+
+inline int printf(const char *fmt, ...) {
+	return 0;
+}
+
+inline void __coloured_LED_init(void) {}
+inline void __red_LED_on(void) {}
+void coloured_LED_init(void)
+	__attribute__((weak, alias("__coloured_LED_init")));
+void red_LED_on(void)
+	__attribute__((weak, alias("__red_LED_on")));
+void hang(void) __attribute__ ((noreturn));
+void hang(void)
+{
+	for (;;)
+		;
+}
diff --git a/board/denx/m28evk/power_init.c b/board/denx/m28evk/power_init.c
new file mode 100644
index 0000000..27322b4
--- /dev/null
+++ b/board/denx/m28evk/power_init.c
@@ -0,0 +1,913 @@
+/*
+ * Freescale i.MX28 Boot PMIC init
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+
+#include "m28_init.h"
+
+void mx28_power_clock2xtal(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/* Set XTAL as CPU reference clock */
+	writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
+		&clkctrl_regs->hw_clkctrl_clkseq_set);
+}
+
+void mx28_power_clock2pll(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	writel(CLKCTRL_PLL0CTRL0_POWER,
+		&clkctrl_regs->hw_clkctrl_pll0ctrl0_set);
+	early_delay(100);
+	writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
+		&clkctrl_regs->hw_clkctrl_clkseq_clr);
+}
+
+void mx28_power_clear_auto_restart(void)
+{
+	struct mx28_rtc_regs *rtc_regs =
+		(struct mx28_rtc_regs *)MXS_RTC_BASE;
+
+	writel(RTC_CTRL_SFTRST, &rtc_regs->hw_rtc_ctrl_clr);
+	while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_SFTRST)
+		;
+
+	writel(RTC_CTRL_CLKGATE, &rtc_regs->hw_rtc_ctrl_clr);
+	while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_CLKGATE)
+		;
+
+	/*
+	 * Due to the hardware design bug of mx28 EVK-A
+	 * we need to set the AUTO_RESTART bit.
+	 */
+	if (readl(&rtc_regs->hw_rtc_persistent0) & RTC_PERSISTENT0_AUTO_RESTART)
+		return;
+
+	while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK)
+		;
+
+	setbits_le32(&rtc_regs->hw_rtc_persistent0,
+			RTC_PERSISTENT0_AUTO_RESTART);
+	writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_set);
+	writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_clr);
+	while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK)
+		;
+	while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_STALE_REGS_MASK)
+		;
+}
+
+void mx28_power_set_linreg(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/* Set linear regulator 25mV below switching converter */
+	clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+			POWER_VDDDCTRL_LINREG_OFFSET_MASK,
+			POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
+
+	clrsetbits_le32(&power_regs->hw_power_vddactrl,
+			POWER_VDDACTRL_LINREG_OFFSET_MASK,
+			POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW);
+
+	clrsetbits_le32(&power_regs->hw_power_vddioctrl,
+			POWER_VDDIOCTRL_LINREG_OFFSET_MASK,
+			POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW);
+}
+
+void mx28_power_setup_5v_detect(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/* Start 5V detection */
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+			POWER_5VCTRL_VBUSVALID_TRSH_MASK,
+			POWER_5VCTRL_VBUSVALID_TRSH_4V4 |
+			POWER_5VCTRL_PWRUP_VBUS_CMPS);
+}
+
+void mx28_src_power_init(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/* Improve efficieny and reduce transient ripple */
+	writel(POWER_LOOPCTRL_TOGGLE_DIF | POWER_LOOPCTRL_EN_CM_HYST |
+		POWER_LOOPCTRL_EN_DF_HYST, &power_regs->hw_power_loopctrl_set);
+
+	clrsetbits_le32(&power_regs->hw_power_dclimits,
+			POWER_DCLIMITS_POSLIMIT_BUCK_MASK,
+			0x30 << POWER_DCLIMITS_POSLIMIT_BUCK_OFFSET);
+
+	setbits_le32(&power_regs->hw_power_battmonitor,
+			POWER_BATTMONITOR_EN_BATADJ);
+
+	/* Increase the RCSCALE level for quick DCDC response to dynamic load */
+	clrsetbits_le32(&power_regs->hw_power_loopctrl,
+			POWER_LOOPCTRL_EN_RCSCALE_MASK,
+			POWER_LOOPCTRL_RCSCALE_THRESH |
+			POWER_LOOPCTRL_EN_RCSCALE_8X);
+
+	clrsetbits_le32(&power_regs->hw_power_minpwr,
+			POWER_MINPWR_HALFFETS, POWER_MINPWR_DOUBLE_FETS);
+
+	/* 5V to battery handoff ... FIXME */
+	setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
+	early_delay(30);
+	clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
+}
+
+void mx28_power_init_4p2_params(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/* Setup 4P2 parameters */
+	clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
+		POWER_DCDC4P2_CMPTRIP_MASK | POWER_DCDC4P2_TRG_MASK,
+		POWER_DCDC4P2_TRG_4V2 | (31 << POWER_DCDC4P2_CMPTRIP_OFFSET));
+
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+		POWER_5VCTRL_HEADROOM_ADJ_MASK,
+		0x4 << POWER_5VCTRL_HEADROOM_ADJ_OFFSET);
+
+	clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
+		POWER_DCDC4P2_DROPOUT_CTRL_MASK,
+		POWER_DCDC4P2_DROPOUT_CTRL_100MV |
+		POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL);
+
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+		POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
+		0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
+}
+
+void mx28_enable_4p2_dcdc_input(int xfer)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp, vbus_thresh, vbus_5vdetect, pwd_bo;
+	uint32_t prev_5v_brnout, prev_5v_droop;
+
+	prev_5v_brnout = readl(&power_regs->hw_power_5vctrl) &
+				POWER_5VCTRL_PWDN_5VBRNOUT;
+	prev_5v_droop = readl(&power_regs->hw_power_ctrl) &
+				POWER_CTRL_ENIRQ_VDD5V_DROOP;
+
+	clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_PWDN_5VBRNOUT);
+	writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
+		&power_regs->hw_power_reset);
+
+	clrbits_le32(&power_regs->hw_power_ctrl, POWER_CTRL_ENIRQ_VDD5V_DROOP);
+
+	if (xfer && (readl(&power_regs->hw_power_5vctrl) &
+			POWER_5VCTRL_ENABLE_DCDC)) {
+		return;
+	}
+
+	/*
+	 * Recording orignal values that will be modified temporarlily
+	 * to handle a chip bug. See chip errata for CQ ENGR00115837
+	 */
+	tmp = readl(&power_regs->hw_power_5vctrl);
+	vbus_thresh = tmp & POWER_5VCTRL_VBUSVALID_TRSH_MASK;
+	vbus_5vdetect = tmp & POWER_5VCTRL_VBUSVALID_5VDETECT;
+
+	pwd_bo = readl(&power_regs->hw_power_minpwr) & POWER_MINPWR_PWD_BO;
+
+	/*
+	 * Disable mechanisms that get erroneously tripped by when setting
+	 * the DCDC4P2 EN_DCDC
+	 */
+	clrbits_le32(&power_regs->hw_power_5vctrl,
+		POWER_5VCTRL_VBUSVALID_5VDETECT |
+		POWER_5VCTRL_VBUSVALID_TRSH_MASK);
+
+	writel(POWER_MINPWR_PWD_BO, &power_regs->hw_power_minpwr_set);
+
+	if (xfer) {
+		setbits_le32(&power_regs->hw_power_5vctrl,
+				POWER_5VCTRL_DCDC_XFER);
+		early_delay(20);
+		clrbits_le32(&power_regs->hw_power_5vctrl,
+				POWER_5VCTRL_DCDC_XFER);
+
+		setbits_le32(&power_regs->hw_power_5vctrl,
+				POWER_5VCTRL_ENABLE_DCDC);
+	} else {
+		setbits_le32(&power_regs->hw_power_dcdc4p2,
+				POWER_DCDC4P2_ENABLE_DCDC);
+	}
+
+	early_delay(25);
+
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+			POWER_5VCTRL_VBUSVALID_TRSH_MASK, vbus_thresh);
+
+	if (vbus_5vdetect)
+		writel(vbus_5vdetect, &power_regs->hw_power_5vctrl_set);
+
+	if (!pwd_bo)
+		clrbits_le32(&power_regs->hw_power_minpwr, POWER_MINPWR_PWD_BO);
+
+	while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ)
+		clrbits_le32(&power_regs->hw_power_ctrl,
+				POWER_CTRL_VBUS_VALID_IRQ);
+
+	if (prev_5v_brnout) {
+		writel(POWER_5VCTRL_PWDN_5VBRNOUT,
+			&power_regs->hw_power_5vctrl_set);
+		writel(POWER_RESET_UNLOCK_KEY,
+			&power_regs->hw_power_reset);
+	} else {
+		writel(POWER_5VCTRL_PWDN_5VBRNOUT,
+			&power_regs->hw_power_5vctrl_clr);
+		writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
+			&power_regs->hw_power_reset);
+	}
+
+	while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VDD5V_DROOP_IRQ)
+		clrbits_le32(&power_regs->hw_power_ctrl,
+				POWER_CTRL_VDD5V_DROOP_IRQ);
+
+	if (prev_5v_droop)
+		clrbits_le32(&power_regs->hw_power_ctrl,
+				POWER_CTRL_ENIRQ_VDD5V_DROOP);
+	else
+		setbits_le32(&power_regs->hw_power_ctrl,
+				POWER_CTRL_ENIRQ_VDD5V_DROOP);
+}
+
+void mx28_power_init_4p2_regulator(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp, tmp2;
+
+	setbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_ENABLE_4P2);
+
+	writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_set);
+
+	writel(POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
+		&power_regs->hw_power_5vctrl_clr);
+	clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_TRG_MASK);
+
+	/* Power up the 4p2 rail and logic/control */
+	writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+		&power_regs->hw_power_5vctrl_clr);
+
+	/*
+	 * Start charging up the 4p2 capacitor. We ramp of this charge
+	 * gradually to avoid large inrush current from the 5V cable which can
+	 * cause transients/problems
+	 */
+	mx28_enable_4p2_dcdc_input(0);
+
+	if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) {
+		/*
+		 * If we arrived here, we were unable to recover from mx23 chip
+		 * errata 5837. 4P2 is disabled and sufficient battery power is
+		 * not present. Exiting to not enable DCDC power during 5V
+		 * connected state.
+		 */
+		clrbits_le32(&power_regs->hw_power_dcdc4p2,
+			POWER_DCDC4P2_ENABLE_DCDC);
+		writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+			&power_regs->hw_power_5vctrl_set);
+		hang();
+	}
+
+	/*
+	 * Here we set the 4p2 brownout level to something very close to 4.2V.
+	 * We then check the brownout status. If the brownout status is false,
+	 * the voltage is already close to the target voltage of 4.2V so we
+	 * can go ahead and set the 4P2 current limit to our max target limit.
+	 * If the brownout status is true, we need to ramp us the current limit
+	 * so that we don't cause large inrush current issues. We step up the
+	 * current limit until the brownout status is false or until we've
+	 * reached our maximum defined 4p2 current limit.
+	 */
+	clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
+			POWER_DCDC4P2_BO_MASK,
+			22 << POWER_DCDC4P2_BO_OFFSET);	/* 4.15V */
+
+	if (!(readl(&power_regs->hw_power_sts) & POWER_STS_DCDC_4P2_BO)) {
+		setbits_le32(&power_regs->hw_power_5vctrl,
+			0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
+	} else {
+		tmp = (readl(&power_regs->hw_power_5vctrl) &
+			POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK) >>
+			POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET;
+		while (tmp < 0x3f) {
+			if (!(readl(&power_regs->hw_power_sts) &
+					POWER_STS_DCDC_4P2_BO)) {
+				tmp = readl(&power_regs->hw_power_5vctrl);
+				tmp |= POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK;
+				early_delay(100);
+				writel(tmp, &power_regs->hw_power_5vctrl);
+				break;
+			} else {
+				tmp++;
+				tmp2 = readl(&power_regs->hw_power_5vctrl);
+				tmp2 &= ~POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK;
+				tmp2 |= tmp <<
+					POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET;
+				writel(tmp2, &power_regs->hw_power_5vctrl);
+				early_delay(100);
+			}
+		}
+	}
+
+	clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_BO_MASK);
+	writel(POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+}
+
+void mx28_power_init_dcdc_4p2_source(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	if (!(readl(&power_regs->hw_power_dcdc4p2) &
+		POWER_DCDC4P2_ENABLE_DCDC)) {
+		hang();
+	}
+
+	mx28_enable_4p2_dcdc_input(1);
+
+	if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) {
+		clrbits_le32(&power_regs->hw_power_dcdc4p2,
+			POWER_DCDC4P2_ENABLE_DCDC);
+		writel(POWER_5VCTRL_ENABLE_DCDC,
+			&power_regs->hw_power_5vctrl_clr);
+		writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+			&power_regs->hw_power_5vctrl_set);
+	}
+}
+
+void mx28_power_enable_4p2(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t vdddctrl, vddactrl, vddioctrl;
+	uint32_t tmp;
+
+	vdddctrl = readl(&power_regs->hw_power_vdddctrl);
+	vddactrl = readl(&power_regs->hw_power_vddactrl);
+	vddioctrl = readl(&power_regs->hw_power_vddioctrl);
+
+	setbits_le32(&power_regs->hw_power_vdddctrl,
+		POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG |
+		POWER_VDDDCTRL_PWDN_BRNOUT);
+
+	setbits_le32(&power_regs->hw_power_vddactrl,
+		POWER_VDDACTRL_DISABLE_FET | POWER_VDDACTRL_ENABLE_LINREG |
+		POWER_VDDACTRL_PWDN_BRNOUT);
+
+	setbits_le32(&power_regs->hw_power_vddioctrl,
+		POWER_VDDIOCTRL_DISABLE_FET | POWER_VDDIOCTRL_PWDN_BRNOUT);
+
+	mx28_power_init_4p2_params();
+	mx28_power_init_4p2_regulator();
+
+	/* Shutdown battery (none present) */
+	clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_BO_MASK);
+	writel(POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+	writel(POWER_CTRL_ENIRQ_DCDC4P2_BO, &power_regs->hw_power_ctrl_clr);
+
+	mx28_power_init_dcdc_4p2_source();
+
+	writel(vdddctrl, &power_regs->hw_power_vdddctrl);
+	early_delay(20);
+	writel(vddactrl, &power_regs->hw_power_vddactrl);
+	early_delay(20);
+	writel(vddioctrl, &power_regs->hw_power_vddioctrl);
+
+	/*
+	 * Check if FET is enabled on either powerout and if so,
+	 * disable load.
+	 */
+	tmp = 0;
+	tmp |= !(readl(&power_regs->hw_power_vdddctrl) &
+			POWER_VDDDCTRL_DISABLE_FET);
+	tmp |= !(readl(&power_regs->hw_power_vddactrl) &
+			POWER_VDDACTRL_DISABLE_FET);
+	tmp |= !(readl(&power_regs->hw_power_vddioctrl) &
+			POWER_VDDIOCTRL_DISABLE_FET);
+	if (tmp)
+		writel(POWER_CHARGE_ENABLE_LOAD,
+			&power_regs->hw_power_charge_clr);
+}
+
+void mx28_boot_valid_5v(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/*
+	 * Use VBUSVALID level instead of VDD5V_GT_VDDIO level to trigger a 5V
+	 * disconnect event. FIXME
+	 */
+	writel(POWER_5VCTRL_VBUSVALID_5VDETECT,
+		&power_regs->hw_power_5vctrl_set);
+
+	/* Configure polarity to check for 5V disconnection. */
+	writel(POWER_CTRL_POLARITY_VBUSVALID |
+		POWER_CTRL_POLARITY_VDD5V_GT_VDDIO,
+		&power_regs->hw_power_ctrl_clr);
+
+	writel(POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_VDD5V_GT_VDDIO_IRQ,
+		&power_regs->hw_power_ctrl_clr);
+
+	mx28_power_enable_4p2();
+}
+
+void mx28_powerdown(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	writel(POWER_RESET_UNLOCK_KEY, &power_regs->hw_power_reset);
+	writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
+		&power_regs->hw_power_reset);
+}
+
+void mx28_handle_5v_conflict(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp;
+
+	setbits_le32(&power_regs->hw_power_vddioctrl,
+			POWER_VDDIOCTRL_BO_OFFSET_MASK);
+
+	for (;;) {
+		tmp = readl(&power_regs->hw_power_sts);
+
+		if (tmp & POWER_STS_VDDIO_BO) {
+			mx28_powerdown();
+			break;
+		}
+
+		if (tmp & POWER_STS_VDD5V_GT_VDDIO) {
+			mx28_boot_valid_5v();
+			break;
+		} else {
+			mx28_powerdown();
+			break;
+		}
+	}
+}
+
+int mx28_get_batt_volt(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t volt = readl(&power_regs->hw_power_battmonitor);
+	volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
+	volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
+	volt *= 8;
+	return volt;
+}
+
+int mx28_is_batt_ready(void)
+{
+	return (mx28_get_batt_volt() >= 3600);
+}
+
+void mx28_5v_boot(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/*
+	 * NOTE: In original IMX-Bootlets, this also checks for VBUSVALID,
+	 * but their implementation always returns 1 so we omit it here.
+	 */
+	if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+		mx28_boot_valid_5v();
+		return;
+	}
+
+	early_delay(1000);
+	if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+		mx28_boot_valid_5v();
+		return;
+	}
+
+	mx28_handle_5v_conflict();
+}
+
+void mx28_init_batt_bo(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/* Brownout at 3V */
+	clrsetbits_le32(&power_regs->hw_power_battmonitor,
+		POWER_BATTMONITOR_BRWNOUT_LVL_MASK,
+		15 << POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET);
+
+	writel(POWER_CTRL_BATT_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+	writel(POWER_CTRL_ENIRQ_BATT_BO, &power_regs->hw_power_ctrl_clr);
+}
+
+void mx28_switch_vddd_to_dcdc_source(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+		POWER_VDDDCTRL_LINREG_OFFSET_MASK,
+		POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
+
+	clrbits_le32(&power_regs->hw_power_vdddctrl,
+		POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG |
+		POWER_VDDDCTRL_DISABLE_STEPPING);
+}
+
+int mx28_is_batt_good(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t volt;
+
+	volt = readl(&power_regs->hw_power_battmonitor);
+	volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
+	volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
+	volt *= 8;
+
+	if ((volt >= 2400) && (volt <= 4300))
+		return 1;
+
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+		POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
+		0x3 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
+	writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+		&power_regs->hw_power_5vctrl_clr);
+
+	clrsetbits_le32(&power_regs->hw_power_charge,
+		POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
+		POWER_CHARGE_STOP_ILIMIT_10MA | 0x3);
+
+	writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_clr);
+	writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+		&power_regs->hw_power_5vctrl_clr);
+
+	early_delay(500000);
+
+	volt = readl(&power_regs->hw_power_battmonitor);
+	volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
+	volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
+	volt *= 8;
+
+	if (volt >= 3500)
+		return 0;
+
+	if (volt >= 2400)
+		return 1;
+
+	writel(POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
+		&power_regs->hw_power_charge_clr);
+	writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_set);
+
+	return 0;
+}
+
+void mx28_power_configure_power_source(void)
+{
+	mx28_src_power_init();
+
+	mx28_5v_boot();
+	mx28_power_clock2pll();
+
+	mx28_init_batt_bo();
+	mx28_switch_vddd_to_dcdc_source();
+}
+
+void mx28_enable_output_rail_protection(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
+		POWER_CTRL_VDDIO_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+
+	setbits_le32(&power_regs->hw_power_vdddctrl,
+			POWER_VDDDCTRL_PWDN_BRNOUT);
+
+	setbits_le32(&power_regs->hw_power_vddactrl,
+			POWER_VDDACTRL_PWDN_BRNOUT);
+
+	setbits_le32(&power_regs->hw_power_vddioctrl,
+			POWER_VDDIOCTRL_PWDN_BRNOUT);
+}
+
+int mx28_get_vddio_power_source_off(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp;
+
+	if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+		tmp = readl(&power_regs->hw_power_vddioctrl);
+		if (tmp & POWER_VDDIOCTRL_DISABLE_FET) {
+			if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
+				POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
+				return 1;
+			}
+		}
+
+		if (!(readl(&power_regs->hw_power_5vctrl) &
+			POWER_5VCTRL_ENABLE_DCDC)) {
+			if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
+				POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
+				return 1;
+			}
+		}
+	}
+
+	return 0;
+
+}
+
+int mx28_get_vddd_power_source_off(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp;
+
+	tmp = readl(&power_regs->hw_power_vdddctrl);
+	if (tmp & POWER_VDDDCTRL_DISABLE_FET) {
+		if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
+			POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
+			return 1;
+		}
+	}
+
+	if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+		if (!(readl(&power_regs->hw_power_5vctrl) &
+			POWER_5VCTRL_ENABLE_DCDC)) {
+			return 1;
+		}
+	}
+
+	if (!(tmp & POWER_VDDDCTRL_ENABLE_LINREG)) {
+		if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
+			POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW) {
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+void mx28_power_set_vddio(uint32_t new_target, uint32_t new_brownout)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t cur_target, diff, bo_int = 0;
+	uint32_t powered_by_linreg = 0;
+
+	new_brownout = new_target - new_brownout;
+
+	cur_target = readl(&power_regs->hw_power_vddioctrl);
+	cur_target &= POWER_VDDIOCTRL_TRG_MASK;
+	cur_target *= 50;	/* 50 mV step*/
+	cur_target += 2800;	/* 2800 mV lowest */
+
+	powered_by_linreg = mx28_get_vddio_power_source_off();
+	if (new_target > cur_target) {
+
+		if (powered_by_linreg) {
+			bo_int = readl(&power_regs->hw_power_vddioctrl);
+			clrbits_le32(&power_regs->hw_power_vddioctrl,
+					POWER_CTRL_ENIRQ_VDDIO_BO);
+		}
+
+		setbits_le32(&power_regs->hw_power_vddioctrl,
+				POWER_VDDIOCTRL_BO_OFFSET_MASK);
+		do {
+			if (new_target - cur_target > 100)
+				diff = cur_target + 100;
+			else
+				diff = new_target;
+
+			diff -= 2800;
+			diff /= 50;
+
+			clrsetbits_le32(&power_regs->hw_power_vddioctrl,
+				POWER_VDDIOCTRL_TRG_MASK, diff);
+
+			if (powered_by_linreg)
+				early_delay(1500);
+			else {
+				while (!(readl(&power_regs->hw_power_sts) &
+					POWER_STS_DC_OK))
+					;
+
+			}
+
+			cur_target = readl(&power_regs->hw_power_vddioctrl);
+			cur_target &= POWER_VDDIOCTRL_TRG_MASK;
+			cur_target *= 50;	/* 50 mV step*/
+			cur_target += 2800;	/* 2800 mV lowest */
+		} while (new_target > cur_target);
+
+		if (powered_by_linreg) {
+			writel(POWER_CTRL_VDDIO_BO_IRQ,
+				&power_regs->hw_power_ctrl_clr);
+			if (bo_int & POWER_CTRL_ENIRQ_VDDIO_BO)
+				setbits_le32(&power_regs->hw_power_vddioctrl,
+						POWER_CTRL_ENIRQ_VDDIO_BO);
+		}
+	} else {
+		do {
+			if (cur_target - new_target > 100)
+				diff = cur_target - 100;
+			else
+				diff = new_target;
+
+			diff -= 2800;
+			diff /= 50;
+
+			clrsetbits_le32(&power_regs->hw_power_vddioctrl,
+				POWER_VDDIOCTRL_TRG_MASK, diff);
+
+			if (powered_by_linreg)
+				early_delay(1500);
+			else {
+				while (!(readl(&power_regs->hw_power_sts) &
+					POWER_STS_DC_OK))
+					;
+
+			}
+
+			cur_target = readl(&power_regs->hw_power_vddioctrl);
+			cur_target &= POWER_VDDIOCTRL_TRG_MASK;
+			cur_target *= 50;	/* 50 mV step*/
+			cur_target += 2800;	/* 2800 mV lowest */
+		} while (new_target < cur_target);
+	}
+
+	clrsetbits_le32(&power_regs->hw_power_vddioctrl,
+			POWER_VDDDCTRL_BO_OFFSET_MASK,
+			new_brownout << POWER_VDDDCTRL_BO_OFFSET_OFFSET);
+}
+
+void mx28_power_set_vddd(uint32_t new_target, uint32_t new_brownout)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t cur_target, diff, bo_int = 0;
+	uint32_t powered_by_linreg = 0;
+
+	new_brownout = new_target - new_brownout;
+
+	cur_target = readl(&power_regs->hw_power_vdddctrl);
+	cur_target &= POWER_VDDDCTRL_TRG_MASK;
+	cur_target *= 25;	/* 25 mV step*/
+	cur_target += 800;	/* 800 mV lowest */
+
+	powered_by_linreg = mx28_get_vddd_power_source_off();
+	if (new_target > cur_target) {
+		if (powered_by_linreg) {
+			bo_int = readl(&power_regs->hw_power_vdddctrl);
+			clrbits_le32(&power_regs->hw_power_vdddctrl,
+					POWER_CTRL_ENIRQ_VDDD_BO);
+		}
+
+		setbits_le32(&power_regs->hw_power_vdddctrl,
+				POWER_VDDDCTRL_BO_OFFSET_MASK);
+
+		do {
+			if (new_target - cur_target > 100)
+				diff = cur_target + 100;
+			else
+				diff = new_target;
+
+			diff -= 800;
+			diff /= 25;
+
+			clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+				POWER_VDDDCTRL_TRG_MASK, diff);
+
+			if (powered_by_linreg)
+				early_delay(1500);
+			else {
+				while (!(readl(&power_regs->hw_power_sts) &
+					POWER_STS_DC_OK))
+					;
+
+			}
+
+			cur_target = readl(&power_regs->hw_power_vdddctrl);
+			cur_target &= POWER_VDDDCTRL_TRG_MASK;
+			cur_target *= 25;	/* 25 mV step*/
+			cur_target += 800;	/* 800 mV lowest */
+		} while (new_target > cur_target);
+
+		if (powered_by_linreg) {
+			writel(POWER_CTRL_VDDD_BO_IRQ,
+				&power_regs->hw_power_ctrl_clr);
+			if (bo_int & POWER_CTRL_ENIRQ_VDDD_BO)
+				setbits_le32(&power_regs->hw_power_vdddctrl,
+						POWER_CTRL_ENIRQ_VDDD_BO);
+		}
+	} else {
+		do {
+			if (cur_target - new_target > 100)
+				diff = cur_target - 100;
+			else
+				diff = new_target;
+
+			diff -= 800;
+			diff /= 25;
+
+			clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+					POWER_VDDDCTRL_TRG_MASK, diff);
+
+			if (powered_by_linreg)
+				early_delay(1500);
+			else {
+				while (!(readl(&power_regs->hw_power_sts) &
+					POWER_STS_DC_OK))
+					;
+
+			}
+
+			cur_target = readl(&power_regs->hw_power_vdddctrl);
+			cur_target &= POWER_VDDDCTRL_TRG_MASK;
+			cur_target *= 25;	/* 25 mV step*/
+			cur_target += 800;	/* 800 mV lowest */
+		} while (new_target < cur_target);
+	}
+
+	clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+			POWER_VDDDCTRL_BO_OFFSET_MASK,
+			new_brownout << POWER_VDDDCTRL_BO_OFFSET_OFFSET);
+}
+
+void mx28_power_init(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	mx28_power_clock2xtal();
+	mx28_power_clear_auto_restart();
+	mx28_power_set_linreg();
+	mx28_power_setup_5v_detect();
+	mx28_power_configure_power_source();
+	mx28_enable_output_rail_protection();
+
+	mx28_power_set_vddio(3300, 3150);
+
+	mx28_power_set_vddd(1350, 1200);
+
+	writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
+		POWER_CTRL_VDDIO_BO_IRQ | POWER_CTRL_VDD5V_DROOP_IRQ |
+		POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_BATT_BO_IRQ |
+		POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+
+	writel(POWER_5VCTRL_PWDN_5VBRNOUT, &power_regs->hw_power_5vctrl_set);
+
+	early_delay(1000);
+}
+
+#ifdef	CONFIG_SPL_MX28_PSWITCH_WAIT
+void mx28_power_wait_pswitch(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	while (!(readl(&power_regs->hw_power_sts) & POWER_STS_PSWITCH_MASK))
+		;
+}
+#endif
diff --git a/board/denx/m28evk/start.S b/board/denx/m28evk/start.S
new file mode 100644
index 0000000..cf67599
--- /dev/null
+++ b/board/denx/m28evk/start.S
@@ -0,0 +1,396 @@
+/*
+ *  armboot - Startup Code for ARM926EJS CPU-core
+ *
+ *  Copyright (c) 2003  Texas Instruments
+ *
+ *  ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------
+ *
+ *  Copyright (c) 2001	Marius Groger <mag@sysgo.de>
+ *  Copyright (c) 2002	Alex Zupke <azu@sysgo.de>
+ *  Copyright (c) 2002	Gary Jennejohn <garyj@denx.de>
+ *  Copyright (c) 2003	Richard Woodruff <r-woodruff2@ti.com>
+ *  Copyright (c) 2003	Kshitij <kshitij@ti.com>
+ *  Copyright (c) 2010	Albert Aribaud <albert.u.boot@aribaud.net>
+ *
+ * Change to support call back into iMX28 bootrom
+ * Copyright (c) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <common.h>
+#include <version.h>
+
+#if defined(CONFIG_OMAP1610)
+#include <./configs/omap1510.h>
+#elif defined(CONFIG_OMAP730)
+#include <./configs/omap730.h>
+#endif
+
+/*
+ *************************************************************************
+ *
+ * Jump vector table as in table 3.1 in [1]
+ *
+ *************************************************************************
+ */
+
+
+.globl _start
+_start:
+	b	reset
+#ifdef CONFIG_SPL_BUILD
+/* No exception handlers in preloader */
+	ldr	pc, _hang
+	ldr	pc, _hang
+	ldr	pc, _hang
+	ldr	pc, _hang
+	b	reset
+	ldr	pc, _hang
+	ldr	pc, _hang
+
+_hang:
+	.word	do_hang
+/* pad to 64 byte boundary */
+	.word	0x12345678
+	.word	0x12345678
+	.word	0x12345678
+	.word	0x12345678
+	.word	0x12345678
+	.word	0x12345678
+	.word	0x12345678
+#else
+	ldr	pc, _undefined_instruction
+	ldr	pc, _software_interrupt
+	ldr	pc, _prefetch_abort
+	ldr	pc, _data_abort
+	ldr	pc, _not_used
+	ldr	pc, _irq
+	ldr	pc, _fiq
+
+_undefined_instruction:
+	.word undefined_instruction
+_software_interrupt:
+	.word software_interrupt
+_prefetch_abort:
+	.word prefetch_abort
+_data_abort:
+	.word data_abort
+_not_used:
+	.word not_used
+_irq:
+	.word irq
+_fiq:
+	.word fiq
+
+#endif	/* CONFIG_SPL_BUILD */
+	.balignl 16,0xdeadbeef
+
+
+/*
+ *************************************************************************
+ *
+ * Startup Code (reset vector)
+ *
+ * do important init only if we don't start from memory!
+ * setup Memory and board specific bits prior to relocation.
+ * relocate armboot to ram
+ * setup stack
+ *
+ *************************************************************************
+ */
+
+.globl _TEXT_BASE
+_TEXT_BASE:
+	.word	CONFIG_SYS_TEXT_BASE
+
+/*
+ * These are defined in the board-specific linker script.
+ * Subtracting _start from them lets the linker put their
+ * relative position in the executable instead of leaving
+ * them null.
+ */
+.globl _bss_start_ofs
+_bss_start_ofs:
+	.word __bss_start - _start
+
+.globl _bss_end_ofs
+_bss_end_ofs:
+	.word __bss_end__ - _start
+
+.globl _end_ofs
+_end_ofs:
+	.word _end - _start
+
+#ifdef CONFIG_USE_IRQ
+/* IRQ stack memory (calculated at run-time) */
+.globl IRQ_STACK_START
+IRQ_STACK_START:
+	.word	0x0badc0de
+
+/* IRQ stack memory (calculated at run-time) */
+.globl FIQ_STACK_START
+FIQ_STACK_START:
+	.word 0x0badc0de
+#endif
+
+/* IRQ stack memory (calculated at run-time) + 8 bytes */
+.globl IRQ_STACK_START_IN
+IRQ_STACK_START_IN:
+	.word	0x0badc0de
+
+/*
+ * the actual reset code
+ */
+
+reset:
+	/*
+	 * Store all registers on old stack pointer, this will allow us later to
+	 * return to the BootROM and let the BootROM load U-Boot into RAM.
+	 */
+	push	{r0-r12,r14}
+
+	/*
+	 * set the cpu to SVC32 mode
+	 */
+	mrs	r0,cpsr
+	bic	r0,r0,#0x1f
+	orr	r0,r0,#0xd3
+	msr	cpsr,r0
+
+	/*
+	 * we do sys-critical inits only at reboot,
+	 * not when booting from ram!
+	 */
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+	bl	cpu_init_crit
+#endif
+
+	bl	board_init_ll
+
+	pop	{r0-r12,r14}
+	bx	lr
+
+/*
+ *************************************************************************
+ *
+ * CPU_init_critical registers
+ *
+ * setup important registers
+ * setup memory timing
+ *
+ *************************************************************************
+ */
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+cpu_init_crit:
+	/*
+	 * flush v4 I/D caches
+	 */
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c7, 0	/* flush v3/v4 cache */
+	mcr	p15, 0, r0, c8, c7, 0	/* flush v4 TLB */
+
+	/*
+	 * disable MMU stuff and caches
+	 */
+	mrc	p15, 0, r0, c1, c0, 0
+	bic	r0, r0, #0x00002300	/* clear bits 13, 9:8 (--V- --RS) */
+	bic	r0, r0, #0x00000087	/* clear bits 7, 2:0 (B--- -CAM) */
+	orr	r0, r0, #0x00000002	/* set bit 2 (A) Align */
+	orr	r0, r0, #0x00001000	/* set bit 12 (I) I-Cache */
+	mcr	p15, 0, r0, c1, c0, 0
+
+	mov	pc, lr		/* back to my caller */
+#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
+
+#ifndef CONFIG_SPL_BUILD
+/*
+ *************************************************************************
+ *
+ * Interrupt handling
+ *
+ *************************************************************************
+ */
+
+@
+@ IRQ stack frame.
+@
+#define S_FRAME_SIZE	72
+
+#define S_OLD_R0	68
+#define S_PSR		64
+#define S_PC		60
+#define S_LR		56
+#define S_SP		52
+
+#define S_IP		48
+#define S_FP		44
+#define S_R10		40
+#define S_R9		36
+#define S_R8		32
+#define S_R7		28
+#define S_R6		24
+#define S_R5		20
+#define S_R4		16
+#define S_R3		12
+#define S_R2		8
+#define S_R1		4
+#define S_R0		0
+
+#define MODE_SVC 0x13
+#define I_BIT	 0x80
+
+/*
+ * use bad_save_user_regs for abort/prefetch/undef/swi ...
+ * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
+ */
+
+	.macro	bad_save_user_regs
+	@ carve out a frame on current user stack
+	sub	sp, sp, #S_FRAME_SIZE
+	stmia	sp, {r0 - r12}	@ Save user registers (now in svc mode) r0-r12
+	ldr	r2, IRQ_STACK_START_IN
+	@ get values for "aborted" pc and cpsr (into parm regs)
+	ldmia	r2, {r2 - r3}
+	add	r0, sp, #S_FRAME_SIZE		@ grab pointer to old stack
+	add	r5, sp, #S_SP
+	mov	r1, lr
+	stmia	r5, {r0 - r3}	@ save sp_SVC, lr_SVC, pc, cpsr
+	mov	r0, sp		@ save current stack into r0 (param register)
+	.endm
+
+	.macro	irq_save_user_regs
+	sub	sp, sp, #S_FRAME_SIZE
+	stmia	sp, {r0 - r12}			@ Calling r0-r12
+	@ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
+	add	r8, sp, #S_PC
+	stmdb	r8, {sp, lr}^		@ Calling SP, LR
+	str	lr, [r8, #0]		@ Save calling PC
+	mrs	r6, spsr
+	str	r6, [r8, #4]		@ Save CPSR
+	str	r0, [r8, #8]		@ Save OLD_R0
+	mov	r0, sp
+	.endm
+
+	.macro	irq_restore_user_regs
+	ldmia	sp, {r0 - lr}^			@ Calling r0 - lr
+	mov	r0, r0
+	ldr	lr, [sp, #S_PC]			@ Get PC
+	add	sp, sp, #S_FRAME_SIZE
+	subs	pc, lr, #4		@ return & move spsr_svc into cpsr
+	.endm
+
+	.macro get_bad_stack
+	ldr	r13, IRQ_STACK_START_IN		@ setup our mode stack
+
+	str	lr, [r13]	@ save caller lr in position 0 of saved stack
+	mrs	lr, spsr	@ get the spsr
+	str	lr, [r13, #4]	@ save spsr in position 1 of saved stack
+	mov	r13, #MODE_SVC	@ prepare SVC-Mode
+	@ msr	spsr_c, r13
+	msr	spsr, r13	@ switch modes, make sure moves will execute
+	mov	lr, pc		@ capture return pc
+	movs	pc, lr		@ jump to next instruction & switch modes.
+	.endm
+
+	.macro get_irq_stack			@ setup IRQ stack
+	ldr	sp, IRQ_STACK_START
+	.endm
+
+	.macro get_fiq_stack			@ setup FIQ stack
+	ldr	sp, FIQ_STACK_START
+	.endm
+#endif	/* CONFIG_SPL_BUILD */
+
+/*
+ * exception handlers
+ */
+#ifdef CONFIG_SPL_BUILD
+	.align	5
+do_hang:
+	ldr	sp, _TEXT_BASE			/* switch to abort stack */
+1:
+	bl	1b				/* hang and never return */
+#else	/* !CONFIG_SPL_BUILD */
+	.align  5
+undefined_instruction:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_undefined_instruction
+
+	.align	5
+software_interrupt:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_software_interrupt
+
+	.align	5
+prefetch_abort:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_prefetch_abort
+
+	.align	5
+data_abort:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_data_abort
+
+	.align	5
+not_used:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_not_used
+
+#ifdef CONFIG_USE_IRQ
+
+	.align	5
+irq:
+	get_irq_stack
+	irq_save_user_regs
+	bl	do_irq
+	irq_restore_user_regs
+
+	.align	5
+fiq:
+	get_fiq_stack
+	/* someone ought to write a more effiction fiq_save_user_regs */
+	irq_save_user_regs
+	bl	do_fiq
+	irq_restore_user_regs
+
+#else
+
+	.align	5
+irq:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_irq
+
+	.align	5
+fiq:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_fiq
+
+#endif
+#endif	/* CONFIG_SPL_BUILD */
diff --git a/board/denx/m28evk/u-boot-spl.lds b/board/denx/m28evk/u-boot-spl.lds
new file mode 100644
index 0000000..e296a92
--- /dev/null
+++ b/board/denx/m28evk/u-boot-spl.lds
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * January 2004 - Changed to support H4 device
+ * Copyright (c) 2004-2008 Texas Instruments
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+	. = 0x00000000;
+
+	. = ALIGN(4);
+	.text	:
+	{
+		board/denx/m28evk/start.o	(.text)
+		*(.text)
+	}
+
+	. = ALIGN(4);
+	.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
+
+	. = ALIGN(4);
+	.data : {
+		*(.data)
+	}
+
+	. = ALIGN(4);
+	__u_boot_cmd_start = .;
+	.u_boot_cmd : { *(.u_boot_cmd) }
+	__u_boot_cmd_end = .;
+
+	. = ALIGN(4);
+
+	.rel.dyn : {
+		__rel_dyn_start = .;
+		*(.rel*)
+		__rel_dyn_end = .;
+	}
+
+	.dynsym : {
+		__dynsym_start = .;
+		*(.dynsym)
+	}
+
+	_end = .;
+
+	.bss __rel_dyn_start (OVERLAY) : {
+		__bss_start = .;
+		*(.bss)
+		 . = ALIGN(4);
+		__bss_end__ = .;
+	}
+
+	/DISCARD/ : { *(.bss*) }
+	/DISCARD/ : { *(.dynstr*) }
+	/DISCARD/ : { *(.dynsym*) }
+	/DISCARD/ : { *(.dynamic*) }
+	/DISCARD/ : { *(.hash*) }
+	/DISCARD/ : { *(.plt*) }
+	/DISCARD/ : { *(.interp*) }
+	/DISCARD/ : { *(.gnu*) }
+}
diff --git a/board/denx/m28evk/u-boot.bd b/board/denx/m28evk/u-boot.bd
new file mode 100644
index 0000000..3ce7f92
--- /dev/null
+++ b/board/denx/m28evk/u-boot.bd
@@ -0,0 +1,14 @@
+sources {
+	u_boot_spl="spl/u-boot-spl.bin";
+	u_boot="u-boot.bin";
+}
+
+section (0) {
+        load u_boot_spl > 0x0000;
+        load ivt (entry = 0x0014) > 0x8000;
+	hab call 0x8000;
+
+        load u_boot > 0x40000100;
+        load ivt (entry = 0x40000100) > 0x8000;
+	hab call 0x8000;
+}
diff --git a/include/configs/m28evk.h b/include/configs/m28evk.h
index 44a09a0..89d2938 100644
--- a/include/configs/m28evk.h
+++ b/include/configs/m28evk.h
@@ -43,6 +43,14 @@
 #define	CONFIG_ARCH_CPU_INIT
 
 /*
+ * SPL
+ */
+#define	CONFIG_SPL
+#define	CONFIG_SPL_NO_CPU_SUPPORT_CODE
+#define	CONFIG_SPL_START_S_PATH		"board/denx/m28evk"
+#define	CONFIG_SPL_LDSCRIPT		"board/denx/m28evk/u-boot-spl.lds"
+
+/*
  * U-Boot Commands
  */
 #include <config_cmd_default.h>
-- 
1.7.5.4

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

* [U-Boot] [PATCH 01/15 V3] iMX28: Initial support for iMX28 CPU
  2011-09-27 13:45   ` [U-Boot] [PATCH 01/15 V2] " Marek Vasut
@ 2011-09-30  9:42     ` Marek Vasut
  2011-10-13 16:19       ` Stefano Babic
                         ` (2 more replies)
  0 siblings, 3 replies; 116+ messages in thread
From: Marek Vasut @ 2011-09-30  9:42 UTC (permalink / raw)
  To: u-boot

This patch supports:
- Timers
- Debug UART
- Clock

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 arch/arm/cpu/arm926ejs/mx28/Makefile          |   46 +
 arch/arm/cpu/arm926ejs/mx28/clock.c           |  355 +++++++
 arch/arm/cpu/arm926ejs/mx28/mx28.c            |  194 ++++
 arch/arm/cpu/arm926ejs/mx28/timer.c           |  141 +++
 arch/arm/include/asm/arch-mx28/clock.h        |   61 ++
 arch/arm/include/asm/arch-mx28/imx-regs.h     |   38 +
 arch/arm/include/asm/arch-mx28/regs-base.h    |   88 ++
 arch/arm/include/asm/arch-mx28/regs-bch.h     |  230 +++++
 arch/arm/include/asm/arch-mx28/regs-clkctrl.h |  312 ++++++
 arch/arm/include/asm/arch-mx28/regs-common.h  |   66 ++
 arch/arm/include/asm/arch-mx28/regs-gpmi.h    |  222 +++++
 arch/arm/include/asm/arch-mx28/regs-i2c.h     |  207 ++++
 arch/arm/include/asm/arch-mx28/regs-ocotp.h   |  173 ++++
 arch/arm/include/asm/arch-mx28/regs-pinctrl.h | 1284 +++++++++++++++++++++++++
 arch/arm/include/asm/arch-mx28/regs-power.h   |  413 ++++++++
 arch/arm/include/asm/arch-mx28/regs-rtc.h     |  147 +++
 arch/arm/include/asm/arch-mx28/regs-ssp.h     |  349 +++++++
 arch/arm/include/asm/arch-mx28/regs-timrot.h  |  171 ++++
 arch/arm/include/asm/arch-mx28/sys_proto.h    |   30 +
 19 files changed, 4527 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/Makefile
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/clock.c
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/mx28.c
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/timer.c
 create mode 100644 arch/arm/include/asm/arch-mx28/clock.h
 create mode 100644 arch/arm/include/asm/arch-mx28/imx-regs.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-base.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-bch.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-clkctrl.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-common.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-gpmi.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-i2c.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-ocotp.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-pinctrl.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-power.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-rtc.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-ssp.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-timrot.h
 create mode 100644 arch/arm/include/asm/arch-mx28/sys_proto.h

V2: Use watchdog for reset
V3: Remove redundant power_regs from cpu_reset() (gcc4.6)

diff --git a/arch/arm/cpu/arm926ejs/mx28/Makefile b/arch/arm/cpu/arm926ejs/mx28/Makefile
new file mode 100644
index 0000000..98504f9
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/Makefile
@@ -0,0 +1,46 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(SOC).o
+
+COBJS	= clock.o mx28.o timer.o
+
+SRCS	:= $(START:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+START	:= $(addprefix $(obj),$(START))
+
+all:	$(obj).depend $(LIB)
+
+$(LIB):	$(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/arm/cpu/arm926ejs/mx28/clock.c b/arch/arm/cpu/arm926ejs/mx28/clock.c
new file mode 100644
index 0000000..f698506
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/clock.c
@@ -0,0 +1,355 @@
+/*
+ * Freescale i.MX28 clock setup code
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+
+/* The PLL frequency is always 480MHz, see section 10.2 in iMX28 datasheet. */
+#define	PLL_FREQ_KHZ	480000
+#define	PLL_FREQ_COEF	18
+/* The XTAL frequency is always 24MHz, see section 10.2 in iMX28 datasheet. */
+#define	XTAL_FREQ_KHZ	24000
+
+#define	PLL_FREQ_MHZ	(PLL_FREQ_KHZ / 1000)
+#define	XTAL_FREQ_MHZ	(XTAL_FREQ_KHZ / 1000)
+
+static uint32_t mx28_get_pclk(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	uint32_t clkctrl, clkseq, clkfrac;
+	uint32_t frac, div;
+
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_cpu);
+
+	/* No support of fractional divider calculation */
+	if (clkctrl &
+		(CLKCTRL_CPU_DIV_XTAL_FRAC_EN | CLKCTRL_CPU_DIV_CPU_FRAC_EN)) {
+		return 0;
+	}
+
+	clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+
+	/* XTAL Path */
+	if (clkseq & CLKCTRL_CLKSEQ_BYPASS_CPU) {
+		div = (clkctrl & CLKCTRL_CPU_DIV_XTAL_MASK) >>
+			CLKCTRL_CPU_DIV_XTAL_OFFSET;
+		return XTAL_FREQ_MHZ / div;
+	}
+
+	/* REF Path */
+	clkfrac = readl(&clkctrl_regs->hw_clkctrl_frac0);
+	frac = clkfrac & CLKCTRL_FRAC0_CPUFRAC_MASK;
+	div = clkctrl & CLKCTRL_CPU_DIV_CPU_MASK;
+	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
+}
+
+static uint32_t mx28_get_hclk(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	uint32_t div;
+	uint32_t clkctrl;
+
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_hbus);
+
+	/* No support of fractional divider calculation */
+	if (clkctrl & CLKCTRL_HBUS_DIV_FRAC_EN)
+		return 0;
+
+	div = clkctrl & CLKCTRL_HBUS_DIV_MASK;
+	return mx28_get_pclk() / div;
+}
+
+static uint32_t mx28_get_emiclk(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	uint32_t frac, div;
+	uint32_t clkctrl, clkseq, clkfrac;
+
+	clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_emi);
+
+	/* XTAL Path */
+	if (clkseq & CLKCTRL_CLKSEQ_BYPASS_EMI) {
+		div = (clkctrl & CLKCTRL_EMI_DIV_XTAL_MASK) >>
+			CLKCTRL_EMI_DIV_XTAL_OFFSET;
+		return XTAL_FREQ_MHZ / div;
+	}
+
+	clkfrac = readl(&clkctrl_regs->hw_clkctrl_frac0);
+
+	/* REF Path */
+	frac = (clkfrac & CLKCTRL_FRAC0_EMIFRAC_MASK) >>
+		CLKCTRL_FRAC0_EMIFRAC_OFFSET;
+	div = clkctrl & CLKCTRL_EMI_DIV_EMI_MASK;
+	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
+}
+
+static uint32_t mx28_get_gpmiclk(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	uint32_t frac, div;
+	uint32_t clkctrl, clkseq, clkfrac;
+
+	clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_gpmi);
+
+	/* XTAL Path */
+	if (clkseq & CLKCTRL_CLKSEQ_BYPASS_GPMI) {
+		div = clkctrl & CLKCTRL_GPMI_DIV_MASK;
+		return XTAL_FREQ_MHZ / div;
+	}
+
+	clkfrac = readl(&clkctrl_regs->hw_clkctrl_frac1);
+
+	/* REF Path */
+	frac = (clkfrac & CLKCTRL_FRAC1_GPMIFRAC_MASK) >>
+		CLKCTRL_FRAC1_GPMIFRAC_OFFSET;
+	div = clkctrl & CLKCTRL_GPMI_DIV_MASK;
+	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
+}
+
+/*
+ * Set IO clock frequency, in kHz
+ */
+void mx28_set_ioclk(enum mxs_ioclock io, uint32_t freq)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t div;
+
+	if (freq == 0)
+		return;
+
+	if (io > MXC_IOCLK1)
+		return;
+
+	div = (PLL_FREQ_KHZ * PLL_FREQ_COEF) / freq;
+
+	if (div < 18)
+		div = 18;
+
+	if (div > 35)
+		div = 35;
+
+	if (io == MXC_IOCLK0) {
+		writel(CLKCTRL_FRAC0_CLKGATEIO0,
+			&clkctrl_regs->hw_clkctrl_frac0_set);
+		clrsetbits_le32(&clkctrl_regs->hw_clkctrl_frac0,
+				CLKCTRL_FRAC0_IO0FRAC_MASK,
+				div << CLKCTRL_FRAC0_IO0FRAC_OFFSET);
+		writel(CLKCTRL_FRAC0_CLKGATEIO0,
+			&clkctrl_regs->hw_clkctrl_frac0_clr);
+	} else {
+		writel(CLKCTRL_FRAC0_CLKGATEIO1,
+			&clkctrl_regs->hw_clkctrl_frac0_set);
+		clrsetbits_le32(&clkctrl_regs->hw_clkctrl_frac0,
+				CLKCTRL_FRAC0_IO1FRAC_MASK,
+				div << CLKCTRL_FRAC0_IO1FRAC_OFFSET);
+		writel(CLKCTRL_FRAC0_CLKGATEIO1,
+			&clkctrl_regs->hw_clkctrl_frac0_clr);
+	}
+}
+
+/*
+ * Get IO clock, returns IO clock in kHz
+ */
+static uint32_t mx28_get_ioclk(enum mxs_ioclock io)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t tmp, ret;
+
+	if (io > MXC_IOCLK1)
+		return 0;
+
+	tmp = readl(&clkctrl_regs->hw_clkctrl_frac0);
+
+	if (io == MXC_IOCLK0)
+		ret = (tmp & CLKCTRL_FRAC0_IO0FRAC_MASK) >>
+			CLKCTRL_FRAC0_IO0FRAC_OFFSET;
+	else
+		ret = (tmp & CLKCTRL_FRAC0_IO1FRAC_MASK) >>
+			CLKCTRL_FRAC0_IO1FRAC_OFFSET;
+
+	return (PLL_FREQ_KHZ * PLL_FREQ_COEF) / ret;
+}
+
+/*
+ * Configure SSP clock frequency, in kHz
+ */
+void mx28_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t clk, clkreg;
+
+	if (ssp > MXC_SSPCLK3)
+		return;
+
+	clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) +
+			(ssp * sizeof(struct mx28_register));
+
+	clrbits_le32(clkreg, CLKCTRL_SSP_CLKGATE);
+	while (readl(clkreg) & CLKCTRL_SSP_CLKGATE)
+		;
+
+	if (xtal)
+		clk = XTAL_FREQ_KHZ;
+	else
+		clk = mx28_get_ioclk(ssp >> 1);
+
+	if (freq > clk)
+		return;
+
+	/* Calculate the divider and cap it if necessary */
+	clk /= freq;
+	if (clk > CLKCTRL_SSP_DIV_MASK)
+		clk = CLKCTRL_SSP_DIV_MASK;
+
+	clrsetbits_le32(clkreg, CLKCTRL_SSP_DIV_MASK, clk);
+	while (readl(clkreg) & CLKCTRL_SSP_BUSY)
+		;
+
+	if (xtal)
+		writel(CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp,
+			&clkctrl_regs->hw_clkctrl_clkseq_set);
+	else
+		writel(CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp,
+			&clkctrl_regs->hw_clkctrl_clkseq_clr);
+}
+
+/*
+ * Return SSP frequency, in kHz
+ */
+static uint32_t mx28_get_sspclk(enum mxs_sspclock ssp)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t clkreg;
+	uint32_t clk, tmp;
+
+	if (ssp > MXC_SSPCLK3)
+		return 0;
+
+	tmp = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+	if (tmp & (CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp))
+		return XTAL_FREQ_KHZ;
+
+	clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) +
+			(ssp * sizeof(struct mx28_register));
+
+	tmp = readl(clkreg) & CLKCTRL_SSP_DIV_MASK;
+
+	if (tmp == 0)
+		return 0;
+
+	clk = mx28_get_ioclk(ssp >> 1);
+
+	return clk / tmp;
+}
+
+/*
+ * Set SSP/MMC bus frequency, in kHz)
+ */
+void mx28_set_ssp_busclock(unsigned int bus, uint32_t freq)
+{
+	struct mx28_ssp_regs *ssp_regs;
+	const uint32_t sspclk = mx28_get_sspclk(bus);
+	uint32_t reg;
+	uint32_t divide, rate, tgtclk;
+
+	ssp_regs = (struct mx28_ssp_regs *)(MXS_SSP0_BASE + (bus * 0x2000));
+
+	/*
+	 * SSP bit rate = SSPCLK / (CLOCK_DIVIDE * (1 + CLOCK_RATE)),
+	 * CLOCK_DIVIDE has to be an even value from 2 to 254, and
+	 * CLOCK_RATE could be any integer from 0 to 255.
+	 */
+	for (divide = 2; divide < 254; divide += 2) {
+		rate = sspclk / freq / divide;
+		if (rate <= 256)
+			break;
+	}
+
+	tgtclk = sspclk / divide / rate;
+	while (tgtclk > freq) {
+		rate++;
+		tgtclk = sspclk / divide / rate;
+	}
+	if (rate > 256)
+		rate = 256;
+
+	/* Always set timeout the maximum */
+	reg = SSP_TIMING_TIMEOUT_MASK |
+		(divide << SSP_TIMING_CLOCK_DIVIDE_OFFSET) |
+		((rate - 1) << SSP_TIMING_CLOCK_RATE_OFFSET);
+	writel(reg, &ssp_regs->hw_ssp_timing);
+
+	debug("SPI%d: Set freq rate to %d KHz (requested %d KHz)\n",
+		bus, tgtclk, freq);
+}
+
+uint32_t mxc_get_clock(enum mxc_clock clk)
+{
+	switch (clk) {
+	case MXC_ARM_CLK:
+		return mx28_get_pclk() * 1000000;
+	case MXC_GPMI_CLK:
+		return mx28_get_gpmiclk() * 1000000;
+	case MXC_AHB_CLK:
+	case MXC_IPG_CLK:
+		return mx28_get_hclk() * 1000000;
+	case MXC_EMI_CLK:
+		return mx28_get_emiclk();
+	case MXC_IO0_CLK:
+		return mx28_get_ioclk(MXC_IOCLK0);
+	case MXC_IO1_CLK:
+		return mx28_get_ioclk(MXC_IOCLK1);
+	case MXC_SSP0_CLK:
+		return mx28_get_sspclk(MXC_SSPCLK0);
+	case MXC_SSP1_CLK:
+		return mx28_get_sspclk(MXC_SSPCLK1);
+	case MXC_SSP2_CLK:
+		return mx28_get_sspclk(MXC_SSPCLK2);
+	case MXC_SSP3_CLK:
+		return mx28_get_sspclk(MXC_SSPCLK3);
+	}
+
+	return 0;
+}
diff --git a/arch/arm/cpu/arm926ejs/mx28/mx28.c b/arch/arm/cpu/arm926ejs/mx28/mx28.c
new file mode 100644
index 0000000..c882cbc
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/mx28.c
@@ -0,0 +1,194 @@
+/*
+ * Freescale i.MX28 common code
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/iomux-mx28.h>
+
+/* 1 second delay should be plenty of time for block reset. */
+#define	RESET_MAX_TIMEOUT	1000000
+
+#define	MX28_BLOCK_SFTRST	(1 << 31)
+#define	MX28_BLOCK_CLKGATE	(1 << 30)
+
+/* Lowlevel init isn't used on i.MX28, so just have a dummy here */
+inline void lowlevel_init(void) {}
+
+void reset_cpu(ulong ignored) __attribute__((noreturn));
+
+void reset_cpu(ulong ignored)
+{
+
+	struct mx28_rtc_regs *rtc_regs =
+		(struct mx28_rtc_regs *)MXS_RTC_BASE;
+
+	/* Wait 1 uS before doing the actual watchdog reset */
+	writel(1, &rtc_regs->hw_rtc_watchdog);
+	writel(RTC_CTRL_WATCHDOGEN, &rtc_regs->hw_rtc_ctrl_set);
+
+	/* Endless loop, reset will exit from here */
+	for (;;)
+		;
+}
+
+int mx28_wait_mask_set(struct mx28_register *reg, uint32_t mask, int timeout)
+{
+	while (--timeout) {
+		if ((readl(&reg->reg) & mask) == mask)
+			break;
+		udelay(1);
+	}
+
+	return !timeout;
+}
+
+int mx28_wait_mask_clr(struct mx28_register *reg, uint32_t mask, int timeout)
+{
+	while (--timeout) {
+		if ((readl(&reg->reg) & mask) == 0)
+			break;
+		udelay(1);
+	}
+
+	return !timeout;
+}
+
+int mx28_reset_block(struct mx28_register *reg)
+{
+	/* Clear SFTRST */
+	writel(MX28_BLOCK_SFTRST, &reg->reg_clr);
+
+	if (mx28_wait_mask_clr(reg, MX28_BLOCK_SFTRST, RESET_MAX_TIMEOUT))
+		return 1;
+
+	/* Clear CLKGATE */
+	writel(MX28_BLOCK_CLKGATE, &reg->reg_clr);
+
+	/* Set SFTRST */
+	writel(MX28_BLOCK_SFTRST, &reg->reg_set);
+
+	/* Wait for CLKGATE being set */
+	if (mx28_wait_mask_set(reg, MX28_BLOCK_CLKGATE, RESET_MAX_TIMEOUT))
+		return 1;
+
+	/* Clear SFTRST */
+	writel(MX28_BLOCK_SFTRST, &reg->reg_clr);
+
+	if (mx28_wait_mask_clr(reg, MX28_BLOCK_SFTRST, RESET_MAX_TIMEOUT))
+		return 1;
+
+	/* Clear CLKGATE */
+	writel(MX28_BLOCK_CLKGATE, &reg->reg_clr);
+
+	if (mx28_wait_mask_clr(reg, MX28_BLOCK_CLKGATE, RESET_MAX_TIMEOUT))
+		return 1;
+
+	return 0;
+}
+
+#ifdef	CONFIG_ARCH_CPU_INIT
+int arch_cpu_init(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/*
+	 * Enable NAND clock
+	 */
+	/* Clear bypass bit */
+	writel(CLKCTRL_CLKSEQ_BYPASS_GPMI,
+		&clkctrl_regs->hw_clkctrl_clkseq_set);
+
+	/* Set GPMI clock to ref_gpmi / 12 */
+	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_gpmi,
+		CLKCTRL_GPMI_CLKGATE | CLKCTRL_GPMI_DIV_MASK, 1);
+
+	udelay(1000);
+
+	return 0;
+}
+#endif
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+int print_cpuinfo(void)
+{
+	printf("Freescale i.MX28 family\n");
+	return 0;
+}
+#endif
+
+int do_mx28_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	printf("CPU:   %3d MHz\n", mxc_get_clock(MXC_ARM_CLK) / 1000000);
+	printf("BUS:   %3d MHz\n", mxc_get_clock(MXC_AHB_CLK) / 1000000);
+	printf("EMI:   %3d MHz\n", mxc_get_clock(MXC_EMI_CLK));
+	printf("GPMI:  %3d MHz\n", mxc_get_clock(MXC_GPMI_CLK) / 1000000);
+	return 0;
+}
+
+/*
+ * Initializes on-chip ethernet controllers.
+ */
+#ifdef	CONFIG_CMD_NET
+int cpu_eth_init(bd_t *bis)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/* Turn on ENET clocks */
+	clrbits_le32(&clkctrl_regs->hw_clkctrl_enet,
+		CLKCTRL_ENET_SLEEP | CLKCTRL_ENET_DISABLE);
+
+	/* Set up ENET PLL for 50 MHz */
+	/* Power on ENET PLL */
+	writel(CLKCTRL_PLL2CTRL0_POWER,
+		&clkctrl_regs->hw_clkctrl_pll2ctrl0_set);
+
+	udelay(10);
+
+	/* Gate on ENET PLL */
+	writel(CLKCTRL_PLL2CTRL0_CLKGATE,
+		&clkctrl_regs->hw_clkctrl_pll2ctrl0_clr);
+
+	/* Enable pad output */
+	setbits_le32(&clkctrl_regs->hw_clkctrl_enet, CLKCTRL_ENET_CLK_OUT_EN);
+
+	return 0;
+}
+#endif
+
+U_BOOT_CMD(
+	clocks,	CONFIG_SYS_MAXARGS, 1, do_mx28_showclocks,
+	"display clocks",
+	""
+);
diff --git a/arch/arm/cpu/arm926ejs/mx28/timer.c b/arch/arm/cpu/arm926ejs/mx28/timer.c
new file mode 100644
index 0000000..dbc904d
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/timer.c
@@ -0,0 +1,141 @@
+/*
+ * Freescale i.MX28 timer driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * (C) Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+
+/* Maximum fixed count */
+#define TIMER_LOAD_VAL	0xffffffff
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define timestamp (gd->tbl)
+#define lastdec (gd->lastinc)
+
+/*
+ * This driver uses 1kHz clock source.
+ */
+#define	MX28_INCREMENTER_HZ		1000
+
+static inline unsigned long tick_to_time(unsigned long tick)
+{
+	return tick / (MX28_INCREMENTER_HZ / CONFIG_SYS_HZ);
+}
+
+static inline unsigned long time_to_tick(unsigned long time)
+{
+	return time * (MX28_INCREMENTER_HZ / CONFIG_SYS_HZ);
+}
+
+/* Calculate how many ticks happen in "us" microseconds */
+static inline unsigned long us_to_tick(unsigned long us)
+{
+	return (us * MX28_INCREMENTER_HZ) / 1000000;
+}
+
+int timer_init(void)
+{
+	struct mx28_timrot_regs *timrot_regs =
+		(struct mx28_timrot_regs *)MXS_TIMROT_BASE;
+
+	/* Reset Timers and Rotary Encoder module */
+	mx28_reset_block(&timrot_regs->hw_timrot_rotctrl_reg);
+
+	/* Set fixed_count to 0 */
+	writel(0, &timrot_regs->hw_timrot_fixed_count0);
+
+	/* Set UPDATE bit and 1Khz frequency */
+	writel(TIMROT_TIMCTRLn_UPDATE | TIMROT_TIMCTRLn_RELOAD |
+		TIMROT_TIMCTRLn_SELECT_1KHZ_XTAL,
+		&timrot_regs->hw_timrot_timctrl0);
+
+	/* Set fixed_count to maximal value */
+	writel(TIMER_LOAD_VAL, &timrot_regs->hw_timrot_fixed_count0);
+
+	return 0;
+}
+
+ulong get_timer(ulong base)
+{
+	struct mx28_timrot_regs *timrot_regs =
+		(struct mx28_timrot_regs *)MXS_TIMROT_BASE;
+
+	/* Current tick value */
+	uint32_t now = readl(&timrot_regs->hw_timrot_running_count0);
+
+	if (lastdec >= now) {
+		/*
+		 * normal mode (non roll)
+		 * move stamp forward with absolut diff ticks
+		 */
+		timestamp += (lastdec - now);
+	} else {
+		/* we have rollover of decrementer */
+		timestamp += (TIMER_LOAD_VAL - now) + lastdec;
+
+	}
+	lastdec = now;
+
+	return tick_to_time(timestamp) - base;
+}
+
+/* We use the HW_DIGCTL_MICROSECONDS register for sub-millisecond timer. */
+#define	MX28_HW_DIGCTL_MICROSECONDS	0x8001c0c0
+
+void __udelay(unsigned long usec)
+{
+	uint32_t old, new, incr;
+	uint32_t counter = 0;
+
+	old = readl(MX28_HW_DIGCTL_MICROSECONDS);
+
+	while (counter < usec) {
+		new = readl(MX28_HW_DIGCTL_MICROSECONDS);
+
+		/* Check if the timer wrapped. */
+		if (new < old) {
+			incr = 0xffffffff - old;
+			incr += new;
+		} else {
+			incr = new - old;
+		}
+
+		/*
+		 * Check if we are close to the maximum time and the counter
+		 * would wrap if incremented. If that's the case, break out
+		 * from the loop as the requested delay time passed.
+		 */
+		if (counter + incr < counter)
+			break;
+
+		counter += incr;
+		old = new;
+	}
+}
diff --git a/arch/arm/include/asm/arch-mx28/clock.h b/arch/arm/include/asm/arch-mx28/clock.h
new file mode 100644
index 0000000..1700fe3
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/clock.h
@@ -0,0 +1,61 @@
+/*
+ * Freescale i.MX28 Clock
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __CLOCK_H__
+#define __CLOCK_H__
+
+enum mxc_clock {
+	MXC_ARM_CLK = 0,
+	MXC_AHB_CLK,
+	MXC_IPG_CLK,
+	MXC_EMI_CLK,
+	MXC_GPMI_CLK,
+	MXC_IO0_CLK,
+	MXC_IO1_CLK,
+	MXC_SSP0_CLK,
+	MXC_SSP1_CLK,
+	MXC_SSP2_CLK,
+	MXC_SSP3_CLK,
+};
+
+enum mxs_ioclock {
+	MXC_IOCLK0 = 0,
+	MXC_IOCLK1,
+};
+
+enum mxs_sspclock {
+	MXC_SSPCLK0 = 0,
+	MXC_SSPCLK1,
+	MXC_SSPCLK2,
+	MXC_SSPCLK3,
+};
+
+uint32_t mxc_get_clock(enum mxc_clock clk);
+
+void mx28_set_ioclk(enum mxs_ioclock io, uint32_t freq);
+void mx28_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal);
+void mx28_set_ssp_busclock(unsigned int bus, uint32_t freq);
+
+/* Compatibility with the FEC Ethernet driver */
+#define	imx_get_fecclk()	mxc_get_clock(MXC_AHB_CLK)
+
+#endif	/* __CLOCK_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/imx-regs.h b/arch/arm/include/asm/arch-mx28/imx-regs.h
new file mode 100644
index 0000000..32bfd7e
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/imx-regs.h
@@ -0,0 +1,38 @@
+/*
+ * Freescale i.MX28 Registers
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __IMX_REGS_H__
+#define __IMX_REGS_H__
+
+#include <asm/arch/regs-base.h>
+#include <asm/arch/regs-bch.h>
+#include <asm/arch/regs-clkctrl.h>
+#include <asm/arch/regs-gpmi.h>
+#include <asm/arch/regs-i2c.h>
+#include <asm/arch/regs-ocotp.h>
+#include <asm/arch/regs-pinctrl.h>
+#include <asm/arch/regs-power.h>
+#include <asm/arch/regs-rtc.h>
+#include <asm/arch/regs-ssp.h>
+#include <asm/arch/regs-timrot.h>
+
+#endif	/* __IMX_REGS_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-base.h b/arch/arm/include/asm/arch-mx28/regs-base.h
new file mode 100644
index 0000000..dbdcc2b
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-base.h
@@ -0,0 +1,88 @@
+/*
+ * Freescale i.MX28 Peripheral Base Addresses
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright (C) 2008 Embedded Alley Solutions Inc.
+ *
+ * (C) Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __MX28_REGS_BASE_H__
+#define __MX28_REGS_BASE_H__
+
+/*
+ * Register base address
+ */
+#define	MXS_ICOL_BASE		0x80000000
+#define	MXS_HSADC_BASE		0x80002000
+#define	MXS_APBH_BASE		0x80004000
+#define	MXS_PERFMON_BASE	0x80006000
+#define	MXS_BCH_BASE		0x8000A000
+#define	MXS_GPMI_BASE		0x8000C000
+#define	MXS_SSP0_BASE		0x80010000
+#define	MXS_SSP1_BASE		0x80012000
+#define	MXS_SSP2_BASE		0x80014000
+#define	MXS_SSP3_BASE		0x80016000
+#define	MXS_PINCTRL_BASE	0x80018000
+#define	MXS_DIGCTL_BASE		0x8001C000
+#define	MXS_ETM_BASE		0x80022000
+#define	MXS_APBX_BASE		0x80024000
+#define	MXS_DCP_BASE		0x80028000
+#define	MXS_PXP_BASE		0x8002A000
+#define	MXS_OCOTP_BASE		0x8002C000
+#define	MXS_AXI_AHB0_BASE	0x8002E000
+#define	MXS_LCDIF_BASE		0x80030000
+#define	MXS_CAN0_BASE		0x80032000
+#define	MXS_CAN1_BASE		0x80034000
+#define	MXS_SIMDBG_BASE		0x8003C000
+#define	MXS_SIMGPMISEL_BASE	0x8003C200
+#define	MXS_SIMSSPSEL_BASE	0x8003C300
+#define	MXS_SIMMEMSEL_BASE	0x8003C400
+#define	MXS_GPIOMON_BASE	0x8003C500
+#define	MXS_SIMENET_BASE	0x8003C700
+#define	MXS_ARMJTAG_BASE	0x8003C800
+#define	MXS_CLKCTRL_BASE	0x80040000
+#define	MXS_SAIF0_BASE		0x80042000
+#define	MXS_POWER_BASE		0x80044000
+#define	MXS_SAIF1_BASE		0x80046000
+#define	MXS_LRADC_BASE		0x80050000
+#define	MXS_SPDIF_BASE		0x80054000
+#define	MXS_RTC_BASE		0x80056000
+#define	MXS_I2C0_BASE		0x80058000
+#define	MXS_I2C1_BASE		0x8005A000
+#define	MXS_PWM_BASE		0x80064000
+#define	MXS_TIMROT_BASE		0x80068000
+#define	MXS_UARTAPP0_BASE	0x8006A000
+#define	MXS_UARTAPP1_BASE	0x8006C000
+#define	MXS_UARTAPP2_BASE	0x8006E000
+#define	MXS_UARTAPP3_BASE	0x80070000
+#define	MXS_UARTAPP4_BASE	0x80072000
+#define	MXS_UARTDBG_BASE	0x80074000
+#define	MXS_USBPHY0_BASE	0x8007C000
+#define	MXS_USBPHY1_BASE	0x8007E000
+#define	MXS_USBCTRL0_BASE	0x80080000
+#define	MXS_USBCTRL1_BASE	0x80090000
+#define	MXS_DFLPT_BASE		0x800C0000
+#define	MXS_DRAM_BASE		0x800E0000
+#define	MXS_ENET0_BASE		0x800F0000
+#define	MXS_ENET1_BASE		0x800F4000
+
+#endif /* __MX28_REGS_BASE_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-bch.h b/arch/arm/include/asm/arch-mx28/regs-bch.h
new file mode 100644
index 0000000..cac0470
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-bch.h
@@ -0,0 +1,230 @@
+/*
+ * Freescale i.MX28 BCH Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_BCH_H__
+#define __MX28_REGS_BCH_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_bch_regs {
+	mx28_reg(hw_bch_ctrl)
+	mx28_reg(hw_bch_status0)
+	mx28_reg(hw_bch_mode)
+	mx28_reg(hw_bch_encodeptr)
+	mx28_reg(hw_bch_dataptr)
+	mx28_reg(hw_bch_metaptr)
+
+	uint32_t	reserved[4];
+
+	mx28_reg(hw_bch_layoutselect)
+	mx28_reg(hw_bch_flash0layout0)
+	mx28_reg(hw_bch_flash0layout1)
+	mx28_reg(hw_bch_flash1layout0)
+	mx28_reg(hw_bch_flash1layout1)
+	mx28_reg(hw_bch_flash2layout0)
+	mx28_reg(hw_bch_flash2layout1)
+	mx28_reg(hw_bch_flash3layout0)
+	mx28_reg(hw_bch_flash3layout1)
+	mx28_reg(hw_bch_dbgkesread)
+	mx28_reg(hw_bch_dbgcsferead)
+	mx28_reg(hw_bch_dbgsyndegread)
+	mx28_reg(hw_bch_dbgahbmread)
+	mx28_reg(hw_bch_blockname)
+	mx28_reg(hw_bch_version)
+};
+#endif
+
+#define	BCH_CTRL_SFTRST					(1 << 31)
+#define	BCH_CTRL_CLKGATE				(1 << 30)
+#define	BCH_CTRL_DEBUGSYNDROME				(1 << 22)
+#define	BCH_CTRL_M2M_LAYOUT_MASK			(0x3 << 18)
+#define	BCH_CTRL_M2M_LAYOUT_OFFSET			18
+#define	BCH_CTRL_M2M_ENCODE				(1 << 17)
+#define	BCH_CTRL_M2M_ENABLE				(1 << 16)
+#define	BCH_CTRL_DEBUG_STALL_IRQ_EN			(1 << 10)
+#define	BCH_CTRL_COMPLETE_IRQ_EN			(1 << 8)
+#define	BCH_CTRL_BM_ERROR_IRQ				(1 << 3)
+#define	BCH_CTRL_DEBUG_STALL_IRQ			(1 << 2)
+#define	BCH_CTRL_COMPLETE_IRQ				(1 << 0)
+
+#define	BCH_STATUS0_HANDLE_MASK				(0xfff << 20)
+#define	BCH_STATUS0_HANDLE_OFFSET			20
+#define	BCH_STATUS0_COMPLETED_CE_MASK			(0xf << 16)
+#define	BCH_STATUS0_COMPLETED_CE_OFFSET			16
+#define	BCH_STATUS0_STATUS_BLK0_MASK			(0xff << 8)
+#define	BCH_STATUS0_STATUS_BLK0_OFFSET			8
+#define	BCH_STATUS0_STATUS_BLK0_ZERO			(0x00 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERROR1			(0x01 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERROR2			(0x02 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERROR3			(0x03 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERROR4			(0x04 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_UNCORRECTABLE		(0xfe << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERASED			(0xff << 8)
+#define	BCH_STATUS0_ALLONES				(1 << 4)
+#define	BCH_STATUS0_CORRECTED				(1 << 3)
+#define	BCH_STATUS0_UNCORRECTABLE			(1 << 2)
+
+#define	BCH_MODE_ERASE_THRESHOLD_MASK			0xff
+#define	BCH_MODE_ERASE_THRESHOLD_OFFSET			0
+
+#define	BCH_ENCODEPTR_ADDR_MASK				0xffffffff
+#define	BCH_ENCODEPTR_ADDR_OFFSET			0
+
+#define	BCH_DATAPTR_ADDR_MASK				0xffffffff
+#define	BCH_DATAPTR_ADDR_OFFSET				0
+
+#define	BCH_METAPTR_ADDR_MASK				0xffffffff
+#define	BCH_METAPTR_ADDR_OFFSET				0
+
+#define	BCH_LAYOUTSELECT_CS15_SELECT_MASK		(0x3 << 30)
+#define	BCH_LAYOUTSELECT_CS15_SELECT_OFFSET		30
+#define	BCH_LAYOUTSELECT_CS14_SELECT_MASK		(0x3 << 28)
+#define	BCH_LAYOUTSELECT_CS14_SELECT_OFFSET		28
+#define	BCH_LAYOUTSELECT_CS13_SELECT_MASK		(0x3 << 26)
+#define	BCH_LAYOUTSELECT_CS13_SELECT_OFFSET		26
+#define	BCH_LAYOUTSELECT_CS12_SELECT_MASK		(0x3 << 24)
+#define	BCH_LAYOUTSELECT_CS12_SELECT_OFFSET		24
+#define	BCH_LAYOUTSELECT_CS11_SELECT_MASK		(0x3 << 22)
+#define	BCH_LAYOUTSELECT_CS11_SELECT_OFFSET		22
+#define	BCH_LAYOUTSELECT_CS10_SELECT_MASK		(0x3 << 20)
+#define	BCH_LAYOUTSELECT_CS10_SELECT_OFFSET		20
+#define	BCH_LAYOUTSELECT_CS9_SELECT_MASK		(0x3 << 18)
+#define	BCH_LAYOUTSELECT_CS9_SELECT_OFFSET		18
+#define	BCH_LAYOUTSELECT_CS8_SELECT_MASK		(0x3 << 16)
+#define	BCH_LAYOUTSELECT_CS8_SELECT_OFFSET		16
+#define	BCH_LAYOUTSELECT_CS7_SELECT_MASK		(0x3 << 14)
+#define	BCH_LAYOUTSELECT_CS7_SELECT_OFFSET		14
+#define	BCH_LAYOUTSELECT_CS6_SELECT_MASK		(0x3 << 12)
+#define	BCH_LAYOUTSELECT_CS6_SELECT_OFFSET		12
+#define	BCH_LAYOUTSELECT_CS5_SELECT_MASK		(0x3 << 10)
+#define	BCH_LAYOUTSELECT_CS5_SELECT_OFFSET		10
+#define	BCH_LAYOUTSELECT_CS4_SELECT_MASK		(0x3 << 8)
+#define	BCH_LAYOUTSELECT_CS4_SELECT_OFFSET		8
+#define	BCH_LAYOUTSELECT_CS3_SELECT_MASK		(0x3 << 6)
+#define	BCH_LAYOUTSELECT_CS3_SELECT_OFFSET		6
+#define	BCH_LAYOUTSELECT_CS2_SELECT_MASK		(0x3 << 4)
+#define	BCH_LAYOUTSELECT_CS2_SELECT_OFFSET		4
+#define	BCH_LAYOUTSELECT_CS1_SELECT_MASK		(0x3 << 2)
+#define	BCH_LAYOUTSELECT_CS1_SELECT_OFFSET		2
+#define	BCH_LAYOUTSELECT_CS0_SELECT_MASK		(0x3 << 0)
+#define	BCH_LAYOUTSELECT_CS0_SELECT_OFFSET		0
+
+#define	BCH_FLASHLAYOUT0_NBLOCKS_MASK			(0xff << 24)
+#define	BCH_FLASHLAYOUT0_NBLOCKS_OFFSET			24
+#define	BCH_FLASHLAYOUT0_META_SIZE_MASK			(0xff << 16)
+#define	BCH_FLASHLAYOUT0_META_SIZE_OFFSET		16
+#define	BCH_FLASHLAYOUT0_ECC0_MASK			(0xf << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_OFFSET			12
+#define	BCH_FLASHLAYOUT0_ECC0_NONE			(0x0 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC2			(0x1 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC4			(0x2 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC6			(0x3 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC8			(0x4 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC10			(0x5 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC12			(0x6 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC14			(0x7 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC16			(0x8 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC18			(0x9 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC20			(0xa << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC22			(0xb << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC24			(0xc << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC26			(0xd << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC28			(0xe << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC30			(0xf << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC32			(0x10 << 12)
+#define	BCH_FLASHLAYOUT0_GF13_0_GF14_1			(1 << 10)
+#define	BCH_FLASHLAYOUT0_DATA0_SIZE_MASK		0xfff
+#define	BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET		0
+
+#define	BCH_FLASHLAYOUT1_PAGE_SIZE_MASK			(0xffff << 16)
+#define	BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET		16
+#define	BCH_FLASHLAYOUT1_ECCN_MASK			(0xf << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_OFFSET			12
+#define	BCH_FLASHLAYOUT1_ECCN_NONE			(0x0 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC2			(0x1 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC4			(0x2 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC6			(0x3 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC8			(0x4 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC10			(0x5 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC12			(0x6 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC14			(0x7 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC16			(0x8 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC18			(0x9 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC20			(0xa << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC22			(0xb << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC24			(0xc << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC26			(0xd << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC28			(0xe << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC30			(0xf << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC32			(0x10 << 12)
+#define	BCH_FLASHLAYOUT1_GF13_0_GF14_1			(1 << 10)
+#define	BCH_FLASHLAYOUT1_DATAN_SIZE_MASK		0xfff
+#define	BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET		0
+
+#define	BCH_DEBUG0_RSVD1_MASK				(0x1f << 27)
+#define	BCH_DEBUG0_RSVD1_OFFSET				27
+#define	BCH_DEBUG0_ROM_BIST_ENABLE			(1 << 26)
+#define	BCH_DEBUG0_ROM_BIST_COMPLETE			(1 << 25)
+#define	BCH_DEBUG0_KES_DEBUG_SYNDROME_SYMBOL_MASK	(0x1ff << 16)
+#define	BCH_DEBUG0_KES_DEBUG_SYNDROME_SYMBOL_OFFSET	16
+#define	BCH_DEBUG0_KES_DEBUG_SYNDROME_SYMBOL_NORMAL	(0x0 << 16)
+#define	BCH_DEBUG0_KES_DEBUG_SYNDROME_SYMBOL_TEST_MODE	(0x1 << 16)
+#define	BCH_DEBUG0_KES_DEBUG_SHIFT_SYND			(1 << 15)
+#define	BCH_DEBUG0_KES_DEBUG_PAYLOAD_FLAG		(1 << 14)
+#define	BCH_DEBUG0_KES_DEBUG_MODE4K			(1 << 13)
+#define	BCH_DEBUG0_KES_DEBUG_KICK			(1 << 12)
+#define	BCH_DEBUG0_KES_STANDALONE			(1 << 11)
+#define	BCH_DEBUG0_KES_DEBUG_STEP			(1 << 10)
+#define	BCH_DEBUG0_KES_DEBUG_STALL			(1 << 9)
+#define	BCH_DEBUG0_BM_KES_TEST_BYPASS			(1 << 8)
+#define	BCH_DEBUG0_RSVD0_MASK				(0x3 << 6)
+#define	BCH_DEBUG0_RSVD0_OFFSET				6
+#define	BCH_DEBUG0_DEBUG_REG_SELECT_MASK		0x3f
+#define	BCH_DEBUG0_DEBUG_REG_SELECT_OFFSET		0
+
+#define	BCH_DBGKESREAD_VALUES_MASK			0xffffffff
+#define	BCH_DBGKESREAD_VALUES_OFFSET			0
+
+#define	BCH_DBGCSFEREAD_VALUES_MASK			0xffffffff
+#define	BCH_DBGCSFEREAD_VALUES_OFFSET			0
+
+#define	BCH_DBGSYNDGENREAD_VALUES_MASK			0xffffffff
+#define	BCH_DBGSYNDGENREAD_VALUES_OFFSET		0
+
+#define	BCH_DBGAHBMREAD_VALUES_MASK			0xffffffff
+#define	BCH_DBGAHBMREAD_VALUES_OFFSET			0
+
+#define	BCH_BLOCKNAME_NAME_MASK				0xffffffff
+#define	BCH_BLOCKNAME_NAME_OFFSET			0
+
+#define	BCH_VERSION_MAJOR_MASK				(0xff << 24)
+#define	BCH_VERSION_MAJOR_OFFSET			24
+#define	BCH_VERSION_MINOR_MASK				(0xff << 16)
+#define	BCH_VERSION_MINOR_OFFSET			16
+#define	BCH_VERSION_STEP_MASK				0xffff
+#define	BCH_VERSION_STEP_OFFSET				0
+
+#endif	/* __MX28_REGS_BCH_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-clkctrl.h b/arch/arm/include/asm/arch-mx28/regs-clkctrl.h
new file mode 100644
index 0000000..93d0397
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-clkctrl.h
@@ -0,0 +1,312 @@
+/*
+ * Freescale i.MX28 CLKCTRL Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_CLKCTRL_H__
+#define __MX28_REGS_CLKCTRL_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_clkctrl_regs {
+	mx28_reg(hw_clkctrl_pll0ctrl0)		/* 0x00 */
+	mx28_reg(hw_clkctrl_pll0ctrl1)		/* 0x10 */
+	mx28_reg(hw_clkctrl_pll1ctrl0)		/* 0x20 */
+	mx28_reg(hw_clkctrl_pll1ctrl1)		/* 0x30 */
+	mx28_reg(hw_clkctrl_pll2ctrl0)		/* 0x40 */
+	mx28_reg(hw_clkctrl_cpu)		/* 0x50 */
+	mx28_reg(hw_clkctrl_hbus)		/* 0x60 */
+	mx28_reg(hw_clkctrl_xbus)		/* 0x70 */
+	mx28_reg(hw_clkctrl_xtal)		/* 0x80 */
+	mx28_reg(hw_clkctrl_ssp0)		/* 0x90 */
+	mx28_reg(hw_clkctrl_ssp1)		/* 0xa0 */
+	mx28_reg(hw_clkctrl_ssp2)		/* 0xb0 */
+	mx28_reg(hw_clkctrl_ssp3)		/* 0xc0 */
+	mx28_reg(hw_clkctrl_gpmi)		/* 0xd0 */
+	mx28_reg(hw_clkctrl_spdif)		/* 0xe0 */
+	mx28_reg(hw_clkctrl_emi)		/* 0xf0 */
+	mx28_reg(hw_clkctrl_saif0)		/* 0x100 */
+	mx28_reg(hw_clkctrl_saif1)		/* 0x110 */
+	mx28_reg(hw_clkctrl_lcdif)		/* 0x120 */
+	mx28_reg(hw_clkctrl_etm)		/* 0x130 */
+	mx28_reg(hw_clkctrl_enet)		/* 0x140 */
+	mx28_reg(hw_clkctrl_hsadc)		/* 0x150 */
+	mx28_reg(hw_clkctrl_flexcan)		/* 0x160 */
+
+	uint32_t	reserved[16];
+
+	mx28_reg(hw_clkctrl_frac0)		/* 0x1b0 */
+	mx28_reg(hw_clkctrl_frac1)		/* 0x1c0 */
+	mx28_reg(hw_clkctrl_clkseq)		/* 0x1d0 */
+	mx28_reg(hw_clkctrl_reset)		/* 0x1e0 */
+	mx28_reg(hw_clkctrl_status)		/* 0x1f0 */
+	mx28_reg(hw_clkctrl_version)		/* 0x200 */
+};
+#endif
+
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_MASK		(0x3 << 28)
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_OFFSET	28
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_DEFAULT	(0x0 << 28)
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_TIMES_2	(0x1 << 28)
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_TIMES_05	(0x2 << 28)
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_UNDEFINED	(0x3 << 28)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_MASK		(0x3 << 24)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_OFFSET		24
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_DEFAULT	(0x0 << 24)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_TIMES_2	(0x1 << 24)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_TIMES_05	(0x2 << 24)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_UNDEFINED	(0x3 << 24)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_MASK		(0x3 << 20)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_OFFSET	20
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_DEFAULT	(0x0 << 20)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_LOWER		(0x1 << 20)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_LOWEST	(0x2 << 20)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_UNDEFINED	(0x3 << 20)
+#define	CLKCTRL_PLL0CTRL0_EN_USB_CLKS		(1 << 18)
+#define	CLKCTRL_PLL0CTRL0_POWER			(1 << 17)
+
+#define	CLKCTRL_PLL0CTRL1_LOCK			(1 << 31)
+#define	CLKCTRL_PLL0CTRL1_FORCE_LOCK		(1 << 30)
+#define	CLKCTRL_PLL0CTRL1_LOCK_COUNT_MASK	0xffff
+#define	CLKCTRL_PLL0CTRL1_LOCK_COUNT_OFFSET	0
+
+#define	CLKCTRL_PLL1CTRL0_CLKGATEEMI		(1 << 31)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_MASK		(0x3 << 28)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_OFFSET	28
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_DEFAULT	(0x0 << 28)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_TIMES_2	(0x1 << 28)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_TIMES_05	(0x2 << 28)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_UNDEFINED	(0x3 << 28)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_MASK		(0x3 << 24)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_OFFSET		24
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_DEFAULT	(0x0 << 24)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_TIMES_2	(0x1 << 24)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_TIMES_05	(0x2 << 24)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_UNDEFINED	(0x3 << 24)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_MASK		(0x3 << 20)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_OFFSET	20
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_DEFAULT	(0x0 << 20)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_LOWER		(0x1 << 20)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_LOWEST	(0x2 << 20)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_UNDEFINED	(0x3 << 20)
+#define	CLKCTRL_PLL1CTRL0_EN_USB_CLKS		(1 << 18)
+#define	CLKCTRL_PLL1CTRL0_POWER			(1 << 17)
+
+#define	CLKCTRL_PLL1CTRL1_LOCK			(1 << 31)
+#define	CLKCTRL_PLL1CTRL1_FORCE_LOCK		(1 << 30)
+#define	CLKCTRL_PLL1CTRL1_LOCK_COUNT_MASK	0xffff
+#define	CLKCTRL_PLL1CTRL1_LOCK_COUNT_OFFSET	0
+
+#define	CLKCTRL_PLL2CTRL0_CLKGATE		(1 << 31)
+#define	CLKCTRL_PLL2CTRL0_LFR_SEL_MASK		(0x3 << 28)
+#define	CLKCTRL_PLL2CTRL0_LFR_SEL_OFFSET	28
+#define	CLKCTRL_PLL2CTRL0_HOLD_RING_OFF_B	(1 << 26)
+#define	CLKCTRL_PLL2CTRL0_CP_SEL_MASK		(0x3 << 24)
+#define	CLKCTRL_PLL2CTRL0_CP_SEL_OFFSET		24
+#define	CLKCTRL_PLL2CTRL0_POWER			(1 << 23)
+
+#define	CLKCTRL_CPU_BUSY_REF_XTAL		(1 << 29)
+#define	CLKCTRL_CPU_BUSY_REF_CPU		(1 << 28)
+#define	CLKCTRL_CPU_DIV_XTAL_FRAC_EN		(1 << 26)
+#define	CLKCTRL_CPU_DIV_XTAL_MASK		(0x3ff << 16)
+#define	CLKCTRL_CPU_DIV_XTAL_OFFSET		16
+#define	CLKCTRL_CPU_INTERRUPT_WAIT		(1 << 12)
+#define	CLKCTRL_CPU_DIV_CPU_FRAC_EN		(1 << 10)
+#define	CLKCTRL_CPU_DIV_CPU_MASK		0x3f
+#define	CLKCTRL_CPU_DIV_CPU_OFFSET		0
+
+#define	CLKCTRL_HBUS_ASM_BUSY			(1 << 31)
+#define	CLKCTRL_HBUS_DCP_AS_ENABLE		(1 << 30)
+#define	CLKCTRL_HBUS_PXP_AS_ENABLE		(1 << 29)
+#define	CLKCTRL_HBUS_ASM_EMIPORT_AS_ENABLE	(1 << 27)
+#define	CLKCTRL_HBUS_APBHDMA_AS_ENABLE		(1 << 26)
+#define	CLKCTRL_HBUS_APBXDMA_AS_ENABLE		(1 << 25)
+#define	CLKCTRL_HBUS_TRAFFIC_JAM_AS_ENABLE	(1 << 24)
+#define	CLKCTRL_HBUS_TRAFFIC_AS_ENABLE		(1 << 23)
+#define	CLKCTRL_HBUS_CPU_DATA_AS_ENABLE		(1 << 22)
+#define	CLKCTRL_HBUS_CPU_INSTR_AS_ENABLE	(1 << 21)
+#define	CLKCTRL_HBUS_ASM_ENABLE			(1 << 20)
+#define	CLKCTRL_HBUS_AUTO_CLEAR_DIV_ENABLE	(1 << 19)
+#define	CLKCTRL_HBUS_SLOW_DIV_MASK		(0x7 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_OFFSET		16
+#define	CLKCTRL_HBUS_SLOW_DIV_BY1		(0x0 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY2		(0x1 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY4		(0x2 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY8		(0x3 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY16		(0x4 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY32		(0x5 << 16)
+#define	CLKCTRL_HBUS_DIV_FRAC_EN		(1 << 5)
+#define	CLKCTRL_HBUS_DIV_MASK			0x1f
+#define	CLKCTRL_HBUS_DIV_OFFSET			0
+
+#define	CLKCTRL_XBUS_BUSY			(1 << 31)
+#define	CLKCTRL_XBUS_AUTO_CLEAR_DIV_ENABLE	(1 << 11)
+#define	CLKCTRL_XBUS_DIV_FRAC_EN		(1 << 10)
+#define	CLKCTRL_XBUS_DIV_MASK			0x3ff
+#define	CLKCTRL_XBUS_DIV_OFFSET			0
+
+#define	CLKCTRL_XTAL_UART_CLK_GATE		(1 << 31)
+#define	CLKCTRL_XTAL_PWM_CLK24M_GATE		(1 << 29)
+#define	CLKCTRL_XTAL_TIMROT_CLK32K_GATE		(1 << 26)
+#define	CLKCTRL_XTAL_DIV_UART_MASK		0x3
+#define	CLKCTRL_XTAL_DIV_UART_OFFSET		0
+
+#define	CLKCTRL_SSP_CLKGATE			(1 << 31)
+#define	CLKCTRL_SSP_BUSY			(1 << 29)
+#define	CLKCTRL_SSP_DIV_FRAC_EN			(1 << 9)
+#define	CLKCTRL_SSP_DIV_MASK			0x1ff
+#define	CLKCTRL_SSP_DIV_OFFSET			0
+
+#define	CLKCTRL_GPMI_CLKGATE			(1 << 31)
+#define	CLKCTRL_GPMI_BUSY			(1 << 29)
+#define	CLKCTRL_GPMI_DIV_FRAC_EN		(1 << 10)
+#define	CLKCTRL_GPMI_DIV_MASK			0x3ff
+#define	CLKCTRL_GPMI_DIV_OFFSET			0
+
+#define	CLKCTRL_SPDIF_CLKGATE			(1 << 31)
+
+#define	CLKCTRL_EMI_CLKGATE			(1 << 31)
+#define	CLKCTRL_EMI_SYNC_MODE_EN		(1 << 30)
+#define	CLKCTRL_EMI_BUSY_REF_XTAL		(1 << 29)
+#define	CLKCTRL_EMI_BUSY_REF_EMI		(1 << 28)
+#define	CLKCTRL_EMI_BUSY_REF_CPU		(1 << 27)
+#define	CLKCTRL_EMI_BUSY_SYNC_MODE		(1 << 26)
+#define	CLKCTRL_EMI_BUSY_DCC_RESYNC		(1 << 17)
+#define	CLKCTRL_EMI_DCC_RESYNC_ENABLE		(1 << 16)
+#define	CLKCTRL_EMI_DIV_XTAL_MASK		(0xf << 8)
+#define	CLKCTRL_EMI_DIV_XTAL_OFFSET		8
+#define	CLKCTRL_EMI_DIV_EMI_MASK		0x3f
+#define	CLKCTRL_EMI_DIV_EMI_OFFSET		0
+
+#define	CLKCTRL_SAIF0_CLKGATE			(1 << 31)
+#define	CLKCTRL_SAIF0_BUSY			(1 << 29)
+#define	CLKCTRL_SAIF0_DIV_FRAC_EN		(1 << 16)
+#define	CLKCTRL_SAIF0_DIV_MASK			0xffff
+#define	CLKCTRL_SAIF0_DIV_OFFSET		0
+
+#define	CLKCTRL_SAIF1_CLKGATE			(1 << 31)
+#define	CLKCTRL_SAIF1_BUSY			(1 << 29)
+#define	CLKCTRL_SAIF1_DIV_FRAC_EN		(1 << 16)
+#define	CLKCTRL_SAIF1_DIV_MASK			0xffff
+#define	CLKCTRL_SAIF1_DIV_OFFSET		0
+
+#define	CLKCTRL_DIS_LCDIF_CLKGATE		(1 << 31)
+#define	CLKCTRL_DIS_LCDIF_BUSY			(1 << 29)
+#define	CLKCTRL_DIS_LCDIF_DIV_FRAC_EN		(1 << 13)
+#define	CLKCTRL_DIS_LCDIF_DIV_MASK		0x1fff
+#define	CLKCTRL_DIS_LCDIF_DIV_OFFSET		0
+
+#define	CLKCTRL_ETM_CLKGATE			(1 << 31)
+#define	CLKCTRL_ETM_BUSY			(1 << 29)
+#define	CLKCTRL_ETM_DIV_FRAC_EN			(1 << 7)
+#define	CLKCTRL_ETM_DIV_MASK			0x7f
+#define	CLKCTRL_ETM_DIV_OFFSET			0
+
+#define	CLKCTRL_ENET_SLEEP			(1 << 31)
+#define	CLKCTRL_ENET_DISABLE			(1 << 30)
+#define	CLKCTRL_ENET_STATUS			(1 << 29)
+#define	CLKCTRL_ENET_BUSY_TIME			(1 << 27)
+#define	CLKCTRL_ENET_DIV_TIME_MASK		(0x3f << 21)
+#define	CLKCTRL_ENET_DIV_TIME_OFFSET		21
+#define	CLKCTRL_ENET_TIME_SEL_MASK		(0x3 << 19)
+#define	CLKCTRL_ENET_TIME_SEL_OFFSET		19
+#define	CLKCTRL_ENET_TIME_SEL_XTAL		(0x0 << 19)
+#define	CLKCTRL_ENET_TIME_SEL_PLL		(0x1 << 19)
+#define	CLKCTRL_ENET_TIME_SEL_RMII_CLK		(0x2 << 19)
+#define	CLKCTRL_ENET_TIME_SEL_UNDEFINED		(0x3 << 19)
+#define	CLKCTRL_ENET_CLK_OUT_EN			(1 << 18)
+#define	CLKCTRL_ENET_RESET_BY_SW_CHIP		(1 << 17)
+#define	CLKCTRL_ENET_RESET_BY_SW		(1 << 16)
+
+#define	CLKCTRL_HSADC_RESETB			(1 << 30)
+#define	CLKCTRL_HSADC_FREQDIV_MASK		(0x3 << 28)
+#define	CLKCTRL_HSADC_FREQDIV_OFFSET		28
+
+#define	CLKCTRL_FLEXCAN_STOP_CAN0		(1 << 30)
+#define	CLKCTRL_FLEXCAN_CAN0_STATUS		(1 << 29)
+#define	CLKCTRL_FLEXCAN_STOP_CAN1		(1 << 28)
+#define	CLKCTRL_FLEXCAN_CAN1_STATUS		(1 << 27)
+
+#define	CLKCTRL_FRAC0_CLKGATEIO0		(1 << 31)
+#define	CLKCTRL_FRAC0_IO0_STABLE		(1 << 30)
+#define	CLKCTRL_FRAC0_IO0FRAC_MASK		(0x3f << 24)
+#define	CLKCTRL_FRAC0_IO0FRAC_OFFSET		24
+#define	CLKCTRL_FRAC0_CLKGATEIO1		(1 << 23)
+#define	CLKCTRL_FRAC0_IO1_STABLE		(1 << 22)
+#define	CLKCTRL_FRAC0_IO1FRAC_MASK		(0x3f << 16)
+#define	CLKCTRL_FRAC0_IO1FRAC_OFFSET		16
+#define	CLKCTRL_FRAC0_CLKGATEEMI		(1 << 15)
+#define	CLKCTRL_FRAC0_EMI_STABLE		(1 << 14)
+#define	CLKCTRL_FRAC0_EMIFRAC_MASK		(0x3f << 8)
+#define	CLKCTRL_FRAC0_EMIFRAC_OFFSET		8
+#define	CLKCTRL_FRAC0_CLKGATECPU		(1 << 7)
+#define	CLKCTRL_FRAC0_CPU_STABLE		(1 << 6)
+#define	CLKCTRL_FRAC0_CPUFRAC_MASK		0x3f
+#define	CLKCTRL_FRAC0_CPUFRAC_OFFSET		0
+
+#define	CLKCTRL_FRAC1_CLKGATEGPMI		(1 << 23)
+#define	CLKCTRL_FRAC1_GPMI_STABLE		(1 << 22)
+#define	CLKCTRL_FRAC1_GPMIFRAC_MASK		(0x3f << 16)
+#define	CLKCTRL_FRAC1_GPMIFRAC_OFFSET		16
+#define	CLKCTRL_FRAC1_CLKGATEHSADC		(1 << 15)
+#define	CLKCTRL_FRAC1_HSADC_STABLE		(1 << 14)
+#define	CLKCTRL_FRAC1_HSADCFRAC_MASK		(0x3f << 8)
+#define	CLKCTRL_FRAC1_HSADCFRAC_OFFSET		8
+#define	CLKCTRL_FRAC1_CLKGATEPIX		(1 << 7)
+#define	CLKCTRL_FRAC1_PIX_STABLE		(1 << 6)
+#define	CLKCTRL_FRAC1_PIXFRAC_MASK		0x3f
+#define	CLKCTRL_FRAC1_PIXFRAC_OFFSET		0
+
+#define	CLKCTRL_CLKSEQ_BYPASS_CPU		(1 << 18)
+#define	CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF		(1 << 14)
+#define	CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF_BYPASS	(0x1 << 14)
+#define	CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF_PFD	(0x0 << 14)
+#define	CLKCTRL_CLKSEQ_BYPASS_ETM		(1 << 8)
+#define	CLKCTRL_CLKSEQ_BYPASS_EMI		(1 << 7)
+#define	CLKCTRL_CLKSEQ_BYPASS_SSP3		(1 << 6)
+#define	CLKCTRL_CLKSEQ_BYPASS_SSP2		(1 << 5)
+#define	CLKCTRL_CLKSEQ_BYPASS_SSP1		(1 << 4)
+#define	CLKCTRL_CLKSEQ_BYPASS_SSP0		(1 << 3)
+#define	CLKCTRL_CLKSEQ_BYPASS_GPMI		(1 << 2)
+#define	CLKCTRL_CLKSEQ_BYPASS_SAIF1		(1 << 1)
+#define	CLKCTRL_CLKSEQ_BYPASS_SAIF0		(1 << 0)
+
+#define	CLKCTRL_RESET_WDOG_POR_DISABLE		(1 << 5)
+#define	CLKCTRL_RESET_EXTERNAL_RESET_ENABLE	(1 << 4)
+#define	CLKCTRL_RESET_THERMAL_RESET_ENABLE	(1 << 3)
+#define	CLKCTRL_RESET_THERMAL_RESET_DEFAULT	(1 << 2)
+#define	CLKCTRL_RESET_CHIP			(1 << 1)
+#define	CLKCTRL_RESET_DIG			(1 << 0)
+
+#define	CLKCTRL_STATUS_CPU_LIMIT_MASK		(0x3 << 30)
+#define	CLKCTRL_STATUS_CPU_LIMIT_OFFSET		30
+
+#define	CLKCTRL_VERSION_MAJOR_MASK		(0xff << 24)
+#define	CLKCTRL_VERSION_MAJOR_OFFSET		24
+#define	CLKCTRL_VERSION_MINOR_MASK		(0xff << 16)
+#define	CLKCTRL_VERSION_MINOR_OFFSET		16
+#define	CLKCTRL_VERSION_STEP_MASK		0xffff
+#define	CLKCTRL_VERSION_STEP_OFFSET		0
+
+#endif /* __MX28_REGS_CLKCTRL_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-common.h b/arch/arm/include/asm/arch-mx28/regs-common.h
new file mode 100644
index 0000000..efe975b
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-common.h
@@ -0,0 +1,66 @@
+/*
+ * Freescale i.MX28 Register Accessors
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_COMMON_H__
+#define __MX28_REGS_COMMON_H__
+
+/*
+ * The i.MX28 has interesting feature when it comes to register access. There
+ * are four kinds of access to one particular register. Those are:
+ *
+ * 1) Common read/write access. To use this mode, just write to the address of
+ *    the register.
+ * 2) Set bits only access. To set bits, write which bits you want to set to the
+ *    address of the register + 0x4.
+ * 3) Clear bits only access. To clear bits, write which bits you want to clear
+ *    to the address of the register + 0x8.
+ * 4) Toggle bits only access. To toggle bits, write which bits you want to
+ *    toggle to the address of the register + 0xc.
+ *
+ * IMPORTANT NOTE: Not all registers support accesses 2-4! Also, not all bits
+ * can be set/cleared by pure write as in access type 1, some need to be
+ * explicitly set/cleared by using access type 2-3.
+ *
+ * The following macros and structures allow the user to either access the
+ * register in all aforementioned modes (by accessing reg_name, reg_name_set,
+ * reg_name_clr, reg_name_tog) or pass the register structure further into
+ * various functions with correct type information (by accessing reg_name_reg).
+ *
+ */
+
+#define	__mx28_reg(name)		\
+	uint32_t name;			\
+	uint32_t name##_set;		\
+	uint32_t name##_clr;		\
+	uint32_t name##_tog;
+
+struct mx28_register {
+	__mx28_reg(reg)
+};
+
+#define	mx28_reg(name)					\
+	union {						\
+		struct { __mx28_reg(name) };		\
+		struct mx28_register name##_reg;	\
+	};
+
+#endif	/* __MX28_REGS_COMMON_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-gpmi.h b/arch/arm/include/asm/arch-mx28/regs-gpmi.h
new file mode 100644
index 0000000..0096793
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-gpmi.h
@@ -0,0 +1,222 @@
+/*
+ * Freescale i.MX28 GPMI Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_GPMI_H__
+#define __MX28_REGS_GPMI_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_gpmi_regs {
+	mx28_reg(hw_gpmi_ctrl0)
+	mx28_reg(hw_gpmi_compare)
+	mx28_reg(hw_gpmi_eccctrl)
+	mx28_reg(hw_gpmi_ecccount)
+	mx28_reg(hw_gpmi_payload)
+	mx28_reg(hw_gpmi_auxiliary)
+	mx28_reg(hw_gpmi_ctrl1)
+	mx28_reg(hw_gpmi_timing0)
+	mx28_reg(hw_gpmi_timing1)
+
+	uint32_t	reserved[4];
+
+	mx28_reg(hw_gpmi_data)
+	mx28_reg(hw_gpmi_stat)
+	mx28_reg(hw_gpmi_debug)
+	mx28_reg(hw_gpmi_version)
+};
+#endif
+
+#define	GPMI_CTRL0_SFTRST				(1 << 31)
+#define	GPMI_CTRL0_CLKGATE				(1 << 30)
+#define	GPMI_CTRL0_RUN					(1 << 29)
+#define	GPMI_CTRL0_DEV_IRQ_EN				(1 << 28)
+#define	GPMI_CTRL0_LOCK_CS				(1 << 27)
+#define	GPMI_CTRL0_UDMA					(1 << 26)
+#define	GPMI_CTRL0_COMMAND_MODE_MASK			(0x3 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_OFFSET			24
+#define	GPMI_CTRL0_COMMAND_MODE_WRITE			(0x0 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_READ			(0x1 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_READ_AND_COMPARE	(0x2 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY		(0x3 << 24)
+#define	GPMI_CTRL0_WORD_LENGTH				(1 << 23)
+#define	GPMI_CTRL0_CS_MASK				(0x7 << 20)
+#define	GPMI_CTRL0_CS_OFFSET				20
+#define	GPMI_CTRL0_ADDRESS_MASK				(0x7 << 17)
+#define	GPMI_CTRL0_ADDRESS_OFFSET			17
+#define	GPMI_CTRL0_ADDRESS_NAND_DATA			(0x0 << 17)
+#define	GPMI_CTRL0_ADDRESS_NAND_CLE			(0x1 << 17)
+#define	GPMI_CTRL0_ADDRESS_NAND_ALE			(0x2 << 17)
+#define	GPMI_CTRL0_ADDRESS_INCREMENT			(1 << 16)
+#define	GPMI_CTRL0_XFER_COUNT_MASK			0xffff
+#define	GPMI_CTRL0_XFER_COUNT_OFFSET			0
+
+#define	GPMI_COMPARE_MASK_MASK				(0xffff << 16)
+#define	GPMI_COMPARE_MASK_OFFSET			16
+#define	GPMI_COMPARE_REFERENCE_MASK			0xffff
+#define	GPMI_COMPARE_REFERENCE_OFFSET			0
+
+#define	GPMI_ECCCTRL_HANDLE_MASK			(0xffff << 16)
+#define	GPMI_ECCCTRL_HANDLE_OFFSET			16
+#define	GPMI_ECCCTRL_ECC_CMD_MASK			(0x3 << 13)
+#define	GPMI_ECCCTRL_ECC_CMD_OFFSET			13
+#define	GPMI_ECCCTRL_ECC_CMD_DECODE			(0x0 << 13)
+#define	GPMI_ECCCTRL_ECC_CMD_ENCODE			(0x1 << 13)
+#define	GPMI_ECCCTRL_ENABLE_ECC				(1 << 12)
+#define	GPMI_ECCCTRL_BUFFER_MASK_MASK			0x1ff
+#define	GPMI_ECCCTRL_BUFFER_MASK_OFFSET			0
+#define	GPMI_ECCCTRL_BUFFER_MASK_BCH_AUXONLY		0x100
+#define	GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE		0x1ff
+
+#define	GPMI_ECCCOUNT_COUNT_MASK			0xffff
+#define	GPMI_ECCCOUNT_COUNT_OFFSET			0
+
+#define	GPMI_PAYLOAD_ADDRESS_MASK			(0x3fffffff << 2)
+#define	GPMI_PAYLOAD_ADDRESS_OFFSET			2
+
+#define	GPMI_AUXILIARY_ADDRESS_MASK			(0x3fffffff << 2)
+#define	GPMI_AUXILIARY_ADDRESS_OFFSET			2
+
+#define	GPMI_CTRL1_DECOUPLE_CS				(1 << 24)
+#define	GPMI_CTRL1_WRN_DLY_SEL_MASK			(0x3 << 22)
+#define	GPMI_CTRL1_WRN_DLY_SEL_OFFSET			22
+#define	GPMI_CTRL1_TIMEOUT_IRQ_EN			(1 << 20)
+#define	GPMI_CTRL1_GANGED_RDYBUSY			(1 << 19)
+#define	GPMI_CTRL1_BCH_MODE				(1 << 18)
+#define	GPMI_CTRL1_DLL_ENABLE				(1 << 17)
+#define	GPMI_CTRL1_HALF_PERIOD				(1 << 16)
+#define	GPMI_CTRL1_RDN_DELAY_MASK			(0xf << 12)
+#define	GPMI_CTRL1_RDN_DELAY_OFFSET			12
+#define	GPMI_CTRL1_DMA2ECC_MODE				(1 << 11)
+#define	GPMI_CTRL1_DEV_IRQ				(1 << 10)
+#define	GPMI_CTRL1_TIMEOUT_IRQ				(1 << 9)
+#define	GPMI_CTRL1_BURST_EN				(1 << 8)
+#define	GPMI_CTRL1_ABORT_WAIT_REQUEST			(1 << 7)
+#define	GPMI_CTRL1_ABORT_WAIT_FOR_READY_CHANNEL_MASK	(0x7 << 4)
+#define	GPMI_CTRL1_ABORT_WAIT_FOR_READY_CHANNEL_OFFSET	4
+#define	GPMI_CTRL1_DEV_RESET				(1 << 3)
+#define	GPMI_CTRL1_ATA_IRQRDY_POLARITY			(1 << 2)
+#define	GPMI_CTRL1_CAMERA_MODE				(1 << 1)
+#define	GPMI_CTRL1_GPMI_MODE				(1 << 0)
+
+#define	GPMI_TIMING0_ADDRESS_SETUP_MASK			(0xff << 16)
+#define	GPMI_TIMING0_ADDRESS_SETUP_OFFSET		16
+#define	GPMI_TIMING0_DATA_HOLD_MASK			(0xff << 8)
+#define	GPMI_TIMING0_DATA_HOLD_OFFSET			8
+#define	GPMI_TIMING0_DATA_SETUP_MASK			0xff
+#define	GPMI_TIMING0_DATA_SETUP_OFFSET			0
+
+#define	GPMI_TIMING1_DEVICE_BUSY_TIMEOUT_MASK		(0xffff << 16)
+#define	GPMI_TIMING1_DEVICE_BUSY_TIMEOUT_OFFSET		16
+
+#define	GPMI_TIMING2_UDMA_TRP_MASK			(0xff << 24)
+#define	GPMI_TIMING2_UDMA_TRP_OFFSET			24
+#define	GPMI_TIMING2_UDMA_ENV_MASK			(0xff << 16)
+#define	GPMI_TIMING2_UDMA_ENV_OFFSET			16
+#define	GPMI_TIMING2_UDMA_HOLD_MASK			(0xff << 8)
+#define	GPMI_TIMING2_UDMA_HOLD_OFFSET			8
+#define	GPMI_TIMING2_UDMA_SETUP_MASK			0xff
+#define	GPMI_TIMING2_UDMA_SETUP_OFFSET			0
+
+#define	GPMI_DATA_DATA_MASK				0xffffffff
+#define	GPMI_DATA_DATA_OFFSET				0
+
+#define	GPMI_STAT_READY_BUSY_MASK			(0xff << 24)
+#define	GPMI_STAT_READY_BUSY_OFFSET			24
+#define	GPMI_STAT_RDY_TIMEOUT_MASK			(0xff << 16)
+#define	GPMI_STAT_RDY_TIMEOUT_OFFSET			16
+#define	GPMI_STAT_DEV7_ERROR				(1 << 15)
+#define	GPMI_STAT_DEV6_ERROR				(1 << 14)
+#define	GPMI_STAT_DEV5_ERROR				(1 << 13)
+#define	GPMI_STAT_DEV4_ERROR				(1 << 12)
+#define	GPMI_STAT_DEV3_ERROR				(1 << 11)
+#define	GPMI_STAT_DEV2_ERROR				(1 << 10)
+#define	GPMI_STAT_DEV1_ERROR				(1 << 9)
+#define	GPMI_STAT_DEV0_ERROR				(1 << 8)
+#define	GPMI_STAT_ATA_IRQ				(1 << 4)
+#define	GPMI_STAT_INVALID_BUFFER_MASK			(1 << 3)
+#define	GPMI_STAT_FIFO_EMPTY				(1 << 2)
+#define	GPMI_STAT_FIFO_FULL				(1 << 1)
+#define	GPMI_STAT_PRESENT				(1 << 0)
+
+#define	GPMI_DEBUG_WAIT_FOR_READY_END_MASK		(0xff << 24)
+#define	GPMI_DEBUG_WAIT_FOR_READY_END_OFFSET		24
+#define	GPMI_DEBUG_DMA_SENSE_MASK			(0xff << 16)
+#define	GPMI_DEBUG_DMA_SENSE_OFFSET			16
+#define	GPMI_DEBUG_DMAREQ_MASK				(0xff << 8)
+#define	GPMI_DEBUG_DMAREQ_OFFSET			8
+#define	GPMI_DEBUG_CMD_END_MASK				0xff
+#define	GPMI_DEBUG_CMD_END_OFFSET			0
+
+#define	GPMI_VERSION_MAJOR_MASK				(0xff << 24)
+#define	GPMI_VERSION_MAJOR_OFFSET			24
+#define	GPMI_VERSION_MINOR_MASK				(0xff << 16)
+#define	GPMI_VERSION_MINOR_OFFSET			16
+#define	GPMI_VERSION_STEP_MASK				0xffff
+#define	GPMI_VERSION_STEP_OFFSET			0
+
+#define	GPMI_DEBUG2_UDMA_STATE_MASK			(0xf << 24)
+#define	GPMI_DEBUG2_UDMA_STATE_OFFSET			24
+#define	GPMI_DEBUG2_BUSY				(1 << 23)
+#define	GPMI_DEBUG2_PIN_STATE_MASK			(0x7 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_OFFSET			20
+#define	GPMI_DEBUG2_PIN_STATE_PSM_IDLE			(0x0 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_BYTCNT		(0x1 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_ADDR			(0x2 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_STALL			(0x3 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_STROBE		(0x4 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_ATARDY		(0x5 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_DHOLD			(0x6 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_DONE			(0x7 << 20)
+#define	GPMI_DEBUG2_MAIN_STATE_MASK			(0xf << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_OFFSET			16
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_IDLE			(0x0 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_BYTCNT		(0x1 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_WAITFE		(0x2 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_WAITFR		(0x3 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_DMAREQ		(0x4 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_DMAACK		(0x5 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_WAITFF		(0x6 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_LDFIFO		(0x7 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_LDDMAR		(0x8 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_RDCMP		(0x9 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_DONE			(0xa << 16)
+#define	GPMI_DEBUG2_SYND2GPMI_BE_MASK			(0xf << 12)
+#define	GPMI_DEBUG2_SYND2GPMI_BE_OFFSET			12
+#define	GPMI_DEBUG2_GPMI2SYND_VALID			(1 << 11)
+#define	GPMI_DEBUG2_GPMI2SYND_READY			(1 << 10)
+#define	GPMI_DEBUG2_SYND2GPMI_VALID			(1 << 9)
+#define	GPMI_DEBUG2_SYND2GPMI_READY			(1 << 8)
+#define	GPMI_DEBUG2_VIEW_DELAYED_RDN			(1 << 7)
+#define	GPMI_DEBUG2_UPDATE_WINDOW			(1 << 6)
+#define	GPMI_DEBUG2_RDN_TAP_MASK			0x3f
+#define	GPMI_DEBUG2_RDN_TAP_OFFSET			0
+
+#define	GPMI_DEBUG3_APB_WORD_CNTR_MASK			(0xffff << 16)
+#define	GPMI_DEBUG3_APB_WORD_CNTR_OFFSET		16
+#define	GPMI_DEBUG3_DEV_WORD_CNTR_MASK			0xffff
+#define	GPMI_DEBUG3_DEV_WORD_CNTR_OFFSET		0
+
+#endif	/* __MX28_REGS_GPMI_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-i2c.h b/arch/arm/include/asm/arch-mx28/regs-i2c.h
new file mode 100644
index 0000000..30e0ed7
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-i2c.h
@@ -0,0 +1,207 @@
+/*
+ * Freescale i.MX28 I2C Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_I2C_H__
+#define __MX28_REGS_I2C_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_i2c_regs {
+	mx28_reg(hw_i2c_ctrl0)
+	mx28_reg(hw_i2c_timing0)
+	mx28_reg(hw_i2c_timing1)
+	mx28_reg(hw_i2c_timing2)
+	mx28_reg(hw_i2c_ctrl1)
+	mx28_reg(hw_i2c_stat)
+	mx28_reg(hw_i2c_queuectrl)
+	mx28_reg(hw_i2c_queuestat)
+	mx28_reg(hw_i2c_queuecmd)
+	mx28_reg(hw_i2c_queuedata)
+	mx28_reg(hw_i2c_data)
+	mx28_reg(hw_i2c_debug0)
+	mx28_reg(hw_i2c_debug1)
+	mx28_reg(hw_i2c_version)
+};
+#endif
+
+#define	I2C_CTRL_SFTRST				(1 << 31)
+#define	I2C_CTRL_CLKGATE			(1 << 30)
+#define	I2C_CTRL_RUN				(1 << 29)
+#define	I2C_CTRL_PREACK				(1 << 27)
+#define	I2C_CTRL_ACKNOWLEDGE			(1 << 26)
+#define	I2C_CTRL_SEND_NAK_ON_LAST		(1 << 25)
+#define	I2C_CTRL_MULTI_MASTER			(1 << 23)
+#define	I2C_CTRL_CLOCK_HELD			(1 << 22)
+#define	I2C_CTRL_RETAIN_CLOCK			(1 << 21)
+#define	I2C_CTRL_POST_SEND_STOP			(1 << 20)
+#define	I2C_CTRL_PRE_SEND_START			(1 << 19)
+#define	I2C_CTRL_SLAVE_ADDRESS_ENABLE		(1 << 18)
+#define	I2C_CTRL_MASTER_MODE			(1 << 17)
+#define	I2C_CTRL_DIRECTION			(1 << 16)
+#define	I2C_CTRL_XFER_COUNT_MASK		0xffff
+#define	I2C_CTRL_XFER_COUNT_OFFSET		0
+
+#define	I2C_TIMING0_HIGH_COUNT_MASK		(0x3ff << 16)
+#define	I2C_TIMING0_HIGH_COUNT_OFFSET		16
+#define	I2C_TIMING0_RCV_COUNT_MASK		0x3ff
+#define	I2C_TIMING0_RCV_COUNT_OFFSET		0
+
+#define	I2C_TIMING1_LOW_COUNT_MASK		(0x3ff << 16)
+#define	I2C_TIMING1_LOW_COUNT_OFFSET		16
+#define	I2C_TIMING1_XMIT_COUNT_MASK		0x3ff
+#define	I2C_TIMING1_XMIT_COUNT_OFFSET		0
+
+#define	I2C_TIMING2_BUS_FREE_MASK		(0x3ff << 16)
+#define	I2C_TIMING2_BUS_FREE_OFFSET		16
+#define	I2C_TIMING2_LEADIN_COUNT_MASK		0x3ff
+#define	I2C_TIMING2_LEADIN_COUNT_OFFSET		0
+
+#define	I2C_CTRL1_RD_QUEUE_IRQ			(1 << 30)
+#define	I2C_CTRL1_WR_QUEUE_IRQ			(1 << 29)
+#define	I2C_CTRL1_CLR_GOT_A_NAK			(1 << 28)
+#define	I2C_CTRL1_ACK_MODE			(1 << 27)
+#define	I2C_CTRL1_FORCE_DATA_IDLE		(1 << 26)
+#define	I2C_CTRL1_FORCE_CLK_IDLE		(1 << 25)
+#define	I2C_CTRL1_BCAST_SLAVE_EN		(1 << 24)
+#define	I2C_CTRL1_SLAVE_ADDRESS_BYTE_MASK	(0xff << 16)
+#define	I2C_CTRL1_SLAVE_ADDRESS_BYTE_OFFSET	16
+#define	I2C_CTRL1_BUS_FREE_IRQ_EN		(1 << 15)
+#define	I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ_EN	(1 << 14)
+#define	I2C_CTRL1_NO_SLAVE_ACK_IRQ_EN		(1 << 13)
+#define	I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ_EN	(1 << 12)
+#define	I2C_CTRL1_EARLY_TERM_IRQ_EN		(1 << 11)
+#define	I2C_CTRL1_MASTER_LOSS_IRQ_EN		(1 << 10)
+#define	I2C_CTRL1_SLAVE_STOP_IRQ_EN		(1 << 9)
+#define	I2C_CTRL1_SLAVE_IRQ_EN			(1 << 8)
+#define	I2C_CTRL1_BUS_FREE_IRQ			(1 << 7)
+#define	I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ		(1 << 6)
+#define	I2C_CTRL1_NO_SLAVE_ACK_IRQ		(1 << 5)
+#define	I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ	(1 << 4)
+#define	I2C_CTRL1_EARLY_TERM_IRQ		(1 << 3)
+#define	I2C_CTRL1_MASTER_LOSS_IRQ		(1 << 2)
+#define	I2C_CTRL1_SLAVE_STOP_IRQ		(1 << 1)
+#define	I2C_CTRL1_SLAVE_IRQ			(1 << 0)
+
+#define	I2C_STAT_MASTER_PRESENT			(1 << 31)
+#define	I2C_STAT_SLAVE_PRESENT			(1 << 30)
+#define	I2C_STAT_ANY_ENABLED_IRQ		(1 << 29)
+#define	I2C_STAT_GOT_A_NAK			(1 << 28)
+#define	I2C_STAT_RCVD_SLAVE_ADDR_MASK		(0xff << 16)
+#define	I2C_STAT_RCVD_SLAVE_ADDR_OFFSET		16
+#define	I2C_STAT_SLAVE_ADDR_EQ_ZERO		(1 << 15)
+#define	I2C_STAT_SLAVE_FOUND			(1 << 14)
+#define	I2C_STAT_SLAVE_SEARCHING		(1 << 13)
+#define	I2C_STAT_DATA_ENGING_DMA_WAIT		(1 << 12)
+#define	I2C_STAT_BUS_BUSY			(1 << 11)
+#define	I2C_STAT_CLK_GEN_BUSY			(1 << 10)
+#define	I2C_STAT_DATA_ENGINE_BUSY		(1 << 9)
+#define	I2C_STAT_SLAVE_BUSY			(1 << 8)
+#define	I2C_STAT_BUS_FREE_IRQ_SUMMARY		(1 << 7)
+#define	I2C_STAT_DATA_ENGINE_CMPLT_IRQ_SUMMARY	(1 << 6)
+#define	I2C_STAT_NO_SLAVE_ACK_IRQ_SUMMARY	(1 << 5)
+#define	I2C_STAT_OVERSIZE_XFER_TERM_IRQ_SUMMARY	(1 << 4)
+#define	I2C_STAT_EARLY_TERM_IRQ_SUMMARY		(1 << 3)
+#define	I2C_STAT_MASTER_LOSS_IRQ_SUMMARY	(1 << 2)
+#define	I2C_STAT_SLAVE_STOP_IRQ_SUMMARY		(1 << 1)
+#define	I2C_STAT_SLAVE_IRQ_SUMMARY		(1 << 0)
+
+#define	I2C_QUEUECTRL_RD_THRESH_MASK		(0x1f << 16)
+#define	I2C_QUEUECTRL_RD_THRESH_OFFSET		16
+#define	I2C_QUEUECTRL_WR_THRESH_MASK		(0x1f << 8)
+#define	I2C_QUEUECTRL_WR_THRESH_OFFSET		8
+#define	I2C_QUEUECTRL_QUEUE_RUN			(1 << 5)
+#define	I2C_QUEUECTRL_RD_CLEAR			(1 << 4)
+#define	I2C_QUEUECTRL_WR_CLEAR			(1 << 3)
+#define	I2C_QUEUECTRL_PIO_QUEUE_MODE		(1 << 2)
+#define	I2C_QUEUECTRL_RD_QUEUE_IRQ_EN		(1 << 1)
+#define	I2C_QUEUECTRL_WR_QUEUE_IRQ_EN		(1 << 0)
+
+#define	I2C_QUEUESTAT_RD_QUEUE_FULL		(1 << 14)
+#define	I2C_QUEUESTAT_RD_QUEUE_EMPTY		(1 << 13)
+#define	I2C_QUEUESTAT_RD_QUEUE_CNT_MASK		(0x1f << 8)
+#define	I2C_QUEUESTAT_RD_QUEUE_CNT_OFFSET	8
+#define	I2C_QUEUESTAT_WR_QUEUE_FULL		(1 << 6)
+#define	I2C_QUEUESTAT_WR_QUEUE_EMPTY		(1 << 5)
+#define	I2C_QUEUESTAT_WR_QUEUE_CNT_MASK		0x1f
+#define	I2C_QUEUESTAT_WR_QUEUE_CNT_OFFSET	0
+
+#define	I2C_QUEUECMD_PREACK			(1 << 27)
+#define	I2C_QUEUECMD_ACKNOWLEDGE		(1 << 26)
+#define	I2C_QUEUECMD_SEND_NAK_ON_LAST		(1 << 25)
+#define	I2C_QUEUECMD_MULTI_MASTER		(1 << 23)
+#define	I2C_QUEUECMD_CLOCK_HELD			(1 << 22)
+#define	I2C_QUEUECMD_RETAIN_CLOCK		(1 << 21)
+#define	I2C_QUEUECMD_POST_SEND_STOP		(1 << 20)
+#define	I2C_QUEUECMD_PRE_SEND_START		(1 << 19)
+#define	I2C_QUEUECMD_SLAVE_ADDRESS_ENABLE	(1 << 18)
+#define	I2C_QUEUECMD_MASTER_MODE		(1 << 17)
+#define	I2C_QUEUECMD_DIRECTION			(1 << 16)
+#define	I2C_QUEUECMD_XFER_COUNT_MASK		0xffff
+#define	I2C_QUEUECMD_XFER_COUNT_OFFSET		0
+
+#define	I2C_QUEUEDATA_DATA_MASK			0xffffffff
+#define	I2C_QUEUEDATA_DATA_OFFSET		0
+
+#define	I2C_DATA_DATA_MASK			0xffffffff
+#define	I2C_DATA_DATA_OFFSET			0
+
+#define	I2C_DEBUG0_DMAREQ			(1 << 31)
+#define	I2C_DEBUG0_DMAENDCMD			(1 << 30)
+#define	I2C_DEBUG0_DMAKICK			(1 << 29)
+#define	I2C_DEBUG0_DMATERMINATE			(1 << 28)
+#define	I2C_DEBUG0_STATE_VALUE_MASK		(0x3 << 26)
+#define	I2C_DEBUG0_STATE_VALUE_OFFSET		26
+#define	I2C_DEBUG0_DMA_STATE_MASK		(0x3ff << 16)
+#define	I2C_DEBUG0_DMA_STATE_OFFSET		16
+#define	I2C_DEBUG0_START_TOGGLE			(1 << 15)
+#define	I2C_DEBUG0_STOP_TOGGLE			(1 << 14)
+#define	I2C_DEBUG0_GRAB_TOGGLE			(1 << 13)
+#define	I2C_DEBUG0_CHANGE_TOGGLE		(1 << 12)
+#define	I2C_DEBUG0_STATE_LATCH			(1 << 11)
+#define	I2C_DEBUG0_SLAVE_HOLD_CLK		(1 << 10)
+#define	I2C_DEBUG0_STATE_STATE_MASK		0x3ff
+#define	I2C_DEBUG0_STATE_STATE_OFFSET		0
+
+#define	I2C_DEBUG1_I2C_CLK_IN			(1 << 31)
+#define	I2C_DEBUG1_I2C_DATA_IN			(1 << 30)
+#define	I2C_DEBUG1_DMA_BYTE_ENABLES_MASK	(0xf << 24)
+#define	I2C_DEBUG1_DMA_BYTE_ENABLES_OFFSET	24
+#define	I2C_DEBUG1_CLK_GEN_STATE_MASK		(0xff << 16)
+#define	I2C_DEBUG1_CLK_GEN_STATE_OFFSET		16
+#define	I2C_DEBUG1_LST_MODE_MASK		(0x3 << 9)
+#define	I2C_DEBUG1_LST_MODE_OFFSET		9
+#define	I2C_DEBUG1_LOCAL_SLAVE_TEST		(1 << 8)
+#define	I2C_DEBUG1_FORCE_CLK_ON			(1 << 4)
+#define	I2C_DEBUG1_FORCE_ABR_LOSS		(1 << 3)
+#define	I2C_DEBUG1_FORCE_RCV_ACK		(1 << 2)
+#define	I2C_DEBUG1_FORCE_I2C_DATA_OE		(1 << 1)
+#define	I2C_DEBUG1_FORCE_I2C_CLK_OE		(1 << 0)
+
+#define	I2C_VERSION_MAJOR_MASK			(0xff << 24)
+#define	I2C_VERSION_MAJOR_OFFSET		24
+#define	I2C_VERSION_MINOR_MASK			(0xff << 16)
+#define	I2C_VERSION_MINOR_OFFSET		16
+#define	I2C_VERSION_STEP_MASK			0xffff
+#define	I2C_VERSION_STEP_OFFSET			0
+
+#endif	/* __MX28_REGS_I2C_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-ocotp.h b/arch/arm/include/asm/arch-mx28/regs-ocotp.h
new file mode 100644
index 0000000..ea2fd7b
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-ocotp.h
@@ -0,0 +1,173 @@
+/*
+ * Freescale i.MX28 OCOTP Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_OCOTP_H__
+#define __MX28_REGS_OCOTP_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_ocotp_regs {
+	mx28_reg(hw_ocotp_ctrl)		/* 0x0 */
+	mx28_reg(hw_ocotp_data)		/* 0x10 */
+	mx28_reg(hw_ocotp_cust0)	/* 0x20 */
+	mx28_reg(hw_ocotp_cust1)	/* 0x30 */
+	mx28_reg(hw_ocotp_cust2)	/* 0x40 */
+	mx28_reg(hw_ocotp_cust3)	/* 0x50 */
+	mx28_reg(hw_ocotp_crypto0)	/* 0x60 */
+	mx28_reg(hw_ocotp_crypto1)	/* 0x70 */
+	mx28_reg(hw_ocotp_crypto2)	/* 0x80 */
+	mx28_reg(hw_ocotp_crypto3)	/* 0x90 */
+	mx28_reg(hw_ocotp_hwcap0)	/* 0xa0 */
+	mx28_reg(hw_ocotp_hwcap1)	/* 0xb0 */
+	mx28_reg(hw_ocotp_hwcap2)	/* 0xc0 */
+	mx28_reg(hw_ocotp_hwcap3)	/* 0xd0 */
+	mx28_reg(hw_ocotp_hwcap4)	/* 0xe0 */
+	mx28_reg(hw_ocotp_hwcap5)	/* 0xf0 */
+	mx28_reg(hw_ocotp_swcap)	/* 0x100 */
+	mx28_reg(hw_ocotp_custcap)	/* 0x110 */
+	mx28_reg(hw_ocotp_lock)		/* 0x120 */
+	mx28_reg(hw_ocotp_ops0)		/* 0x130 */
+	mx28_reg(hw_ocotp_ops1)		/* 0x140 */
+	mx28_reg(hw_ocotp_ops2)		/* 0x150 */
+	mx28_reg(hw_ocotp_ops3)		/* 0x160 */
+	mx28_reg(hw_ocotp_un0)		/* 0x170 */
+	mx28_reg(hw_ocotp_un1)		/* 0x180 */
+	mx28_reg(hw_ocotp_un2)		/* 0x190 */
+	mx28_reg(hw_ocotp_rom0)		/* 0x1a0 */
+	mx28_reg(hw_ocotp_rom1)		/* 0x1b0 */
+	mx28_reg(hw_ocotp_rom2)		/* 0x1c0 */
+	mx28_reg(hw_ocotp_rom3)		/* 0x1d0 */
+	mx28_reg(hw_ocotp_rom4)		/* 0x1e0 */
+	mx28_reg(hw_ocotp_rom5)		/* 0x1f0 */
+	mx28_reg(hw_ocotp_rom6)		/* 0x200 */
+	mx28_reg(hw_ocotp_rom7)		/* 0x210 */
+	mx28_reg(hw_ocotp_srk0)		/* 0x220 */
+	mx28_reg(hw_ocotp_srk1)		/* 0x230 */
+	mx28_reg(hw_ocotp_srk2)		/* 0x240 */
+	mx28_reg(hw_ocotp_srk3)		/* 0x250 */
+	mx28_reg(hw_ocotp_srk4)		/* 0x260 */
+	mx28_reg(hw_ocotp_srk5)		/* 0x270 */
+	mx28_reg(hw_ocotp_srk6)		/* 0x280 */
+	mx28_reg(hw_ocotp_srk7)		/* 0x290 */
+	mx28_reg(hw_ocotp_version)	/* 0x2a0 */
+};
+#endif
+
+#define	OCOTP_CTRL_WR_UNLOCK_MASK		(0xffff << 16)
+#define	OCOTP_CTRL_WR_UNLOCK_OFFSET		16
+#define	OCOTP_CTRL_WR_UNLOCK_KEY		(0x3e77 << 16)
+#define	OCOTP_CTRL_RELOAD_SHADOWS		(1 << 13)
+#define	OCOTP_CTRL_RD_BANK_OPEN			(1 << 12)
+#define	OCOTP_CTRL_ERROR			(1 << 9)
+#define	OCOTP_CTRL_BUSY				(1 << 8)
+#define	OCOTP_CTRL_ADDR_MASK			0x3f
+#define	OCOTP_CTRL_ADDR_OFFSET			0
+
+#define	OCOTP_DATA_DATA_MASK			0xffffffff
+#define	OCOTP_DATA_DATA_OFFSET			0
+
+#define	OCOTP_CUST_BITS_MASK			0xffffffff
+#define	OCOTP_CUST_BITS_OFFSET			0
+
+#define	OCOTP_CRYPTO_BITS_MASK			0xffffffff
+#define	OCOTP_CRYPTO_BITS_OFFSET		0
+
+#define	OCOTP_HWCAP_BITS_MASK			0xffffffff
+#define	OCOTP_HWCAP_BITS_OFFSET			0
+
+#define	OCOTP_SWCAP_BITS_MASK			0xffffffff
+#define	OCOTP_SWCAP_BITS_OFFSET			0
+
+#define	OCOTP_CUSTCAP_RTC_XTAL_32768_PRESENT	(1 << 2)
+#define	OCOTP_CUSTCAP_RTC_XTAL_32000_PRESENT	(1 << 1)
+
+#define	OCOTP_LOCK_ROM7				(1 << 31)
+#define	OCOTP_LOCK_ROM6				(1 << 30)
+#define	OCOTP_LOCK_ROM5				(1 << 29)
+#define	OCOTP_LOCK_ROM4				(1 << 28)
+#define	OCOTP_LOCK_ROM3				(1 << 27)
+#define	OCOTP_LOCK_ROM2				(1 << 26)
+#define	OCOTP_LOCK_ROM1				(1 << 25)
+#define	OCOTP_LOCK_ROM0				(1 << 24)
+#define	OCOTP_LOCK_HWSW_SHADOW_ALT		(1 << 23)
+#define	OCOTP_LOCK_CRYPTODCP_ALT		(1 << 22)
+#define	OCOTP_LOCK_CRYPTOKEY_ALT		(1 << 21)
+#define	OCOTP_LOCK_PIN				(1 << 20)
+#define	OCOTP_LOCK_OPS				(1 << 19)
+#define	OCOTP_LOCK_UN2				(1 << 18)
+#define	OCOTP_LOCK_UN1				(1 << 17)
+#define	OCOTP_LOCK_UN0				(1 << 16)
+#define	OCOTP_LOCK_SRK				(1 << 15)
+#define	OCOTP_LOCK_UNALLOCATED_MASK		(0x7 << 12)
+#define	OCOTP_LOCK_UNALLOCATED_OFFSET		12
+#define	OCOTP_LOCK_SRK_SHADOW			(1 << 11)
+#define	OCOTP_LOCK_ROM_SHADOW			(1 << 10)
+#define	OCOTP_LOCK_CUSTCAP			(1 << 9)
+#define	OCOTP_LOCK_HWSW				(1 << 8)
+#define	OCOTP_LOCK_CUSTCAP_SHADOW		(1 << 7)
+#define	OCOTP_LOCK_HWSW_SHADOW			(1 << 6)
+#define	OCOTP_LOCK_CRYPTODCP			(1 << 5)
+#define	OCOTP_LOCK_CRYPTOKEY			(1 << 4)
+#define	OCOTP_LOCK_CUST3			(1 << 3)
+#define	OCOTP_LOCK_CUST2			(1 << 2)
+#define	OCOTP_LOCK_CUST1			(1 << 1)
+#define	OCOTP_LOCK_CUST0			(1 << 0)
+
+#define	OCOTP_OPS_BITS_MASK			0xffffffff
+#define	OCOTP_OPS_BITS_OFFSET			0
+
+#define	OCOTP_UN_BITS_MASK			0xffffffff
+#define	OCOTP_UN_BITS_OFFSET			0
+
+#define	OCOTP_ROM_BOOT_MODE_MASK		(0xff << 24)
+#define	OCOTP_ROM_BOOT_MODE_OFFSET		24
+#define	OCOTP_ROM_SD_MMC_MODE_MASK		(0x3 << 22)
+#define	OCOTP_ROM_SD_MMC_MODE_OFFSET		22
+#define	OCOTP_ROM_SD_POWER_GATE_GPIO_MASK	(0x3 << 20)
+#define	OCOTP_ROM_SD_POWER_GATE_GPIO_OFFSET	20
+#define	OCOTP_ROM_SD_POWER_UP_DELAY_MASK	(0x3f << 14)
+#define	OCOTP_ROM_SD_POWER_UP_DELAY_OFFSET	14
+#define	OCOTP_ROM_SD_BUS_WIDTH_MASK		(0x3 << 12)
+#define	OCOTP_ROM_SD_BUS_WIDTH_OFFSET		12
+#define	OCOTP_ROM_SSP_SCK_INDEX_MASK		(0xf << 8)
+#define	OCOTP_ROM_SSP_SCK_INDEX_OFFSET		8
+#define	OCOTP_ROM_EMMC_USE_DDR			(1 << 7)
+#define	OCOTP_ROM_DISABLE_SPI_NOR_FAST_READ	(1 << 6)
+#define	OCOTP_ROM_ENABLE_USB_BOOT_SERIAL_NUM	(1 << 5)
+#define	OCOTP_ROM_ENABLE_UNENCRYPTED_BOOT	(1 << 4)
+#define	OCOTP_ROM_SD_MBR_BOOT			(1 << 3)
+
+#define	OCOTP_SRK_BITS_MASK			0xffffffff
+#define	OCOTP_SRK_BITS_OFFSET			0
+
+#define	OCOTP_VERSION_MAJOR_MASK		(0xff << 24)
+#define	OCOTP_VERSION_MAJOR_OFFSET		24
+#define	OCOTP_VERSION_MINOR_MASK		(0xff << 16)
+#define	OCOTP_VERSION_MINOR_OFFSET		16
+#define	OCOTP_VERSION_STEP_MASK			0xffff
+#define	OCOTP_VERSION_STEP_OFFSET		0
+
+#endif /* __MX28_REGS_OCOTP_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-pinctrl.h b/arch/arm/include/asm/arch-mx28/regs-pinctrl.h
new file mode 100644
index 0000000..73739ca
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-pinctrl.h
@@ -0,0 +1,1284 @@
+/*
+ * Freescale i.MX28 PINCTRL Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_PINCTRL_H__
+#define __MX28_REGS_PINCTRL_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_pinctrl_regs {
+	mx28_reg(hw_pinctrl_ctrl)		/* 0x0 */
+
+	uint32_t	reserved1[60];
+
+	mx28_reg(hw_pinctrl_muxsel0)		/* 0x100 */
+	mx28_reg(hw_pinctrl_muxsel1)		/* 0x110 */
+	mx28_reg(hw_pinctrl_muxsel2)		/* 0x120 */
+	mx28_reg(hw_pinctrl_muxsel3)		/* 0x130 */
+	mx28_reg(hw_pinctrl_muxsel4)		/* 0x140 */
+	mx28_reg(hw_pinctrl_muxsel5)		/* 0x150 */
+	mx28_reg(hw_pinctrl_muxsel6)		/* 0x160 */
+	mx28_reg(hw_pinctrl_muxsel7)		/* 0x170 */
+	mx28_reg(hw_pinctrl_muxsel8)		/* 0x180 */
+	mx28_reg(hw_pinctrl_muxsel9)		/* 0x190 */
+	mx28_reg(hw_pinctrl_muxsel10)		/* 0x1a0 */
+	mx28_reg(hw_pinctrl_muxsel11)		/* 0x1b0 */
+	mx28_reg(hw_pinctrl_muxsel12)		/* 0x1c0 */
+	mx28_reg(hw_pinctrl_muxsel13)		/* 0x1d0 */
+
+	uint32_t	reserved2[72];
+
+	mx28_reg(hw_pinctrl_drive0)		/* 0x300 */
+	mx28_reg(hw_pinctrl_drive1)		/* 0x310 */
+	mx28_reg(hw_pinctrl_drive2)		/* 0x320 */
+	mx28_reg(hw_pinctrl_drive3)		/* 0x330 */
+	mx28_reg(hw_pinctrl_drive4)		/* 0x340 */
+	mx28_reg(hw_pinctrl_drive5)		/* 0x350 */
+	mx28_reg(hw_pinctrl_drive6)		/* 0x360 */
+	mx28_reg(hw_pinctrl_drive7)		/* 0x370 */
+	mx28_reg(hw_pinctrl_drive8)		/* 0x380 */
+	mx28_reg(hw_pinctrl_drive9)		/* 0x390 */
+	mx28_reg(hw_pinctrl_drive10)		/* 0x3a0 */
+	mx28_reg(hw_pinctrl_drive11)		/* 0x3b0 */
+	mx28_reg(hw_pinctrl_drive12)		/* 0x3c0 */
+	mx28_reg(hw_pinctrl_drive13)		/* 0x3d0 */
+	mx28_reg(hw_pinctrl_drive14)		/* 0x3e0 */
+	mx28_reg(hw_pinctrl_drive15)		/* 0x3f0 */
+	mx28_reg(hw_pinctrl_drive16)		/* 0x400 */
+	mx28_reg(hw_pinctrl_drive17)		/* 0x410 */
+	mx28_reg(hw_pinctrl_drive18)		/* 0x420 */
+	mx28_reg(hw_pinctrl_drive19)		/* 0x430 */
+
+	uint32_t	reserved3[112];
+
+	mx28_reg(hw_pinctrl_pull0)		/* 0x600 */
+	mx28_reg(hw_pinctrl_pull1)		/* 0x610 */
+	mx28_reg(hw_pinctrl_pull2)		/* 0x620 */
+	mx28_reg(hw_pinctrl_pull3)		/* 0x630 */
+	mx28_reg(hw_pinctrl_pull4)		/* 0x640 */
+	mx28_reg(hw_pinctrl_pull5)		/* 0x650 */
+	mx28_reg(hw_pinctrl_pull6)		/* 0x660 */
+
+	uint32_t	reserved4[36];
+
+	mx28_reg(hw_pinctrl_dout0)		/* 0x700 */
+	mx28_reg(hw_pinctrl_dout1)		/* 0x710 */
+	mx28_reg(hw_pinctrl_dout2)		/* 0x720 */
+	mx28_reg(hw_pinctrl_dout3)		/* 0x730 */
+	mx28_reg(hw_pinctrl_dout4)		/* 0x740 */
+
+	uint32_t	reserved5[108];
+
+	mx28_reg(hw_pinctrl_din0)		/* 0x900 */
+	mx28_reg(hw_pinctrl_din1)		/* 0x910 */
+	mx28_reg(hw_pinctrl_din2)		/* 0x920 */
+	mx28_reg(hw_pinctrl_din3)		/* 0x930 */
+	mx28_reg(hw_pinctrl_din4)		/* 0x940 */
+
+	uint32_t	reserved6[108];
+
+	mx28_reg(hw_pinctrl_doe0)		/* 0xb00 */
+	mx28_reg(hw_pinctrl_doe1)		/* 0xb10 */
+	mx28_reg(hw_pinctrl_doe2)		/* 0xb20 */
+	mx28_reg(hw_pinctrl_doe3)		/* 0xb30 */
+	mx28_reg(hw_pinctrl_doe4)		/* 0xb40 */
+
+	uint32_t	reserved7[300];
+
+	mx28_reg(hw_pinctrl_pin2irq0)		/* 0x1000 */
+	mx28_reg(hw_pinctrl_pin2irq1)		/* 0x1010 */
+	mx28_reg(hw_pinctrl_pin2irq2)		/* 0x1020 */
+	mx28_reg(hw_pinctrl_pin2irq3)		/* 0x1030 */
+	mx28_reg(hw_pinctrl_pin2irq4)		/* 0x1040 */
+
+	uint32_t	reserved8[44];
+
+	mx28_reg(hw_pinctrl_irqen0)		/* 0x1100 */
+	mx28_reg(hw_pinctrl_irqen1)		/* 0x1110 */
+	mx28_reg(hw_pinctrl_irqen2)		/* 0x1120 */
+	mx28_reg(hw_pinctrl_irqen3)		/* 0x1130 */
+	mx28_reg(hw_pinctrl_irqen4)		/* 0x1140 */
+
+	uint32_t	reserved9[44];
+
+	mx28_reg(hw_pinctrl_irqlevel0)		/* 0x1200 */
+	mx28_reg(hw_pinctrl_irqlevel1)		/* 0x1210 */
+	mx28_reg(hw_pinctrl_irqlevel2)		/* 0x1220 */
+	mx28_reg(hw_pinctrl_irqlevel3)		/* 0x1230 */
+	mx28_reg(hw_pinctrl_irqlevel4)		/* 0x1240 */
+
+	uint32_t	reserved10[44];
+
+	mx28_reg(hw_pinctrl_irqpol0)		/* 0x1300 */
+	mx28_reg(hw_pinctrl_irqpol1)		/* 0x1310 */
+	mx28_reg(hw_pinctrl_irqpol2)		/* 0x1320 */
+	mx28_reg(hw_pinctrl_irqpol3)		/* 0x1330 */
+	mx28_reg(hw_pinctrl_irqpol4)		/* 0x1340 */
+
+	uint32_t	reserved11[44];
+
+	mx28_reg(hw_pinctrl_irqstat0)		/* 0x1400 */
+	mx28_reg(hw_pinctrl_irqstat1)		/* 0x1410 */
+	mx28_reg(hw_pinctrl_irqstat2)		/* 0x1420 */
+	mx28_reg(hw_pinctrl_irqstat3)		/* 0x1430 */
+	mx28_reg(hw_pinctrl_irqstat4)		/* 0x1440 */
+
+	uint32_t	reserved12[380];
+
+	mx28_reg(hw_pinctrl_emi_odt_ctrl)	/* 0x1a40 */
+
+	uint32_t	reserved13[76];
+
+	mx28_reg(hw_pinctrl_emi_ds_ctrl)	/* 0x1b80 */
+};
+#endif
+
+#define	PINCTRL_CTRL_SFTRST				(1 << 31)
+#define	PINCTRL_CTRL_CLKGATE				(1 << 30)
+#define	PINCTRL_CTRL_PRESENT4				(1 << 24)
+#define	PINCTRL_CTRL_PRESENT3				(1 << 23)
+#define	PINCTRL_CTRL_PRESENT2				(1 << 22)
+#define	PINCTRL_CTRL_PRESENT1				(1 << 21)
+#define	PINCTRL_CTRL_PRESENT0				(1 << 20)
+#define	PINCTRL_CTRL_IRQOUT4				(1 << 4)
+#define	PINCTRL_CTRL_IRQOUT3				(1 << 3)
+#define	PINCTRL_CTRL_IRQOUT2				(1 << 2)
+#define	PINCTRL_CTRL_IRQOUT1				(1 << 1)
+#define	PINCTRL_CTRL_IRQOUT0				(1 << 0)
+
+#define	PINCTRL_MUXSEL0_BANK0_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL0_BANK0_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL0_BANK0_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL0_BANK0_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL0_BANK0_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL0_BANK0_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL0_BANK0_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL0_BANK0_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL0_BANK0_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL0_BANK0_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL0_BANK0_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL0_BANK0_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL0_BANK0_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL0_BANK0_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL0_BANK0_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL0_BANK0_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL1_BANK0_PIN28_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL1_BANK0_PIN28_OFFSET		24
+#define	PINCTRL_MUXSEL1_BANK0_PIN27_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL1_BANK0_PIN27_OFFSET		22
+#define	PINCTRL_MUXSEL1_BANK0_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL1_BANK0_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL1_BANK0_PIN25_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL1_BANK0_PIN25_OFFSET		18
+#define	PINCTRL_MUXSEL1_BANK0_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL1_BANK0_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL1_BANK0_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL1_BANK0_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL1_BANK0_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL1_BANK0_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL1_BANK0_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL1_BANK0_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL1_BANK0_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL1_BANK0_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL1_BANK0_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL1_BANK0_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL1_BANK0_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL1_BANK0_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL1_BANK0_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL1_BANK0_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL1_BANK0_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL1_BANK0_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL2_BANK1_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL2_BANK1_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL2_BANK1_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL2_BANK1_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL2_BANK1_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL2_BANK1_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL2_BANK1_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL2_BANK1_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL2_BANK1_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL2_BANK1_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL2_BANK1_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL2_BANK1_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL2_BANK1_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL2_BANK1_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL2_BANK1_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL2_BANK1_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL2_BANK1_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL2_BANK1_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL2_BANK1_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL2_BANK1_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL2_BANK1_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL2_BANK1_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL2_BANK1_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL2_BANK1_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL2_BANK1_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL2_BANK1_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL2_BANK1_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL2_BANK1_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL2_BANK1_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL2_BANK1_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL2_BANK1_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL2_BANK1_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL3_BANK1_PIN31_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL3_BANK1_PIN31_OFFSET		30
+#define	PINCTRL_MUXSEL3_BANK1_PIN30_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL3_BANK1_PIN30_OFFSET		28
+#define	PINCTRL_MUXSEL3_BANK1_PIN29_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL3_BANK1_PIN29_OFFSET		26
+#define	PINCTRL_MUXSEL3_BANK1_PIN28_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL3_BANK1_PIN28_OFFSET		24
+#define	PINCTRL_MUXSEL3_BANK1_PIN27_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL3_BANK1_PIN27_OFFSET		22
+#define	PINCTRL_MUXSEL3_BANK1_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL3_BANK1_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL3_BANK1_PIN25_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL3_BANK1_PIN25_OFFSET		18
+#define	PINCTRL_MUXSEL3_BANK1_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL3_BANK1_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL3_BANK1_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL3_BANK1_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL3_BANK1_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL3_BANK1_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL3_BANK1_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL3_BANK1_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL3_BANK1_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL3_BANK1_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL3_BANK1_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL3_BANK1_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL3_BANK1_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL3_BANK1_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL3_BANK1_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL3_BANK1_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL3_BANK1_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL3_BANK1_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL4_BANK2_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL4_BANK2_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL4_BANK2_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL4_BANK2_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL4_BANK2_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL4_BANK2_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL4_BANK2_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL4_BANK2_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL4_BANK2_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL4_BANK2_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL4_BANK2_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL4_BANK2_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL4_BANK2_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL4_BANK2_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL4_BANK2_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL4_BANK2_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL4_BANK2_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL4_BANK2_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL4_BANK2_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL4_BANK2_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL4_BANK2_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL4_BANK2_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL4_BANK2_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL4_BANK2_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL4_BANK2_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL4_BANK2_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL4_BANK2_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL4_BANK2_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL4_BANK2_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL4_BANK2_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL5_BANK2_PIN27_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL5_BANK2_PIN27_OFFSET		22
+#define	PINCTRL_MUXSEL5_BANK2_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL5_BANK2_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL5_BANK2_PIN25_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL5_BANK2_PIN25_OFFSET		18
+#define	PINCTRL_MUXSEL5_BANK2_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL5_BANK2_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL5_BANK2_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL5_BANK2_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL5_BANK2_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL5_BANK2_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL5_BANK2_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL5_BANK2_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL5_BANK2_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL5_BANK2_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL5_BANK2_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL5_BANK2_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL5_BANK2_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL5_BANK2_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL6_BANK3_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL6_BANK3_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL6_BANK3_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL6_BANK3_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL6_BANK3_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL6_BANK3_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL6_BANK3_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL6_BANK3_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL6_BANK3_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL6_BANK3_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL6_BANK3_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL6_BANK3_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL6_BANK3_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL6_BANK3_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL6_BANK3_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL6_BANK3_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL6_BANK3_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL6_BANK3_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL6_BANK3_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL6_BANK3_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL6_BANK3_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL6_BANK3_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL6_BANK3_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL6_BANK3_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL6_BANK3_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL6_BANK3_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL6_BANK3_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL6_BANK3_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL6_BANK3_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL6_BANK3_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL6_BANK3_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL6_BANK3_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL7_BANK3_PIN30_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL7_BANK3_PIN30_OFFSET		28
+#define	PINCTRL_MUXSEL7_BANK3_PIN29_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL7_BANK3_PIN29_OFFSET		26
+#define	PINCTRL_MUXSEL7_BANK3_PIN28_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL7_BANK3_PIN28_OFFSET		24
+#define	PINCTRL_MUXSEL7_BANK3_PIN27_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL7_BANK3_PIN27_OFFSET		22
+#define	PINCTRL_MUXSEL7_BANK3_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL7_BANK3_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL7_BANK3_PIN25_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL7_BANK3_PIN25_OFFSET		18
+#define	PINCTRL_MUXSEL7_BANK3_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL7_BANK3_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL7_BANK3_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL7_BANK3_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL7_BANK3_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL7_BANK3_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL7_BANK3_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL7_BANK3_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL7_BANK3_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL7_BANK3_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL7_BANK3_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL7_BANK3_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL7_BANK3_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL7_BANK3_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL7_BANK3_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL7_BANK3_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL8_BANK4_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL8_BANK4_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL8_BANK4_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL8_BANK4_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL8_BANK4_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL8_BANK4_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL8_BANK4_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL8_BANK4_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL8_BANK4_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL8_BANK4_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL8_BANK4_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL8_BANK4_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL8_BANK4_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL8_BANK4_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL8_BANK4_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL8_BANK4_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL8_BANK4_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL8_BANK4_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL8_BANK4_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL8_BANK4_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL8_BANK4_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL8_BANK4_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL8_BANK4_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL8_BANK4_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL8_BANK4_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL8_BANK4_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL8_BANK4_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL8_BANK4_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL8_BANK4_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL8_BANK4_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL8_BANK4_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL8_BANK4_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL9_BANK4_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL9_BANK4_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL9_BANK4_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL9_BANK4_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL10_BANK5_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL10_BANK5_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL10_BANK5_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL10_BANK5_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL10_BANK5_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL10_BANK5_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL10_BANK5_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL10_BANK5_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL10_BANK5_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL10_BANK5_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL10_BANK5_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL10_BANK5_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL10_BANK5_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL10_BANK5_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL10_BANK5_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL10_BANK5_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL10_BANK5_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL10_BANK5_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL10_BANK5_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL10_BANK5_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL10_BANK5_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL10_BANK5_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL10_BANK5_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL10_BANK5_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL10_BANK5_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL10_BANK5_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL10_BANK5_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL10_BANK5_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL10_BANK5_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL10_BANK5_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL10_BANK5_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL10_BANK5_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL11_BANK5_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL11_BANK5_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL11_BANK5_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL11_BANK5_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL11_BANK5_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL11_BANK5_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL11_BANK5_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL11_BANK5_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL11_BANK5_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL11_BANK5_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL11_BANK5_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL11_BANK5_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL11_BANK5_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL11_BANK5_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL11_BANK5_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL11_BANK5_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL11_BANK5_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL11_BANK5_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL12_BANK6_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL12_BANK6_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL12_BANK6_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL12_BANK6_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL12_BANK6_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL12_BANK6_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL12_BANK6_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL12_BANK6_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL12_BANK6_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL12_BANK6_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL12_BANK6_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL12_BANK6_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL12_BANK6_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL12_BANK6_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL12_BANK6_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL12_BANK6_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL12_BANK6_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL12_BANK6_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL12_BANK6_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL12_BANK6_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL12_BANK6_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL12_BANK6_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL12_BANK6_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL12_BANK6_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL12_BANK6_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL12_BANK6_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL12_BANK6_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL12_BANK6_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL12_BANK6_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL12_BANK6_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL13_BANK6_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL13_BANK6_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL13_BANK6_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL13_BANK6_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL13_BANK6_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL13_BANK6_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL13_BANK6_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL13_BANK6_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL13_BANK6_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL13_BANK6_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL13_BANK6_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL13_BANK6_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL13_BANK6_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL13_BANK6_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL13_BANK6_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL13_BANK6_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL13_BANK6_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL13_BANK6_PIN16_OFFSET		0
+
+#define	PINCTRL_DRIVE0_BANK0_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE0_BANK0_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE0_BANK0_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE0_BANK0_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE0_BANK0_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE0_BANK0_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE0_BANK0_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE0_BANK0_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE0_BANK0_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE0_BANK0_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE0_BANK0_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE0_BANK0_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE0_BANK0_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE0_BANK0_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE0_BANK0_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE0_BANK0_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE0_BANK0_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE0_BANK0_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE0_BANK0_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE0_BANK0_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE0_BANK0_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE0_BANK0_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE0_BANK0_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE0_BANK0_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE2_BANK0_PIN23_V			(1 << 30)
+#define	PINCTRL_DRIVE2_BANK0_PIN23_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE2_BANK0_PIN23_MA_OFFSET		28
+#define	PINCTRL_DRIVE2_BANK0_PIN22_V			(1 << 26)
+#define	PINCTRL_DRIVE2_BANK0_PIN22_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE2_BANK0_PIN22_MA_OFFSET		24
+#define	PINCTRL_DRIVE2_BANK0_PIN21_V			(1 << 22)
+#define	PINCTRL_DRIVE2_BANK0_PIN21_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE2_BANK0_PIN21_MA_OFFSET		20
+#define	PINCTRL_DRIVE2_BANK0_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE2_BANK0_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE2_BANK0_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE2_BANK0_PIN19_V			(1 << 14)
+#define	PINCTRL_DRIVE2_BANK0_PIN19_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE2_BANK0_PIN19_MA_OFFSET		12
+#define	PINCTRL_DRIVE2_BANK0_PIN18_V			(1 << 10)
+#define	PINCTRL_DRIVE2_BANK0_PIN18_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE2_BANK0_PIN18_MA_OFFSET		8
+#define	PINCTRL_DRIVE2_BANK0_PIN17_V			(1 << 6)
+#define	PINCTRL_DRIVE2_BANK0_PIN17_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE2_BANK0_PIN17_MA_OFFSET		4
+#define	PINCTRL_DRIVE2_BANK0_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE2_BANK0_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE2_BANK0_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE3_BANK0_PIN28_V			(1 << 18)
+#define	PINCTRL_DRIVE3_BANK0_PIN28_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE3_BANK0_PIN28_MA_OFFSET		16
+#define	PINCTRL_DRIVE3_BANK0_PIN27_V			(1 << 14)
+#define	PINCTRL_DRIVE3_BANK0_PIN27_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE3_BANK0_PIN27_MA_OFFSET		12
+#define	PINCTRL_DRIVE3_BANK0_PIN26_V			(1 << 10)
+#define	PINCTRL_DRIVE3_BANK0_PIN26_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE3_BANK0_PIN26_MA_OFFSET		8
+#define	PINCTRL_DRIVE3_BANK0_PIN25_V			(1 << 6)
+#define	PINCTRL_DRIVE3_BANK0_PIN25_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE3_BANK0_PIN25_MA_OFFSET		4
+#define	PINCTRL_DRIVE3_BANK0_PIN24_V			(1 << 2)
+#define	PINCTRL_DRIVE3_BANK0_PIN24_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE3_BANK0_PIN24_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE4_BANK1_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE4_BANK1_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE4_BANK1_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE4_BANK1_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE4_BANK1_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE4_BANK1_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE4_BANK1_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE4_BANK1_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE4_BANK1_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE4_BANK1_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE4_BANK1_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE4_BANK1_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE4_BANK1_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE4_BANK1_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE4_BANK1_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE4_BANK1_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE4_BANK1_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE4_BANK1_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE4_BANK1_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE4_BANK1_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE4_BANK1_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE4_BANK1_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE4_BANK1_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE4_BANK1_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE5_BANK1_PIN15_V			(1 << 30)
+#define	PINCTRL_DRIVE5_BANK1_PIN15_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE5_BANK1_PIN15_MA_OFFSET		28
+#define	PINCTRL_DRIVE5_BANK1_PIN14_V			(1 << 26)
+#define	PINCTRL_DRIVE5_BANK1_PIN14_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE5_BANK1_PIN14_MA_OFFSET		24
+#define	PINCTRL_DRIVE5_BANK1_PIN13_V			(1 << 22)
+#define	PINCTRL_DRIVE5_BANK1_PIN13_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE5_BANK1_PIN13_MA_OFFSET		20
+#define	PINCTRL_DRIVE5_BANK1_PIN12_V			(1 << 18)
+#define	PINCTRL_DRIVE5_BANK1_PIN12_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE5_BANK1_PIN12_MA_OFFSET		16
+#define	PINCTRL_DRIVE5_BANK1_PIN11_V			(1 << 14)
+#define	PINCTRL_DRIVE5_BANK1_PIN11_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE5_BANK1_PIN11_MA_OFFSET		12
+#define	PINCTRL_DRIVE5_BANK1_PIN10_V			(1 << 10)
+#define	PINCTRL_DRIVE5_BANK1_PIN10_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE5_BANK1_PIN10_MA_OFFSET		8
+#define	PINCTRL_DRIVE5_BANK1_PIN09_V			(1 << 6)
+#define	PINCTRL_DRIVE5_BANK1_PIN09_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE5_BANK1_PIN09_MA_OFFSET		4
+#define	PINCTRL_DRIVE5_BANK1_PIN08_V			(1 << 2)
+#define	PINCTRL_DRIVE5_BANK1_PIN08_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE5_BANK1_PIN08_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE6_BANK1_PIN23_V			(1 << 30)
+#define	PINCTRL_DRIVE6_BANK1_PIN23_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE6_BANK1_PIN23_MA_OFFSET		28
+#define	PINCTRL_DRIVE6_BANK1_PIN22_V			(1 << 26)
+#define	PINCTRL_DRIVE6_BANK1_PIN22_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE6_BANK1_PIN22_MA_OFFSET		24
+#define	PINCTRL_DRIVE6_BANK1_PIN21_V			(1 << 22)
+#define	PINCTRL_DRIVE6_BANK1_PIN21_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE6_BANK1_PIN21_MA_OFFSET		20
+#define	PINCTRL_DRIVE6_BANK1_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE6_BANK1_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE6_BANK1_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE6_BANK1_PIN19_V			(1 << 14)
+#define	PINCTRL_DRIVE6_BANK1_PIN19_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE6_BANK1_PIN19_MA_OFFSET		12
+#define	PINCTRL_DRIVE6_BANK1_PIN18_V			(1 << 10)
+#define	PINCTRL_DRIVE6_BANK1_PIN18_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE6_BANK1_PIN18_MA_OFFSET		8
+#define	PINCTRL_DRIVE6_BANK1_PIN17_V			(1 << 6)
+#define	PINCTRL_DRIVE6_BANK1_PIN17_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE6_BANK1_PIN17_MA_OFFSET		4
+#define	PINCTRL_DRIVE6_BANK1_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE6_BANK1_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE6_BANK1_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE7_BANK1_PIN31_V			(1 << 30)
+#define	PINCTRL_DRIVE7_BANK1_PIN31_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE7_BANK1_PIN31_MA_OFFSET		28
+#define	PINCTRL_DRIVE7_BANK1_PIN30_V			(1 << 26)
+#define	PINCTRL_DRIVE7_BANK1_PIN30_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE7_BANK1_PIN30_MA_OFFSET		24
+#define	PINCTRL_DRIVE7_BANK1_PIN29_V			(1 << 22)
+#define	PINCTRL_DRIVE7_BANK1_PIN29_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE7_BANK1_PIN29_MA_OFFSET		20
+#define	PINCTRL_DRIVE7_BANK1_PIN28_V			(1 << 18)
+#define	PINCTRL_DRIVE7_BANK1_PIN28_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE7_BANK1_PIN28_MA_OFFSET		16
+#define	PINCTRL_DRIVE7_BANK1_PIN27_V			(1 << 14)
+#define	PINCTRL_DRIVE7_BANK1_PIN27_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE7_BANK1_PIN27_MA_OFFSET		12
+#define	PINCTRL_DRIVE7_BANK1_PIN26_V			(1 << 10)
+#define	PINCTRL_DRIVE7_BANK1_PIN26_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE7_BANK1_PIN26_MA_OFFSET		8
+#define	PINCTRL_DRIVE7_BANK1_PIN25_V			(1 << 6)
+#define	PINCTRL_DRIVE7_BANK1_PIN25_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE7_BANK1_PIN25_MA_OFFSET		4
+#define	PINCTRL_DRIVE7_BANK1_PIN24_V			(1 << 2)
+#define	PINCTRL_DRIVE7_BANK1_PIN24_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE7_BANK1_PIN24_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE8_BANK2_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE8_BANK2_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE8_BANK2_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE8_BANK2_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE8_BANK2_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE8_BANK2_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE8_BANK2_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE8_BANK2_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE8_BANK2_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE8_BANK2_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE8_BANK2_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE8_BANK2_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE8_BANK2_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE8_BANK2_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE8_BANK2_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE8_BANK2_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE8_BANK2_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE8_BANK2_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE8_BANK2_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE8_BANK2_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE8_BANK2_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE8_BANK2_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE8_BANK2_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE8_BANK2_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE9_BANK2_PIN15_V			(1 << 30)
+#define	PINCTRL_DRIVE9_BANK2_PIN15_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE9_BANK2_PIN15_MA_OFFSET		28
+#define	PINCTRL_DRIVE9_BANK2_PIN14_V			(1 << 26)
+#define	PINCTRL_DRIVE9_BANK2_PIN14_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE9_BANK2_PIN14_MA_OFFSET		24
+#define	PINCTRL_DRIVE9_BANK2_PIN13_V			(1 << 22)
+#define	PINCTRL_DRIVE9_BANK2_PIN13_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE9_BANK2_PIN13_MA_OFFSET		20
+#define	PINCTRL_DRIVE9_BANK2_PIN12_V			(1 << 18)
+#define	PINCTRL_DRIVE9_BANK2_PIN12_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE9_BANK2_PIN12_MA_OFFSET		16
+#define	PINCTRL_DRIVE9_BANK2_PIN10_V			(1 << 10)
+#define	PINCTRL_DRIVE9_BANK2_PIN10_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE9_BANK2_PIN10_MA_OFFSET		8
+#define	PINCTRL_DRIVE9_BANK2_PIN09_V			(1 << 6)
+#define	PINCTRL_DRIVE9_BANK2_PIN09_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE9_BANK2_PIN09_MA_OFFSET		4
+#define	PINCTRL_DRIVE9_BANK2_PIN08_V			(1 << 2)
+#define	PINCTRL_DRIVE9_BANK2_PIN08_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE9_BANK2_PIN08_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE10_BANK2_PIN21_V			(1 << 22)
+#define	PINCTRL_DRIVE10_BANK2_PIN21_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE10_BANK2_PIN21_MA_OFFSET		20
+#define	PINCTRL_DRIVE10_BANK2_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE10_BANK2_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE10_BANK2_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE10_BANK2_PIN19_V			(1 << 14)
+#define	PINCTRL_DRIVE10_BANK2_PIN19_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE10_BANK2_PIN19_MA_OFFSET		12
+#define	PINCTRL_DRIVE10_BANK2_PIN18_V			(1 << 10)
+#define	PINCTRL_DRIVE10_BANK2_PIN18_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE10_BANK2_PIN18_MA_OFFSET		8
+#define	PINCTRL_DRIVE10_BANK2_PIN17_V			(1 << 6)
+#define	PINCTRL_DRIVE10_BANK2_PIN17_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE10_BANK2_PIN17_MA_OFFSET		4
+#define	PINCTRL_DRIVE10_BANK2_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE10_BANK2_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE10_BANK2_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE11_BANK2_PIN27_V			(1 << 14)
+#define	PINCTRL_DRIVE11_BANK2_PIN27_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE11_BANK2_PIN27_MA_OFFSET		12
+#define	PINCTRL_DRIVE11_BANK2_PIN26_V			(1 << 10)
+#define	PINCTRL_DRIVE11_BANK2_PIN26_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE11_BANK2_PIN26_MA_OFFSET		8
+#define	PINCTRL_DRIVE11_BANK2_PIN25_V			(1 << 6)
+#define	PINCTRL_DRIVE11_BANK2_PIN25_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE11_BANK2_PIN25_MA_OFFSET		4
+#define	PINCTRL_DRIVE11_BANK2_PIN24_V			(1 << 2)
+#define	PINCTRL_DRIVE11_BANK2_PIN24_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE11_BANK2_PIN24_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE12_BANK3_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE12_BANK3_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE12_BANK3_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE12_BANK3_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE12_BANK3_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE12_BANK3_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE12_BANK3_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE12_BANK3_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE12_BANK3_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE12_BANK3_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE12_BANK3_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE12_BANK3_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE12_BANK3_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE12_BANK3_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE12_BANK3_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE12_BANK3_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE12_BANK3_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE12_BANK3_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE12_BANK3_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE12_BANK3_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE12_BANK3_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE12_BANK3_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE12_BANK3_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE12_BANK3_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE13_BANK3_PIN15_V			(1 << 30)
+#define	PINCTRL_DRIVE13_BANK3_PIN15_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE13_BANK3_PIN15_MA_OFFSET		28
+#define	PINCTRL_DRIVE13_BANK3_PIN14_V			(1 << 26)
+#define	PINCTRL_DRIVE13_BANK3_PIN14_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE13_BANK3_PIN14_MA_OFFSET		24
+#define	PINCTRL_DRIVE13_BANK3_PIN13_V			(1 << 22)
+#define	PINCTRL_DRIVE13_BANK3_PIN13_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE13_BANK3_PIN13_MA_OFFSET		20
+#define	PINCTRL_DRIVE13_BANK3_PIN12_V			(1 << 18)
+#define	PINCTRL_DRIVE13_BANK3_PIN12_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE13_BANK3_PIN12_MA_OFFSET		16
+#define	PINCTRL_DRIVE13_BANK3_PIN11_V			(1 << 14)
+#define	PINCTRL_DRIVE13_BANK3_PIN11_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE13_BANK3_PIN11_MA_OFFSET		12
+#define	PINCTRL_DRIVE13_BANK3_PIN10_V			(1 << 10)
+#define	PINCTRL_DRIVE13_BANK3_PIN10_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE13_BANK3_PIN10_MA_OFFSET		8
+#define	PINCTRL_DRIVE13_BANK3_PIN09_V			(1 << 6)
+#define	PINCTRL_DRIVE13_BANK3_PIN09_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE13_BANK3_PIN09_MA_OFFSET		4
+#define	PINCTRL_DRIVE13_BANK3_PIN08_V			(1 << 2)
+#define	PINCTRL_DRIVE13_BANK3_PIN08_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE13_BANK3_PIN08_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE14_BANK3_PIN23_V			(1 << 30)
+#define	PINCTRL_DRIVE14_BANK3_PIN23_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE14_BANK3_PIN23_MA_OFFSET		28
+#define	PINCTRL_DRIVE14_BANK3_PIN22_V			(1 << 26)
+#define	PINCTRL_DRIVE14_BANK3_PIN22_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE14_BANK3_PIN22_MA_OFFSET		24
+#define	PINCTRL_DRIVE14_BANK3_PIN21_V			(1 << 22)
+#define	PINCTRL_DRIVE14_BANK3_PIN21_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE14_BANK3_PIN21_MA_OFFSET		20
+#define	PINCTRL_DRIVE14_BANK3_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE14_BANK3_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE14_BANK3_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE14_BANK3_PIN18_V			(1 << 10)
+#define	PINCTRL_DRIVE14_BANK3_PIN18_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE14_BANK3_PIN18_MA_OFFSET		8
+#define	PINCTRL_DRIVE14_BANK3_PIN17_V			(1 << 6)
+#define	PINCTRL_DRIVE14_BANK3_PIN17_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE14_BANK3_PIN17_MA_OFFSET		4
+#define	PINCTRL_DRIVE14_BANK3_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE14_BANK3_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE14_BANK3_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE15_BANK3_PIN30_V			(1 << 26)
+#define	PINCTRL_DRIVE15_BANK3_PIN30_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE15_BANK3_PIN30_MA_OFFSET		24
+#define	PINCTRL_DRIVE15_BANK3_PIN29_V			(1 << 22)
+#define	PINCTRL_DRIVE15_BANK3_PIN29_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE15_BANK3_PIN29_MA_OFFSET		20
+#define	PINCTRL_DRIVE15_BANK3_PIN28_V			(1 << 18)
+#define	PINCTRL_DRIVE15_BANK3_PIN28_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE15_BANK3_PIN28_MA_OFFSET		16
+#define	PINCTRL_DRIVE15_BANK3_PIN27_V			(1 << 14)
+#define	PINCTRL_DRIVE15_BANK3_PIN27_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE15_BANK3_PIN27_MA_OFFSET		12
+#define	PINCTRL_DRIVE15_BANK3_PIN26_V			(1 << 10)
+#define	PINCTRL_DRIVE15_BANK3_PIN26_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE15_BANK3_PIN26_MA_OFFSET		8
+#define	PINCTRL_DRIVE15_BANK3_PIN25_V			(1 << 6)
+#define	PINCTRL_DRIVE15_BANK3_PIN25_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE15_BANK3_PIN25_MA_OFFSET		4
+#define	PINCTRL_DRIVE15_BANK3_PIN24_V			(1 << 2)
+#define	PINCTRL_DRIVE15_BANK3_PIN24_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE15_BANK3_PIN24_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE16_BANK4_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE16_BANK4_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE16_BANK4_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE16_BANK4_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE16_BANK4_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE16_BANK4_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE16_BANK4_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE16_BANK4_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE16_BANK4_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE16_BANK4_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE16_BANK4_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE16_BANK4_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE16_BANK4_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE16_BANK4_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE16_BANK4_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE16_BANK4_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE16_BANK4_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE16_BANK4_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE16_BANK4_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE16_BANK4_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE16_BANK4_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE16_BANK4_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE16_BANK4_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE16_BANK4_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE17_BANK4_PIN15_V			(1 << 30)
+#define	PINCTRL_DRIVE17_BANK4_PIN15_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE17_BANK4_PIN15_MA_OFFSET		28
+#define	PINCTRL_DRIVE17_BANK4_PIN14_V			(1 << 26)
+#define	PINCTRL_DRIVE17_BANK4_PIN14_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE17_BANK4_PIN14_MA_OFFSET		24
+#define	PINCTRL_DRIVE17_BANK4_PIN13_V			(1 << 22)
+#define	PINCTRL_DRIVE17_BANK4_PIN13_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE17_BANK4_PIN13_MA_OFFSET		20
+#define	PINCTRL_DRIVE17_BANK4_PIN12_V			(1 << 18)
+#define	PINCTRL_DRIVE17_BANK4_PIN12_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE17_BANK4_PIN12_MA_OFFSET		16
+#define	PINCTRL_DRIVE17_BANK4_PIN11_V			(1 << 14)
+#define	PINCTRL_DRIVE17_BANK4_PIN11_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE17_BANK4_PIN11_MA_OFFSET		12
+#define	PINCTRL_DRIVE17_BANK4_PIN10_V			(1 << 10)
+#define	PINCTRL_DRIVE17_BANK4_PIN10_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE17_BANK4_PIN10_MA_OFFSET		8
+#define	PINCTRL_DRIVE17_BANK4_PIN09_V			(1 << 6)
+#define	PINCTRL_DRIVE17_BANK4_PIN09_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE17_BANK4_PIN09_MA_OFFSET		4
+#define	PINCTRL_DRIVE17_BANK4_PIN08_V			(1 << 2)
+#define	PINCTRL_DRIVE17_BANK4_PIN08_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE17_BANK4_PIN08_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE18_BANK4_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE18_BANK4_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE18_BANK4_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE18_BANK4_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE18_BANK4_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE18_BANK4_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_PULL0_BANK0_PIN28			(1 << 28)
+#define	PINCTRL_PULL0_BANK0_PIN27			(1 << 27)
+#define	PINCTRL_PULL0_BANK0_PIN26			(1 << 26)
+#define	PINCTRL_PULL0_BANK0_PIN25			(1 << 25)
+#define	PINCTRL_PULL0_BANK0_PIN24			(1 << 24)
+#define	PINCTRL_PULL0_BANK0_PIN23			(1 << 23)
+#define	PINCTRL_PULL0_BANK0_PIN22			(1 << 22)
+#define	PINCTRL_PULL0_BANK0_PIN21			(1 << 21)
+#define	PINCTRL_PULL0_BANK0_PIN20			(1 << 20)
+#define	PINCTRL_PULL0_BANK0_PIN19			(1 << 19)
+#define	PINCTRL_PULL0_BANK0_PIN18			(1 << 18)
+#define	PINCTRL_PULL0_BANK0_PIN17			(1 << 17)
+#define	PINCTRL_PULL0_BANK0_PIN16			(1 << 16)
+#define	PINCTRL_PULL0_BANK0_PIN07			(1 << 7)
+#define	PINCTRL_PULL0_BANK0_PIN06			(1 << 6)
+#define	PINCTRL_PULL0_BANK0_PIN05			(1 << 5)
+#define	PINCTRL_PULL0_BANK0_PIN04			(1 << 4)
+#define	PINCTRL_PULL0_BANK0_PIN03			(1 << 3)
+#define	PINCTRL_PULL0_BANK0_PIN02			(1 << 2)
+#define	PINCTRL_PULL0_BANK0_PIN01			(1 << 1)
+#define	PINCTRL_PULL0_BANK0_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL1_BANK1_PIN31			(1 << 31)
+#define	PINCTRL_PULL1_BANK1_PIN30			(1 << 30)
+#define	PINCTRL_PULL1_BANK1_PIN29			(1 << 29)
+#define	PINCTRL_PULL1_BANK1_PIN28			(1 << 28)
+#define	PINCTRL_PULL1_BANK1_PIN27			(1 << 27)
+#define	PINCTRL_PULL1_BANK1_PIN26			(1 << 26)
+#define	PINCTRL_PULL1_BANK1_PIN25			(1 << 25)
+#define	PINCTRL_PULL1_BANK1_PIN24			(1 << 24)
+#define	PINCTRL_PULL1_BANK1_PIN23			(1 << 23)
+#define	PINCTRL_PULL1_BANK1_PIN22			(1 << 22)
+#define	PINCTRL_PULL1_BANK1_PIN21			(1 << 21)
+#define	PINCTRL_PULL1_BANK1_PIN20			(1 << 20)
+#define	PINCTRL_PULL1_BANK1_PIN19			(1 << 19)
+#define	PINCTRL_PULL1_BANK1_PIN18			(1 << 18)
+#define	PINCTRL_PULL1_BANK1_PIN17			(1 << 17)
+#define	PINCTRL_PULL1_BANK1_PIN16			(1 << 16)
+#define	PINCTRL_PULL1_BANK1_PIN15			(1 << 15)
+#define	PINCTRL_PULL1_BANK1_PIN14			(1 << 14)
+#define	PINCTRL_PULL1_BANK1_PIN13			(1 << 13)
+#define	PINCTRL_PULL1_BANK1_PIN12			(1 << 12)
+#define	PINCTRL_PULL1_BANK1_PIN11			(1 << 11)
+#define	PINCTRL_PULL1_BANK1_PIN10			(1 << 10)
+#define	PINCTRL_PULL1_BANK1_PIN09			(1 << 9)
+#define	PINCTRL_PULL1_BANK1_PIN08			(1 << 8)
+#define	PINCTRL_PULL1_BANK1_PIN07			(1 << 7)
+#define	PINCTRL_PULL1_BANK1_PIN06			(1 << 6)
+#define	PINCTRL_PULL1_BANK1_PIN05			(1 << 5)
+#define	PINCTRL_PULL1_BANK1_PIN04			(1 << 4)
+#define	PINCTRL_PULL1_BANK1_PIN03			(1 << 3)
+#define	PINCTRL_PULL1_BANK1_PIN02			(1 << 2)
+#define	PINCTRL_PULL1_BANK1_PIN01			(1 << 1)
+#define	PINCTRL_PULL1_BANK1_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL2_BANK2_PIN27			(1 << 27)
+#define	PINCTRL_PULL2_BANK2_PIN26			(1 << 26)
+#define	PINCTRL_PULL2_BANK2_PIN25			(1 << 25)
+#define	PINCTRL_PULL2_BANK2_PIN24			(1 << 24)
+#define	PINCTRL_PULL2_BANK2_PIN21			(1 << 21)
+#define	PINCTRL_PULL2_BANK2_PIN20			(1 << 20)
+#define	PINCTRL_PULL2_BANK2_PIN19			(1 << 19)
+#define	PINCTRL_PULL2_BANK2_PIN18			(1 << 18)
+#define	PINCTRL_PULL2_BANK2_PIN17			(1 << 17)
+#define	PINCTRL_PULL2_BANK2_PIN16			(1 << 16)
+#define	PINCTRL_PULL2_BANK2_PIN15			(1 << 15)
+#define	PINCTRL_PULL2_BANK2_PIN14			(1 << 14)
+#define	PINCTRL_PULL2_BANK2_PIN13			(1 << 13)
+#define	PINCTRL_PULL2_BANK2_PIN12			(1 << 12)
+#define	PINCTRL_PULL2_BANK2_PIN10			(1 << 10)
+#define	PINCTRL_PULL2_BANK2_PIN09			(1 << 9)
+#define	PINCTRL_PULL2_BANK2_PIN08			(1 << 8)
+#define	PINCTRL_PULL2_BANK2_PIN07			(1 << 7)
+#define	PINCTRL_PULL2_BANK2_PIN06			(1 << 6)
+#define	PINCTRL_PULL2_BANK2_PIN05			(1 << 5)
+#define	PINCTRL_PULL2_BANK2_PIN04			(1 << 4)
+#define	PINCTRL_PULL2_BANK2_PIN03			(1 << 3)
+#define	PINCTRL_PULL2_BANK2_PIN02			(1 << 2)
+#define	PINCTRL_PULL2_BANK2_PIN01			(1 << 1)
+#define	PINCTRL_PULL2_BANK2_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL3_BANK3_PIN30			(1 << 30)
+#define	PINCTRL_PULL3_BANK3_PIN29			(1 << 29)
+#define	PINCTRL_PULL3_BANK3_PIN28			(1 << 28)
+#define	PINCTRL_PULL3_BANK3_PIN27			(1 << 27)
+#define	PINCTRL_PULL3_BANK3_PIN26			(1 << 26)
+#define	PINCTRL_PULL3_BANK3_PIN25			(1 << 25)
+#define	PINCTRL_PULL3_BANK3_PIN24			(1 << 24)
+#define	PINCTRL_PULL3_BANK3_PIN23			(1 << 23)
+#define	PINCTRL_PULL3_BANK3_PIN22			(1 << 22)
+#define	PINCTRL_PULL3_BANK3_PIN21			(1 << 21)
+#define	PINCTRL_PULL3_BANK3_PIN20			(1 << 20)
+#define	PINCTRL_PULL3_BANK3_PIN18			(1 << 18)
+#define	PINCTRL_PULL3_BANK3_PIN17			(1 << 17)
+#define	PINCTRL_PULL3_BANK3_PIN16			(1 << 16)
+#define	PINCTRL_PULL3_BANK3_PIN15			(1 << 15)
+#define	PINCTRL_PULL3_BANK3_PIN14			(1 << 14)
+#define	PINCTRL_PULL3_BANK3_PIN13			(1 << 13)
+#define	PINCTRL_PULL3_BANK3_PIN12			(1 << 12)
+#define	PINCTRL_PULL3_BANK3_PIN11			(1 << 11)
+#define	PINCTRL_PULL3_BANK3_PIN10			(1 << 10)
+#define	PINCTRL_PULL3_BANK3_PIN09			(1 << 9)
+#define	PINCTRL_PULL3_BANK3_PIN08			(1 << 8)
+#define	PINCTRL_PULL3_BANK3_PIN07			(1 << 7)
+#define	PINCTRL_PULL3_BANK3_PIN06			(1 << 6)
+#define	PINCTRL_PULL3_BANK3_PIN05			(1 << 5)
+#define	PINCTRL_PULL3_BANK3_PIN04			(1 << 4)
+#define	PINCTRL_PULL3_BANK3_PIN03			(1 << 3)
+#define	PINCTRL_PULL3_BANK3_PIN02			(1 << 2)
+#define	PINCTRL_PULL3_BANK3_PIN01			(1 << 1)
+#define	PINCTRL_PULL3_BANK3_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL4_BANK4_PIN20			(1 << 20)
+#define	PINCTRL_PULL4_BANK4_PIN16			(1 << 16)
+#define	PINCTRL_PULL4_BANK4_PIN15			(1 << 15)
+#define	PINCTRL_PULL4_BANK4_PIN14			(1 << 14)
+#define	PINCTRL_PULL4_BANK4_PIN13			(1 << 13)
+#define	PINCTRL_PULL4_BANK4_PIN12			(1 << 12)
+#define	PINCTRL_PULL4_BANK4_PIN11			(1 << 11)
+#define	PINCTRL_PULL4_BANK4_PIN10			(1 << 10)
+#define	PINCTRL_PULL4_BANK4_PIN09			(1 << 9)
+#define	PINCTRL_PULL4_BANK4_PIN08			(1 << 8)
+#define	PINCTRL_PULL4_BANK4_PIN07			(1 << 7)
+#define	PINCTRL_PULL4_BANK4_PIN06			(1 << 6)
+#define	PINCTRL_PULL4_BANK4_PIN05			(1 << 5)
+#define	PINCTRL_PULL4_BANK4_PIN04			(1 << 4)
+#define	PINCTRL_PULL4_BANK4_PIN03			(1 << 3)
+#define	PINCTRL_PULL4_BANK4_PIN02			(1 << 2)
+#define	PINCTRL_PULL4_BANK4_PIN01			(1 << 1)
+#define	PINCTRL_PULL4_BANK4_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL5_BANK5_PIN26			(1 << 26)
+#define	PINCTRL_PULL5_BANK5_PIN23			(1 << 23)
+#define	PINCTRL_PULL5_BANK5_PIN22			(1 << 22)
+#define	PINCTRL_PULL5_BANK5_PIN21			(1 << 21)
+#define	PINCTRL_PULL5_BANK5_PIN20			(1 << 20)
+#define	PINCTRL_PULL5_BANK5_PIN19			(1 << 19)
+#define	PINCTRL_PULL5_BANK5_PIN18			(1 << 18)
+#define	PINCTRL_PULL5_BANK5_PIN17			(1 << 17)
+#define	PINCTRL_PULL5_BANK5_PIN16			(1 << 16)
+#define	PINCTRL_PULL5_BANK5_PIN15			(1 << 15)
+#define	PINCTRL_PULL5_BANK5_PIN14			(1 << 14)
+#define	PINCTRL_PULL5_BANK5_PIN13			(1 << 13)
+#define	PINCTRL_PULL5_BANK5_PIN12			(1 << 12)
+#define	PINCTRL_PULL5_BANK5_PIN11			(1 << 11)
+#define	PINCTRL_PULL5_BANK5_PIN10			(1 << 10)
+#define	PINCTRL_PULL5_BANK5_PIN09			(1 << 9)
+#define	PINCTRL_PULL5_BANK5_PIN08			(1 << 8)
+#define	PINCTRL_PULL5_BANK5_PIN07			(1 << 7)
+#define	PINCTRL_PULL5_BANK5_PIN06			(1 << 6)
+#define	PINCTRL_PULL5_BANK5_PIN05			(1 << 5)
+#define	PINCTRL_PULL5_BANK5_PIN04			(1 << 4)
+#define	PINCTRL_PULL5_BANK5_PIN03			(1 << 3)
+#define	PINCTRL_PULL5_BANK5_PIN02			(1 << 2)
+#define	PINCTRL_PULL5_BANK5_PIN01			(1 << 1)
+#define	PINCTRL_PULL5_BANK5_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL6_BANK6_PIN24			(1 << 24)
+#define	PINCTRL_PULL6_BANK6_PIN23			(1 << 23)
+#define	PINCTRL_PULL6_BANK6_PIN22			(1 << 22)
+#define	PINCTRL_PULL6_BANK6_PIN21			(1 << 21)
+#define	PINCTRL_PULL6_BANK6_PIN20			(1 << 20)
+#define	PINCTRL_PULL6_BANK6_PIN19			(1 << 19)
+#define	PINCTRL_PULL6_BANK6_PIN18			(1 << 18)
+#define	PINCTRL_PULL6_BANK6_PIN17			(1 << 17)
+#define	PINCTRL_PULL6_BANK6_PIN16			(1 << 16)
+#define	PINCTRL_PULL6_BANK6_PIN14			(1 << 14)
+#define	PINCTRL_PULL6_BANK6_PIN13			(1 << 13)
+#define	PINCTRL_PULL6_BANK6_PIN12			(1 << 12)
+#define	PINCTRL_PULL6_BANK6_PIN11			(1 << 11)
+#define	PINCTRL_PULL6_BANK6_PIN10			(1 << 10)
+#define	PINCTRL_PULL6_BANK6_PIN09			(1 << 9)
+#define	PINCTRL_PULL6_BANK6_PIN08			(1 << 8)
+#define	PINCTRL_PULL6_BANK6_PIN07			(1 << 7)
+#define	PINCTRL_PULL6_BANK6_PIN06			(1 << 6)
+#define	PINCTRL_PULL6_BANK6_PIN05			(1 << 5)
+#define	PINCTRL_PULL6_BANK6_PIN04			(1 << 4)
+#define	PINCTRL_PULL6_BANK6_PIN03			(1 << 3)
+#define	PINCTRL_PULL6_BANK6_PIN02			(1 << 2)
+#define	PINCTRL_PULL6_BANK6_PIN01			(1 << 1)
+#define	PINCTRL_PULL6_BANK6_PIN00			(1 << 0)
+
+#define	PINCTRL_DOUT0_DOUT_MASK				0x1fffffff
+#define	PINCTRL_DOUT0_DOUT_OFFSET			0
+
+#define	PINCTRL_DOUT1_DOUT_MASK				0xffffffff
+#define	PINCTRL_DOUT1_DOUT_OFFSET			0
+
+#define	PINCTRL_DOUT2_DOUT_MASK				0xfffffff
+#define	PINCTRL_DOUT2_DOUT_OFFSET			0
+
+#define	PINCTRL_DOUT3_DOUT_MASK				0x7fffffff
+#define	PINCTRL_DOUT3_DOUT_OFFSET			0
+
+#define	PINCTRL_DOUT4_DOUT_MASK				0x1fffff
+#define	PINCTRL_DOUT4_DOUT_OFFSET			0
+
+#define	PINCTRL_DIN0_DIN_MASK				0x1fffffff
+#define	PINCTRL_DIN0_DIN_OFFSET				0
+
+#define	PINCTRL_DIN1_DIN_MASK				0xffffffff
+#define	PINCTRL_DIN1_DIN_OFFSET				0
+
+#define	PINCTRL_DIN2_DIN_MASK				0xfffffff
+#define	PINCTRL_DIN2_DIN_OFFSET				0
+
+#define	PINCTRL_DIN3_DIN_MASK				0x7fffffff
+#define	PINCTRL_DIN3_DIN_OFFSET				0
+
+#define	PINCTRL_DIN4_DIN_MASK				0x1fffff
+#define	PINCTRL_DIN4_DIN_OFFSET				0
+
+#define	PINCTRL_DOE0_DOE_MASK				0x1fffffff
+#define	PINCTRL_DOE0_DOE_OFFSET				0
+
+#define	PINCTRL_DOE1_DOE_MASK				0xffffffff
+#define	PINCTRL_DOE1_DOE_OFFSET				0
+
+#define	PINCTRL_DOE2_DOE_MASK				0xfffffff
+#define	PINCTRL_DOE2_DOE_OFFSET				0
+
+#define	PINCTRL_DOE3_DOE_MASK				0x7fffffff
+#define	PINCTRL_DOE3_DOE_OFFSET				0
+
+#define	PINCTRL_DOE4_DOE_MASK				0x1fffff
+#define	PINCTRL_DOE4_DOE_OFFSET				0
+
+#define	PINCTRL_PIN2IRQ0_PIN2IRQ_MASK			0x1fffffff
+#define	PINCTRL_PIN2IRQ0_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_PIN2IRQ1_PIN2IRQ_MASK			0xffffffff
+#define	PINCTRL_PIN2IRQ1_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_PIN2IRQ2_PIN2IRQ_MASK			0xfffffff
+#define	PINCTRL_PIN2IRQ2_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_PIN2IRQ3_PIN2IRQ_MASK			0x7fffffff
+#define	PINCTRL_PIN2IRQ3_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_PIN2IRQ4_PIN2IRQ_MASK			0x1fffff
+#define	PINCTRL_PIN2IRQ4_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_IRQEN0_IRQEN_MASK			0x1fffffff
+#define	PINCTRL_IRQEN0_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQEN1_IRQEN_MASK			0xffffffff
+#define	PINCTRL_IRQEN1_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQEN2_IRQEN_MASK			0xfffffff
+#define	PINCTRL_IRQEN2_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQEN3_IRQEN_MASK			0x7fffffff
+#define	PINCTRL_IRQEN3_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQEN4_IRQEN_MASK			0x1fffff
+#define	PINCTRL_IRQEN4_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQLEVEL0_IRQLEVEL_MASK			0x1fffffff
+#define	PINCTRL_IRQLEVEL0_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQLEVEL1_IRQLEVEL_MASK			0xffffffff
+#define	PINCTRL_IRQLEVEL1_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQLEVEL2_IRQLEVEL_MASK			0xfffffff
+#define	PINCTRL_IRQLEVEL2_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQLEVEL3_IRQLEVEL_MASK			0x7fffffff
+#define	PINCTRL_IRQLEVEL3_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQLEVEL4_IRQLEVEL_MASK			0x1fffff
+#define	PINCTRL_IRQLEVEL4_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQPOL0_IRQPOL_MASK			0x1fffffff
+#define	PINCTRL_IRQPOL0_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQPOL1_IRQPOL_MASK			0xffffffff
+#define	PINCTRL_IRQPOL1_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQPOL2_IRQPOL_MASK			0xfffffff
+#define	PINCTRL_IRQPOL2_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQPOL3_IRQPOL_MASK			0x7fffffff
+#define	PINCTRL_IRQPOL3_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQPOL4_IRQPOL_MASK			0x1fffff
+#define	PINCTRL_IRQPOL4_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQSTAT0_IRQSTAT_MASK			0x1fffffff
+#define	PINCTRL_IRQSTAT0_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_IRQSTAT1_IRQSTAT_MASK			0xffffffff
+#define	PINCTRL_IRQSTAT1_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_IRQSTAT2_IRQSTAT_MASK			0xfffffff
+#define	PINCTRL_IRQSTAT2_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_IRQSTAT3_IRQSTAT_MASK			0x7fffffff
+#define	PINCTRL_IRQSTAT3_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_IRQSTAT4_IRQSTAT_MASK			0x1fffff
+#define	PINCTRL_IRQSTAT4_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_EMI_ODT_CTRL_ADDRESS_CALIB_MASK		(0x3 << 26)
+#define	PINCTRL_EMI_ODT_CTRL_ADDRESS_CALIB_OFFSET	26
+#define	PINCTRL_EMI_ODT_CTRL_ADDRESS_TLOAD_MASK		(0x3 << 24)
+#define	PINCTRL_EMI_ODT_CTRL_ADDRESS_TLOAD_OFFSET	24
+#define	PINCTRL_EMI_ODT_CTRL_CONTROL_CALIB_MASK		(0x3 << 22)
+#define	PINCTRL_EMI_ODT_CTRL_CONTROL_CALIB_OFFSET	22
+#define	PINCTRL_EMI_ODT_CTRL_CONTROL_TLOAD_MASK		(0x3 << 20)
+#define	PINCTRL_EMI_ODT_CTRL_CONTROL_TLOAD_OFFSET	20
+#define	PINCTRL_EMI_ODT_CTRL_DUALPAD_CALIB_MASK		(0x3 << 18)
+#define	PINCTRL_EMI_ODT_CTRL_DUALPAD_CALIB_OFFSET	18
+#define	PINCTRL_EMI_ODT_CTRL_DUALPAD_TLOAD_MASK		(0x3 << 16)
+#define	PINCTRL_EMI_ODT_CTRL_DUALPAD_TLOAD_OFFSET	16
+#define	PINCTRL_EMI_ODT_CTRL_SLICE3_CALIB_MASK		(0x3 << 14)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE3_CALIB_OFFSET	14
+#define	PINCTRL_EMI_ODT_CTRL_SLICE3_TLOAD_MASK		(0x3 << 12)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE3_TLOAD_OFFSET	12
+#define	PINCTRL_EMI_ODT_CTRL_SLICE2_CALIB_MASK		(0x3 << 10)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE2_CALIB_OFFSET	10
+#define	PINCTRL_EMI_ODT_CTRL_SLICE2_TLOAD_MASK		(0x3 << 8)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE2_TLOAD_OFFSET	8
+#define	PINCTRL_EMI_ODT_CTRL_SLICE1_CALIB_MASK		(0x3 << 6)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE1_CALIB_OFFSET	6
+#define	PINCTRL_EMI_ODT_CTRL_SLICE1_TLOAD_MASK		(0x3 << 4)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE1_TLOAD_OFFSET	4
+#define	PINCTRL_EMI_ODT_CTRL_SLICE0_CALIB_MASK		(0x3 << 2)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE0_CALIB_OFFSET	2
+#define	PINCTRL_EMI_ODT_CTRL_SLICE0_TLOAD_MASK		(0x3 << 0)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE0_TLOAD_OFFSET	0
+
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_MASK		(0x3 << 16)
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_OFFSET		16
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_mDDR		(0x0 << 16)
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_GPIO		(0x1 << 16)
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_LVDDR2		(0x2 << 16)
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2		(0x3 << 16)
+#define	PINCTRL_EMI_DS_CTRL_ADDRESS_MA_MASK		(0x3 << 12)
+#define	PINCTRL_EMI_DS_CTRL_ADDRESS_MA_OFFSET		12
+#define	PINCTRL_EMI_DS_CTRL_CONTROL_MA_MASK		(0x3 << 10)
+#define	PINCTRL_EMI_DS_CTRL_CONTROL_MA_OFFSET		10
+#define	PINCTRL_EMI_DS_CTRL_DUALPAD_MA_MASK		(0x3 << 8)
+#define	PINCTRL_EMI_DS_CTRL_DUALPAD_MA_OFFSET		8
+#define	PINCTRL_EMI_DS_CTRL_SLICE3_MA_MASK		(0x3 << 6)
+#define	PINCTRL_EMI_DS_CTRL_SLICE3_MA_OFFSET		6
+#define	PINCTRL_EMI_DS_CTRL_SLICE2_MA_MASK		(0x3 << 4)
+#define	PINCTRL_EMI_DS_CTRL_SLICE2_MA_OFFSET		4
+#define	PINCTRL_EMI_DS_CTRL_SLICE1_MA_MASK		(0x3 << 2)
+#define	PINCTRL_EMI_DS_CTRL_SLICE1_MA_OFFSET		2
+#define	PINCTRL_EMI_DS_CTRL_SLICE0_MA_MASK		(0x3 << 0)
+#define	PINCTRL_EMI_DS_CTRL_SLICE0_MA_OFFSET		0
+
+#endif /* __MX28_REGS_PINCTRL_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-power.h b/arch/arm/include/asm/arch-mx28/regs-power.h
new file mode 100644
index 0000000..9da63ad
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-power.h
@@ -0,0 +1,413 @@
+/*
+ * Freescale i.MX28 Power Controller Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_POWER_H__
+#define __MX28_REGS_POWER_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_power_regs {
+	mx28_reg(hw_power_ctrl)
+	mx28_reg(hw_power_5vctrl)
+	mx28_reg(hw_power_minpwr)
+	mx28_reg(hw_power_charge)
+	uint32_t	hw_power_vdddctrl;
+	uint32_t	reserved_vddd[3];
+	uint32_t	hw_power_vddactrl;
+	uint32_t	reserved_vdda[3];
+	uint32_t	hw_power_vddioctrl;
+	uint32_t	reserved_vddio[3];
+	uint32_t	hw_power_vddmemctrl;
+	uint32_t	reserved_vddmem[3];
+	uint32_t	hw_power_dcdc4p2;
+	uint32_t	reserved_dcdc4p2[3];
+	uint32_t	hw_power_misc;
+	uint32_t	reserved_misc[3];
+	uint32_t	hw_power_dclimits;
+	uint32_t	reserved_dclimits[3];
+	mx28_reg(hw_power_loopctrl)
+	uint32_t	hw_power_sts;
+	uint32_t	reserved_sts[3];
+	mx28_reg(hw_power_speed)
+	uint32_t	hw_power_battmonitor;
+	uint32_t	reserved_battmonitor[3];
+
+	uint32_t	reserved[4];
+
+	mx28_reg(hw_power_reset)
+	mx28_reg(hw_power_debug)
+	mx28_reg(hw_power_thermal)
+	mx28_reg(hw_power_usb1ctrl)
+	mx28_reg(hw_power_special)
+	mx28_reg(hw_power_version)
+	mx28_reg(hw_power_anaclkctrl)
+	mx28_reg(hw_power_refctrl)
+};
+#endif
+
+#define	POWER_CTRL_PSWITCH_MID_TRAN			(1 << 27)
+#define	POWER_CTRL_DCDC4P2_BO_IRQ			(1 << 24)
+#define	POWER_CTRL_ENIRQ_DCDC4P2_BO			(1 << 23)
+#define	POWER_CTRL_VDD5V_DROOP_IRQ			(1 << 22)
+#define	POWER_CTRL_ENIRQ_VDD5V_DROOP			(1 << 21)
+#define	POWER_CTRL_PSWITCH_IRQ				(1 << 20)
+#define	POWER_CTRL_PSWITCH_IRQ_SRC			(1 << 19)
+#define	POWER_CTRL_POLARITY_PSWITCH			(1 << 18)
+#define	POWER_CTRL_ENIRQ_PSWITCH			(1 << 17)
+#define	POWER_CTRL_POLARITY_DC_OK			(1 << 16)
+#define	POWER_CTRL_DC_OK_IRQ				(1 << 15)
+#define	POWER_CTRL_ENIRQ_DC_OK				(1 << 14)
+#define	POWER_CTRL_BATT_BO_IRQ				(1 << 13)
+#define	POWER_CTRL_ENIRQ_BATT_BO			(1 << 12)
+#define	POWER_CTRL_VDDIO_BO_IRQ				(1 << 11)
+#define	POWER_CTRL_ENIRQ_VDDIO_BO			(1 << 10)
+#define	POWER_CTRL_VDDA_BO_IRQ				(1 << 9)
+#define	POWER_CTRL_ENIRQ_VDDA_BO			(1 << 8)
+#define	POWER_CTRL_VDDD_BO_IRQ				(1 << 7)
+#define	POWER_CTRL_ENIRQ_VDDD_BO			(1 << 6)
+#define	POWER_CTRL_POLARITY_VBUSVALID			(1 << 5)
+#define	POWER_CTRL_VBUS_VALID_IRQ			(1 << 4)
+#define	POWER_CTRL_ENIRQ_VBUS_VALID			(1 << 3)
+#define	POWER_CTRL_POLARITY_VDD5V_GT_VDDIO		(1 << 2)
+#define	POWER_CTRL_VDD5V_GT_VDDIO_IRQ			(1 << 1)
+#define	POWER_CTRL_ENIRQ_VDD5V_GT_VDDIO			(1 << 0)
+
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_MASK		(0x3 << 30)
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_OFFSET		30
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_4V3			(0x0 << 30)
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_4V4			(0x1 << 30)
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_4V5			(0x2 << 30)
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_4V7			(0x3 << 30)
+#define	POWER_5VCTRL_HEADROOM_ADJ_MASK			(0x7 << 24)
+#define	POWER_5VCTRL_HEADROOM_ADJ_OFFSET		24
+#define	POWER_5VCTRL_PWD_CHARGE_4P2_MASK		(0x3 << 20)
+#define	POWER_5VCTRL_PWD_CHARGE_4P2_OFFSET		20
+#define	POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK		(0x3f << 12)
+#define	POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET		12
+#define	POWER_5VCTRL_VBUSVALID_TRSH_MASK		(0x7 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_OFFSET		8
+#define	POWER_5VCTRL_VBUSVALID_TRSH_2V9			(0x0 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V0			(0x1 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V1			(0x2 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V2			(0x3 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V3			(0x4 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V4			(0x5 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V5			(0x6 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V6			(0x7 << 8)
+#define	POWER_5VCTRL_PWDN_5VBRNOUT			(1 << 7)
+#define	POWER_5VCTRL_ENABLE_LINREG_ILIMIT		(1 << 6)
+#define	POWER_5VCTRL_DCDC_XFER				(1 << 5)
+#define	POWER_5VCTRL_VBUSVALID_5VDETECT			(1 << 4)
+#define	POWER_5VCTRL_VBUSVALID_TO_B			(1 << 3)
+#define	POWER_5VCTRL_ILIMIT_EQ_ZERO			(1 << 2)
+#define	POWER_5VCTRL_PWRUP_VBUS_CMPS			(1 << 1)
+#define	POWER_5VCTRL_ENABLE_DCDC			(1 << 0)
+
+#define	POWER_MINPWR_LOWPWR_4P2				(1 << 14)
+#define	POWER_MINPWR_PWD_BO				(1 << 12)
+#define	POWER_MINPWR_USE_VDDXTAL_VBG			(1 << 11)
+#define	POWER_MINPWR_PWD_ANA_CMPS			(1 << 10)
+#define	POWER_MINPWR_ENABLE_OSC				(1 << 9)
+#define	POWER_MINPWR_SELECT_OSC				(1 << 8)
+#define	POWER_MINPWR_FBG_OFF				(1 << 7)
+#define	POWER_MINPWR_DOUBLE_FETS			(1 << 6)
+#define	POWER_MINPWR_HALFFETS				(1 << 5)
+#define	POWER_MINPWR_LESSANA_I				(1 << 4)
+#define	POWER_MINPWR_PWD_XTAL24				(1 << 3)
+#define	POWER_MINPWR_DC_STOPCLK				(1 << 2)
+#define	POWER_MINPWR_EN_DC_PFM				(1 << 1)
+#define	POWER_MINPWR_DC_HALFCLK				(1 << 0)
+
+#define	POWER_CHARGE_ADJ_VOLT_MASK			(0x7 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_OFFSET			24
+#define	POWER_CHARGE_ADJ_VOLT_M025P			(0x1 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_P050P			(0x2 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_M075P			(0x3 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_P025P			(0x4 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_M050P			(0x5 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_P075P			(0x6 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_M100P			(0x7 << 24)
+#define	POWER_CHARGE_ENABLE_LOAD			(1 << 22)
+#define	POWER_CHARGE_ENABLE_FAULT_DETECT		(1 << 20)
+#define	POWER_CHARGE_CHRG_STS_OFF			(1 << 19)
+#define	POWER_CHARGE_LIION_4P1				(1 << 18)
+#define	POWER_CHARGE_PWD_BATTCHRG			(1 << 16)
+#define	POWER_CHARGE_ENABLE_CHARGER_USB1		(1 << 13)
+#define	POWER_CHARGE_ENABLE_CHARGER_USB0		(1 << 12)
+#define	POWER_CHARGE_STOP_ILIMIT_MASK			(0xf << 8)
+#define	POWER_CHARGE_STOP_ILIMIT_OFFSET			8
+#define	POWER_CHARGE_STOP_ILIMIT_10MA			(0x1 << 8)
+#define	POWER_CHARGE_STOP_ILIMIT_20MA			(0x2 << 8)
+#define	POWER_CHARGE_STOP_ILIMIT_50MA			(0x4 << 8)
+#define	POWER_CHARGE_STOP_ILIMIT_100MA			(0x8 << 8)
+#define	POWER_CHARGE_BATTCHRG_I_MASK			0x3f
+#define	POWER_CHARGE_BATTCHRG_I_OFFSET			0
+#define	POWER_CHARGE_BATTCHRG_I_10MA			0x01
+#define	POWER_CHARGE_BATTCHRG_I_20MA			0x02
+#define	POWER_CHARGE_BATTCHRG_I_50MA			0x04
+#define	POWER_CHARGE_BATTCHRG_I_100MA			0x08
+#define	POWER_CHARGE_BATTCHRG_I_200MA			0x10
+#define	POWER_CHARGE_BATTCHRG_I_400MA			0x20
+
+#define	POWER_VDDDCTRL_ADJTN_MASK			(0xf << 28)
+#define	POWER_VDDDCTRL_ADJTN_OFFSET			28
+#define	POWER_VDDDCTRL_PWDN_BRNOUT			(1 << 23)
+#define	POWER_VDDDCTRL_DISABLE_STEPPING			(1 << 22)
+#define	POWER_VDDDCTRL_ENABLE_LINREG			(1 << 21)
+#define	POWER_VDDDCTRL_DISABLE_FET			(1 << 20)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_MASK		(0x3 << 16)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_OFFSET		16
+#define	POWER_VDDDCTRL_LINREG_OFFSET_0STEPS		(0x0 << 16)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_ABOVE	(0x1 << 16)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW	(0x2 << 16)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_2STEPS_BELOW	(0x3 << 16)
+#define	POWER_VDDDCTRL_BO_OFFSET_MASK			(0x7 << 8)
+#define	POWER_VDDDCTRL_BO_OFFSET_OFFSET			8
+#define	POWER_VDDDCTRL_TRG_MASK				0x1f
+#define	POWER_VDDDCTRL_TRG_OFFSET			0
+
+#define	POWER_VDDACTRL_PWDN_BRNOUT			(1 << 19)
+#define	POWER_VDDACTRL_DISABLE_STEPPING			(1 << 18)
+#define	POWER_VDDACTRL_ENABLE_LINREG			(1 << 17)
+#define	POWER_VDDACTRL_DISABLE_FET			(1 << 16)
+#define	POWER_VDDACTRL_LINREG_OFFSET_MASK		(0x3 << 12)
+#define	POWER_VDDACTRL_LINREG_OFFSET_OFFSET		12
+#define	POWER_VDDACTRL_LINREG_OFFSET_0STEPS		(0x0 << 12)
+#define	POWER_VDDACTRL_LINREG_OFFSET_1STEPS_ABOVE	(0x1 << 12)
+#define	POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW	(0x2 << 12)
+#define	POWER_VDDACTRL_LINREG_OFFSET_2STEPS_BELOW	(0x3 << 12)
+#define	POWER_VDDACTRL_BO_OFFSET_MASK			(0x7 << 8)
+#define	POWER_VDDACTRL_BO_OFFSET_OFFSET			8
+#define	POWER_VDDACTRL_TRG_MASK				0x1f
+#define	POWER_VDDACTRL_TRG_OFFSET			0
+
+#define	POWER_VDDIOCTRL_ADJTN_MASK			(0xf << 20)
+#define	POWER_VDDIOCTRL_ADJTN_OFFSET			20
+#define	POWER_VDDIOCTRL_PWDN_BRNOUT			(1 << 18)
+#define	POWER_VDDIOCTRL_DISABLE_STEPPING		(1 << 17)
+#define	POWER_VDDIOCTRL_DISABLE_FET			(1 << 16)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_MASK		(0x3 << 12)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_OFFSET		12
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_0STEPS		(0x0 << 12)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_ABOVE	(0x1 << 12)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW	(0x2 << 12)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_2STEPS_BELOW	(0x3 << 12)
+#define	POWER_VDDIOCTRL_BO_OFFSET_MASK			(0x7 << 8)
+#define	POWER_VDDIOCTRL_BO_OFFSET_OFFSET		8
+#define	POWER_VDDIOCTRL_TRG_MASK			0x1f
+#define	POWER_VDDIOCTRL_TRG_OFFSET			0
+
+#define	POWER_VDDMEMCTRL_PULLDOWN_ACTIVE		(1 << 10)
+#define	POWER_VDDMEMCTRL_ENABLE_ILIMIT			(1 << 9)
+#define	POWER_VDDMEMCTRL_ENABLE_LINREG			(1 << 8)
+#define	POWER_VDDMEMCTRL_BO_OFFSET_MASK			(0x7 << 5)
+#define	POWER_VDDMEMCTRL_BO_OFFSET_OFFSET		5
+#define	POWER_VDDMEMCTRL_TRG_MASK			0x1f
+#define	POWER_VDDMEMCTRL_TRG_OFFSET			0
+
+#define	POWER_DCDC4P2_DROPOUT_CTRL_MASK			(0xf << 28)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_OFFSET		28
+#define	POWER_DCDC4P2_DROPOUT_CTRL_200MV		(0x3 << 30)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_100MV		(0x2 << 30)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_50MV			(0x1 << 30)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_25MV			(0x0 << 30)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_SRC_4P2		(0x0 << 28)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_SRC_4P2_LT_BATT	(0x1 << 28)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL		(0x2 << 28)
+#define	POWER_DCDC4P2_ISTEAL_THRESH_MASK		(0x3 << 24)
+#define	POWER_DCDC4P2_ISTEAL_THRESH_OFFSET		24
+#define	POWER_DCDC4P2_ENABLE_4P2			(1 << 23)
+#define	POWER_DCDC4P2_ENABLE_DCDC			(1 << 22)
+#define	POWER_DCDC4P2_HYST_DIR				(1 << 21)
+#define	POWER_DCDC4P2_HYST_THRESH			(1 << 20)
+#define	POWER_DCDC4P2_TRG_MASK				(0x7 << 16)
+#define	POWER_DCDC4P2_TRG_OFFSET			16
+#define	POWER_DCDC4P2_TRG_4V2				(0x0 << 16)
+#define	POWER_DCDC4P2_TRG_4V1				(0x1 << 16)
+#define	POWER_DCDC4P2_TRG_4V0				(0x2 << 16)
+#define	POWER_DCDC4P2_TRG_3V9				(0x3 << 16)
+#define	POWER_DCDC4P2_TRG_BATT				(0x4 << 16)
+#define	POWER_DCDC4P2_BO_MASK				(0x1f << 8)
+#define	POWER_DCDC4P2_BO_OFFSET				8
+#define	POWER_DCDC4P2_CMPTRIP_MASK			0x1f
+#define	POWER_DCDC4P2_CMPTRIP_OFFSET			0
+
+#define	POWER_MISC_FREQSEL_MASK				(0x7 << 4)
+#define	POWER_MISC_FREQSEL_OFFSET			4
+#define	POWER_MISC_FREQSEL_20MHZ			(0x1 << 4)
+#define	POWER_MISC_FREQSEL_24MHZ			(0x2 << 4)
+#define	POWER_MISC_FREQSEL_19MHZ			(0x3 << 4)
+#define	POWER_MISC_FREQSEL_14MHZ			(0x4 << 4)
+#define	POWER_MISC_FREQSEL_18MHZ			(0x5 << 4)
+#define	POWER_MISC_FREQSEL_21MHZ			(0x6 << 4)
+#define	POWER_MISC_FREQSEL_17MHZ			(0x7 << 4)
+#define	POWER_MISC_DISABLE_FET_BO_LOGIC			(1 << 3)
+#define	POWER_MISC_DELAY_TIMING				(1 << 2)
+#define	POWER_MISC_TEST					(1 << 1)
+#define	POWER_MISC_SEL_PLLCLK				(1 << 0)
+
+#define	POWER_DCLIMITS_POSLIMIT_BUCK_MASK		(0x7f << 8)
+#define	POWER_DCLIMITS_POSLIMIT_BUCK_OFFSET		8
+#define	POWER_DCLIMITS_NEGLIMIT_MASK			0x7f
+#define	POWER_DCLIMITS_NETLIMIT_OFFSET			0
+
+#define	POWER_LOOPCTRL_TOGGLE_DIF			(1 << 20)
+#define	POWER_LOOPCTRL_HYST_SIGN			(1 << 19)
+#define	POWER_LOOPCTRL_EN_CM_HYST			(1 << 18)
+#define	POWER_LOOPCTRL_EN_DF_HYST			(1 << 17)
+#define	POWER_LOOPCTRL_CM_HYST_THRESH			(1 << 16)
+#define	POWER_LOOPCTRL_DF_HYST_THRESH			(1 << 15)
+#define	POWER_LOOPCTRL_RCSCALE_THRESH			(1 << 14)
+#define	POWER_LOOPCTRL_EN_RCSCALE_MASK			(0x3 << 12)
+#define	POWER_LOOPCTRL_EN_RCSCALE_OFFSET		12
+#define	POWER_LOOPCTRL_EN_RCSCALE_DIS			(0x0 << 12)
+#define	POWER_LOOPCTRL_EN_RCSCALE_2X			(0x1 << 12)
+#define	POWER_LOOPCTRL_EN_RCSCALE_4X			(0x2 << 12)
+#define	POWER_LOOPCTRL_EN_RCSCALE_8X			(0x3 << 12)
+#define	POWER_LOOPCTRL_DC_FF_MASK			(0x7 << 8)
+#define	POWER_LOOPCTRL_DC_FF_OFFSET			8
+#define	POWER_LOOPCTRL_DC_R_MASK			(0xf << 4)
+#define	POWER_LOOPCTRL_DC_R_OFFSET			4
+#define	POWER_LOOPCTRL_DC_C_MASK			0x3
+#define	POWER_LOOPCTRL_DC_C_OFFSET			0
+#define	POWER_LOOPCTRL_DC_C_MAX				0x0
+#define	POWER_LOOPCTRL_DC_C_2X				0x1
+#define	POWER_LOOPCTRL_DC_C_4X				0x2
+#define	POWER_LOOPCTRL_DC_C_MIN				0x3
+
+#define	POWER_STS_PWRUP_SOURCE_MASK			(0x3f << 24)
+#define	POWER_STS_PWRUP_SOURCE_OFFSET			24
+#define	POWER_STS_PWRUP_SOURCE_5V			(0x20 << 24)
+#define	POWER_STS_PWRUP_SOURCE_RTC			(0x10 << 24)
+#define	POWER_STS_PWRUP_SOURCE_PSWITCH_HIGH		(0x02 << 24)
+#define	POWER_STS_PWRUP_SOURCE_PSWITCH_MID		(0x01 << 24)
+#define	POWER_STS_PSWITCH_MASK				(0x3 << 20)
+#define	POWER_STS_PSWITCH_OFFSET			20
+#define	POWER_STS_THERMAL_WARNING			(1 << 19)
+#define	POWER_STS_VDDMEM_BO				(1 << 18)
+#define	POWER_STS_AVALID0_STATUS			(1 << 17)
+#define	POWER_STS_BVALID0_STATUS			(1 << 16)
+#define	POWER_STS_VBUSVALID0_STATUS			(1 << 15)
+#define	POWER_STS_SESSEND0_STATUS			(1 << 14)
+#define	POWER_STS_BATT_BO				(1 << 13)
+#define	POWER_STS_VDD5V_FAULT				(1 << 12)
+#define	POWER_STS_CHRGSTS				(1 << 11)
+#define	POWER_STS_DCDC_4P2_BO				(1 << 10)
+#define	POWER_STS_DC_OK					(1 << 9)
+#define	POWER_STS_VDDIO_BO				(1 << 8)
+#define	POWER_STS_VDDA_BO				(1 << 7)
+#define	POWER_STS_VDDD_BO				(1 << 6)
+#define	POWER_STS_VDD5V_GT_VDDIO			(1 << 5)
+#define	POWER_STS_VDD5V_DROOP				(1 << 4)
+#define	POWER_STS_AVALID0				(1 << 3)
+#define	POWER_STS_BVALID0				(1 << 2)
+#define	POWER_STS_VBUSVALID0				(1 << 1)
+#define	POWER_STS_SESSEND0				(1 << 0)
+
+#define	POWER_SPEED_STATUS_MASK				(0xffff << 8)
+#define	POWER_SPEED_STATUS_OFFSET			8
+#define	POWER_SPEED_STATUS_SEL_MASK			(0x3 << 6)
+#define	POWER_SPEED_STATUS_SEL_OFFSET			6
+#define	POWER_SPEED_STATUS_SEL_DCDC_STAT		(0x0 << 6)
+#define	POWER_SPEED_STATUS_SEL_CORE_STAT		(0x1 << 6)
+#define	POWER_SPEED_STATUS_SEL_ARM_STAT			(0x2 << 6)
+#define	POWER_SPEED_CTRL_MASK				0x3
+#define	POWER_SPEED_CTRL_OFFSET				0
+#define	POWER_SPEED_CTRL_SS_OFF				0x0
+#define	POWER_SPEED_CTRL_SS_ON				0x1
+#define	POWER_SPEED_CTRL_SS_ENABLE			0x3
+
+#define	POWER_BATTMONITOR_BATT_VAL_MASK			(0x3ff << 16)
+#define	POWER_BATTMONITOR_BATT_VAL_OFFSET		16
+#define	POWER_BATTMONITOR_PWDN_BATTBRNOUT_5VDETECT_EN	(1 << 11)
+#define	POWER_BATTMONITOR_EN_BATADJ			(1 << 10)
+#define	POWER_BATTMONITOR_PWDN_BATTBRNOUT		(1 << 9)
+#define	POWER_BATTMONITOR_BRWNOUT_PWD			(1 << 8)
+#define	POWER_BATTMONITOR_BRWNOUT_LVL_MASK		0x1f
+#define	POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET		0
+
+#define	POWER_RESET_UNLOCK_MASK				(0xffff << 16)
+#define	POWER_RESET_UNLOCK_OFFSET			16
+#define	POWER_RESET_UNLOCK_KEY				(0x3e77 << 16)
+#define	POWER_RESET_FASTFALL_PSWITCH_OFF		(1 << 2)
+#define	POWER_RESET_PWD_OFF				(1 << 1)
+#define	POWER_RESET_PWD					(1 << 0)
+
+#define	POWER_DEBUG_VBUSVALIDPIOLOCK			(1 << 3)
+#define	POWER_DEBUG_AVALIDPIOLOCK			(1 << 2)
+#define	POWER_DEBUG_BVALIDPIOLOCK			(1 << 1)
+#define	POWER_DEBUG_SESSENDPIOLOCK			(1 << 0)
+
+#define	POWER_THERMAL_TEST				(1 << 8)
+#define	POWER_THERMAL_PWD				(1 << 7)
+#define	POWER_THERMAL_LOW_POWER				(1 << 6)
+#define	POWER_THERMAL_OFFSET_ADJ_MASK			(0x3 << 4)
+#define	POWER_THERMAL_OFFSET_ADJ_OFFSET			4
+#define	POWER_THERMAL_OFFSET_ADJ_ENABLE			(1 << 3)
+#define	POWER_THERMAL_TEMP_THRESHOLD_MASK		0x7
+#define	POWER_THERMAL_TEMP_THRESHOLD_OFFSET		0
+
+#define	POWER_USB1CTRL_AVALID1				(1 << 3)
+#define	POWER_USB1CTRL_BVALID1				(1 << 2)
+#define	POWER_USB1CTRL_VBUSVALID1			(1 << 1)
+#define	POWER_USB1CTRL_SESSEND1				(1 << 0)
+
+#define	POWER_SPECIAL_TEST_MASK				0xffffffff
+#define	POWER_SPECIAL_TEST_OFFSET			0
+
+#define	POWER_VERSION_MAJOR_MASK			(0xff << 24)
+#define	POWER_VERSION_MAJOR_OFFSET			24
+#define	POWER_VERSION_MINOR_MASK			(0xff << 16)
+#define	POWER_VERSION_MINOR_OFFSET			16
+#define	POWER_VERSION_STEP_MASK				0xffff
+#define	POWER_VERSION_STEP_OFFSET			0
+
+#define	POWER_ANACLKCTRL_CLKGATE_0			(1 << 31)
+#define	POWER_ANACLKCTRL_OUTDIV_MASK			(0x7 << 28)
+#define	POWER_ANACLKCTRL_OUTDIV_OFFSET			28
+#define	POWER_ANACLKCTRL_INVERT_OUTCLK			(1 << 27)
+#define	POWER_ANACLKCTRL_CLKGATE_I			(1 << 26)
+#define	POWER_ANACLKCTRL_DITHER_OFF			(1 << 10)
+#define	POWER_ANACLKCTRL_SLOW_DITHER			(1 << 9)
+#define	POWER_ANACLKCTRL_INVERT_INCLK			(1 << 8)
+#define	POWER_ANACLKCTRL_INCLK_SHIFT_MASK		(0x3 << 4)
+#define	POWER_ANACLKCTRL_INCLK_SHIFT_OFFSET		4
+#define	POWER_ANACLKCTRL_INDIV_MASK			0x7
+#define	POWER_ANACLKCTRL_INDIV_OFFSET			0
+
+#define	POWER_REFCTRL_FASTSETTLING			(1 << 26)
+#define	POWER_REFCTRL_RAISE_REF				(1 << 25)
+#define	POWER_REFCTRL_XTAL_BGR_BIAS			(1 << 24)
+#define	POWER_REFCTRL_VBG_ADJ_MASK			(0x7 << 20)
+#define	POWER_REFCTRL_VBG_ADJ_OFFSET			20
+#define	POWER_REFCTRL_LOW_PWR				(1 << 19)
+#define	POWER_REFCTRL_BIAS_CTRL_MASK			(0x3 << 16)
+#define	POWER_REFCTRL_BIAS_CTRL_OFFSET			16
+#define	POWER_REFCTRL_VDDXTAL_TO_VDDD			(1 << 14)
+#define	POWER_REFCTRL_ADJ_ANA				(1 << 13)
+#define	POWER_REFCTRL_ADJ_VAG				(1 << 12)
+#define	POWER_REFCTRL_ANA_REFVAL_MASK			(0xf << 8)
+#define	POWER_REFCTRL_ANA_REFVAL_OFFSET			8
+#define	POWER_REFCTRL_VAG_VAL_MASK			(0xf << 4)
+#define	POWER_REFCTRL_VAG_VAL_OFFSET			4
+
+#endif	/* __MX28_REGS_POWER_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-rtc.h b/arch/arm/include/asm/arch-mx28/regs-rtc.h
new file mode 100644
index 0000000..fe2fda9
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-rtc.h
@@ -0,0 +1,147 @@
+/*
+ * Freescale i.MX28 RTC Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_RTC_H__
+#define __MX28_REGS_RTC_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_rtc_regs {
+	mx28_reg(hw_rtc_ctrl)
+	mx28_reg(hw_rtc_stat)
+	mx28_reg(hw_rtc_milliseconds)
+	mx28_reg(hw_rtc_seconds)
+	mx28_reg(hw_rtc_rtc_alarm)
+	mx28_reg(hw_rtc_watchdog)
+	mx28_reg(hw_rtc_persistent0)
+	mx28_reg(hw_rtc_persistent1)
+	mx28_reg(hw_rtc_persistent2)
+	mx28_reg(hw_rtc_persistent3)
+	mx28_reg(hw_rtc_persistent4)
+	mx28_reg(hw_rtc_persistent5)
+	mx28_reg(hw_rtc_debug)
+	mx28_reg(hw_rtc_version)
+};
+#endif
+
+#define	RTC_CTRL_SFTRST				(1 << 31)
+#define	RTC_CTRL_CLKGATE			(1 << 30)
+#define	RTC_CTRL_SUPPRESS_COPY2ANALOG		(1 << 6)
+#define	RTC_CTRL_FORCE_UPDATE			(1 << 5)
+#define	RTC_CTRL_WATCHDOGEN			(1 << 4)
+#define	RTC_CTRL_ONEMSEC_IRQ			(1 << 3)
+#define	RTC_CTRL_ALARM_IRQ			(1 << 2)
+#define	RTC_CTRL_ONEMSEC_IRQ_EN			(1 << 1)
+#define	RTC_CTRL_ALARM_IRQ_EN			(1 << 0)
+
+#define	RTC_STAT_RTC_PRESENT			(1 << 31)
+#define	RTC_STAT_ALARM_PRESENT			(1 << 30)
+#define	RTC_STAT_WATCHDOG_PRESENT		(1 << 29)
+#define	RTC_STAT_XTAL32000_PRESENT		(1 << 28)
+#define	RTC_STAT_XTAL32768_PRESENT		(1 << 27)
+#define	RTC_STAT_STALE_REGS_MASK		(0xff << 16)
+#define	RTC_STAT_STALE_REGS_OFFSET		16
+#define	RTC_STAT_NEW_REGS_MASK			(0xff << 8)
+#define	RTC_STAT_NEW_REGS_OFFSET		8
+
+#define	RTC_MILLISECONDS_COUNT_MASK		0xffffffff
+#define	RTC_MILLISECONDS_COUNT_OFFSET		0
+
+#define	RTC_SECONDS_COUNT_MASK			0xffffffff
+#define	RTC_SECONDS_COUNT_OFFSET		0
+
+#define	RTC_ALARM_VALUE_MASK			0xffffffff
+#define	RTC_ALARM_VALUE_OFFSET			0
+
+#define	RTC_WATCHDOG_COUNT_MASK			0xffffffff
+#define	RTC_WATCHDOG_COUNT_OFFSET		0
+
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_MASK	(0xf << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_OFFSET	28
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V83	(0x0 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V78	(0x1 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V73	(0x2 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V68	(0x3 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V62	(0x4 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V57	(0x5 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V52	(0x6 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V48	(0x7 << 28)
+#define	RTC_PERSISTENT0_EXTERNAL_RESET		(1 << 21)
+#define	RTC_PERSISTENT0_THERMAL_RESET		(1 << 20)
+#define	RTC_PERSISTENT0_ENABLE_LRADC_PWRUP	(1 << 18)
+#define	RTC_PERSISTENT0_AUTO_RESTART		(1 << 17)
+#define	RTC_PERSISTENT0_DISABLE_PSWITCH		(1 << 16)
+#define	RTC_PERSISTENT0_LOWERBIAS_MASK		(0xf << 14)
+#define	RTC_PERSISTENT0_LOWERBIAS_OFFSET	14
+#define	RTC_PERSISTENT0_LOWERBIAS_NOMINAL	(0x0 << 14)
+#define	RTC_PERSISTENT0_LOWERBIAS_M25P		(0x1 << 14)
+#define	RTC_PERSISTENT0_LOWERBIAS_M50P		(0x3 << 14)
+#define	RTC_PERSISTENT0_DISABLE_XTALOK		(1 << 13)
+#define	RTC_PERSISTENT0_MSEC_RES_MASK		(0x1f << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_OFFSET		8
+#define	RTC_PERSISTENT0_MSEC_RES_1MS		(0x01 << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_2MS		(0x02 << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_4MS		(0x04 << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_8MS		(0x08 << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_16MS		(0x10 << 8)
+#define	RTC_PERSISTENT0_ALARM_WAKE		(1 << 7)
+#define	RTC_PERSISTENT0_XTAL32_FREQ		(1 << 6)
+#define	RTC_PERSISTENT0_XTAL32KHZ_PWRUP		(1 << 5)
+#define	RTC_PERSISTENT0_XTAL24KHZ_PWRUP		(1 << 4)
+#define	RTC_PERSISTENT0_LCK_SECS		(1 << 3)
+#define	RTC_PERSISTENT0_ALARM_EN		(1 << 2)
+#define	RTC_PERSISTENT0_ALARM_WAKE_EN		(1 << 1)
+#define	RTC_PERSISTENT0_CLOCKSOURCE		(1 << 0)
+
+#define	RTC_PERSISTENT1_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT1_GENERAL_OFFSET		0
+#define	RTC_PERSISTENT1_GENERAL_OTG_ALT_ROLE	0x0080
+#define	RTC_PERSISTENT1_GENERAL_OTG_HNP		0x0100
+#define	RTC_PERSISTENT1_GENERAL_USB_LPM		0x0200
+#define	RTC_PERSISTENT1_GENERAL_SKIP_CHECKDISK	0x0400
+#define	RTC_PERSISTENT1_GENERAL_USB_BOOT_PLAYER	0x0800
+#define	RTC_PERSISTENT1_GENERAL_ENUM_500MA_2X	0x1000
+
+#define	RTC_PERSISTENT2_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT2_GENERAL_OFFSET		0
+
+#define	RTC_PERSISTENT3_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT3_GENERAL_OFFSET		0
+
+#define	RTC_PERSISTENT4_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT4_GENERAL_OFFSET		0
+
+#define	RTC_PERSISTENT5_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT5_GENERAL_OFFSET		0
+
+#define	RTC_DEBUG_WATCHDOG_RESET_MASK		(1 << 1)
+#define	RTC_DEBUG_WATCHDOG_RESET		(1 << 0)
+
+#define	RTC_VERSION_MAJOR_MASK			(0xff << 24)
+#define	RTC_VERSION_MAJOR_OFFSET		24
+#define	RTC_VERSION_MINOR_MASK			(0xff << 16)
+#define	RTC_VERSION_MINOR_OFFSET		16
+#define	RTC_VERSION_STEP_MASK			0xffff
+#define	RTC_VERSION_STEP_OFFSET			0
+
+#endif	/* __MX28_REGS_RTC_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-ssp.h b/arch/arm/include/asm/arch-mx28/regs-ssp.h
new file mode 100644
index 0000000..ab3870c
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-ssp.h
@@ -0,0 +1,349 @@
+/*
+ * Freescale i.MX28 SSP Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_SSP_H__
+#define __MX28_REGS_SSP_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_ssp_regs {
+	mx28_reg(hw_ssp_ctrl0)
+	mx28_reg(hw_ssp_cmd0)
+	mx28_reg(hw_ssp_cmd1)
+	mx28_reg(hw_ssp_xfer_size)
+	mx28_reg(hw_ssp_block_size)
+	mx28_reg(hw_ssp_compref)
+	mx28_reg(hw_ssp_compmask)
+	mx28_reg(hw_ssp_timing)
+	mx28_reg(hw_ssp_ctrl1)
+	mx28_reg(hw_ssp_data)
+	mx28_reg(hw_ssp_sdresp0)
+	mx28_reg(hw_ssp_sdresp1)
+	mx28_reg(hw_ssp_sdresp2)
+	mx28_reg(hw_ssp_sdresp3)
+	mx28_reg(hw_ssp_ddr_ctrl)
+	mx28_reg(hw_ssp_dll_ctrl)
+	mx28_reg(hw_ssp_status)
+	mx28_reg(hw_ssp_dll_sts)
+	mx28_reg(hw_ssp_debug)
+	mx28_reg(hw_ssp_version)
+};
+#endif
+
+#define	SSP_CTRL0_SFTRST			(1 << 31)
+#define	SSP_CTRL0_CLKGATE			(1 << 30)
+#define	SSP_CTRL0_RUN				(1 << 29)
+#define	SSP_CTRL0_SDIO_IRQ_CHECK		(1 << 28)
+#define	SSP_CTRL0_LOCK_CS			(1 << 27)
+#define	SSP_CTRL0_IGNORE_CRC			(1 << 26)
+#define	SSP_CTRL0_READ				(1 << 25)
+#define	SSP_CTRL0_DATA_XFER			(1 << 24)
+#define	SSP_CTRL0_BUS_WIDTH_MASK		(0x3 << 22)
+#define	SSP_CTRL0_BUS_WIDTH_OFFSET		22
+#define	SSP_CTRL0_BUS_WIDTH_ONE_BIT		(0x0 << 22)
+#define	SSP_CTRL0_BUS_WIDTH_FOUR_BIT		(0x1 << 22)
+#define	SSP_CTRL0_BUS_WIDTH_EIGHT_BIT		(0x2 << 22)
+#define	SSP_CTRL0_WAIT_FOR_IRQ			(1 << 21)
+#define	SSP_CTRL0_WAIT_FOR_CMD			(1 << 20)
+#define	SSP_CTRL0_LONG_RESP			(1 << 19)
+#define	SSP_CTRL0_CHECK_RESP			(1 << 18)
+#define	SSP_CTRL0_GET_RESP			(1 << 17)
+#define	SSP_CTRL0_ENABLE			(1 << 16)
+
+#define	SSP_CMD0_SOFT_TERMINATE			(1 << 26)
+#define	SSP_CMD0_DBL_DATA_RATE_EN		(1 << 25)
+#define	SSP_CMD0_PRIM_BOOT_OP_EN		(1 << 24)
+#define	SSP_CMD0_BOOT_ACK_EN			(1 << 23)
+#define	SSP_CMD0_SLOW_CLKING_EN			(1 << 22)
+#define	SSP_CMD0_CONT_CLKING_EN			(1 << 21)
+#define	SSP_CMD0_APPEND_8CYC			(1 << 20)
+#define	SSP_CMD0_CMD_MASK			0xff
+#define	SSP_CMD0_CMD_OFFSET			0
+#define	SSP_CMD0_CMD_MMC_GO_IDLE_STATE		0x00
+#define	SSP_CMD0_CMD_MMC_SEND_OP_COND		0x01
+#define	SSP_CMD0_CMD_MMC_ALL_SEND_CID		0x02
+#define	SSP_CMD0_CMD_MMC_SET_RELATIVE_ADDR	0x03
+#define	SSP_CMD0_CMD_MMC_SET_DSR		0x04
+#define	SSP_CMD0_CMD_MMC_RESERVED_5		0x05
+#define	SSP_CMD0_CMD_MMC_SWITCH			0x06
+#define	SSP_CMD0_CMD_MMC_SELECT_DESELECT_CARD	0x07
+#define	SSP_CMD0_CMD_MMC_SEND_EXT_CSD		0x08
+#define	SSP_CMD0_CMD_MMC_SEND_CSD		0x09
+#define	SSP_CMD0_CMD_MMC_SEND_CID		0x0a
+#define	SSP_CMD0_CMD_MMC_READ_DAT_UNTIL_STOP	0x0b
+#define	SSP_CMD0_CMD_MMC_STOP_TRANSMISSION	0x0c
+#define	SSP_CMD0_CMD_MMC_SEND_STATUS		0x0d
+#define	SSP_CMD0_CMD_MMC_BUSTEST_R		0x0e
+#define	SSP_CMD0_CMD_MMC_GO_INACTIVE_STATE	0x0f
+#define	SSP_CMD0_CMD_MMC_SET_BLOCKLEN		0x10
+#define	SSP_CMD0_CMD_MMC_READ_SINGLE_BLOCK	0x11
+#define	SSP_CMD0_CMD_MMC_READ_MULTIPLE_BLOCK	0x12
+#define	SSP_CMD0_CMD_MMC_BUSTEST_W		0x13
+#define	SSP_CMD0_CMD_MMC_WRITE_DAT_UNTIL_STOP	0x14
+#define	SSP_CMD0_CMD_MMC_SET_BLOCK_COUNT	0x17
+#define	SSP_CMD0_CMD_MMC_WRITE_BLOCK		0x18
+#define	SSP_CMD0_CMD_MMC_WRITE_MULTIPLE_BLOCK	0x19
+#define	SSP_CMD0_CMD_MMC_PROGRAM_CID		0x1a
+#define	SSP_CMD0_CMD_MMC_PROGRAM_CSD		0x1b
+#define	SSP_CMD0_CMD_MMC_SET_WRITE_PROT		0x1c
+#define	SSP_CMD0_CMD_MMC_CLR_WRITE_PROT		0x1d
+#define	SSP_CMD0_CMD_MMC_SEND_WRITE_PROT	0x1e
+#define	SSP_CMD0_CMD_MMC_ERASE_GROUP_START	0x23
+#define	SSP_CMD0_CMD_MMC_ERASE_GROUP_END	0x24
+#define	SSP_CMD0_CMD_MMC_ERASE			0x26
+#define	SSP_CMD0_CMD_MMC_FAST_IO		0x27
+#define	SSP_CMD0_CMD_MMC_GO_IRQ_STATE		0x28
+#define	SSP_CMD0_CMD_MMC_LOCK_UNLOCK		0x2a
+#define	SSP_CMD0_CMD_MMC_APP_CMD		0x37
+#define	SSP_CMD0_CMD_MMC_GEN_CMD		0x38
+#define	SSP_CMD0_CMD_SD_GO_IDLE_STATE		0x00
+#define	SSP_CMD0_CMD_SD_ALL_SEND_CID		0x02
+#define	SSP_CMD0_CMD_SD_SEND_RELATIVE_ADDR	0x03
+#define	SSP_CMD0_CMD_SD_SET_DSR			0x04
+#define	SSP_CMD0_CMD_SD_IO_SEND_OP_COND		0x05
+#define	SSP_CMD0_CMD_SD_SELECT_DESELECT_CARD	0x07
+#define	SSP_CMD0_CMD_SD_SEND_CSD		0x09
+#define	SSP_CMD0_CMD_SD_SEND_CID		0x0a
+#define	SSP_CMD0_CMD_SD_STOP_TRANSMISSION	0x0c
+#define	SSP_CMD0_CMD_SD_SEND_STATUS		0x0d
+#define	SSP_CMD0_CMD_SD_GO_INACTIVE_STATE	0x0f
+#define	SSP_CMD0_CMD_SD_SET_BLOCKLEN		0x10
+#define	SSP_CMD0_CMD_SD_READ_SINGLE_BLOCK	0x11
+#define	SSP_CMD0_CMD_SD_READ_MULTIPLE_BLOCK	0x12
+#define	SSP_CMD0_CMD_SD_WRITE_BLOCK		0x18
+#define	SSP_CMD0_CMD_SD_WRITE_MULTIPLE_BLOCK	0x19
+#define	SSP_CMD0_CMD_SD_PROGRAM_CSD		0x1b
+#define	SSP_CMD0_CMD_SD_SET_WRITE_PROT		0x1c
+#define	SSP_CMD0_CMD_SD_CLR_WRITE_PROT		0x1d
+#define	SSP_CMD0_CMD_SD_SEND_WRITE_PROT		0x1e
+#define	SSP_CMD0_CMD_SD_ERASE_WR_BLK_START	0x20
+#define	SSP_CMD0_CMD_SD_ERASE_WR_BLK_END	0x21
+#define	SSP_CMD0_CMD_SD_ERASE_GROUP_START	0x23
+#define	SSP_CMD0_CMD_SD_ERASE_GROUP_END		0x24
+#define	SSP_CMD0_CMD_SD_ERASE			0x26
+#define	SSP_CMD0_CMD_SD_LOCK_UNLOCK		0x2a
+#define	SSP_CMD0_CMD_SD_IO_RW_DIRECT		0x34
+#define	SSP_CMD0_CMD_SD_IO_RW_EXTENDED		0x35
+#define	SSP_CMD0_CMD_SD_APP_CMD			0x37
+#define	SSP_CMD0_CMD_SD_GEN_CMD			0x38
+
+#define	SSP_CMD1_CMD_ARG_MASK			0xffffffff
+#define	SSP_CMD1_CMD_ARG_OFFSET			0
+
+#define	SSP_XFER_SIZE_XFER_COUNT_MASK		0xffffffff
+#define	SSP_XFER_SIZE_XFER_COUNT_OFFSET		0
+
+#define	SSP_BLOCK_SIZE_BLOCK_COUNT_MASK		(0xffffff << 4)
+#define	SSP_BLOCK_SIZE_BLOCK_COUNT_OFFSET	4
+#define	SSP_BLOCK_SIZE_BLOCK_SIZE_MASK		0xf
+#define	SSP_BLOCK_SIZE_BLOCK_SIZE_OFFSET	0
+
+#define	SSP_COMPREF_REFERENCE_MASK		0xffffffff
+#define	SSP_COMPREF_REFERENCE_OFFSET		0
+
+#define	SSP_COMPMASK_MASK_MASK			0xffffffff
+#define	SSP_COMPMASK_MASK_OFFSET		0
+
+#define	SSP_TIMING_TIMEOUT_MASK			(0xffff << 16)
+#define	SSP_TIMING_TIMEOUT_OFFSET		16
+#define	SSP_TIMING_CLOCK_DIVIDE_MASK		(0xff << 8)
+#define	SSP_TIMING_CLOCK_DIVIDE_OFFSET		8
+#define	SSP_TIMING_CLOCK_RATE_MASK		0xff
+#define	SSP_TIMING_CLOCK_RATE_OFFSET		0
+
+#define	SSP_CTRL1_SDIO_IRQ			(1 << 31)
+#define	SSP_CTRL1_SDIO_IRQ_EN			(1 << 30)
+#define	SSP_CTRL1_RESP_ERR_IRQ			(1 << 29)
+#define	SSP_CTRL1_RESP_ERR_IRQ_EN		(1 << 28)
+#define	SSP_CTRL1_RESP_TIMEOUT_IRQ		(1 << 27)
+#define	SSP_CTRL1_RESP_TIMEOUT_IRQ_EN		(1 << 26)
+#define	SSP_CTRL1_DATA_TIMEOUT_IRQ		(1 << 25)
+#define	SSP_CTRL1_DATA_TIMEOUT_IRQ_EN		(1 << 24)
+#define	SSP_CTRL1_DATA_CRC_IRQ			(1 << 23)
+#define	SSP_CTRL1_DATA_CRC_IRQ_EN		(1 << 22)
+#define	SSP_CTRL1_FIFO_UNDERRUN_IRQ		(1 << 21)
+#define	SSP_CTRL1_FIFO_UNDERRUN_EN		(1 << 20)
+#define	SSP_CTRL1_CEATA_CCS_ERR_IRQ		(1 << 19)
+#define	SSP_CTRL1_CEATA_CCS_ERR_IRQ_EN		(1 << 18)
+#define	SSP_CTRL1_RECV_TIMEOUT_IRQ		(1 << 17)
+#define	SSP_CTRL1_RECV_TIMEOUT_IRQ_EN		(1 << 16)
+#define	SSP_CTRL1_FIFO_OVERRUN_IRQ		(1 << 15)
+#define	SSP_CTRL1_FIFO_OVERRUN_IRQ_EN		(1 << 14)
+#define	SSP_CTRL1_DMA_ENABLE			(1 << 13)
+#define	SSP_CTRL1_CEATA_CCS_ERR_EN		(1 << 12)
+#define	SSP_CTRL1_SLAVE_OUT_DISABLE		(1 << 11)
+#define	SSP_CTRL1_PHASE				(1 << 10)
+#define	SSP_CTRL1_POLARITY			(1 << 9)
+#define	SSP_CTRL1_SLAVE_MODE			(1 << 8)
+#define	SSP_CTRL1_WORD_LENGTH_MASK		(0xf << 4)
+#define	SSP_CTRL1_WORD_LENGTH_OFFSET		4
+#define	SSP_CTRL1_WORD_LENGTH_RESERVED0		(0x0 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_RESERVED1		(0x1 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_RESERVED2		(0x2 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_FOUR_BITS		(0x3 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_EIGHT_BITS	(0x7 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_SIXTEEN_BITS	(0xf << 4)
+#define	SSP_CTRL1_SSP_MODE_MASK			0xf
+#define	SSP_CTRL1_SSP_MODE_OFFSET		0
+#define	SSP_CTRL1_SSP_MODE_SPI			0x0
+#define	SSP_CTRL1_SSP_MODE_SSI			0x1
+#define	SSP_CTRL1_SSP_MODE_SD_MMC		0x3
+#define	SSP_CTRL1_SSP_MODE_MS			0x4
+
+#define	SSP_DATA_DATA_MASK			0xffffffff
+#define	SSP_DATA_DATA_OFFSET			0
+
+#define	SSP_SDRESP0_RESP0_MASK			0xffffffff
+#define	SSP_SDRESP0_RESP0_OFFSET		0
+
+#define	SSP_SDRESP1_RESP1_MASK			0xffffffff
+#define	SSP_SDRESP1_RESP1_OFFSET		0
+
+#define	SSP_SDRESP2_RESP2_MASK			0xffffffff
+#define	SSP_SDRESP2_RESP2_OFFSET		0
+
+#define	SSP_SDRESP3_RESP3_MASK			0xffffffff
+#define	SSP_SDRESP3_RESP3_OFFSET		0
+
+#define	SSP_DDR_CTRL_DMA_BURST_TYPE_MASK	(0x3 << 30)
+#define	SSP_DDR_CTRL_DMA_BURST_TYPE_OFFSET	30
+#define	SSP_DDR_CTRL_NIBBLE_POS			(1 << 1)
+#define	SSP_DDR_CTRL_TXCLK_DELAY_TYPE		(1 << 0)
+
+#define	SSP_DLL_CTRL_REF_UPDATE_INT_MASK	(0xf << 28)
+#define	SSP_DLL_CTRL_REF_UPDATE_INT_OFFSET	28
+#define	SSP_DLL_CTRL_SLV_UPDATE_INT_MASK	(0xff << 20)
+#define	SSP_DLL_CTRL_SLV_UPDATE_INT_OFFSET	20
+#define	SSP_DLL_CTRL_SLV_OVERRIDE_VAL_MASK	(0x3f << 10)
+#define	SSP_DLL_CTRL_SLV_OVERRIDE_VAL_OFFSET	10
+#define	SSP_DLL_CTRL_SLV_OVERRIDE		(1 << 9)
+#define	SSP_DLL_CTRL_GATE_UPDATE		(1 << 7)
+#define	SSP_DLL_CTRL_SLV_DLY_TARGET_MASK	(0xf << 3)
+#define	SSP_DLL_CTRL_SLV_DLY_TARGET_OFFSET	3
+#define	SSP_DLL_CTRL_SLV_FORCE_UPD		(1 << 2)
+#define	SSP_DLL_CTRL_RESET			(1 << 1)
+#define	SSP_DLL_CTRL_ENABLE			(1 << 0)
+
+#define	SSP_STATUS_PRESENT			(1 << 31)
+#define	SSP_STATUS_MS_PRESENT			(1 << 30)
+#define	SSP_STATUS_SD_PRESENT			(1 << 29)
+#define	SSP_STATUS_CARD_DETECT			(1 << 28)
+#define	SSP_STATUS_DMABURST			(1 << 22)
+#define	SSP_STATUS_DMASENSE			(1 << 21)
+#define	SSP_STATUS_DMATERM			(1 << 20)
+#define	SSP_STATUS_DMAREQ			(1 << 19)
+#define	SSP_STATUS_DMAEND			(1 << 18)
+#define	SSP_STATUS_SDIO_IRQ			(1 << 17)
+#define	SSP_STATUS_RESP_CRC_ERR			(1 << 16)
+#define	SSP_STATUS_RESP_ERR			(1 << 15)
+#define	SSP_STATUS_RESP_TIMEOUT			(1 << 14)
+#define	SSP_STATUS_DATA_CRC_ERR			(1 << 13)
+#define	SSP_STATUS_TIMEOUT			(1 << 12)
+#define	SSP_STATUS_RECV_TIMEOUT_STAT		(1 << 11)
+#define	SSP_STATUS_CEATA_CCS_ERR		(1 << 10)
+#define	SSP_STATUS_FIFO_OVRFLW			(1 << 9)
+#define	SSP_STATUS_FIFO_FULL			(1 << 8)
+#define	SSP_STATUS_FIFO_EMPTY			(1 << 5)
+#define	SSP_STATUS_FIFO_UNDRFLW			(1 << 4)
+#define	SSP_STATUS_CMD_BUSY			(1 << 3)
+#define	SSP_STATUS_DATA_BUSY			(1 << 2)
+#define	SSP_STATUS_BUSY				(1 << 0)
+
+#define	SSP_DLL_STS_REF_SEL_MASK		(0x3f << 8)
+#define	SSP_DLL_STS_REF_SEL_OFFSET		8
+#define	SSP_DLL_STS_SLV_SEL_MASK		(0x3f << 2)
+#define	SSP_DLL_STS_SLV_SEL_OFFSET		2
+#define	SSP_DLL_STS_REF_LOCK			(1 << 1)
+#define	SSP_DLL_STS_SLV_LOCK			(1 << 0)
+
+#define	SSP_DEBUG_DATACRC_ERR_MASK		(0xf << 28)
+#define	SSP_DEBUG_DATACRC_ERR_OFFSET		28
+#define	SSP_DEBUG_DATA_STALL			(1 << 27)
+#define	SSP_DEBUG_DAT_SM_MASK			(0x7 << 24)
+#define	SSP_DEBUG_DAT_SM_OFFSET			24
+#define	SSP_DEBUG_DAT_SM_DSM_IDLE		(0x0 << 24)
+#define	SSP_DEBUG_DAT_SM_DSM_WORD		(0x2 << 24)
+#define	SSP_DEBUG_DAT_SM_DSM_CRC1		(0x3 << 24)
+#define	SSP_DEBUG_DAT_SM_DSM_CRC2		(0x4 << 24)
+#define	SSP_DEBUG_DAT_SM_DSM_END		(0x5 << 24)
+#define	SSP_DEBUG_MSTK_SM_MASK			(0xf << 20)
+#define	SSP_DEBUG_MSTK_SM_OFFSET		20
+#define	SSP_DEBUG_MSTK_SM_MSTK_IDLE		(0x0 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_CKON		(0x1 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_BS1		(0x2 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_TPC		(0x3 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_BS2		(0x4 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_HDSHK		(0x5 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_BS3		(0x6 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_RW		(0x7 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_CRC1		(0x8 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_CRC2		(0x9 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_BS0		(0xa << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_END1		(0xb << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_END2W		(0xc << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_END2R		(0xd << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_DONE		(0xe << 20)
+#define	SSP_DEBUG_CMD_OE			(1 << 19)
+#define	SSP_DEBUG_DMA_SM_MASK			(0x7 << 16)
+#define	SSP_DEBUG_DMA_SM_OFFSET			16
+#define	SSP_DEBUG_DMA_SM_DMA_IDLE		(0x0 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_DMAREQ		(0x1 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_DMAACK		(0x2 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_STALL		(0x3 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_BUSY		(0x4 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_DONE		(0x5 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_COUNT		(0x6 << 16)
+#define	SSP_DEBUG_MMC_SM_MASK			(0xf << 12)
+#define	SSP_DEBUG_MMC_SM_OFFSET			12
+#define	SSP_DEBUG_MMC_SM_MMC_IDLE		(0x0 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_CMD		(0x1 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_TRC		(0x2 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_RESP		(0x3 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_RPRX		(0x4 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_TX			(0x5 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_CTOK		(0x6 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_RX			(0x7 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_CCS		(0x8 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_PUP		(0x9 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_WAIT		(0xa << 12)
+#define	SSP_DEBUG_CMD_SM_MASK			(0x3 << 10)
+#define	SSP_DEBUG_CMD_SM_OFFSET			10
+#define	SSP_DEBUG_CMD_SM_CSM_IDLE		(0x0 << 10)
+#define	SSP_DEBUG_CMD_SM_CSM_INDEX		(0x1 << 10)
+#define	SSP_DEBUG_CMD_SM_CSM_ARG		(0x2 << 10)
+#define	SSP_DEBUG_CMD_SM_CSM_CRC		(0x3 << 10)
+#define	SSP_DEBUG_SSP_CMD			(1 << 9)
+#define	SSP_DEBUG_SSP_RESP			(1 << 8)
+#define	SSP_DEBUG_SSP_RXD_MASK			0xff
+#define	SSP_DEBUG_SSP_RXD_OFFSET		0
+
+#define	SSP_VERSION_MAJOR_MASK			(0xff << 24)
+#define	SSP_VERSION_MAJOR_OFFSET		24
+#define	SSP_VERSION_MINOR_MASK			(0xff << 16)
+#define	SSP_VERSION_MINOR_OFFSET		16
+#define	SSP_VERSION_STEP_MASK			0xffff
+#define	SSP_VERSION_STEP_OFFSET			0
+
+#endif /* __MX28_REGS_SSP_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-timrot.h b/arch/arm/include/asm/arch-mx28/regs-timrot.h
new file mode 100644
index 0000000..1b941cf
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-timrot.h
@@ -0,0 +1,171 @@
+/*
+ * Freescale i.MX28 TIMROT Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_TIMROT_H__
+#define __MX28_REGS_TIMROT_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_timrot_regs {
+	mx28_reg(hw_timrot_rotctrl)
+	mx28_reg(hw_timrot_rotcount)
+	mx28_reg(hw_timrot_timctrl0)
+	mx28_reg(hw_timrot_running_count0)
+	mx28_reg(hw_timrot_fixed_count0)
+	mx28_reg(hw_timrot_match_count0)
+	mx28_reg(hw_timrot_timctrl1)
+	mx28_reg(hw_timrot_running_count1)
+	mx28_reg(hw_timrot_fixed_count1)
+	mx28_reg(hw_timrot_match_count1)
+	mx28_reg(hw_timrot_timctrl2)
+	mx28_reg(hw_timrot_running_count2)
+	mx28_reg(hw_timrot_fixed_count2)
+	mx28_reg(hw_timrot_match_count2)
+	mx28_reg(hw_timrot_timctrl3)
+	mx28_reg(hw_timrot_running_count3)
+	mx28_reg(hw_timrot_fixed_count3)
+	mx28_reg(hw_timrot_match_count3)
+	mx28_reg(hw_timrot_version)
+};
+#endif
+
+#define	TIMROT_ROTCTRL_SFTRST				(1 << 31)
+#define	TIMROT_ROTCTRL_CLKGATE				(1 << 30)
+#define	TIMROT_ROTCTRL_ROTARY_PRESENT			(1 << 29)
+#define	TIMROT_ROTCTRL_TIM3_PRESENT			(1 << 28)
+#define	TIMROT_ROTCTRL_TIM2_PRESENT			(1 << 27)
+#define	TIMROT_ROTCTRL_TIM1_PRESENT			(1 << 26)
+#define	TIMROT_ROTCTRL_TIM0_PRESENT			(1 << 25)
+#define	TIMROT_ROTCTRL_STATE_MASK			(0x7 << 22)
+#define	TIMROT_ROTCTRL_STATE_OFFSET			22
+#define	TIMROT_ROTCTRL_DIVIDER_MASK			(0x3f << 16)
+#define	TIMROT_ROTCTRL_DIVIDER_OFFSET			16
+#define	TIMROT_ROTCTRL_RELATIVE				(1 << 12)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_MASK			(0x3 << 10)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_OFFSET		10
+#define	TIMROT_ROTCTRL_OVERSAMPLE_8X			(0x0 << 10)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_4X			(0x1 << 10)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_2X			(0x2 << 10)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_1X			(0x3 << 10)
+#define	TIMROT_ROTCTRL_POLARITY_B			(1 << 9)
+#define	TIMROT_ROTCTRL_POLARITY_A			(1 << 8)
+#define	TIMROT_ROTCTRL_SELECT_B_MASK			(0xf << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_OFFSET			4
+#define	TIMROT_ROTCTRL_SELECT_B_NEVER_TICK		(0x0 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM0			(0x1 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM1			(0x2 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM2			(0x3 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM3			(0x4 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM4			(0x5 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM5			(0x6 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM6			(0x7 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM7			(0x8 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_ROTARYA			(0x9 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_ROTARYB			(0xa << 4)
+#define	TIMROT_ROTCTRL_SELECT_A_MASK			0xf
+#define	TIMROT_ROTCTRL_SELECT_A_OFFSET			0
+#define	TIMROT_ROTCTRL_SELECT_A_NEVER_TICK		0x0
+#define	TIMROT_ROTCTRL_SELECT_A_PWM0			0x1
+#define	TIMROT_ROTCTRL_SELECT_A_PWM1			0x2
+#define	TIMROT_ROTCTRL_SELECT_A_PWM2			0x3
+#define	TIMROT_ROTCTRL_SELECT_A_PWM3			0x4
+#define	TIMROT_ROTCTRL_SELECT_A_PWM4			0x5
+#define	TIMROT_ROTCTRL_SELECT_A_PWM5			0x6
+#define	TIMROT_ROTCTRL_SELECT_A_PWM6			0x7
+#define	TIMROT_ROTCTRL_SELECT_A_PWM7			0x8
+#define	TIMROT_ROTCTRL_SELECT_A_ROTARYA			0x9
+#define	TIMROT_ROTCTRL_SELECT_A_ROTARYB			0xa
+
+#define	TIMROT_ROTCOUNT_UPDOWN_MASK			0xffff
+#define	TIMROT_ROTCOUNT_UPDOWN_OFFSET			0
+
+#define	TIMROT_TIMCTRLn_IRQ				(1 << 15)
+#define	TIMROT_TIMCTRLn_IRQ_EN				(1 << 14)
+#define	TIMROT_TIMCTRLn_MATCH_MODE			(1 << 11)
+#define	TIMROT_TIMCTRLn_POLARITY			(1 << 8)
+#define	TIMROT_TIMCTRLn_UPDATE				(1 << 7)
+#define	TIMROT_TIMCTRLn_RELOAD				(1 << 6)
+#define	TIMROT_TIMCTRLn_PRESCALE_MASK			(0x3 << 4)
+#define	TIMROT_TIMCTRLn_PRESCALE_OFFSET			4
+#define	TIMROT_TIMCTRLn_PRESCALE_DIV_BY_1		(0x0 << 4)
+#define	TIMROT_TIMCTRLn_PRESCALE_DIV_BY_2		(0x1 << 4)
+#define	TIMROT_TIMCTRLn_PRESCALE_DIV_BY_4		(0x2 << 4)
+#define	TIMROT_TIMCTRLn_PRESCALE_DIV_BY_8		(0x3 << 4)
+#define	TIMROT_TIMCTRLn_SELECT_MASK			0xf
+#define	TIMROT_TIMCTRLn_SELECT_OFFSET			0
+#define	TIMROT_TIMCTRLn_SELECT_NEVER_TICK		0x0
+#define	TIMROT_TIMCTRLn_SELECT_PWM0			0x1
+#define	TIMROT_TIMCTRLn_SELECT_PWM1			0x2
+#define	TIMROT_TIMCTRLn_SELECT_PWM2			0x3
+#define	TIMROT_TIMCTRLn_SELECT_PWM3			0x4
+#define	TIMROT_TIMCTRLn_SELECT_PWM4			0x5
+#define	TIMROT_TIMCTRLn_SELECT_PWM5			0x6
+#define	TIMROT_TIMCTRLn_SELECT_PWM6			0x7
+#define	TIMROT_TIMCTRLn_SELECT_PWM7			0x8
+#define	TIMROT_TIMCTRLn_SELECT_ROTARYA			0x9
+#define	TIMROT_TIMCTRLn_SELECT_ROTARYB			0xa
+#define	TIMROT_TIMCTRLn_SELECT_32KHZ_XTAL		0xb
+#define	TIMROT_TIMCTRLn_SELECT_8KHZ_XTAL		0xc
+#define	TIMROT_TIMCTRLn_SELECT_4KHZ_XTAL		0xd
+#define	TIMROT_TIMCTRLn_SELECT_1KHZ_XTAL		0xe
+#define	TIMROT_TIMCTRLn_SELECT_TICK_ALWAYS		0xf
+
+#define	TIMROT_RUNNING_COUNTn_RUNNING_COUNT_MASK	0xffffffff
+#define	TIMROT_RUNNING_COUNTn_RUNNING_COUNT_OFFSET	0
+
+#define	TIMROT_FIXED_COUNTn_FIXED_COUNT_MASK		0xffffffff
+#define	TIMROT_FIXED_COUNTn_FIXED_COUNT_OFFSET		0
+
+#define	TIMROT_MATCH_COUNTn_MATCH_COUNT_MASK		0xffffffff
+#define	TIMROT_MATCH_COUNTn_MATCH_COUNT_OFFSET		0
+
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_MASK		(0xf << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_OFFSET		16
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_NEVER_TICK		(0x0 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM0		(0x1 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM1		(0x2 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM2		(0x3 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM3		(0x4 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM4		(0x5 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM5		(0x6 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM6		(0x7 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM7		(0x8 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_ROTARYA		(0x9 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_ROTARYB		(0xa << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_32KHZ_XTAL		(0xb << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_8KHZ_XTAL		(0xc << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_4KHZ_XTAL		(0xd << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_1KHZ_XTAL		(0xe << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_TICK_ALWAYS		(0xf << 16)
+#define	TIMROT_TIMCTRL3_DUTY_CYCLE			(1 << 9)
+
+#define	TIMROT_VERSION_MAJOR_MASK			(0xff << 24)
+#define	TIMROT_VERSION_MAJOR_OFFSET			24
+#define	TIMROT_VERSION_MINOR_MASK			(0xff << 16)
+#define	TIMROT_VERSION_MINOR_OFFSET			16
+#define	TIMROT_VERSION_STEP_MASK			0xffff
+#define	TIMROT_VERSION_STEP_OFFSET			0
+
+#endif /* __MX28_REGS_TIMROT_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/sys_proto.h b/arch/arm/include/asm/arch-mx28/sys_proto.h
new file mode 100644
index 0000000..a262c05
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/sys_proto.h
@@ -0,0 +1,30 @@
+/*
+ * Freescale i.MX28 MX28 specific functions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __MX28_H__
+#define __MX28_H__
+
+int mx28_reset_block(struct mx28_register *reg);
+int mx28_wait_mask_set(struct mx28_register *reg, uint32_t mask, int timeout);
+int mx28_wait_mask_clr(struct mx28_register *reg, uint32_t mask, int timeout);
+
+#endif	/* __MX28_H__ */
-- 
1.7.5.4

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

* [U-Boot] [PATCH 09/15 V5] iMX28: Add GPMI NAND driver
  2011-09-30  9:39         ` [U-Boot] [PATCH 09/15 V5] " Marek Vasut
@ 2011-10-10 21:06           ` Scott Wood
  0 siblings, 0 replies; 116+ messages in thread
From: Scott Wood @ 2011-10-10 21:06 UTC (permalink / raw)
  To: u-boot

On 09/30/2011 04:39 AM, Marek Vasut wrote:
> +/*
> + * There are several places in this driver where we have to handle the OOB and
> + * block marks. This is the function where things are the most complicated, so
> + * this is where we try to explain it all. All the other places refer back to
> + * here.
> + *
> + * These are the rules, in order of decreasing importance:
> + *
> + * 1) Nothing the caller does can be allowed to imperil the block mark, so all
> + *    write operations take measures to protect it.
> + *
> + * 2) In read operations, the first byte of the OOB we return must reflect the
> + *    true state of the block mark, no matter where that block mark appears in
> + *    the physical page.
> + *
> + * 3) ECC-based read operations return an OOB full of set bits (since we never
> + *    allow ECC-based writes to the OOB, it doesn't matter what ECC-based reads
> + *    return).
> + *
> + * 4) "Raw" read operations return a direct view of the physical bytes in the
> + *    page, using the conventional definition of which bytes are data and which
> + *    are OOB. This gives the caller a way to see the actual, physical bytes
> + *    in the page, without the distortions applied by our ECC engine.

As discussed, #4 is not a "rule" of the Linux/U-Boot NAND interface.  If
it's something you're doing as a hack, then say so -- make it clear that
you're deviating from the normal interface.

Otherwise, Acked-By: Scott Wood <scottwood@freescale.com>

-Scott

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

* [U-Boot] [PATCH 01/15 V3] iMX28: Initial support for iMX28 CPU
  2011-09-30  9:42     ` [U-Boot] [PATCH 01/15 V3] " Marek Vasut
@ 2011-10-13 16:19       ` Stefano Babic
  2011-10-13 18:14         ` Marek Vasut
  2011-10-13 23:38       ` [U-Boot] [PATCH 01/15 V4] " Marek Vasut
  2011-10-14 21:01       ` [U-Boot] [PATCH 01/15 V3] " Wolfgang Denk
  2 siblings, 1 reply; 116+ messages in thread
From: Stefano Babic @ 2011-10-13 16:19 UTC (permalink / raw)
  To: u-boot

On 09/30/2011 11:42 AM, Marek Vasut wrote:
> This patch supports:
> - Timers
> - Debug UART
> - Clock

Hi Marek,

/opt/tools/bin/checkpatch.pl --no-tree
~/Desktop/U-Boot-01-15-V3-iMX28-Initial-support-for-iMX28-CPU.patch
WARNING: line over 80 characters
#634: FILE: arch/arm/cpu/arm926ejs/mx28/mx28.c:150:
+int do_mx28_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char *
const argv[])

total: 0 errors, 1 warnings, 4527 lines checked

Can you fix and resubmit ?

Stefano

-- 
=====================================================================
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de
=====================================================================

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

* [U-Boot] [PATCH 01/15 V3] iMX28: Initial support for iMX28 CPU
  2011-10-13 16:19       ` Stefano Babic
@ 2011-10-13 18:14         ` Marek Vasut
  2011-10-13 20:45           ` Wolfgang Denk
  2011-10-14  7:51           ` Stefano Babic
  0 siblings, 2 replies; 116+ messages in thread
From: Marek Vasut @ 2011-10-13 18:14 UTC (permalink / raw)
  To: u-boot

On Thursday, October 13, 2011 06:19:44 PM Stefano Babic wrote:
> On 09/30/2011 11:42 AM, Marek Vasut wrote:
> > This patch supports:
> > - Timers
> > - Debug UART
> > - Clock
> 
> Hi Marek,
> 
> /opt/tools/bin/checkpatch.pl --no-tree
> ~/Desktop/U-Boot-01-15-V3-iMX28-Initial-support-for-iMX28-CPU.patch
> WARNING: line over 80 characters
> #634: FILE: arch/arm/cpu/arm926ejs/mx28/mx28.c:150:
> +int do_mx28_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char *
> const argv[])
> 
> total: 0 errors, 1 warnings, 4527 lines checked
> 
> Can you fix and resubmit ?
> 
> Stefano

Hi Stefano,

the patch is big and will need approval to be let into ML. Removing the space in 
char * const argv[] shall do the trick, can you please do that by hand ?

Cheers

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

* [U-Boot] [PATCH 01/15 V3] iMX28: Initial support for iMX28 CPU
  2011-10-13 18:14         ` Marek Vasut
@ 2011-10-13 20:45           ` Wolfgang Denk
  2011-10-14  7:51           ` Stefano Babic
  1 sibling, 0 replies; 116+ messages in thread
From: Wolfgang Denk @ 2011-10-13 20:45 UTC (permalink / raw)
  To: u-boot

Dear Marek Vasut,

In message <201110132014.55510.marek.vasut@gmail.com> you wrote:
>
> the patch is big and will need approval to be let into ML. Removing the space in 
> char * const argv[] shall do the trick, can you please do that by hand ?

It will do the trick and trigger a new checkpatch warning?

Please fix yourself, test, and resubmit.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Some people march to the beat of a different drummer. And some people
tango!

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

* [U-Boot] [PATCH 01/15 V4] iMX28: Initial support for iMX28 CPU
  2011-09-30  9:42     ` [U-Boot] [PATCH 01/15 V3] " Marek Vasut
  2011-10-13 16:19       ` Stefano Babic
@ 2011-10-13 23:38       ` Marek Vasut
  2011-10-14 21:14         ` [U-Boot] [PATCH 01/15 V5] " Marek Vasut
  2011-10-14 21:01       ` [U-Boot] [PATCH 01/15 V3] " Wolfgang Denk
  2 siblings, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-10-13 23:38 UTC (permalink / raw)
  To: u-boot

This patch supports:
- Timers
- Debug UART
- Clock

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 arch/arm/cpu/arm926ejs/mx28/Makefile          |   46 +
 arch/arm/cpu/arm926ejs/mx28/clock.c           |  355 +++++++
 arch/arm/cpu/arm926ejs/mx28/mx28.c            |  194 ++++
 arch/arm/cpu/arm926ejs/mx28/timer.c           |  141 +++
 arch/arm/include/asm/arch-mx28/clock.h        |   61 ++
 arch/arm/include/asm/arch-mx28/imx-regs.h     |   38 +
 arch/arm/include/asm/arch-mx28/regs-base.h    |   88 ++
 arch/arm/include/asm/arch-mx28/regs-bch.h     |  230 +++++
 arch/arm/include/asm/arch-mx28/regs-clkctrl.h |  312 ++++++
 arch/arm/include/asm/arch-mx28/regs-common.h  |   66 ++
 arch/arm/include/asm/arch-mx28/regs-gpmi.h    |  222 +++++
 arch/arm/include/asm/arch-mx28/regs-i2c.h     |  207 ++++
 arch/arm/include/asm/arch-mx28/regs-ocotp.h   |  173 ++++
 arch/arm/include/asm/arch-mx28/regs-pinctrl.h | 1284 +++++++++++++++++++++++++
 arch/arm/include/asm/arch-mx28/regs-power.h   |  413 ++++++++
 arch/arm/include/asm/arch-mx28/regs-rtc.h     |  147 +++
 arch/arm/include/asm/arch-mx28/regs-ssp.h     |  349 +++++++
 arch/arm/include/asm/arch-mx28/regs-timrot.h  |  171 ++++
 arch/arm/include/asm/arch-mx28/sys_proto.h    |   30 +
 19 files changed, 4527 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/Makefile
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/clock.c
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/mx28.c
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/timer.c
 create mode 100644 arch/arm/include/asm/arch-mx28/clock.h
 create mode 100644 arch/arm/include/asm/arch-mx28/imx-regs.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-base.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-bch.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-clkctrl.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-common.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-gpmi.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-i2c.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-ocotp.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-pinctrl.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-power.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-rtc.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-ssp.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-timrot.h
 create mode 100644 arch/arm/include/asm/arch-mx28/sys_proto.h

V2: Use watchdog for reset
V3: Remove redundant power_regs from cpu_reset() (gcc4.6)
V4: Squash checkpatch issue

diff --git a/arch/arm/cpu/arm926ejs/mx28/Makefile b/arch/arm/cpu/arm926ejs/mx28/Makefile
new file mode 100644
index 0000000..98504f9
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/Makefile
@@ -0,0 +1,46 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(SOC).o
+
+COBJS	= clock.o mx28.o timer.o
+
+SRCS	:= $(START:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+START	:= $(addprefix $(obj),$(START))
+
+all:	$(obj).depend $(LIB)
+
+$(LIB):	$(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/arm/cpu/arm926ejs/mx28/clock.c b/arch/arm/cpu/arm926ejs/mx28/clock.c
new file mode 100644
index 0000000..f698506
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/clock.c
@@ -0,0 +1,355 @@
+/*
+ * Freescale i.MX28 clock setup code
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+
+/* The PLL frequency is always 480MHz, see section 10.2 in iMX28 datasheet. */
+#define	PLL_FREQ_KHZ	480000
+#define	PLL_FREQ_COEF	18
+/* The XTAL frequency is always 24MHz, see section 10.2 in iMX28 datasheet. */
+#define	XTAL_FREQ_KHZ	24000
+
+#define	PLL_FREQ_MHZ	(PLL_FREQ_KHZ / 1000)
+#define	XTAL_FREQ_MHZ	(XTAL_FREQ_KHZ / 1000)
+
+static uint32_t mx28_get_pclk(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	uint32_t clkctrl, clkseq, clkfrac;
+	uint32_t frac, div;
+
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_cpu);
+
+	/* No support of fractional divider calculation */
+	if (clkctrl &
+		(CLKCTRL_CPU_DIV_XTAL_FRAC_EN | CLKCTRL_CPU_DIV_CPU_FRAC_EN)) {
+		return 0;
+	}
+
+	clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+
+	/* XTAL Path */
+	if (clkseq & CLKCTRL_CLKSEQ_BYPASS_CPU) {
+		div = (clkctrl & CLKCTRL_CPU_DIV_XTAL_MASK) >>
+			CLKCTRL_CPU_DIV_XTAL_OFFSET;
+		return XTAL_FREQ_MHZ / div;
+	}
+
+	/* REF Path */
+	clkfrac = readl(&clkctrl_regs->hw_clkctrl_frac0);
+	frac = clkfrac & CLKCTRL_FRAC0_CPUFRAC_MASK;
+	div = clkctrl & CLKCTRL_CPU_DIV_CPU_MASK;
+	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
+}
+
+static uint32_t mx28_get_hclk(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	uint32_t div;
+	uint32_t clkctrl;
+
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_hbus);
+
+	/* No support of fractional divider calculation */
+	if (clkctrl & CLKCTRL_HBUS_DIV_FRAC_EN)
+		return 0;
+
+	div = clkctrl & CLKCTRL_HBUS_DIV_MASK;
+	return mx28_get_pclk() / div;
+}
+
+static uint32_t mx28_get_emiclk(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	uint32_t frac, div;
+	uint32_t clkctrl, clkseq, clkfrac;
+
+	clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_emi);
+
+	/* XTAL Path */
+	if (clkseq & CLKCTRL_CLKSEQ_BYPASS_EMI) {
+		div = (clkctrl & CLKCTRL_EMI_DIV_XTAL_MASK) >>
+			CLKCTRL_EMI_DIV_XTAL_OFFSET;
+		return XTAL_FREQ_MHZ / div;
+	}
+
+	clkfrac = readl(&clkctrl_regs->hw_clkctrl_frac0);
+
+	/* REF Path */
+	frac = (clkfrac & CLKCTRL_FRAC0_EMIFRAC_MASK) >>
+		CLKCTRL_FRAC0_EMIFRAC_OFFSET;
+	div = clkctrl & CLKCTRL_EMI_DIV_EMI_MASK;
+	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
+}
+
+static uint32_t mx28_get_gpmiclk(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	uint32_t frac, div;
+	uint32_t clkctrl, clkseq, clkfrac;
+
+	clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_gpmi);
+
+	/* XTAL Path */
+	if (clkseq & CLKCTRL_CLKSEQ_BYPASS_GPMI) {
+		div = clkctrl & CLKCTRL_GPMI_DIV_MASK;
+		return XTAL_FREQ_MHZ / div;
+	}
+
+	clkfrac = readl(&clkctrl_regs->hw_clkctrl_frac1);
+
+	/* REF Path */
+	frac = (clkfrac & CLKCTRL_FRAC1_GPMIFRAC_MASK) >>
+		CLKCTRL_FRAC1_GPMIFRAC_OFFSET;
+	div = clkctrl & CLKCTRL_GPMI_DIV_MASK;
+	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
+}
+
+/*
+ * Set IO clock frequency, in kHz
+ */
+void mx28_set_ioclk(enum mxs_ioclock io, uint32_t freq)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t div;
+
+	if (freq == 0)
+		return;
+
+	if (io > MXC_IOCLK1)
+		return;
+
+	div = (PLL_FREQ_KHZ * PLL_FREQ_COEF) / freq;
+
+	if (div < 18)
+		div = 18;
+
+	if (div > 35)
+		div = 35;
+
+	if (io == MXC_IOCLK0) {
+		writel(CLKCTRL_FRAC0_CLKGATEIO0,
+			&clkctrl_regs->hw_clkctrl_frac0_set);
+		clrsetbits_le32(&clkctrl_regs->hw_clkctrl_frac0,
+				CLKCTRL_FRAC0_IO0FRAC_MASK,
+				div << CLKCTRL_FRAC0_IO0FRAC_OFFSET);
+		writel(CLKCTRL_FRAC0_CLKGATEIO0,
+			&clkctrl_regs->hw_clkctrl_frac0_clr);
+	} else {
+		writel(CLKCTRL_FRAC0_CLKGATEIO1,
+			&clkctrl_regs->hw_clkctrl_frac0_set);
+		clrsetbits_le32(&clkctrl_regs->hw_clkctrl_frac0,
+				CLKCTRL_FRAC0_IO1FRAC_MASK,
+				div << CLKCTRL_FRAC0_IO1FRAC_OFFSET);
+		writel(CLKCTRL_FRAC0_CLKGATEIO1,
+			&clkctrl_regs->hw_clkctrl_frac0_clr);
+	}
+}
+
+/*
+ * Get IO clock, returns IO clock in kHz
+ */
+static uint32_t mx28_get_ioclk(enum mxs_ioclock io)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t tmp, ret;
+
+	if (io > MXC_IOCLK1)
+		return 0;
+
+	tmp = readl(&clkctrl_regs->hw_clkctrl_frac0);
+
+	if (io == MXC_IOCLK0)
+		ret = (tmp & CLKCTRL_FRAC0_IO0FRAC_MASK) >>
+			CLKCTRL_FRAC0_IO0FRAC_OFFSET;
+	else
+		ret = (tmp & CLKCTRL_FRAC0_IO1FRAC_MASK) >>
+			CLKCTRL_FRAC0_IO1FRAC_OFFSET;
+
+	return (PLL_FREQ_KHZ * PLL_FREQ_COEF) / ret;
+}
+
+/*
+ * Configure SSP clock frequency, in kHz
+ */
+void mx28_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t clk, clkreg;
+
+	if (ssp > MXC_SSPCLK3)
+		return;
+
+	clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) +
+			(ssp * sizeof(struct mx28_register));
+
+	clrbits_le32(clkreg, CLKCTRL_SSP_CLKGATE);
+	while (readl(clkreg) & CLKCTRL_SSP_CLKGATE)
+		;
+
+	if (xtal)
+		clk = XTAL_FREQ_KHZ;
+	else
+		clk = mx28_get_ioclk(ssp >> 1);
+
+	if (freq > clk)
+		return;
+
+	/* Calculate the divider and cap it if necessary */
+	clk /= freq;
+	if (clk > CLKCTRL_SSP_DIV_MASK)
+		clk = CLKCTRL_SSP_DIV_MASK;
+
+	clrsetbits_le32(clkreg, CLKCTRL_SSP_DIV_MASK, clk);
+	while (readl(clkreg) & CLKCTRL_SSP_BUSY)
+		;
+
+	if (xtal)
+		writel(CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp,
+			&clkctrl_regs->hw_clkctrl_clkseq_set);
+	else
+		writel(CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp,
+			&clkctrl_regs->hw_clkctrl_clkseq_clr);
+}
+
+/*
+ * Return SSP frequency, in kHz
+ */
+static uint32_t mx28_get_sspclk(enum mxs_sspclock ssp)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t clkreg;
+	uint32_t clk, tmp;
+
+	if (ssp > MXC_SSPCLK3)
+		return 0;
+
+	tmp = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+	if (tmp & (CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp))
+		return XTAL_FREQ_KHZ;
+
+	clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) +
+			(ssp * sizeof(struct mx28_register));
+
+	tmp = readl(clkreg) & CLKCTRL_SSP_DIV_MASK;
+
+	if (tmp == 0)
+		return 0;
+
+	clk = mx28_get_ioclk(ssp >> 1);
+
+	return clk / tmp;
+}
+
+/*
+ * Set SSP/MMC bus frequency, in kHz)
+ */
+void mx28_set_ssp_busclock(unsigned int bus, uint32_t freq)
+{
+	struct mx28_ssp_regs *ssp_regs;
+	const uint32_t sspclk = mx28_get_sspclk(bus);
+	uint32_t reg;
+	uint32_t divide, rate, tgtclk;
+
+	ssp_regs = (struct mx28_ssp_regs *)(MXS_SSP0_BASE + (bus * 0x2000));
+
+	/*
+	 * SSP bit rate = SSPCLK / (CLOCK_DIVIDE * (1 + CLOCK_RATE)),
+	 * CLOCK_DIVIDE has to be an even value from 2 to 254, and
+	 * CLOCK_RATE could be any integer from 0 to 255.
+	 */
+	for (divide = 2; divide < 254; divide += 2) {
+		rate = sspclk / freq / divide;
+		if (rate <= 256)
+			break;
+	}
+
+	tgtclk = sspclk / divide / rate;
+	while (tgtclk > freq) {
+		rate++;
+		tgtclk = sspclk / divide / rate;
+	}
+	if (rate > 256)
+		rate = 256;
+
+	/* Always set timeout the maximum */
+	reg = SSP_TIMING_TIMEOUT_MASK |
+		(divide << SSP_TIMING_CLOCK_DIVIDE_OFFSET) |
+		((rate - 1) << SSP_TIMING_CLOCK_RATE_OFFSET);
+	writel(reg, &ssp_regs->hw_ssp_timing);
+
+	debug("SPI%d: Set freq rate to %d KHz (requested %d KHz)\n",
+		bus, tgtclk, freq);
+}
+
+uint32_t mxc_get_clock(enum mxc_clock clk)
+{
+	switch (clk) {
+	case MXC_ARM_CLK:
+		return mx28_get_pclk() * 1000000;
+	case MXC_GPMI_CLK:
+		return mx28_get_gpmiclk() * 1000000;
+	case MXC_AHB_CLK:
+	case MXC_IPG_CLK:
+		return mx28_get_hclk() * 1000000;
+	case MXC_EMI_CLK:
+		return mx28_get_emiclk();
+	case MXC_IO0_CLK:
+		return mx28_get_ioclk(MXC_IOCLK0);
+	case MXC_IO1_CLK:
+		return mx28_get_ioclk(MXC_IOCLK1);
+	case MXC_SSP0_CLK:
+		return mx28_get_sspclk(MXC_SSPCLK0);
+	case MXC_SSP1_CLK:
+		return mx28_get_sspclk(MXC_SSPCLK1);
+	case MXC_SSP2_CLK:
+		return mx28_get_sspclk(MXC_SSPCLK2);
+	case MXC_SSP3_CLK:
+		return mx28_get_sspclk(MXC_SSPCLK3);
+	}
+
+	return 0;
+}
diff --git a/arch/arm/cpu/arm926ejs/mx28/mx28.c b/arch/arm/cpu/arm926ejs/mx28/mx28.c
new file mode 100644
index 0000000..f517de4
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/mx28.c
@@ -0,0 +1,194 @@
+/*
+ * Freescale i.MX28 common code
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/iomux-mx28.h>
+
+/* 1 second delay should be plenty of time for block reset. */
+#define	RESET_MAX_TIMEOUT	1000000
+
+#define	MX28_BLOCK_SFTRST	(1 << 31)
+#define	MX28_BLOCK_CLKGATE	(1 << 30)
+
+/* Lowlevel init isn't used on i.MX28, so just have a dummy here */
+inline void lowlevel_init(void) {}
+
+void reset_cpu(ulong ignored) __attribute__((noreturn));
+
+void reset_cpu(ulong ignored)
+{
+
+	struct mx28_rtc_regs *rtc_regs =
+		(struct mx28_rtc_regs *)MXS_RTC_BASE;
+
+	/* Wait 1 uS before doing the actual watchdog reset */
+	writel(1, &rtc_regs->hw_rtc_watchdog);
+	writel(RTC_CTRL_WATCHDOGEN, &rtc_regs->hw_rtc_ctrl_set);
+
+	/* Endless loop, reset will exit from here */
+	for (;;)
+		;
+}
+
+int mx28_wait_mask_set(struct mx28_register *reg, uint32_t mask, int timeout)
+{
+	while (--timeout) {
+		if ((readl(&reg->reg) & mask) == mask)
+			break;
+		udelay(1);
+	}
+
+	return !timeout;
+}
+
+int mx28_wait_mask_clr(struct mx28_register *reg, uint32_t mask, int timeout)
+{
+	while (--timeout) {
+		if ((readl(&reg->reg) & mask) == 0)
+			break;
+		udelay(1);
+	}
+
+	return !timeout;
+}
+
+int mx28_reset_block(struct mx28_register *reg)
+{
+	/* Clear SFTRST */
+	writel(MX28_BLOCK_SFTRST, &reg->reg_clr);
+
+	if (mx28_wait_mask_clr(reg, MX28_BLOCK_SFTRST, RESET_MAX_TIMEOUT))
+		return 1;
+
+	/* Clear CLKGATE */
+	writel(MX28_BLOCK_CLKGATE, &reg->reg_clr);
+
+	/* Set SFTRST */
+	writel(MX28_BLOCK_SFTRST, &reg->reg_set);
+
+	/* Wait for CLKGATE being set */
+	if (mx28_wait_mask_set(reg, MX28_BLOCK_CLKGATE, RESET_MAX_TIMEOUT))
+		return 1;
+
+	/* Clear SFTRST */
+	writel(MX28_BLOCK_SFTRST, &reg->reg_clr);
+
+	if (mx28_wait_mask_clr(reg, MX28_BLOCK_SFTRST, RESET_MAX_TIMEOUT))
+		return 1;
+
+	/* Clear CLKGATE */
+	writel(MX28_BLOCK_CLKGATE, &reg->reg_clr);
+
+	if (mx28_wait_mask_clr(reg, MX28_BLOCK_CLKGATE, RESET_MAX_TIMEOUT))
+		return 1;
+
+	return 0;
+}
+
+#ifdef	CONFIG_ARCH_CPU_INIT
+int arch_cpu_init(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/*
+	 * Enable NAND clock
+	 */
+	/* Clear bypass bit */
+	writel(CLKCTRL_CLKSEQ_BYPASS_GPMI,
+		&clkctrl_regs->hw_clkctrl_clkseq_set);
+
+	/* Set GPMI clock to ref_gpmi / 12 */
+	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_gpmi,
+		CLKCTRL_GPMI_CLKGATE | CLKCTRL_GPMI_DIV_MASK, 1);
+
+	udelay(1000);
+
+	return 0;
+}
+#endif
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+int print_cpuinfo(void)
+{
+	printf("Freescale i.MX28 family\n");
+	return 0;
+}
+#endif
+
+int do_mx28_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+	printf("CPU:   %3d MHz\n", mxc_get_clock(MXC_ARM_CLK) / 1000000);
+	printf("BUS:   %3d MHz\n", mxc_get_clock(MXC_AHB_CLK) / 1000000);
+	printf("EMI:   %3d MHz\n", mxc_get_clock(MXC_EMI_CLK));
+	printf("GPMI:  %3d MHz\n", mxc_get_clock(MXC_GPMI_CLK) / 1000000);
+	return 0;
+}
+
+/*
+ * Initializes on-chip ethernet controllers.
+ */
+#ifdef	CONFIG_CMD_NET
+int cpu_eth_init(bd_t *bis)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/* Turn on ENET clocks */
+	clrbits_le32(&clkctrl_regs->hw_clkctrl_enet,
+		CLKCTRL_ENET_SLEEP | CLKCTRL_ENET_DISABLE);
+
+	/* Set up ENET PLL for 50 MHz */
+	/* Power on ENET PLL */
+	writel(CLKCTRL_PLL2CTRL0_POWER,
+		&clkctrl_regs->hw_clkctrl_pll2ctrl0_set);
+
+	udelay(10);
+
+	/* Gate on ENET PLL */
+	writel(CLKCTRL_PLL2CTRL0_CLKGATE,
+		&clkctrl_regs->hw_clkctrl_pll2ctrl0_clr);
+
+	/* Enable pad output */
+	setbits_le32(&clkctrl_regs->hw_clkctrl_enet, CLKCTRL_ENET_CLK_OUT_EN);
+
+	return 0;
+}
+#endif
+
+U_BOOT_CMD(
+	clocks,	CONFIG_SYS_MAXARGS, 1, do_mx28_showclocks,
+	"display clocks",
+	""
+);
diff --git a/arch/arm/cpu/arm926ejs/mx28/timer.c b/arch/arm/cpu/arm926ejs/mx28/timer.c
new file mode 100644
index 0000000..dbc904d
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/timer.c
@@ -0,0 +1,141 @@
+/*
+ * Freescale i.MX28 timer driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * (C) Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+
+/* Maximum fixed count */
+#define TIMER_LOAD_VAL	0xffffffff
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define timestamp (gd->tbl)
+#define lastdec (gd->lastinc)
+
+/*
+ * This driver uses 1kHz clock source.
+ */
+#define	MX28_INCREMENTER_HZ		1000
+
+static inline unsigned long tick_to_time(unsigned long tick)
+{
+	return tick / (MX28_INCREMENTER_HZ / CONFIG_SYS_HZ);
+}
+
+static inline unsigned long time_to_tick(unsigned long time)
+{
+	return time * (MX28_INCREMENTER_HZ / CONFIG_SYS_HZ);
+}
+
+/* Calculate how many ticks happen in "us" microseconds */
+static inline unsigned long us_to_tick(unsigned long us)
+{
+	return (us * MX28_INCREMENTER_HZ) / 1000000;
+}
+
+int timer_init(void)
+{
+	struct mx28_timrot_regs *timrot_regs =
+		(struct mx28_timrot_regs *)MXS_TIMROT_BASE;
+
+	/* Reset Timers and Rotary Encoder module */
+	mx28_reset_block(&timrot_regs->hw_timrot_rotctrl_reg);
+
+	/* Set fixed_count to 0 */
+	writel(0, &timrot_regs->hw_timrot_fixed_count0);
+
+	/* Set UPDATE bit and 1Khz frequency */
+	writel(TIMROT_TIMCTRLn_UPDATE | TIMROT_TIMCTRLn_RELOAD |
+		TIMROT_TIMCTRLn_SELECT_1KHZ_XTAL,
+		&timrot_regs->hw_timrot_timctrl0);
+
+	/* Set fixed_count to maximal value */
+	writel(TIMER_LOAD_VAL, &timrot_regs->hw_timrot_fixed_count0);
+
+	return 0;
+}
+
+ulong get_timer(ulong base)
+{
+	struct mx28_timrot_regs *timrot_regs =
+		(struct mx28_timrot_regs *)MXS_TIMROT_BASE;
+
+	/* Current tick value */
+	uint32_t now = readl(&timrot_regs->hw_timrot_running_count0);
+
+	if (lastdec >= now) {
+		/*
+		 * normal mode (non roll)
+		 * move stamp forward with absolut diff ticks
+		 */
+		timestamp += (lastdec - now);
+	} else {
+		/* we have rollover of decrementer */
+		timestamp += (TIMER_LOAD_VAL - now) + lastdec;
+
+	}
+	lastdec = now;
+
+	return tick_to_time(timestamp) - base;
+}
+
+/* We use the HW_DIGCTL_MICROSECONDS register for sub-millisecond timer. */
+#define	MX28_HW_DIGCTL_MICROSECONDS	0x8001c0c0
+
+void __udelay(unsigned long usec)
+{
+	uint32_t old, new, incr;
+	uint32_t counter = 0;
+
+	old = readl(MX28_HW_DIGCTL_MICROSECONDS);
+
+	while (counter < usec) {
+		new = readl(MX28_HW_DIGCTL_MICROSECONDS);
+
+		/* Check if the timer wrapped. */
+		if (new < old) {
+			incr = 0xffffffff - old;
+			incr += new;
+		} else {
+			incr = new - old;
+		}
+
+		/*
+		 * Check if we are close to the maximum time and the counter
+		 * would wrap if incremented. If that's the case, break out
+		 * from the loop as the requested delay time passed.
+		 */
+		if (counter + incr < counter)
+			break;
+
+		counter += incr;
+		old = new;
+	}
+}
diff --git a/arch/arm/include/asm/arch-mx28/clock.h b/arch/arm/include/asm/arch-mx28/clock.h
new file mode 100644
index 0000000..1700fe3
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/clock.h
@@ -0,0 +1,61 @@
+/*
+ * Freescale i.MX28 Clock
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __CLOCK_H__
+#define __CLOCK_H__
+
+enum mxc_clock {
+	MXC_ARM_CLK = 0,
+	MXC_AHB_CLK,
+	MXC_IPG_CLK,
+	MXC_EMI_CLK,
+	MXC_GPMI_CLK,
+	MXC_IO0_CLK,
+	MXC_IO1_CLK,
+	MXC_SSP0_CLK,
+	MXC_SSP1_CLK,
+	MXC_SSP2_CLK,
+	MXC_SSP3_CLK,
+};
+
+enum mxs_ioclock {
+	MXC_IOCLK0 = 0,
+	MXC_IOCLK1,
+};
+
+enum mxs_sspclock {
+	MXC_SSPCLK0 = 0,
+	MXC_SSPCLK1,
+	MXC_SSPCLK2,
+	MXC_SSPCLK3,
+};
+
+uint32_t mxc_get_clock(enum mxc_clock clk);
+
+void mx28_set_ioclk(enum mxs_ioclock io, uint32_t freq);
+void mx28_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal);
+void mx28_set_ssp_busclock(unsigned int bus, uint32_t freq);
+
+/* Compatibility with the FEC Ethernet driver */
+#define	imx_get_fecclk()	mxc_get_clock(MXC_AHB_CLK)
+
+#endif	/* __CLOCK_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/imx-regs.h b/arch/arm/include/asm/arch-mx28/imx-regs.h
new file mode 100644
index 0000000..32bfd7e
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/imx-regs.h
@@ -0,0 +1,38 @@
+/*
+ * Freescale i.MX28 Registers
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __IMX_REGS_H__
+#define __IMX_REGS_H__
+
+#include <asm/arch/regs-base.h>
+#include <asm/arch/regs-bch.h>
+#include <asm/arch/regs-clkctrl.h>
+#include <asm/arch/regs-gpmi.h>
+#include <asm/arch/regs-i2c.h>
+#include <asm/arch/regs-ocotp.h>
+#include <asm/arch/regs-pinctrl.h>
+#include <asm/arch/regs-power.h>
+#include <asm/arch/regs-rtc.h>
+#include <asm/arch/regs-ssp.h>
+#include <asm/arch/regs-timrot.h>
+
+#endif	/* __IMX_REGS_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-base.h b/arch/arm/include/asm/arch-mx28/regs-base.h
new file mode 100644
index 0000000..dbdcc2b
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-base.h
@@ -0,0 +1,88 @@
+/*
+ * Freescale i.MX28 Peripheral Base Addresses
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright (C) 2008 Embedded Alley Solutions Inc.
+ *
+ * (C) Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __MX28_REGS_BASE_H__
+#define __MX28_REGS_BASE_H__
+
+/*
+ * Register base address
+ */
+#define	MXS_ICOL_BASE		0x80000000
+#define	MXS_HSADC_BASE		0x80002000
+#define	MXS_APBH_BASE		0x80004000
+#define	MXS_PERFMON_BASE	0x80006000
+#define	MXS_BCH_BASE		0x8000A000
+#define	MXS_GPMI_BASE		0x8000C000
+#define	MXS_SSP0_BASE		0x80010000
+#define	MXS_SSP1_BASE		0x80012000
+#define	MXS_SSP2_BASE		0x80014000
+#define	MXS_SSP3_BASE		0x80016000
+#define	MXS_PINCTRL_BASE	0x80018000
+#define	MXS_DIGCTL_BASE		0x8001C000
+#define	MXS_ETM_BASE		0x80022000
+#define	MXS_APBX_BASE		0x80024000
+#define	MXS_DCP_BASE		0x80028000
+#define	MXS_PXP_BASE		0x8002A000
+#define	MXS_OCOTP_BASE		0x8002C000
+#define	MXS_AXI_AHB0_BASE	0x8002E000
+#define	MXS_LCDIF_BASE		0x80030000
+#define	MXS_CAN0_BASE		0x80032000
+#define	MXS_CAN1_BASE		0x80034000
+#define	MXS_SIMDBG_BASE		0x8003C000
+#define	MXS_SIMGPMISEL_BASE	0x8003C200
+#define	MXS_SIMSSPSEL_BASE	0x8003C300
+#define	MXS_SIMMEMSEL_BASE	0x8003C400
+#define	MXS_GPIOMON_BASE	0x8003C500
+#define	MXS_SIMENET_BASE	0x8003C700
+#define	MXS_ARMJTAG_BASE	0x8003C800
+#define	MXS_CLKCTRL_BASE	0x80040000
+#define	MXS_SAIF0_BASE		0x80042000
+#define	MXS_POWER_BASE		0x80044000
+#define	MXS_SAIF1_BASE		0x80046000
+#define	MXS_LRADC_BASE		0x80050000
+#define	MXS_SPDIF_BASE		0x80054000
+#define	MXS_RTC_BASE		0x80056000
+#define	MXS_I2C0_BASE		0x80058000
+#define	MXS_I2C1_BASE		0x8005A000
+#define	MXS_PWM_BASE		0x80064000
+#define	MXS_TIMROT_BASE		0x80068000
+#define	MXS_UARTAPP0_BASE	0x8006A000
+#define	MXS_UARTAPP1_BASE	0x8006C000
+#define	MXS_UARTAPP2_BASE	0x8006E000
+#define	MXS_UARTAPP3_BASE	0x80070000
+#define	MXS_UARTAPP4_BASE	0x80072000
+#define	MXS_UARTDBG_BASE	0x80074000
+#define	MXS_USBPHY0_BASE	0x8007C000
+#define	MXS_USBPHY1_BASE	0x8007E000
+#define	MXS_USBCTRL0_BASE	0x80080000
+#define	MXS_USBCTRL1_BASE	0x80090000
+#define	MXS_DFLPT_BASE		0x800C0000
+#define	MXS_DRAM_BASE		0x800E0000
+#define	MXS_ENET0_BASE		0x800F0000
+#define	MXS_ENET1_BASE		0x800F4000
+
+#endif /* __MX28_REGS_BASE_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-bch.h b/arch/arm/include/asm/arch-mx28/regs-bch.h
new file mode 100644
index 0000000..cac0470
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-bch.h
@@ -0,0 +1,230 @@
+/*
+ * Freescale i.MX28 BCH Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_BCH_H__
+#define __MX28_REGS_BCH_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_bch_regs {
+	mx28_reg(hw_bch_ctrl)
+	mx28_reg(hw_bch_status0)
+	mx28_reg(hw_bch_mode)
+	mx28_reg(hw_bch_encodeptr)
+	mx28_reg(hw_bch_dataptr)
+	mx28_reg(hw_bch_metaptr)
+
+	uint32_t	reserved[4];
+
+	mx28_reg(hw_bch_layoutselect)
+	mx28_reg(hw_bch_flash0layout0)
+	mx28_reg(hw_bch_flash0layout1)
+	mx28_reg(hw_bch_flash1layout0)
+	mx28_reg(hw_bch_flash1layout1)
+	mx28_reg(hw_bch_flash2layout0)
+	mx28_reg(hw_bch_flash2layout1)
+	mx28_reg(hw_bch_flash3layout0)
+	mx28_reg(hw_bch_flash3layout1)
+	mx28_reg(hw_bch_dbgkesread)
+	mx28_reg(hw_bch_dbgcsferead)
+	mx28_reg(hw_bch_dbgsyndegread)
+	mx28_reg(hw_bch_dbgahbmread)
+	mx28_reg(hw_bch_blockname)
+	mx28_reg(hw_bch_version)
+};
+#endif
+
+#define	BCH_CTRL_SFTRST					(1 << 31)
+#define	BCH_CTRL_CLKGATE				(1 << 30)
+#define	BCH_CTRL_DEBUGSYNDROME				(1 << 22)
+#define	BCH_CTRL_M2M_LAYOUT_MASK			(0x3 << 18)
+#define	BCH_CTRL_M2M_LAYOUT_OFFSET			18
+#define	BCH_CTRL_M2M_ENCODE				(1 << 17)
+#define	BCH_CTRL_M2M_ENABLE				(1 << 16)
+#define	BCH_CTRL_DEBUG_STALL_IRQ_EN			(1 << 10)
+#define	BCH_CTRL_COMPLETE_IRQ_EN			(1 << 8)
+#define	BCH_CTRL_BM_ERROR_IRQ				(1 << 3)
+#define	BCH_CTRL_DEBUG_STALL_IRQ			(1 << 2)
+#define	BCH_CTRL_COMPLETE_IRQ				(1 << 0)
+
+#define	BCH_STATUS0_HANDLE_MASK				(0xfff << 20)
+#define	BCH_STATUS0_HANDLE_OFFSET			20
+#define	BCH_STATUS0_COMPLETED_CE_MASK			(0xf << 16)
+#define	BCH_STATUS0_COMPLETED_CE_OFFSET			16
+#define	BCH_STATUS0_STATUS_BLK0_MASK			(0xff << 8)
+#define	BCH_STATUS0_STATUS_BLK0_OFFSET			8
+#define	BCH_STATUS0_STATUS_BLK0_ZERO			(0x00 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERROR1			(0x01 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERROR2			(0x02 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERROR3			(0x03 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERROR4			(0x04 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_UNCORRECTABLE		(0xfe << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERASED			(0xff << 8)
+#define	BCH_STATUS0_ALLONES				(1 << 4)
+#define	BCH_STATUS0_CORRECTED				(1 << 3)
+#define	BCH_STATUS0_UNCORRECTABLE			(1 << 2)
+
+#define	BCH_MODE_ERASE_THRESHOLD_MASK			0xff
+#define	BCH_MODE_ERASE_THRESHOLD_OFFSET			0
+
+#define	BCH_ENCODEPTR_ADDR_MASK				0xffffffff
+#define	BCH_ENCODEPTR_ADDR_OFFSET			0
+
+#define	BCH_DATAPTR_ADDR_MASK				0xffffffff
+#define	BCH_DATAPTR_ADDR_OFFSET				0
+
+#define	BCH_METAPTR_ADDR_MASK				0xffffffff
+#define	BCH_METAPTR_ADDR_OFFSET				0
+
+#define	BCH_LAYOUTSELECT_CS15_SELECT_MASK		(0x3 << 30)
+#define	BCH_LAYOUTSELECT_CS15_SELECT_OFFSET		30
+#define	BCH_LAYOUTSELECT_CS14_SELECT_MASK		(0x3 << 28)
+#define	BCH_LAYOUTSELECT_CS14_SELECT_OFFSET		28
+#define	BCH_LAYOUTSELECT_CS13_SELECT_MASK		(0x3 << 26)
+#define	BCH_LAYOUTSELECT_CS13_SELECT_OFFSET		26
+#define	BCH_LAYOUTSELECT_CS12_SELECT_MASK		(0x3 << 24)
+#define	BCH_LAYOUTSELECT_CS12_SELECT_OFFSET		24
+#define	BCH_LAYOUTSELECT_CS11_SELECT_MASK		(0x3 << 22)
+#define	BCH_LAYOUTSELECT_CS11_SELECT_OFFSET		22
+#define	BCH_LAYOUTSELECT_CS10_SELECT_MASK		(0x3 << 20)
+#define	BCH_LAYOUTSELECT_CS10_SELECT_OFFSET		20
+#define	BCH_LAYOUTSELECT_CS9_SELECT_MASK		(0x3 << 18)
+#define	BCH_LAYOUTSELECT_CS9_SELECT_OFFSET		18
+#define	BCH_LAYOUTSELECT_CS8_SELECT_MASK		(0x3 << 16)
+#define	BCH_LAYOUTSELECT_CS8_SELECT_OFFSET		16
+#define	BCH_LAYOUTSELECT_CS7_SELECT_MASK		(0x3 << 14)
+#define	BCH_LAYOUTSELECT_CS7_SELECT_OFFSET		14
+#define	BCH_LAYOUTSELECT_CS6_SELECT_MASK		(0x3 << 12)
+#define	BCH_LAYOUTSELECT_CS6_SELECT_OFFSET		12
+#define	BCH_LAYOUTSELECT_CS5_SELECT_MASK		(0x3 << 10)
+#define	BCH_LAYOUTSELECT_CS5_SELECT_OFFSET		10
+#define	BCH_LAYOUTSELECT_CS4_SELECT_MASK		(0x3 << 8)
+#define	BCH_LAYOUTSELECT_CS4_SELECT_OFFSET		8
+#define	BCH_LAYOUTSELECT_CS3_SELECT_MASK		(0x3 << 6)
+#define	BCH_LAYOUTSELECT_CS3_SELECT_OFFSET		6
+#define	BCH_LAYOUTSELECT_CS2_SELECT_MASK		(0x3 << 4)
+#define	BCH_LAYOUTSELECT_CS2_SELECT_OFFSET		4
+#define	BCH_LAYOUTSELECT_CS1_SELECT_MASK		(0x3 << 2)
+#define	BCH_LAYOUTSELECT_CS1_SELECT_OFFSET		2
+#define	BCH_LAYOUTSELECT_CS0_SELECT_MASK		(0x3 << 0)
+#define	BCH_LAYOUTSELECT_CS0_SELECT_OFFSET		0
+
+#define	BCH_FLASHLAYOUT0_NBLOCKS_MASK			(0xff << 24)
+#define	BCH_FLASHLAYOUT0_NBLOCKS_OFFSET			24
+#define	BCH_FLASHLAYOUT0_META_SIZE_MASK			(0xff << 16)
+#define	BCH_FLASHLAYOUT0_META_SIZE_OFFSET		16
+#define	BCH_FLASHLAYOUT0_ECC0_MASK			(0xf << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_OFFSET			12
+#define	BCH_FLASHLAYOUT0_ECC0_NONE			(0x0 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC2			(0x1 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC4			(0x2 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC6			(0x3 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC8			(0x4 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC10			(0x5 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC12			(0x6 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC14			(0x7 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC16			(0x8 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC18			(0x9 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC20			(0xa << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC22			(0xb << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC24			(0xc << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC26			(0xd << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC28			(0xe << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC30			(0xf << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC32			(0x10 << 12)
+#define	BCH_FLASHLAYOUT0_GF13_0_GF14_1			(1 << 10)
+#define	BCH_FLASHLAYOUT0_DATA0_SIZE_MASK		0xfff
+#define	BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET		0
+
+#define	BCH_FLASHLAYOUT1_PAGE_SIZE_MASK			(0xffff << 16)
+#define	BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET		16
+#define	BCH_FLASHLAYOUT1_ECCN_MASK			(0xf << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_OFFSET			12
+#define	BCH_FLASHLAYOUT1_ECCN_NONE			(0x0 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC2			(0x1 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC4			(0x2 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC6			(0x3 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC8			(0x4 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC10			(0x5 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC12			(0x6 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC14			(0x7 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC16			(0x8 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC18			(0x9 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC20			(0xa << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC22			(0xb << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC24			(0xc << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC26			(0xd << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC28			(0xe << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC30			(0xf << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC32			(0x10 << 12)
+#define	BCH_FLASHLAYOUT1_GF13_0_GF14_1			(1 << 10)
+#define	BCH_FLASHLAYOUT1_DATAN_SIZE_MASK		0xfff
+#define	BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET		0
+
+#define	BCH_DEBUG0_RSVD1_MASK				(0x1f << 27)
+#define	BCH_DEBUG0_RSVD1_OFFSET				27
+#define	BCH_DEBUG0_ROM_BIST_ENABLE			(1 << 26)
+#define	BCH_DEBUG0_ROM_BIST_COMPLETE			(1 << 25)
+#define	BCH_DEBUG0_KES_DEBUG_SYNDROME_SYMBOL_MASK	(0x1ff << 16)
+#define	BCH_DEBUG0_KES_DEBUG_SYNDROME_SYMBOL_OFFSET	16
+#define	BCH_DEBUG0_KES_DEBUG_SYNDROME_SYMBOL_NORMAL	(0x0 << 16)
+#define	BCH_DEBUG0_KES_DEBUG_SYNDROME_SYMBOL_TEST_MODE	(0x1 << 16)
+#define	BCH_DEBUG0_KES_DEBUG_SHIFT_SYND			(1 << 15)
+#define	BCH_DEBUG0_KES_DEBUG_PAYLOAD_FLAG		(1 << 14)
+#define	BCH_DEBUG0_KES_DEBUG_MODE4K			(1 << 13)
+#define	BCH_DEBUG0_KES_DEBUG_KICK			(1 << 12)
+#define	BCH_DEBUG0_KES_STANDALONE			(1 << 11)
+#define	BCH_DEBUG0_KES_DEBUG_STEP			(1 << 10)
+#define	BCH_DEBUG0_KES_DEBUG_STALL			(1 << 9)
+#define	BCH_DEBUG0_BM_KES_TEST_BYPASS			(1 << 8)
+#define	BCH_DEBUG0_RSVD0_MASK				(0x3 << 6)
+#define	BCH_DEBUG0_RSVD0_OFFSET				6
+#define	BCH_DEBUG0_DEBUG_REG_SELECT_MASK		0x3f
+#define	BCH_DEBUG0_DEBUG_REG_SELECT_OFFSET		0
+
+#define	BCH_DBGKESREAD_VALUES_MASK			0xffffffff
+#define	BCH_DBGKESREAD_VALUES_OFFSET			0
+
+#define	BCH_DBGCSFEREAD_VALUES_MASK			0xffffffff
+#define	BCH_DBGCSFEREAD_VALUES_OFFSET			0
+
+#define	BCH_DBGSYNDGENREAD_VALUES_MASK			0xffffffff
+#define	BCH_DBGSYNDGENREAD_VALUES_OFFSET		0
+
+#define	BCH_DBGAHBMREAD_VALUES_MASK			0xffffffff
+#define	BCH_DBGAHBMREAD_VALUES_OFFSET			0
+
+#define	BCH_BLOCKNAME_NAME_MASK				0xffffffff
+#define	BCH_BLOCKNAME_NAME_OFFSET			0
+
+#define	BCH_VERSION_MAJOR_MASK				(0xff << 24)
+#define	BCH_VERSION_MAJOR_OFFSET			24
+#define	BCH_VERSION_MINOR_MASK				(0xff << 16)
+#define	BCH_VERSION_MINOR_OFFSET			16
+#define	BCH_VERSION_STEP_MASK				0xffff
+#define	BCH_VERSION_STEP_OFFSET				0
+
+#endif	/* __MX28_REGS_BCH_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-clkctrl.h b/arch/arm/include/asm/arch-mx28/regs-clkctrl.h
new file mode 100644
index 0000000..93d0397
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-clkctrl.h
@@ -0,0 +1,312 @@
+/*
+ * Freescale i.MX28 CLKCTRL Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_CLKCTRL_H__
+#define __MX28_REGS_CLKCTRL_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_clkctrl_regs {
+	mx28_reg(hw_clkctrl_pll0ctrl0)		/* 0x00 */
+	mx28_reg(hw_clkctrl_pll0ctrl1)		/* 0x10 */
+	mx28_reg(hw_clkctrl_pll1ctrl0)		/* 0x20 */
+	mx28_reg(hw_clkctrl_pll1ctrl1)		/* 0x30 */
+	mx28_reg(hw_clkctrl_pll2ctrl0)		/* 0x40 */
+	mx28_reg(hw_clkctrl_cpu)		/* 0x50 */
+	mx28_reg(hw_clkctrl_hbus)		/* 0x60 */
+	mx28_reg(hw_clkctrl_xbus)		/* 0x70 */
+	mx28_reg(hw_clkctrl_xtal)		/* 0x80 */
+	mx28_reg(hw_clkctrl_ssp0)		/* 0x90 */
+	mx28_reg(hw_clkctrl_ssp1)		/* 0xa0 */
+	mx28_reg(hw_clkctrl_ssp2)		/* 0xb0 */
+	mx28_reg(hw_clkctrl_ssp3)		/* 0xc0 */
+	mx28_reg(hw_clkctrl_gpmi)		/* 0xd0 */
+	mx28_reg(hw_clkctrl_spdif)		/* 0xe0 */
+	mx28_reg(hw_clkctrl_emi)		/* 0xf0 */
+	mx28_reg(hw_clkctrl_saif0)		/* 0x100 */
+	mx28_reg(hw_clkctrl_saif1)		/* 0x110 */
+	mx28_reg(hw_clkctrl_lcdif)		/* 0x120 */
+	mx28_reg(hw_clkctrl_etm)		/* 0x130 */
+	mx28_reg(hw_clkctrl_enet)		/* 0x140 */
+	mx28_reg(hw_clkctrl_hsadc)		/* 0x150 */
+	mx28_reg(hw_clkctrl_flexcan)		/* 0x160 */
+
+	uint32_t	reserved[16];
+
+	mx28_reg(hw_clkctrl_frac0)		/* 0x1b0 */
+	mx28_reg(hw_clkctrl_frac1)		/* 0x1c0 */
+	mx28_reg(hw_clkctrl_clkseq)		/* 0x1d0 */
+	mx28_reg(hw_clkctrl_reset)		/* 0x1e0 */
+	mx28_reg(hw_clkctrl_status)		/* 0x1f0 */
+	mx28_reg(hw_clkctrl_version)		/* 0x200 */
+};
+#endif
+
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_MASK		(0x3 << 28)
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_OFFSET	28
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_DEFAULT	(0x0 << 28)
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_TIMES_2	(0x1 << 28)
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_TIMES_05	(0x2 << 28)
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_UNDEFINED	(0x3 << 28)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_MASK		(0x3 << 24)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_OFFSET		24
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_DEFAULT	(0x0 << 24)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_TIMES_2	(0x1 << 24)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_TIMES_05	(0x2 << 24)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_UNDEFINED	(0x3 << 24)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_MASK		(0x3 << 20)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_OFFSET	20
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_DEFAULT	(0x0 << 20)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_LOWER		(0x1 << 20)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_LOWEST	(0x2 << 20)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_UNDEFINED	(0x3 << 20)
+#define	CLKCTRL_PLL0CTRL0_EN_USB_CLKS		(1 << 18)
+#define	CLKCTRL_PLL0CTRL0_POWER			(1 << 17)
+
+#define	CLKCTRL_PLL0CTRL1_LOCK			(1 << 31)
+#define	CLKCTRL_PLL0CTRL1_FORCE_LOCK		(1 << 30)
+#define	CLKCTRL_PLL0CTRL1_LOCK_COUNT_MASK	0xffff
+#define	CLKCTRL_PLL0CTRL1_LOCK_COUNT_OFFSET	0
+
+#define	CLKCTRL_PLL1CTRL0_CLKGATEEMI		(1 << 31)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_MASK		(0x3 << 28)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_OFFSET	28
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_DEFAULT	(0x0 << 28)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_TIMES_2	(0x1 << 28)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_TIMES_05	(0x2 << 28)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_UNDEFINED	(0x3 << 28)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_MASK		(0x3 << 24)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_OFFSET		24
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_DEFAULT	(0x0 << 24)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_TIMES_2	(0x1 << 24)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_TIMES_05	(0x2 << 24)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_UNDEFINED	(0x3 << 24)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_MASK		(0x3 << 20)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_OFFSET	20
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_DEFAULT	(0x0 << 20)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_LOWER		(0x1 << 20)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_LOWEST	(0x2 << 20)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_UNDEFINED	(0x3 << 20)
+#define	CLKCTRL_PLL1CTRL0_EN_USB_CLKS		(1 << 18)
+#define	CLKCTRL_PLL1CTRL0_POWER			(1 << 17)
+
+#define	CLKCTRL_PLL1CTRL1_LOCK			(1 << 31)
+#define	CLKCTRL_PLL1CTRL1_FORCE_LOCK		(1 << 30)
+#define	CLKCTRL_PLL1CTRL1_LOCK_COUNT_MASK	0xffff
+#define	CLKCTRL_PLL1CTRL1_LOCK_COUNT_OFFSET	0
+
+#define	CLKCTRL_PLL2CTRL0_CLKGATE		(1 << 31)
+#define	CLKCTRL_PLL2CTRL0_LFR_SEL_MASK		(0x3 << 28)
+#define	CLKCTRL_PLL2CTRL0_LFR_SEL_OFFSET	28
+#define	CLKCTRL_PLL2CTRL0_HOLD_RING_OFF_B	(1 << 26)
+#define	CLKCTRL_PLL2CTRL0_CP_SEL_MASK		(0x3 << 24)
+#define	CLKCTRL_PLL2CTRL0_CP_SEL_OFFSET		24
+#define	CLKCTRL_PLL2CTRL0_POWER			(1 << 23)
+
+#define	CLKCTRL_CPU_BUSY_REF_XTAL		(1 << 29)
+#define	CLKCTRL_CPU_BUSY_REF_CPU		(1 << 28)
+#define	CLKCTRL_CPU_DIV_XTAL_FRAC_EN		(1 << 26)
+#define	CLKCTRL_CPU_DIV_XTAL_MASK		(0x3ff << 16)
+#define	CLKCTRL_CPU_DIV_XTAL_OFFSET		16
+#define	CLKCTRL_CPU_INTERRUPT_WAIT		(1 << 12)
+#define	CLKCTRL_CPU_DIV_CPU_FRAC_EN		(1 << 10)
+#define	CLKCTRL_CPU_DIV_CPU_MASK		0x3f
+#define	CLKCTRL_CPU_DIV_CPU_OFFSET		0
+
+#define	CLKCTRL_HBUS_ASM_BUSY			(1 << 31)
+#define	CLKCTRL_HBUS_DCP_AS_ENABLE		(1 << 30)
+#define	CLKCTRL_HBUS_PXP_AS_ENABLE		(1 << 29)
+#define	CLKCTRL_HBUS_ASM_EMIPORT_AS_ENABLE	(1 << 27)
+#define	CLKCTRL_HBUS_APBHDMA_AS_ENABLE		(1 << 26)
+#define	CLKCTRL_HBUS_APBXDMA_AS_ENABLE		(1 << 25)
+#define	CLKCTRL_HBUS_TRAFFIC_JAM_AS_ENABLE	(1 << 24)
+#define	CLKCTRL_HBUS_TRAFFIC_AS_ENABLE		(1 << 23)
+#define	CLKCTRL_HBUS_CPU_DATA_AS_ENABLE		(1 << 22)
+#define	CLKCTRL_HBUS_CPU_INSTR_AS_ENABLE	(1 << 21)
+#define	CLKCTRL_HBUS_ASM_ENABLE			(1 << 20)
+#define	CLKCTRL_HBUS_AUTO_CLEAR_DIV_ENABLE	(1 << 19)
+#define	CLKCTRL_HBUS_SLOW_DIV_MASK		(0x7 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_OFFSET		16
+#define	CLKCTRL_HBUS_SLOW_DIV_BY1		(0x0 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY2		(0x1 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY4		(0x2 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY8		(0x3 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY16		(0x4 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY32		(0x5 << 16)
+#define	CLKCTRL_HBUS_DIV_FRAC_EN		(1 << 5)
+#define	CLKCTRL_HBUS_DIV_MASK			0x1f
+#define	CLKCTRL_HBUS_DIV_OFFSET			0
+
+#define	CLKCTRL_XBUS_BUSY			(1 << 31)
+#define	CLKCTRL_XBUS_AUTO_CLEAR_DIV_ENABLE	(1 << 11)
+#define	CLKCTRL_XBUS_DIV_FRAC_EN		(1 << 10)
+#define	CLKCTRL_XBUS_DIV_MASK			0x3ff
+#define	CLKCTRL_XBUS_DIV_OFFSET			0
+
+#define	CLKCTRL_XTAL_UART_CLK_GATE		(1 << 31)
+#define	CLKCTRL_XTAL_PWM_CLK24M_GATE		(1 << 29)
+#define	CLKCTRL_XTAL_TIMROT_CLK32K_GATE		(1 << 26)
+#define	CLKCTRL_XTAL_DIV_UART_MASK		0x3
+#define	CLKCTRL_XTAL_DIV_UART_OFFSET		0
+
+#define	CLKCTRL_SSP_CLKGATE			(1 << 31)
+#define	CLKCTRL_SSP_BUSY			(1 << 29)
+#define	CLKCTRL_SSP_DIV_FRAC_EN			(1 << 9)
+#define	CLKCTRL_SSP_DIV_MASK			0x1ff
+#define	CLKCTRL_SSP_DIV_OFFSET			0
+
+#define	CLKCTRL_GPMI_CLKGATE			(1 << 31)
+#define	CLKCTRL_GPMI_BUSY			(1 << 29)
+#define	CLKCTRL_GPMI_DIV_FRAC_EN		(1 << 10)
+#define	CLKCTRL_GPMI_DIV_MASK			0x3ff
+#define	CLKCTRL_GPMI_DIV_OFFSET			0
+
+#define	CLKCTRL_SPDIF_CLKGATE			(1 << 31)
+
+#define	CLKCTRL_EMI_CLKGATE			(1 << 31)
+#define	CLKCTRL_EMI_SYNC_MODE_EN		(1 << 30)
+#define	CLKCTRL_EMI_BUSY_REF_XTAL		(1 << 29)
+#define	CLKCTRL_EMI_BUSY_REF_EMI		(1 << 28)
+#define	CLKCTRL_EMI_BUSY_REF_CPU		(1 << 27)
+#define	CLKCTRL_EMI_BUSY_SYNC_MODE		(1 << 26)
+#define	CLKCTRL_EMI_BUSY_DCC_RESYNC		(1 << 17)
+#define	CLKCTRL_EMI_DCC_RESYNC_ENABLE		(1 << 16)
+#define	CLKCTRL_EMI_DIV_XTAL_MASK		(0xf << 8)
+#define	CLKCTRL_EMI_DIV_XTAL_OFFSET		8
+#define	CLKCTRL_EMI_DIV_EMI_MASK		0x3f
+#define	CLKCTRL_EMI_DIV_EMI_OFFSET		0
+
+#define	CLKCTRL_SAIF0_CLKGATE			(1 << 31)
+#define	CLKCTRL_SAIF0_BUSY			(1 << 29)
+#define	CLKCTRL_SAIF0_DIV_FRAC_EN		(1 << 16)
+#define	CLKCTRL_SAIF0_DIV_MASK			0xffff
+#define	CLKCTRL_SAIF0_DIV_OFFSET		0
+
+#define	CLKCTRL_SAIF1_CLKGATE			(1 << 31)
+#define	CLKCTRL_SAIF1_BUSY			(1 << 29)
+#define	CLKCTRL_SAIF1_DIV_FRAC_EN		(1 << 16)
+#define	CLKCTRL_SAIF1_DIV_MASK			0xffff
+#define	CLKCTRL_SAIF1_DIV_OFFSET		0
+
+#define	CLKCTRL_DIS_LCDIF_CLKGATE		(1 << 31)
+#define	CLKCTRL_DIS_LCDIF_BUSY			(1 << 29)
+#define	CLKCTRL_DIS_LCDIF_DIV_FRAC_EN		(1 << 13)
+#define	CLKCTRL_DIS_LCDIF_DIV_MASK		0x1fff
+#define	CLKCTRL_DIS_LCDIF_DIV_OFFSET		0
+
+#define	CLKCTRL_ETM_CLKGATE			(1 << 31)
+#define	CLKCTRL_ETM_BUSY			(1 << 29)
+#define	CLKCTRL_ETM_DIV_FRAC_EN			(1 << 7)
+#define	CLKCTRL_ETM_DIV_MASK			0x7f
+#define	CLKCTRL_ETM_DIV_OFFSET			0
+
+#define	CLKCTRL_ENET_SLEEP			(1 << 31)
+#define	CLKCTRL_ENET_DISABLE			(1 << 30)
+#define	CLKCTRL_ENET_STATUS			(1 << 29)
+#define	CLKCTRL_ENET_BUSY_TIME			(1 << 27)
+#define	CLKCTRL_ENET_DIV_TIME_MASK		(0x3f << 21)
+#define	CLKCTRL_ENET_DIV_TIME_OFFSET		21
+#define	CLKCTRL_ENET_TIME_SEL_MASK		(0x3 << 19)
+#define	CLKCTRL_ENET_TIME_SEL_OFFSET		19
+#define	CLKCTRL_ENET_TIME_SEL_XTAL		(0x0 << 19)
+#define	CLKCTRL_ENET_TIME_SEL_PLL		(0x1 << 19)
+#define	CLKCTRL_ENET_TIME_SEL_RMII_CLK		(0x2 << 19)
+#define	CLKCTRL_ENET_TIME_SEL_UNDEFINED		(0x3 << 19)
+#define	CLKCTRL_ENET_CLK_OUT_EN			(1 << 18)
+#define	CLKCTRL_ENET_RESET_BY_SW_CHIP		(1 << 17)
+#define	CLKCTRL_ENET_RESET_BY_SW		(1 << 16)
+
+#define	CLKCTRL_HSADC_RESETB			(1 << 30)
+#define	CLKCTRL_HSADC_FREQDIV_MASK		(0x3 << 28)
+#define	CLKCTRL_HSADC_FREQDIV_OFFSET		28
+
+#define	CLKCTRL_FLEXCAN_STOP_CAN0		(1 << 30)
+#define	CLKCTRL_FLEXCAN_CAN0_STATUS		(1 << 29)
+#define	CLKCTRL_FLEXCAN_STOP_CAN1		(1 << 28)
+#define	CLKCTRL_FLEXCAN_CAN1_STATUS		(1 << 27)
+
+#define	CLKCTRL_FRAC0_CLKGATEIO0		(1 << 31)
+#define	CLKCTRL_FRAC0_IO0_STABLE		(1 << 30)
+#define	CLKCTRL_FRAC0_IO0FRAC_MASK		(0x3f << 24)
+#define	CLKCTRL_FRAC0_IO0FRAC_OFFSET		24
+#define	CLKCTRL_FRAC0_CLKGATEIO1		(1 << 23)
+#define	CLKCTRL_FRAC0_IO1_STABLE		(1 << 22)
+#define	CLKCTRL_FRAC0_IO1FRAC_MASK		(0x3f << 16)
+#define	CLKCTRL_FRAC0_IO1FRAC_OFFSET		16
+#define	CLKCTRL_FRAC0_CLKGATEEMI		(1 << 15)
+#define	CLKCTRL_FRAC0_EMI_STABLE		(1 << 14)
+#define	CLKCTRL_FRAC0_EMIFRAC_MASK		(0x3f << 8)
+#define	CLKCTRL_FRAC0_EMIFRAC_OFFSET		8
+#define	CLKCTRL_FRAC0_CLKGATECPU		(1 << 7)
+#define	CLKCTRL_FRAC0_CPU_STABLE		(1 << 6)
+#define	CLKCTRL_FRAC0_CPUFRAC_MASK		0x3f
+#define	CLKCTRL_FRAC0_CPUFRAC_OFFSET		0
+
+#define	CLKCTRL_FRAC1_CLKGATEGPMI		(1 << 23)
+#define	CLKCTRL_FRAC1_GPMI_STABLE		(1 << 22)
+#define	CLKCTRL_FRAC1_GPMIFRAC_MASK		(0x3f << 16)
+#define	CLKCTRL_FRAC1_GPMIFRAC_OFFSET		16
+#define	CLKCTRL_FRAC1_CLKGATEHSADC		(1 << 15)
+#define	CLKCTRL_FRAC1_HSADC_STABLE		(1 << 14)
+#define	CLKCTRL_FRAC1_HSADCFRAC_MASK		(0x3f << 8)
+#define	CLKCTRL_FRAC1_HSADCFRAC_OFFSET		8
+#define	CLKCTRL_FRAC1_CLKGATEPIX		(1 << 7)
+#define	CLKCTRL_FRAC1_PIX_STABLE		(1 << 6)
+#define	CLKCTRL_FRAC1_PIXFRAC_MASK		0x3f
+#define	CLKCTRL_FRAC1_PIXFRAC_OFFSET		0
+
+#define	CLKCTRL_CLKSEQ_BYPASS_CPU		(1 << 18)
+#define	CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF		(1 << 14)
+#define	CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF_BYPASS	(0x1 << 14)
+#define	CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF_PFD	(0x0 << 14)
+#define	CLKCTRL_CLKSEQ_BYPASS_ETM		(1 << 8)
+#define	CLKCTRL_CLKSEQ_BYPASS_EMI		(1 << 7)
+#define	CLKCTRL_CLKSEQ_BYPASS_SSP3		(1 << 6)
+#define	CLKCTRL_CLKSEQ_BYPASS_SSP2		(1 << 5)
+#define	CLKCTRL_CLKSEQ_BYPASS_SSP1		(1 << 4)
+#define	CLKCTRL_CLKSEQ_BYPASS_SSP0		(1 << 3)
+#define	CLKCTRL_CLKSEQ_BYPASS_GPMI		(1 << 2)
+#define	CLKCTRL_CLKSEQ_BYPASS_SAIF1		(1 << 1)
+#define	CLKCTRL_CLKSEQ_BYPASS_SAIF0		(1 << 0)
+
+#define	CLKCTRL_RESET_WDOG_POR_DISABLE		(1 << 5)
+#define	CLKCTRL_RESET_EXTERNAL_RESET_ENABLE	(1 << 4)
+#define	CLKCTRL_RESET_THERMAL_RESET_ENABLE	(1 << 3)
+#define	CLKCTRL_RESET_THERMAL_RESET_DEFAULT	(1 << 2)
+#define	CLKCTRL_RESET_CHIP			(1 << 1)
+#define	CLKCTRL_RESET_DIG			(1 << 0)
+
+#define	CLKCTRL_STATUS_CPU_LIMIT_MASK		(0x3 << 30)
+#define	CLKCTRL_STATUS_CPU_LIMIT_OFFSET		30
+
+#define	CLKCTRL_VERSION_MAJOR_MASK		(0xff << 24)
+#define	CLKCTRL_VERSION_MAJOR_OFFSET		24
+#define	CLKCTRL_VERSION_MINOR_MASK		(0xff << 16)
+#define	CLKCTRL_VERSION_MINOR_OFFSET		16
+#define	CLKCTRL_VERSION_STEP_MASK		0xffff
+#define	CLKCTRL_VERSION_STEP_OFFSET		0
+
+#endif /* __MX28_REGS_CLKCTRL_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-common.h b/arch/arm/include/asm/arch-mx28/regs-common.h
new file mode 100644
index 0000000..efe975b
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-common.h
@@ -0,0 +1,66 @@
+/*
+ * Freescale i.MX28 Register Accessors
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_COMMON_H__
+#define __MX28_REGS_COMMON_H__
+
+/*
+ * The i.MX28 has interesting feature when it comes to register access. There
+ * are four kinds of access to one particular register. Those are:
+ *
+ * 1) Common read/write access. To use this mode, just write to the address of
+ *    the register.
+ * 2) Set bits only access. To set bits, write which bits you want to set to the
+ *    address of the register + 0x4.
+ * 3) Clear bits only access. To clear bits, write which bits you want to clear
+ *    to the address of the register + 0x8.
+ * 4) Toggle bits only access. To toggle bits, write which bits you want to
+ *    toggle to the address of the register + 0xc.
+ *
+ * IMPORTANT NOTE: Not all registers support accesses 2-4! Also, not all bits
+ * can be set/cleared by pure write as in access type 1, some need to be
+ * explicitly set/cleared by using access type 2-3.
+ *
+ * The following macros and structures allow the user to either access the
+ * register in all aforementioned modes (by accessing reg_name, reg_name_set,
+ * reg_name_clr, reg_name_tog) or pass the register structure further into
+ * various functions with correct type information (by accessing reg_name_reg).
+ *
+ */
+
+#define	__mx28_reg(name)		\
+	uint32_t name;			\
+	uint32_t name##_set;		\
+	uint32_t name##_clr;		\
+	uint32_t name##_tog;
+
+struct mx28_register {
+	__mx28_reg(reg)
+};
+
+#define	mx28_reg(name)					\
+	union {						\
+		struct { __mx28_reg(name) };		\
+		struct mx28_register name##_reg;	\
+	};
+
+#endif	/* __MX28_REGS_COMMON_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-gpmi.h b/arch/arm/include/asm/arch-mx28/regs-gpmi.h
new file mode 100644
index 0000000..0096793
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-gpmi.h
@@ -0,0 +1,222 @@
+/*
+ * Freescale i.MX28 GPMI Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_GPMI_H__
+#define __MX28_REGS_GPMI_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_gpmi_regs {
+	mx28_reg(hw_gpmi_ctrl0)
+	mx28_reg(hw_gpmi_compare)
+	mx28_reg(hw_gpmi_eccctrl)
+	mx28_reg(hw_gpmi_ecccount)
+	mx28_reg(hw_gpmi_payload)
+	mx28_reg(hw_gpmi_auxiliary)
+	mx28_reg(hw_gpmi_ctrl1)
+	mx28_reg(hw_gpmi_timing0)
+	mx28_reg(hw_gpmi_timing1)
+
+	uint32_t	reserved[4];
+
+	mx28_reg(hw_gpmi_data)
+	mx28_reg(hw_gpmi_stat)
+	mx28_reg(hw_gpmi_debug)
+	mx28_reg(hw_gpmi_version)
+};
+#endif
+
+#define	GPMI_CTRL0_SFTRST				(1 << 31)
+#define	GPMI_CTRL0_CLKGATE				(1 << 30)
+#define	GPMI_CTRL0_RUN					(1 << 29)
+#define	GPMI_CTRL0_DEV_IRQ_EN				(1 << 28)
+#define	GPMI_CTRL0_LOCK_CS				(1 << 27)
+#define	GPMI_CTRL0_UDMA					(1 << 26)
+#define	GPMI_CTRL0_COMMAND_MODE_MASK			(0x3 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_OFFSET			24
+#define	GPMI_CTRL0_COMMAND_MODE_WRITE			(0x0 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_READ			(0x1 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_READ_AND_COMPARE	(0x2 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY		(0x3 << 24)
+#define	GPMI_CTRL0_WORD_LENGTH				(1 << 23)
+#define	GPMI_CTRL0_CS_MASK				(0x7 << 20)
+#define	GPMI_CTRL0_CS_OFFSET				20
+#define	GPMI_CTRL0_ADDRESS_MASK				(0x7 << 17)
+#define	GPMI_CTRL0_ADDRESS_OFFSET			17
+#define	GPMI_CTRL0_ADDRESS_NAND_DATA			(0x0 << 17)
+#define	GPMI_CTRL0_ADDRESS_NAND_CLE			(0x1 << 17)
+#define	GPMI_CTRL0_ADDRESS_NAND_ALE			(0x2 << 17)
+#define	GPMI_CTRL0_ADDRESS_INCREMENT			(1 << 16)
+#define	GPMI_CTRL0_XFER_COUNT_MASK			0xffff
+#define	GPMI_CTRL0_XFER_COUNT_OFFSET			0
+
+#define	GPMI_COMPARE_MASK_MASK				(0xffff << 16)
+#define	GPMI_COMPARE_MASK_OFFSET			16
+#define	GPMI_COMPARE_REFERENCE_MASK			0xffff
+#define	GPMI_COMPARE_REFERENCE_OFFSET			0
+
+#define	GPMI_ECCCTRL_HANDLE_MASK			(0xffff << 16)
+#define	GPMI_ECCCTRL_HANDLE_OFFSET			16
+#define	GPMI_ECCCTRL_ECC_CMD_MASK			(0x3 << 13)
+#define	GPMI_ECCCTRL_ECC_CMD_OFFSET			13
+#define	GPMI_ECCCTRL_ECC_CMD_DECODE			(0x0 << 13)
+#define	GPMI_ECCCTRL_ECC_CMD_ENCODE			(0x1 << 13)
+#define	GPMI_ECCCTRL_ENABLE_ECC				(1 << 12)
+#define	GPMI_ECCCTRL_BUFFER_MASK_MASK			0x1ff
+#define	GPMI_ECCCTRL_BUFFER_MASK_OFFSET			0
+#define	GPMI_ECCCTRL_BUFFER_MASK_BCH_AUXONLY		0x100
+#define	GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE		0x1ff
+
+#define	GPMI_ECCCOUNT_COUNT_MASK			0xffff
+#define	GPMI_ECCCOUNT_COUNT_OFFSET			0
+
+#define	GPMI_PAYLOAD_ADDRESS_MASK			(0x3fffffff << 2)
+#define	GPMI_PAYLOAD_ADDRESS_OFFSET			2
+
+#define	GPMI_AUXILIARY_ADDRESS_MASK			(0x3fffffff << 2)
+#define	GPMI_AUXILIARY_ADDRESS_OFFSET			2
+
+#define	GPMI_CTRL1_DECOUPLE_CS				(1 << 24)
+#define	GPMI_CTRL1_WRN_DLY_SEL_MASK			(0x3 << 22)
+#define	GPMI_CTRL1_WRN_DLY_SEL_OFFSET			22
+#define	GPMI_CTRL1_TIMEOUT_IRQ_EN			(1 << 20)
+#define	GPMI_CTRL1_GANGED_RDYBUSY			(1 << 19)
+#define	GPMI_CTRL1_BCH_MODE				(1 << 18)
+#define	GPMI_CTRL1_DLL_ENABLE				(1 << 17)
+#define	GPMI_CTRL1_HALF_PERIOD				(1 << 16)
+#define	GPMI_CTRL1_RDN_DELAY_MASK			(0xf << 12)
+#define	GPMI_CTRL1_RDN_DELAY_OFFSET			12
+#define	GPMI_CTRL1_DMA2ECC_MODE				(1 << 11)
+#define	GPMI_CTRL1_DEV_IRQ				(1 << 10)
+#define	GPMI_CTRL1_TIMEOUT_IRQ				(1 << 9)
+#define	GPMI_CTRL1_BURST_EN				(1 << 8)
+#define	GPMI_CTRL1_ABORT_WAIT_REQUEST			(1 << 7)
+#define	GPMI_CTRL1_ABORT_WAIT_FOR_READY_CHANNEL_MASK	(0x7 << 4)
+#define	GPMI_CTRL1_ABORT_WAIT_FOR_READY_CHANNEL_OFFSET	4
+#define	GPMI_CTRL1_DEV_RESET				(1 << 3)
+#define	GPMI_CTRL1_ATA_IRQRDY_POLARITY			(1 << 2)
+#define	GPMI_CTRL1_CAMERA_MODE				(1 << 1)
+#define	GPMI_CTRL1_GPMI_MODE				(1 << 0)
+
+#define	GPMI_TIMING0_ADDRESS_SETUP_MASK			(0xff << 16)
+#define	GPMI_TIMING0_ADDRESS_SETUP_OFFSET		16
+#define	GPMI_TIMING0_DATA_HOLD_MASK			(0xff << 8)
+#define	GPMI_TIMING0_DATA_HOLD_OFFSET			8
+#define	GPMI_TIMING0_DATA_SETUP_MASK			0xff
+#define	GPMI_TIMING0_DATA_SETUP_OFFSET			0
+
+#define	GPMI_TIMING1_DEVICE_BUSY_TIMEOUT_MASK		(0xffff << 16)
+#define	GPMI_TIMING1_DEVICE_BUSY_TIMEOUT_OFFSET		16
+
+#define	GPMI_TIMING2_UDMA_TRP_MASK			(0xff << 24)
+#define	GPMI_TIMING2_UDMA_TRP_OFFSET			24
+#define	GPMI_TIMING2_UDMA_ENV_MASK			(0xff << 16)
+#define	GPMI_TIMING2_UDMA_ENV_OFFSET			16
+#define	GPMI_TIMING2_UDMA_HOLD_MASK			(0xff << 8)
+#define	GPMI_TIMING2_UDMA_HOLD_OFFSET			8
+#define	GPMI_TIMING2_UDMA_SETUP_MASK			0xff
+#define	GPMI_TIMING2_UDMA_SETUP_OFFSET			0
+
+#define	GPMI_DATA_DATA_MASK				0xffffffff
+#define	GPMI_DATA_DATA_OFFSET				0
+
+#define	GPMI_STAT_READY_BUSY_MASK			(0xff << 24)
+#define	GPMI_STAT_READY_BUSY_OFFSET			24
+#define	GPMI_STAT_RDY_TIMEOUT_MASK			(0xff << 16)
+#define	GPMI_STAT_RDY_TIMEOUT_OFFSET			16
+#define	GPMI_STAT_DEV7_ERROR				(1 << 15)
+#define	GPMI_STAT_DEV6_ERROR				(1 << 14)
+#define	GPMI_STAT_DEV5_ERROR				(1 << 13)
+#define	GPMI_STAT_DEV4_ERROR				(1 << 12)
+#define	GPMI_STAT_DEV3_ERROR				(1 << 11)
+#define	GPMI_STAT_DEV2_ERROR				(1 << 10)
+#define	GPMI_STAT_DEV1_ERROR				(1 << 9)
+#define	GPMI_STAT_DEV0_ERROR				(1 << 8)
+#define	GPMI_STAT_ATA_IRQ				(1 << 4)
+#define	GPMI_STAT_INVALID_BUFFER_MASK			(1 << 3)
+#define	GPMI_STAT_FIFO_EMPTY				(1 << 2)
+#define	GPMI_STAT_FIFO_FULL				(1 << 1)
+#define	GPMI_STAT_PRESENT				(1 << 0)
+
+#define	GPMI_DEBUG_WAIT_FOR_READY_END_MASK		(0xff << 24)
+#define	GPMI_DEBUG_WAIT_FOR_READY_END_OFFSET		24
+#define	GPMI_DEBUG_DMA_SENSE_MASK			(0xff << 16)
+#define	GPMI_DEBUG_DMA_SENSE_OFFSET			16
+#define	GPMI_DEBUG_DMAREQ_MASK				(0xff << 8)
+#define	GPMI_DEBUG_DMAREQ_OFFSET			8
+#define	GPMI_DEBUG_CMD_END_MASK				0xff
+#define	GPMI_DEBUG_CMD_END_OFFSET			0
+
+#define	GPMI_VERSION_MAJOR_MASK				(0xff << 24)
+#define	GPMI_VERSION_MAJOR_OFFSET			24
+#define	GPMI_VERSION_MINOR_MASK				(0xff << 16)
+#define	GPMI_VERSION_MINOR_OFFSET			16
+#define	GPMI_VERSION_STEP_MASK				0xffff
+#define	GPMI_VERSION_STEP_OFFSET			0
+
+#define	GPMI_DEBUG2_UDMA_STATE_MASK			(0xf << 24)
+#define	GPMI_DEBUG2_UDMA_STATE_OFFSET			24
+#define	GPMI_DEBUG2_BUSY				(1 << 23)
+#define	GPMI_DEBUG2_PIN_STATE_MASK			(0x7 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_OFFSET			20
+#define	GPMI_DEBUG2_PIN_STATE_PSM_IDLE			(0x0 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_BYTCNT		(0x1 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_ADDR			(0x2 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_STALL			(0x3 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_STROBE		(0x4 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_ATARDY		(0x5 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_DHOLD			(0x6 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_DONE			(0x7 << 20)
+#define	GPMI_DEBUG2_MAIN_STATE_MASK			(0xf << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_OFFSET			16
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_IDLE			(0x0 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_BYTCNT		(0x1 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_WAITFE		(0x2 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_WAITFR		(0x3 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_DMAREQ		(0x4 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_DMAACK		(0x5 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_WAITFF		(0x6 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_LDFIFO		(0x7 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_LDDMAR		(0x8 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_RDCMP		(0x9 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_DONE			(0xa << 16)
+#define	GPMI_DEBUG2_SYND2GPMI_BE_MASK			(0xf << 12)
+#define	GPMI_DEBUG2_SYND2GPMI_BE_OFFSET			12
+#define	GPMI_DEBUG2_GPMI2SYND_VALID			(1 << 11)
+#define	GPMI_DEBUG2_GPMI2SYND_READY			(1 << 10)
+#define	GPMI_DEBUG2_SYND2GPMI_VALID			(1 << 9)
+#define	GPMI_DEBUG2_SYND2GPMI_READY			(1 << 8)
+#define	GPMI_DEBUG2_VIEW_DELAYED_RDN			(1 << 7)
+#define	GPMI_DEBUG2_UPDATE_WINDOW			(1 << 6)
+#define	GPMI_DEBUG2_RDN_TAP_MASK			0x3f
+#define	GPMI_DEBUG2_RDN_TAP_OFFSET			0
+
+#define	GPMI_DEBUG3_APB_WORD_CNTR_MASK			(0xffff << 16)
+#define	GPMI_DEBUG3_APB_WORD_CNTR_OFFSET		16
+#define	GPMI_DEBUG3_DEV_WORD_CNTR_MASK			0xffff
+#define	GPMI_DEBUG3_DEV_WORD_CNTR_OFFSET		0
+
+#endif	/* __MX28_REGS_GPMI_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-i2c.h b/arch/arm/include/asm/arch-mx28/regs-i2c.h
new file mode 100644
index 0000000..30e0ed7
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-i2c.h
@@ -0,0 +1,207 @@
+/*
+ * Freescale i.MX28 I2C Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_I2C_H__
+#define __MX28_REGS_I2C_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_i2c_regs {
+	mx28_reg(hw_i2c_ctrl0)
+	mx28_reg(hw_i2c_timing0)
+	mx28_reg(hw_i2c_timing1)
+	mx28_reg(hw_i2c_timing2)
+	mx28_reg(hw_i2c_ctrl1)
+	mx28_reg(hw_i2c_stat)
+	mx28_reg(hw_i2c_queuectrl)
+	mx28_reg(hw_i2c_queuestat)
+	mx28_reg(hw_i2c_queuecmd)
+	mx28_reg(hw_i2c_queuedata)
+	mx28_reg(hw_i2c_data)
+	mx28_reg(hw_i2c_debug0)
+	mx28_reg(hw_i2c_debug1)
+	mx28_reg(hw_i2c_version)
+};
+#endif
+
+#define	I2C_CTRL_SFTRST				(1 << 31)
+#define	I2C_CTRL_CLKGATE			(1 << 30)
+#define	I2C_CTRL_RUN				(1 << 29)
+#define	I2C_CTRL_PREACK				(1 << 27)
+#define	I2C_CTRL_ACKNOWLEDGE			(1 << 26)
+#define	I2C_CTRL_SEND_NAK_ON_LAST		(1 << 25)
+#define	I2C_CTRL_MULTI_MASTER			(1 << 23)
+#define	I2C_CTRL_CLOCK_HELD			(1 << 22)
+#define	I2C_CTRL_RETAIN_CLOCK			(1 << 21)
+#define	I2C_CTRL_POST_SEND_STOP			(1 << 20)
+#define	I2C_CTRL_PRE_SEND_START			(1 << 19)
+#define	I2C_CTRL_SLAVE_ADDRESS_ENABLE		(1 << 18)
+#define	I2C_CTRL_MASTER_MODE			(1 << 17)
+#define	I2C_CTRL_DIRECTION			(1 << 16)
+#define	I2C_CTRL_XFER_COUNT_MASK		0xffff
+#define	I2C_CTRL_XFER_COUNT_OFFSET		0
+
+#define	I2C_TIMING0_HIGH_COUNT_MASK		(0x3ff << 16)
+#define	I2C_TIMING0_HIGH_COUNT_OFFSET		16
+#define	I2C_TIMING0_RCV_COUNT_MASK		0x3ff
+#define	I2C_TIMING0_RCV_COUNT_OFFSET		0
+
+#define	I2C_TIMING1_LOW_COUNT_MASK		(0x3ff << 16)
+#define	I2C_TIMING1_LOW_COUNT_OFFSET		16
+#define	I2C_TIMING1_XMIT_COUNT_MASK		0x3ff
+#define	I2C_TIMING1_XMIT_COUNT_OFFSET		0
+
+#define	I2C_TIMING2_BUS_FREE_MASK		(0x3ff << 16)
+#define	I2C_TIMING2_BUS_FREE_OFFSET		16
+#define	I2C_TIMING2_LEADIN_COUNT_MASK		0x3ff
+#define	I2C_TIMING2_LEADIN_COUNT_OFFSET		0
+
+#define	I2C_CTRL1_RD_QUEUE_IRQ			(1 << 30)
+#define	I2C_CTRL1_WR_QUEUE_IRQ			(1 << 29)
+#define	I2C_CTRL1_CLR_GOT_A_NAK			(1 << 28)
+#define	I2C_CTRL1_ACK_MODE			(1 << 27)
+#define	I2C_CTRL1_FORCE_DATA_IDLE		(1 << 26)
+#define	I2C_CTRL1_FORCE_CLK_IDLE		(1 << 25)
+#define	I2C_CTRL1_BCAST_SLAVE_EN		(1 << 24)
+#define	I2C_CTRL1_SLAVE_ADDRESS_BYTE_MASK	(0xff << 16)
+#define	I2C_CTRL1_SLAVE_ADDRESS_BYTE_OFFSET	16
+#define	I2C_CTRL1_BUS_FREE_IRQ_EN		(1 << 15)
+#define	I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ_EN	(1 << 14)
+#define	I2C_CTRL1_NO_SLAVE_ACK_IRQ_EN		(1 << 13)
+#define	I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ_EN	(1 << 12)
+#define	I2C_CTRL1_EARLY_TERM_IRQ_EN		(1 << 11)
+#define	I2C_CTRL1_MASTER_LOSS_IRQ_EN		(1 << 10)
+#define	I2C_CTRL1_SLAVE_STOP_IRQ_EN		(1 << 9)
+#define	I2C_CTRL1_SLAVE_IRQ_EN			(1 << 8)
+#define	I2C_CTRL1_BUS_FREE_IRQ			(1 << 7)
+#define	I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ		(1 << 6)
+#define	I2C_CTRL1_NO_SLAVE_ACK_IRQ		(1 << 5)
+#define	I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ	(1 << 4)
+#define	I2C_CTRL1_EARLY_TERM_IRQ		(1 << 3)
+#define	I2C_CTRL1_MASTER_LOSS_IRQ		(1 << 2)
+#define	I2C_CTRL1_SLAVE_STOP_IRQ		(1 << 1)
+#define	I2C_CTRL1_SLAVE_IRQ			(1 << 0)
+
+#define	I2C_STAT_MASTER_PRESENT			(1 << 31)
+#define	I2C_STAT_SLAVE_PRESENT			(1 << 30)
+#define	I2C_STAT_ANY_ENABLED_IRQ		(1 << 29)
+#define	I2C_STAT_GOT_A_NAK			(1 << 28)
+#define	I2C_STAT_RCVD_SLAVE_ADDR_MASK		(0xff << 16)
+#define	I2C_STAT_RCVD_SLAVE_ADDR_OFFSET		16
+#define	I2C_STAT_SLAVE_ADDR_EQ_ZERO		(1 << 15)
+#define	I2C_STAT_SLAVE_FOUND			(1 << 14)
+#define	I2C_STAT_SLAVE_SEARCHING		(1 << 13)
+#define	I2C_STAT_DATA_ENGING_DMA_WAIT		(1 << 12)
+#define	I2C_STAT_BUS_BUSY			(1 << 11)
+#define	I2C_STAT_CLK_GEN_BUSY			(1 << 10)
+#define	I2C_STAT_DATA_ENGINE_BUSY		(1 << 9)
+#define	I2C_STAT_SLAVE_BUSY			(1 << 8)
+#define	I2C_STAT_BUS_FREE_IRQ_SUMMARY		(1 << 7)
+#define	I2C_STAT_DATA_ENGINE_CMPLT_IRQ_SUMMARY	(1 << 6)
+#define	I2C_STAT_NO_SLAVE_ACK_IRQ_SUMMARY	(1 << 5)
+#define	I2C_STAT_OVERSIZE_XFER_TERM_IRQ_SUMMARY	(1 << 4)
+#define	I2C_STAT_EARLY_TERM_IRQ_SUMMARY		(1 << 3)
+#define	I2C_STAT_MASTER_LOSS_IRQ_SUMMARY	(1 << 2)
+#define	I2C_STAT_SLAVE_STOP_IRQ_SUMMARY		(1 << 1)
+#define	I2C_STAT_SLAVE_IRQ_SUMMARY		(1 << 0)
+
+#define	I2C_QUEUECTRL_RD_THRESH_MASK		(0x1f << 16)
+#define	I2C_QUEUECTRL_RD_THRESH_OFFSET		16
+#define	I2C_QUEUECTRL_WR_THRESH_MASK		(0x1f << 8)
+#define	I2C_QUEUECTRL_WR_THRESH_OFFSET		8
+#define	I2C_QUEUECTRL_QUEUE_RUN			(1 << 5)
+#define	I2C_QUEUECTRL_RD_CLEAR			(1 << 4)
+#define	I2C_QUEUECTRL_WR_CLEAR			(1 << 3)
+#define	I2C_QUEUECTRL_PIO_QUEUE_MODE		(1 << 2)
+#define	I2C_QUEUECTRL_RD_QUEUE_IRQ_EN		(1 << 1)
+#define	I2C_QUEUECTRL_WR_QUEUE_IRQ_EN		(1 << 0)
+
+#define	I2C_QUEUESTAT_RD_QUEUE_FULL		(1 << 14)
+#define	I2C_QUEUESTAT_RD_QUEUE_EMPTY		(1 << 13)
+#define	I2C_QUEUESTAT_RD_QUEUE_CNT_MASK		(0x1f << 8)
+#define	I2C_QUEUESTAT_RD_QUEUE_CNT_OFFSET	8
+#define	I2C_QUEUESTAT_WR_QUEUE_FULL		(1 << 6)
+#define	I2C_QUEUESTAT_WR_QUEUE_EMPTY		(1 << 5)
+#define	I2C_QUEUESTAT_WR_QUEUE_CNT_MASK		0x1f
+#define	I2C_QUEUESTAT_WR_QUEUE_CNT_OFFSET	0
+
+#define	I2C_QUEUECMD_PREACK			(1 << 27)
+#define	I2C_QUEUECMD_ACKNOWLEDGE		(1 << 26)
+#define	I2C_QUEUECMD_SEND_NAK_ON_LAST		(1 << 25)
+#define	I2C_QUEUECMD_MULTI_MASTER		(1 << 23)
+#define	I2C_QUEUECMD_CLOCK_HELD			(1 << 22)
+#define	I2C_QUEUECMD_RETAIN_CLOCK		(1 << 21)
+#define	I2C_QUEUECMD_POST_SEND_STOP		(1 << 20)
+#define	I2C_QUEUECMD_PRE_SEND_START		(1 << 19)
+#define	I2C_QUEUECMD_SLAVE_ADDRESS_ENABLE	(1 << 18)
+#define	I2C_QUEUECMD_MASTER_MODE		(1 << 17)
+#define	I2C_QUEUECMD_DIRECTION			(1 << 16)
+#define	I2C_QUEUECMD_XFER_COUNT_MASK		0xffff
+#define	I2C_QUEUECMD_XFER_COUNT_OFFSET		0
+
+#define	I2C_QUEUEDATA_DATA_MASK			0xffffffff
+#define	I2C_QUEUEDATA_DATA_OFFSET		0
+
+#define	I2C_DATA_DATA_MASK			0xffffffff
+#define	I2C_DATA_DATA_OFFSET			0
+
+#define	I2C_DEBUG0_DMAREQ			(1 << 31)
+#define	I2C_DEBUG0_DMAENDCMD			(1 << 30)
+#define	I2C_DEBUG0_DMAKICK			(1 << 29)
+#define	I2C_DEBUG0_DMATERMINATE			(1 << 28)
+#define	I2C_DEBUG0_STATE_VALUE_MASK		(0x3 << 26)
+#define	I2C_DEBUG0_STATE_VALUE_OFFSET		26
+#define	I2C_DEBUG0_DMA_STATE_MASK		(0x3ff << 16)
+#define	I2C_DEBUG0_DMA_STATE_OFFSET		16
+#define	I2C_DEBUG0_START_TOGGLE			(1 << 15)
+#define	I2C_DEBUG0_STOP_TOGGLE			(1 << 14)
+#define	I2C_DEBUG0_GRAB_TOGGLE			(1 << 13)
+#define	I2C_DEBUG0_CHANGE_TOGGLE		(1 << 12)
+#define	I2C_DEBUG0_STATE_LATCH			(1 << 11)
+#define	I2C_DEBUG0_SLAVE_HOLD_CLK		(1 << 10)
+#define	I2C_DEBUG0_STATE_STATE_MASK		0x3ff
+#define	I2C_DEBUG0_STATE_STATE_OFFSET		0
+
+#define	I2C_DEBUG1_I2C_CLK_IN			(1 << 31)
+#define	I2C_DEBUG1_I2C_DATA_IN			(1 << 30)
+#define	I2C_DEBUG1_DMA_BYTE_ENABLES_MASK	(0xf << 24)
+#define	I2C_DEBUG1_DMA_BYTE_ENABLES_OFFSET	24
+#define	I2C_DEBUG1_CLK_GEN_STATE_MASK		(0xff << 16)
+#define	I2C_DEBUG1_CLK_GEN_STATE_OFFSET		16
+#define	I2C_DEBUG1_LST_MODE_MASK		(0x3 << 9)
+#define	I2C_DEBUG1_LST_MODE_OFFSET		9
+#define	I2C_DEBUG1_LOCAL_SLAVE_TEST		(1 << 8)
+#define	I2C_DEBUG1_FORCE_CLK_ON			(1 << 4)
+#define	I2C_DEBUG1_FORCE_ABR_LOSS		(1 << 3)
+#define	I2C_DEBUG1_FORCE_RCV_ACK		(1 << 2)
+#define	I2C_DEBUG1_FORCE_I2C_DATA_OE		(1 << 1)
+#define	I2C_DEBUG1_FORCE_I2C_CLK_OE		(1 << 0)
+
+#define	I2C_VERSION_MAJOR_MASK			(0xff << 24)
+#define	I2C_VERSION_MAJOR_OFFSET		24
+#define	I2C_VERSION_MINOR_MASK			(0xff << 16)
+#define	I2C_VERSION_MINOR_OFFSET		16
+#define	I2C_VERSION_STEP_MASK			0xffff
+#define	I2C_VERSION_STEP_OFFSET			0
+
+#endif	/* __MX28_REGS_I2C_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-ocotp.h b/arch/arm/include/asm/arch-mx28/regs-ocotp.h
new file mode 100644
index 0000000..ea2fd7b
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-ocotp.h
@@ -0,0 +1,173 @@
+/*
+ * Freescale i.MX28 OCOTP Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_OCOTP_H__
+#define __MX28_REGS_OCOTP_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_ocotp_regs {
+	mx28_reg(hw_ocotp_ctrl)		/* 0x0 */
+	mx28_reg(hw_ocotp_data)		/* 0x10 */
+	mx28_reg(hw_ocotp_cust0)	/* 0x20 */
+	mx28_reg(hw_ocotp_cust1)	/* 0x30 */
+	mx28_reg(hw_ocotp_cust2)	/* 0x40 */
+	mx28_reg(hw_ocotp_cust3)	/* 0x50 */
+	mx28_reg(hw_ocotp_crypto0)	/* 0x60 */
+	mx28_reg(hw_ocotp_crypto1)	/* 0x70 */
+	mx28_reg(hw_ocotp_crypto2)	/* 0x80 */
+	mx28_reg(hw_ocotp_crypto3)	/* 0x90 */
+	mx28_reg(hw_ocotp_hwcap0)	/* 0xa0 */
+	mx28_reg(hw_ocotp_hwcap1)	/* 0xb0 */
+	mx28_reg(hw_ocotp_hwcap2)	/* 0xc0 */
+	mx28_reg(hw_ocotp_hwcap3)	/* 0xd0 */
+	mx28_reg(hw_ocotp_hwcap4)	/* 0xe0 */
+	mx28_reg(hw_ocotp_hwcap5)	/* 0xf0 */
+	mx28_reg(hw_ocotp_swcap)	/* 0x100 */
+	mx28_reg(hw_ocotp_custcap)	/* 0x110 */
+	mx28_reg(hw_ocotp_lock)		/* 0x120 */
+	mx28_reg(hw_ocotp_ops0)		/* 0x130 */
+	mx28_reg(hw_ocotp_ops1)		/* 0x140 */
+	mx28_reg(hw_ocotp_ops2)		/* 0x150 */
+	mx28_reg(hw_ocotp_ops3)		/* 0x160 */
+	mx28_reg(hw_ocotp_un0)		/* 0x170 */
+	mx28_reg(hw_ocotp_un1)		/* 0x180 */
+	mx28_reg(hw_ocotp_un2)		/* 0x190 */
+	mx28_reg(hw_ocotp_rom0)		/* 0x1a0 */
+	mx28_reg(hw_ocotp_rom1)		/* 0x1b0 */
+	mx28_reg(hw_ocotp_rom2)		/* 0x1c0 */
+	mx28_reg(hw_ocotp_rom3)		/* 0x1d0 */
+	mx28_reg(hw_ocotp_rom4)		/* 0x1e0 */
+	mx28_reg(hw_ocotp_rom5)		/* 0x1f0 */
+	mx28_reg(hw_ocotp_rom6)		/* 0x200 */
+	mx28_reg(hw_ocotp_rom7)		/* 0x210 */
+	mx28_reg(hw_ocotp_srk0)		/* 0x220 */
+	mx28_reg(hw_ocotp_srk1)		/* 0x230 */
+	mx28_reg(hw_ocotp_srk2)		/* 0x240 */
+	mx28_reg(hw_ocotp_srk3)		/* 0x250 */
+	mx28_reg(hw_ocotp_srk4)		/* 0x260 */
+	mx28_reg(hw_ocotp_srk5)		/* 0x270 */
+	mx28_reg(hw_ocotp_srk6)		/* 0x280 */
+	mx28_reg(hw_ocotp_srk7)		/* 0x290 */
+	mx28_reg(hw_ocotp_version)	/* 0x2a0 */
+};
+#endif
+
+#define	OCOTP_CTRL_WR_UNLOCK_MASK		(0xffff << 16)
+#define	OCOTP_CTRL_WR_UNLOCK_OFFSET		16
+#define	OCOTP_CTRL_WR_UNLOCK_KEY		(0x3e77 << 16)
+#define	OCOTP_CTRL_RELOAD_SHADOWS		(1 << 13)
+#define	OCOTP_CTRL_RD_BANK_OPEN			(1 << 12)
+#define	OCOTP_CTRL_ERROR			(1 << 9)
+#define	OCOTP_CTRL_BUSY				(1 << 8)
+#define	OCOTP_CTRL_ADDR_MASK			0x3f
+#define	OCOTP_CTRL_ADDR_OFFSET			0
+
+#define	OCOTP_DATA_DATA_MASK			0xffffffff
+#define	OCOTP_DATA_DATA_OFFSET			0
+
+#define	OCOTP_CUST_BITS_MASK			0xffffffff
+#define	OCOTP_CUST_BITS_OFFSET			0
+
+#define	OCOTP_CRYPTO_BITS_MASK			0xffffffff
+#define	OCOTP_CRYPTO_BITS_OFFSET		0
+
+#define	OCOTP_HWCAP_BITS_MASK			0xffffffff
+#define	OCOTP_HWCAP_BITS_OFFSET			0
+
+#define	OCOTP_SWCAP_BITS_MASK			0xffffffff
+#define	OCOTP_SWCAP_BITS_OFFSET			0
+
+#define	OCOTP_CUSTCAP_RTC_XTAL_32768_PRESENT	(1 << 2)
+#define	OCOTP_CUSTCAP_RTC_XTAL_32000_PRESENT	(1 << 1)
+
+#define	OCOTP_LOCK_ROM7				(1 << 31)
+#define	OCOTP_LOCK_ROM6				(1 << 30)
+#define	OCOTP_LOCK_ROM5				(1 << 29)
+#define	OCOTP_LOCK_ROM4				(1 << 28)
+#define	OCOTP_LOCK_ROM3				(1 << 27)
+#define	OCOTP_LOCK_ROM2				(1 << 26)
+#define	OCOTP_LOCK_ROM1				(1 << 25)
+#define	OCOTP_LOCK_ROM0				(1 << 24)
+#define	OCOTP_LOCK_HWSW_SHADOW_ALT		(1 << 23)
+#define	OCOTP_LOCK_CRYPTODCP_ALT		(1 << 22)
+#define	OCOTP_LOCK_CRYPTOKEY_ALT		(1 << 21)
+#define	OCOTP_LOCK_PIN				(1 << 20)
+#define	OCOTP_LOCK_OPS				(1 << 19)
+#define	OCOTP_LOCK_UN2				(1 << 18)
+#define	OCOTP_LOCK_UN1				(1 << 17)
+#define	OCOTP_LOCK_UN0				(1 << 16)
+#define	OCOTP_LOCK_SRK				(1 << 15)
+#define	OCOTP_LOCK_UNALLOCATED_MASK		(0x7 << 12)
+#define	OCOTP_LOCK_UNALLOCATED_OFFSET		12
+#define	OCOTP_LOCK_SRK_SHADOW			(1 << 11)
+#define	OCOTP_LOCK_ROM_SHADOW			(1 << 10)
+#define	OCOTP_LOCK_CUSTCAP			(1 << 9)
+#define	OCOTP_LOCK_HWSW				(1 << 8)
+#define	OCOTP_LOCK_CUSTCAP_SHADOW		(1 << 7)
+#define	OCOTP_LOCK_HWSW_SHADOW			(1 << 6)
+#define	OCOTP_LOCK_CRYPTODCP			(1 << 5)
+#define	OCOTP_LOCK_CRYPTOKEY			(1 << 4)
+#define	OCOTP_LOCK_CUST3			(1 << 3)
+#define	OCOTP_LOCK_CUST2			(1 << 2)
+#define	OCOTP_LOCK_CUST1			(1 << 1)
+#define	OCOTP_LOCK_CUST0			(1 << 0)
+
+#define	OCOTP_OPS_BITS_MASK			0xffffffff
+#define	OCOTP_OPS_BITS_OFFSET			0
+
+#define	OCOTP_UN_BITS_MASK			0xffffffff
+#define	OCOTP_UN_BITS_OFFSET			0
+
+#define	OCOTP_ROM_BOOT_MODE_MASK		(0xff << 24)
+#define	OCOTP_ROM_BOOT_MODE_OFFSET		24
+#define	OCOTP_ROM_SD_MMC_MODE_MASK		(0x3 << 22)
+#define	OCOTP_ROM_SD_MMC_MODE_OFFSET		22
+#define	OCOTP_ROM_SD_POWER_GATE_GPIO_MASK	(0x3 << 20)
+#define	OCOTP_ROM_SD_POWER_GATE_GPIO_OFFSET	20
+#define	OCOTP_ROM_SD_POWER_UP_DELAY_MASK	(0x3f << 14)
+#define	OCOTP_ROM_SD_POWER_UP_DELAY_OFFSET	14
+#define	OCOTP_ROM_SD_BUS_WIDTH_MASK		(0x3 << 12)
+#define	OCOTP_ROM_SD_BUS_WIDTH_OFFSET		12
+#define	OCOTP_ROM_SSP_SCK_INDEX_MASK		(0xf << 8)
+#define	OCOTP_ROM_SSP_SCK_INDEX_OFFSET		8
+#define	OCOTP_ROM_EMMC_USE_DDR			(1 << 7)
+#define	OCOTP_ROM_DISABLE_SPI_NOR_FAST_READ	(1 << 6)
+#define	OCOTP_ROM_ENABLE_USB_BOOT_SERIAL_NUM	(1 << 5)
+#define	OCOTP_ROM_ENABLE_UNENCRYPTED_BOOT	(1 << 4)
+#define	OCOTP_ROM_SD_MBR_BOOT			(1 << 3)
+
+#define	OCOTP_SRK_BITS_MASK			0xffffffff
+#define	OCOTP_SRK_BITS_OFFSET			0
+
+#define	OCOTP_VERSION_MAJOR_MASK		(0xff << 24)
+#define	OCOTP_VERSION_MAJOR_OFFSET		24
+#define	OCOTP_VERSION_MINOR_MASK		(0xff << 16)
+#define	OCOTP_VERSION_MINOR_OFFSET		16
+#define	OCOTP_VERSION_STEP_MASK			0xffff
+#define	OCOTP_VERSION_STEP_OFFSET		0
+
+#endif /* __MX28_REGS_OCOTP_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-pinctrl.h b/arch/arm/include/asm/arch-mx28/regs-pinctrl.h
new file mode 100644
index 0000000..73739ca
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-pinctrl.h
@@ -0,0 +1,1284 @@
+/*
+ * Freescale i.MX28 PINCTRL Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_PINCTRL_H__
+#define __MX28_REGS_PINCTRL_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_pinctrl_regs {
+	mx28_reg(hw_pinctrl_ctrl)		/* 0x0 */
+
+	uint32_t	reserved1[60];
+
+	mx28_reg(hw_pinctrl_muxsel0)		/* 0x100 */
+	mx28_reg(hw_pinctrl_muxsel1)		/* 0x110 */
+	mx28_reg(hw_pinctrl_muxsel2)		/* 0x120 */
+	mx28_reg(hw_pinctrl_muxsel3)		/* 0x130 */
+	mx28_reg(hw_pinctrl_muxsel4)		/* 0x140 */
+	mx28_reg(hw_pinctrl_muxsel5)		/* 0x150 */
+	mx28_reg(hw_pinctrl_muxsel6)		/* 0x160 */
+	mx28_reg(hw_pinctrl_muxsel7)		/* 0x170 */
+	mx28_reg(hw_pinctrl_muxsel8)		/* 0x180 */
+	mx28_reg(hw_pinctrl_muxsel9)		/* 0x190 */
+	mx28_reg(hw_pinctrl_muxsel10)		/* 0x1a0 */
+	mx28_reg(hw_pinctrl_muxsel11)		/* 0x1b0 */
+	mx28_reg(hw_pinctrl_muxsel12)		/* 0x1c0 */
+	mx28_reg(hw_pinctrl_muxsel13)		/* 0x1d0 */
+
+	uint32_t	reserved2[72];
+
+	mx28_reg(hw_pinctrl_drive0)		/* 0x300 */
+	mx28_reg(hw_pinctrl_drive1)		/* 0x310 */
+	mx28_reg(hw_pinctrl_drive2)		/* 0x320 */
+	mx28_reg(hw_pinctrl_drive3)		/* 0x330 */
+	mx28_reg(hw_pinctrl_drive4)		/* 0x340 */
+	mx28_reg(hw_pinctrl_drive5)		/* 0x350 */
+	mx28_reg(hw_pinctrl_drive6)		/* 0x360 */
+	mx28_reg(hw_pinctrl_drive7)		/* 0x370 */
+	mx28_reg(hw_pinctrl_drive8)		/* 0x380 */
+	mx28_reg(hw_pinctrl_drive9)		/* 0x390 */
+	mx28_reg(hw_pinctrl_drive10)		/* 0x3a0 */
+	mx28_reg(hw_pinctrl_drive11)		/* 0x3b0 */
+	mx28_reg(hw_pinctrl_drive12)		/* 0x3c0 */
+	mx28_reg(hw_pinctrl_drive13)		/* 0x3d0 */
+	mx28_reg(hw_pinctrl_drive14)		/* 0x3e0 */
+	mx28_reg(hw_pinctrl_drive15)		/* 0x3f0 */
+	mx28_reg(hw_pinctrl_drive16)		/* 0x400 */
+	mx28_reg(hw_pinctrl_drive17)		/* 0x410 */
+	mx28_reg(hw_pinctrl_drive18)		/* 0x420 */
+	mx28_reg(hw_pinctrl_drive19)		/* 0x430 */
+
+	uint32_t	reserved3[112];
+
+	mx28_reg(hw_pinctrl_pull0)		/* 0x600 */
+	mx28_reg(hw_pinctrl_pull1)		/* 0x610 */
+	mx28_reg(hw_pinctrl_pull2)		/* 0x620 */
+	mx28_reg(hw_pinctrl_pull3)		/* 0x630 */
+	mx28_reg(hw_pinctrl_pull4)		/* 0x640 */
+	mx28_reg(hw_pinctrl_pull5)		/* 0x650 */
+	mx28_reg(hw_pinctrl_pull6)		/* 0x660 */
+
+	uint32_t	reserved4[36];
+
+	mx28_reg(hw_pinctrl_dout0)		/* 0x700 */
+	mx28_reg(hw_pinctrl_dout1)		/* 0x710 */
+	mx28_reg(hw_pinctrl_dout2)		/* 0x720 */
+	mx28_reg(hw_pinctrl_dout3)		/* 0x730 */
+	mx28_reg(hw_pinctrl_dout4)		/* 0x740 */
+
+	uint32_t	reserved5[108];
+
+	mx28_reg(hw_pinctrl_din0)		/* 0x900 */
+	mx28_reg(hw_pinctrl_din1)		/* 0x910 */
+	mx28_reg(hw_pinctrl_din2)		/* 0x920 */
+	mx28_reg(hw_pinctrl_din3)		/* 0x930 */
+	mx28_reg(hw_pinctrl_din4)		/* 0x940 */
+
+	uint32_t	reserved6[108];
+
+	mx28_reg(hw_pinctrl_doe0)		/* 0xb00 */
+	mx28_reg(hw_pinctrl_doe1)		/* 0xb10 */
+	mx28_reg(hw_pinctrl_doe2)		/* 0xb20 */
+	mx28_reg(hw_pinctrl_doe3)		/* 0xb30 */
+	mx28_reg(hw_pinctrl_doe4)		/* 0xb40 */
+
+	uint32_t	reserved7[300];
+
+	mx28_reg(hw_pinctrl_pin2irq0)		/* 0x1000 */
+	mx28_reg(hw_pinctrl_pin2irq1)		/* 0x1010 */
+	mx28_reg(hw_pinctrl_pin2irq2)		/* 0x1020 */
+	mx28_reg(hw_pinctrl_pin2irq3)		/* 0x1030 */
+	mx28_reg(hw_pinctrl_pin2irq4)		/* 0x1040 */
+
+	uint32_t	reserved8[44];
+
+	mx28_reg(hw_pinctrl_irqen0)		/* 0x1100 */
+	mx28_reg(hw_pinctrl_irqen1)		/* 0x1110 */
+	mx28_reg(hw_pinctrl_irqen2)		/* 0x1120 */
+	mx28_reg(hw_pinctrl_irqen3)		/* 0x1130 */
+	mx28_reg(hw_pinctrl_irqen4)		/* 0x1140 */
+
+	uint32_t	reserved9[44];
+
+	mx28_reg(hw_pinctrl_irqlevel0)		/* 0x1200 */
+	mx28_reg(hw_pinctrl_irqlevel1)		/* 0x1210 */
+	mx28_reg(hw_pinctrl_irqlevel2)		/* 0x1220 */
+	mx28_reg(hw_pinctrl_irqlevel3)		/* 0x1230 */
+	mx28_reg(hw_pinctrl_irqlevel4)		/* 0x1240 */
+
+	uint32_t	reserved10[44];
+
+	mx28_reg(hw_pinctrl_irqpol0)		/* 0x1300 */
+	mx28_reg(hw_pinctrl_irqpol1)		/* 0x1310 */
+	mx28_reg(hw_pinctrl_irqpol2)		/* 0x1320 */
+	mx28_reg(hw_pinctrl_irqpol3)		/* 0x1330 */
+	mx28_reg(hw_pinctrl_irqpol4)		/* 0x1340 */
+
+	uint32_t	reserved11[44];
+
+	mx28_reg(hw_pinctrl_irqstat0)		/* 0x1400 */
+	mx28_reg(hw_pinctrl_irqstat1)		/* 0x1410 */
+	mx28_reg(hw_pinctrl_irqstat2)		/* 0x1420 */
+	mx28_reg(hw_pinctrl_irqstat3)		/* 0x1430 */
+	mx28_reg(hw_pinctrl_irqstat4)		/* 0x1440 */
+
+	uint32_t	reserved12[380];
+
+	mx28_reg(hw_pinctrl_emi_odt_ctrl)	/* 0x1a40 */
+
+	uint32_t	reserved13[76];
+
+	mx28_reg(hw_pinctrl_emi_ds_ctrl)	/* 0x1b80 */
+};
+#endif
+
+#define	PINCTRL_CTRL_SFTRST				(1 << 31)
+#define	PINCTRL_CTRL_CLKGATE				(1 << 30)
+#define	PINCTRL_CTRL_PRESENT4				(1 << 24)
+#define	PINCTRL_CTRL_PRESENT3				(1 << 23)
+#define	PINCTRL_CTRL_PRESENT2				(1 << 22)
+#define	PINCTRL_CTRL_PRESENT1				(1 << 21)
+#define	PINCTRL_CTRL_PRESENT0				(1 << 20)
+#define	PINCTRL_CTRL_IRQOUT4				(1 << 4)
+#define	PINCTRL_CTRL_IRQOUT3				(1 << 3)
+#define	PINCTRL_CTRL_IRQOUT2				(1 << 2)
+#define	PINCTRL_CTRL_IRQOUT1				(1 << 1)
+#define	PINCTRL_CTRL_IRQOUT0				(1 << 0)
+
+#define	PINCTRL_MUXSEL0_BANK0_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL0_BANK0_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL0_BANK0_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL0_BANK0_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL0_BANK0_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL0_BANK0_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL0_BANK0_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL0_BANK0_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL0_BANK0_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL0_BANK0_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL0_BANK0_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL0_BANK0_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL0_BANK0_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL0_BANK0_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL0_BANK0_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL0_BANK0_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL1_BANK0_PIN28_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL1_BANK0_PIN28_OFFSET		24
+#define	PINCTRL_MUXSEL1_BANK0_PIN27_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL1_BANK0_PIN27_OFFSET		22
+#define	PINCTRL_MUXSEL1_BANK0_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL1_BANK0_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL1_BANK0_PIN25_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL1_BANK0_PIN25_OFFSET		18
+#define	PINCTRL_MUXSEL1_BANK0_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL1_BANK0_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL1_BANK0_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL1_BANK0_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL1_BANK0_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL1_BANK0_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL1_BANK0_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL1_BANK0_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL1_BANK0_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL1_BANK0_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL1_BANK0_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL1_BANK0_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL1_BANK0_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL1_BANK0_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL1_BANK0_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL1_BANK0_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL1_BANK0_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL1_BANK0_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL2_BANK1_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL2_BANK1_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL2_BANK1_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL2_BANK1_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL2_BANK1_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL2_BANK1_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL2_BANK1_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL2_BANK1_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL2_BANK1_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL2_BANK1_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL2_BANK1_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL2_BANK1_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL2_BANK1_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL2_BANK1_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL2_BANK1_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL2_BANK1_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL2_BANK1_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL2_BANK1_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL2_BANK1_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL2_BANK1_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL2_BANK1_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL2_BANK1_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL2_BANK1_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL2_BANK1_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL2_BANK1_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL2_BANK1_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL2_BANK1_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL2_BANK1_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL2_BANK1_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL2_BANK1_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL2_BANK1_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL2_BANK1_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL3_BANK1_PIN31_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL3_BANK1_PIN31_OFFSET		30
+#define	PINCTRL_MUXSEL3_BANK1_PIN30_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL3_BANK1_PIN30_OFFSET		28
+#define	PINCTRL_MUXSEL3_BANK1_PIN29_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL3_BANK1_PIN29_OFFSET		26
+#define	PINCTRL_MUXSEL3_BANK1_PIN28_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL3_BANK1_PIN28_OFFSET		24
+#define	PINCTRL_MUXSEL3_BANK1_PIN27_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL3_BANK1_PIN27_OFFSET		22
+#define	PINCTRL_MUXSEL3_BANK1_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL3_BANK1_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL3_BANK1_PIN25_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL3_BANK1_PIN25_OFFSET		18
+#define	PINCTRL_MUXSEL3_BANK1_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL3_BANK1_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL3_BANK1_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL3_BANK1_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL3_BANK1_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL3_BANK1_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL3_BANK1_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL3_BANK1_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL3_BANK1_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL3_BANK1_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL3_BANK1_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL3_BANK1_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL3_BANK1_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL3_BANK1_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL3_BANK1_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL3_BANK1_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL3_BANK1_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL3_BANK1_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL4_BANK2_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL4_BANK2_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL4_BANK2_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL4_BANK2_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL4_BANK2_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL4_BANK2_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL4_BANK2_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL4_BANK2_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL4_BANK2_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL4_BANK2_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL4_BANK2_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL4_BANK2_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL4_BANK2_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL4_BANK2_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL4_BANK2_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL4_BANK2_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL4_BANK2_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL4_BANK2_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL4_BANK2_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL4_BANK2_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL4_BANK2_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL4_BANK2_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL4_BANK2_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL4_BANK2_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL4_BANK2_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL4_BANK2_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL4_BANK2_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL4_BANK2_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL4_BANK2_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL4_BANK2_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL5_BANK2_PIN27_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL5_BANK2_PIN27_OFFSET		22
+#define	PINCTRL_MUXSEL5_BANK2_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL5_BANK2_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL5_BANK2_PIN25_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL5_BANK2_PIN25_OFFSET		18
+#define	PINCTRL_MUXSEL5_BANK2_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL5_BANK2_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL5_BANK2_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL5_BANK2_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL5_BANK2_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL5_BANK2_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL5_BANK2_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL5_BANK2_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL5_BANK2_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL5_BANK2_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL5_BANK2_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL5_BANK2_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL5_BANK2_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL5_BANK2_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL6_BANK3_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL6_BANK3_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL6_BANK3_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL6_BANK3_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL6_BANK3_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL6_BANK3_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL6_BANK3_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL6_BANK3_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL6_BANK3_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL6_BANK3_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL6_BANK3_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL6_BANK3_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL6_BANK3_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL6_BANK3_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL6_BANK3_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL6_BANK3_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL6_BANK3_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL6_BANK3_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL6_BANK3_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL6_BANK3_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL6_BANK3_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL6_BANK3_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL6_BANK3_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL6_BANK3_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL6_BANK3_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL6_BANK3_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL6_BANK3_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL6_BANK3_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL6_BANK3_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL6_BANK3_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL6_BANK3_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL6_BANK3_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL7_BANK3_PIN30_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL7_BANK3_PIN30_OFFSET		28
+#define	PINCTRL_MUXSEL7_BANK3_PIN29_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL7_BANK3_PIN29_OFFSET		26
+#define	PINCTRL_MUXSEL7_BANK3_PIN28_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL7_BANK3_PIN28_OFFSET		24
+#define	PINCTRL_MUXSEL7_BANK3_PIN27_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL7_BANK3_PIN27_OFFSET		22
+#define	PINCTRL_MUXSEL7_BANK3_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL7_BANK3_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL7_BANK3_PIN25_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL7_BANK3_PIN25_OFFSET		18
+#define	PINCTRL_MUXSEL7_BANK3_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL7_BANK3_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL7_BANK3_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL7_BANK3_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL7_BANK3_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL7_BANK3_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL7_BANK3_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL7_BANK3_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL7_BANK3_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL7_BANK3_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL7_BANK3_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL7_BANK3_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL7_BANK3_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL7_BANK3_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL7_BANK3_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL7_BANK3_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL8_BANK4_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL8_BANK4_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL8_BANK4_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL8_BANK4_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL8_BANK4_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL8_BANK4_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL8_BANK4_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL8_BANK4_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL8_BANK4_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL8_BANK4_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL8_BANK4_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL8_BANK4_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL8_BANK4_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL8_BANK4_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL8_BANK4_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL8_BANK4_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL8_BANK4_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL8_BANK4_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL8_BANK4_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL8_BANK4_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL8_BANK4_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL8_BANK4_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL8_BANK4_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL8_BANK4_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL8_BANK4_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL8_BANK4_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL8_BANK4_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL8_BANK4_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL8_BANK4_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL8_BANK4_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL8_BANK4_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL8_BANK4_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL9_BANK4_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL9_BANK4_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL9_BANK4_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL9_BANK4_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL10_BANK5_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL10_BANK5_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL10_BANK5_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL10_BANK5_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL10_BANK5_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL10_BANK5_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL10_BANK5_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL10_BANK5_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL10_BANK5_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL10_BANK5_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL10_BANK5_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL10_BANK5_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL10_BANK5_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL10_BANK5_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL10_BANK5_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL10_BANK5_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL10_BANK5_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL10_BANK5_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL10_BANK5_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL10_BANK5_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL10_BANK5_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL10_BANK5_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL10_BANK5_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL10_BANK5_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL10_BANK5_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL10_BANK5_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL10_BANK5_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL10_BANK5_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL10_BANK5_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL10_BANK5_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL10_BANK5_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL10_BANK5_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL11_BANK5_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL11_BANK5_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL11_BANK5_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL11_BANK5_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL11_BANK5_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL11_BANK5_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL11_BANK5_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL11_BANK5_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL11_BANK5_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL11_BANK5_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL11_BANK5_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL11_BANK5_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL11_BANK5_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL11_BANK5_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL11_BANK5_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL11_BANK5_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL11_BANK5_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL11_BANK5_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL12_BANK6_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL12_BANK6_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL12_BANK6_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL12_BANK6_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL12_BANK6_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL12_BANK6_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL12_BANK6_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL12_BANK6_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL12_BANK6_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL12_BANK6_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL12_BANK6_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL12_BANK6_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL12_BANK6_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL12_BANK6_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL12_BANK6_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL12_BANK6_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL12_BANK6_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL12_BANK6_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL12_BANK6_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL12_BANK6_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL12_BANK6_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL12_BANK6_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL12_BANK6_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL12_BANK6_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL12_BANK6_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL12_BANK6_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL12_BANK6_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL12_BANK6_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL12_BANK6_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL12_BANK6_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL13_BANK6_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL13_BANK6_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL13_BANK6_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL13_BANK6_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL13_BANK6_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL13_BANK6_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL13_BANK6_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL13_BANK6_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL13_BANK6_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL13_BANK6_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL13_BANK6_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL13_BANK6_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL13_BANK6_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL13_BANK6_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL13_BANK6_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL13_BANK6_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL13_BANK6_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL13_BANK6_PIN16_OFFSET		0
+
+#define	PINCTRL_DRIVE0_BANK0_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE0_BANK0_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE0_BANK0_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE0_BANK0_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE0_BANK0_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE0_BANK0_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE0_BANK0_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE0_BANK0_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE0_BANK0_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE0_BANK0_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE0_BANK0_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE0_BANK0_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE0_BANK0_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE0_BANK0_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE0_BANK0_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE0_BANK0_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE0_BANK0_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE0_BANK0_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE0_BANK0_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE0_BANK0_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE0_BANK0_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE0_BANK0_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE0_BANK0_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE0_BANK0_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE2_BANK0_PIN23_V			(1 << 30)
+#define	PINCTRL_DRIVE2_BANK0_PIN23_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE2_BANK0_PIN23_MA_OFFSET		28
+#define	PINCTRL_DRIVE2_BANK0_PIN22_V			(1 << 26)
+#define	PINCTRL_DRIVE2_BANK0_PIN22_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE2_BANK0_PIN22_MA_OFFSET		24
+#define	PINCTRL_DRIVE2_BANK0_PIN21_V			(1 << 22)
+#define	PINCTRL_DRIVE2_BANK0_PIN21_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE2_BANK0_PIN21_MA_OFFSET		20
+#define	PINCTRL_DRIVE2_BANK0_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE2_BANK0_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE2_BANK0_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE2_BANK0_PIN19_V			(1 << 14)
+#define	PINCTRL_DRIVE2_BANK0_PIN19_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE2_BANK0_PIN19_MA_OFFSET		12
+#define	PINCTRL_DRIVE2_BANK0_PIN18_V			(1 << 10)
+#define	PINCTRL_DRIVE2_BANK0_PIN18_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE2_BANK0_PIN18_MA_OFFSET		8
+#define	PINCTRL_DRIVE2_BANK0_PIN17_V			(1 << 6)
+#define	PINCTRL_DRIVE2_BANK0_PIN17_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE2_BANK0_PIN17_MA_OFFSET		4
+#define	PINCTRL_DRIVE2_BANK0_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE2_BANK0_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE2_BANK0_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE3_BANK0_PIN28_V			(1 << 18)
+#define	PINCTRL_DRIVE3_BANK0_PIN28_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE3_BANK0_PIN28_MA_OFFSET		16
+#define	PINCTRL_DRIVE3_BANK0_PIN27_V			(1 << 14)
+#define	PINCTRL_DRIVE3_BANK0_PIN27_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE3_BANK0_PIN27_MA_OFFSET		12
+#define	PINCTRL_DRIVE3_BANK0_PIN26_V			(1 << 10)
+#define	PINCTRL_DRIVE3_BANK0_PIN26_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE3_BANK0_PIN26_MA_OFFSET		8
+#define	PINCTRL_DRIVE3_BANK0_PIN25_V			(1 << 6)
+#define	PINCTRL_DRIVE3_BANK0_PIN25_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE3_BANK0_PIN25_MA_OFFSET		4
+#define	PINCTRL_DRIVE3_BANK0_PIN24_V			(1 << 2)
+#define	PINCTRL_DRIVE3_BANK0_PIN24_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE3_BANK0_PIN24_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE4_BANK1_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE4_BANK1_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE4_BANK1_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE4_BANK1_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE4_BANK1_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE4_BANK1_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE4_BANK1_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE4_BANK1_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE4_BANK1_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE4_BANK1_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE4_BANK1_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE4_BANK1_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE4_BANK1_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE4_BANK1_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE4_BANK1_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE4_BANK1_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE4_BANK1_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE4_BANK1_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE4_BANK1_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE4_BANK1_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE4_BANK1_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE4_BANK1_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE4_BANK1_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE4_BANK1_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE5_BANK1_PIN15_V			(1 << 30)
+#define	PINCTRL_DRIVE5_BANK1_PIN15_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE5_BANK1_PIN15_MA_OFFSET		28
+#define	PINCTRL_DRIVE5_BANK1_PIN14_V			(1 << 26)
+#define	PINCTRL_DRIVE5_BANK1_PIN14_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE5_BANK1_PIN14_MA_OFFSET		24
+#define	PINCTRL_DRIVE5_BANK1_PIN13_V			(1 << 22)
+#define	PINCTRL_DRIVE5_BANK1_PIN13_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE5_BANK1_PIN13_MA_OFFSET		20
+#define	PINCTRL_DRIVE5_BANK1_PIN12_V			(1 << 18)
+#define	PINCTRL_DRIVE5_BANK1_PIN12_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE5_BANK1_PIN12_MA_OFFSET		16
+#define	PINCTRL_DRIVE5_BANK1_PIN11_V			(1 << 14)
+#define	PINCTRL_DRIVE5_BANK1_PIN11_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE5_BANK1_PIN11_MA_OFFSET		12
+#define	PINCTRL_DRIVE5_BANK1_PIN10_V			(1 << 10)
+#define	PINCTRL_DRIVE5_BANK1_PIN10_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE5_BANK1_PIN10_MA_OFFSET		8
+#define	PINCTRL_DRIVE5_BANK1_PIN09_V			(1 << 6)
+#define	PINCTRL_DRIVE5_BANK1_PIN09_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE5_BANK1_PIN09_MA_OFFSET		4
+#define	PINCTRL_DRIVE5_BANK1_PIN08_V			(1 << 2)
+#define	PINCTRL_DRIVE5_BANK1_PIN08_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE5_BANK1_PIN08_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE6_BANK1_PIN23_V			(1 << 30)
+#define	PINCTRL_DRIVE6_BANK1_PIN23_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE6_BANK1_PIN23_MA_OFFSET		28
+#define	PINCTRL_DRIVE6_BANK1_PIN22_V			(1 << 26)
+#define	PINCTRL_DRIVE6_BANK1_PIN22_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE6_BANK1_PIN22_MA_OFFSET		24
+#define	PINCTRL_DRIVE6_BANK1_PIN21_V			(1 << 22)
+#define	PINCTRL_DRIVE6_BANK1_PIN21_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE6_BANK1_PIN21_MA_OFFSET		20
+#define	PINCTRL_DRIVE6_BANK1_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE6_BANK1_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE6_BANK1_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE6_BANK1_PIN19_V			(1 << 14)
+#define	PINCTRL_DRIVE6_BANK1_PIN19_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE6_BANK1_PIN19_MA_OFFSET		12
+#define	PINCTRL_DRIVE6_BANK1_PIN18_V			(1 << 10)
+#define	PINCTRL_DRIVE6_BANK1_PIN18_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE6_BANK1_PIN18_MA_OFFSET		8
+#define	PINCTRL_DRIVE6_BANK1_PIN17_V			(1 << 6)
+#define	PINCTRL_DRIVE6_BANK1_PIN17_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE6_BANK1_PIN17_MA_OFFSET		4
+#define	PINCTRL_DRIVE6_BANK1_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE6_BANK1_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE6_BANK1_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE7_BANK1_PIN31_V			(1 << 30)
+#define	PINCTRL_DRIVE7_BANK1_PIN31_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE7_BANK1_PIN31_MA_OFFSET		28
+#define	PINCTRL_DRIVE7_BANK1_PIN30_V			(1 << 26)
+#define	PINCTRL_DRIVE7_BANK1_PIN30_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE7_BANK1_PIN30_MA_OFFSET		24
+#define	PINCTRL_DRIVE7_BANK1_PIN29_V			(1 << 22)
+#define	PINCTRL_DRIVE7_BANK1_PIN29_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE7_BANK1_PIN29_MA_OFFSET		20
+#define	PINCTRL_DRIVE7_BANK1_PIN28_V			(1 << 18)
+#define	PINCTRL_DRIVE7_BANK1_PIN28_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE7_BANK1_PIN28_MA_OFFSET		16
+#define	PINCTRL_DRIVE7_BANK1_PIN27_V			(1 << 14)
+#define	PINCTRL_DRIVE7_BANK1_PIN27_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE7_BANK1_PIN27_MA_OFFSET		12
+#define	PINCTRL_DRIVE7_BANK1_PIN26_V			(1 << 10)
+#define	PINCTRL_DRIVE7_BANK1_PIN26_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE7_BANK1_PIN26_MA_OFFSET		8
+#define	PINCTRL_DRIVE7_BANK1_PIN25_V			(1 << 6)
+#define	PINCTRL_DRIVE7_BANK1_PIN25_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE7_BANK1_PIN25_MA_OFFSET		4
+#define	PINCTRL_DRIVE7_BANK1_PIN24_V			(1 << 2)
+#define	PINCTRL_DRIVE7_BANK1_PIN24_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE7_BANK1_PIN24_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE8_BANK2_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE8_BANK2_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE8_BANK2_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE8_BANK2_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE8_BANK2_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE8_BANK2_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE8_BANK2_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE8_BANK2_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE8_BANK2_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE8_BANK2_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE8_BANK2_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE8_BANK2_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE8_BANK2_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE8_BANK2_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE8_BANK2_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE8_BANK2_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE8_BANK2_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE8_BANK2_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE8_BANK2_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE8_BANK2_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE8_BANK2_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE8_BANK2_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE8_BANK2_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE8_BANK2_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE9_BANK2_PIN15_V			(1 << 30)
+#define	PINCTRL_DRIVE9_BANK2_PIN15_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE9_BANK2_PIN15_MA_OFFSET		28
+#define	PINCTRL_DRIVE9_BANK2_PIN14_V			(1 << 26)
+#define	PINCTRL_DRIVE9_BANK2_PIN14_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE9_BANK2_PIN14_MA_OFFSET		24
+#define	PINCTRL_DRIVE9_BANK2_PIN13_V			(1 << 22)
+#define	PINCTRL_DRIVE9_BANK2_PIN13_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE9_BANK2_PIN13_MA_OFFSET		20
+#define	PINCTRL_DRIVE9_BANK2_PIN12_V			(1 << 18)
+#define	PINCTRL_DRIVE9_BANK2_PIN12_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE9_BANK2_PIN12_MA_OFFSET		16
+#define	PINCTRL_DRIVE9_BANK2_PIN10_V			(1 << 10)
+#define	PINCTRL_DRIVE9_BANK2_PIN10_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE9_BANK2_PIN10_MA_OFFSET		8
+#define	PINCTRL_DRIVE9_BANK2_PIN09_V			(1 << 6)
+#define	PINCTRL_DRIVE9_BANK2_PIN09_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE9_BANK2_PIN09_MA_OFFSET		4
+#define	PINCTRL_DRIVE9_BANK2_PIN08_V			(1 << 2)
+#define	PINCTRL_DRIVE9_BANK2_PIN08_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE9_BANK2_PIN08_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE10_BANK2_PIN21_V			(1 << 22)
+#define	PINCTRL_DRIVE10_BANK2_PIN21_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE10_BANK2_PIN21_MA_OFFSET		20
+#define	PINCTRL_DRIVE10_BANK2_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE10_BANK2_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE10_BANK2_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE10_BANK2_PIN19_V			(1 << 14)
+#define	PINCTRL_DRIVE10_BANK2_PIN19_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE10_BANK2_PIN19_MA_OFFSET		12
+#define	PINCTRL_DRIVE10_BANK2_PIN18_V			(1 << 10)
+#define	PINCTRL_DRIVE10_BANK2_PIN18_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE10_BANK2_PIN18_MA_OFFSET		8
+#define	PINCTRL_DRIVE10_BANK2_PIN17_V			(1 << 6)
+#define	PINCTRL_DRIVE10_BANK2_PIN17_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE10_BANK2_PIN17_MA_OFFSET		4
+#define	PINCTRL_DRIVE10_BANK2_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE10_BANK2_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE10_BANK2_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE11_BANK2_PIN27_V			(1 << 14)
+#define	PINCTRL_DRIVE11_BANK2_PIN27_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE11_BANK2_PIN27_MA_OFFSET		12
+#define	PINCTRL_DRIVE11_BANK2_PIN26_V			(1 << 10)
+#define	PINCTRL_DRIVE11_BANK2_PIN26_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE11_BANK2_PIN26_MA_OFFSET		8
+#define	PINCTRL_DRIVE11_BANK2_PIN25_V			(1 << 6)
+#define	PINCTRL_DRIVE11_BANK2_PIN25_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE11_BANK2_PIN25_MA_OFFSET		4
+#define	PINCTRL_DRIVE11_BANK2_PIN24_V			(1 << 2)
+#define	PINCTRL_DRIVE11_BANK2_PIN24_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE11_BANK2_PIN24_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE12_BANK3_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE12_BANK3_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE12_BANK3_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE12_BANK3_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE12_BANK3_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE12_BANK3_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE12_BANK3_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE12_BANK3_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE12_BANK3_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE12_BANK3_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE12_BANK3_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE12_BANK3_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE12_BANK3_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE12_BANK3_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE12_BANK3_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE12_BANK3_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE12_BANK3_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE12_BANK3_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE12_BANK3_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE12_BANK3_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE12_BANK3_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE12_BANK3_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE12_BANK3_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE12_BANK3_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE13_BANK3_PIN15_V			(1 << 30)
+#define	PINCTRL_DRIVE13_BANK3_PIN15_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE13_BANK3_PIN15_MA_OFFSET		28
+#define	PINCTRL_DRIVE13_BANK3_PIN14_V			(1 << 26)
+#define	PINCTRL_DRIVE13_BANK3_PIN14_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE13_BANK3_PIN14_MA_OFFSET		24
+#define	PINCTRL_DRIVE13_BANK3_PIN13_V			(1 << 22)
+#define	PINCTRL_DRIVE13_BANK3_PIN13_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE13_BANK3_PIN13_MA_OFFSET		20
+#define	PINCTRL_DRIVE13_BANK3_PIN12_V			(1 << 18)
+#define	PINCTRL_DRIVE13_BANK3_PIN12_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE13_BANK3_PIN12_MA_OFFSET		16
+#define	PINCTRL_DRIVE13_BANK3_PIN11_V			(1 << 14)
+#define	PINCTRL_DRIVE13_BANK3_PIN11_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE13_BANK3_PIN11_MA_OFFSET		12
+#define	PINCTRL_DRIVE13_BANK3_PIN10_V			(1 << 10)
+#define	PINCTRL_DRIVE13_BANK3_PIN10_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE13_BANK3_PIN10_MA_OFFSET		8
+#define	PINCTRL_DRIVE13_BANK3_PIN09_V			(1 << 6)
+#define	PINCTRL_DRIVE13_BANK3_PIN09_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE13_BANK3_PIN09_MA_OFFSET		4
+#define	PINCTRL_DRIVE13_BANK3_PIN08_V			(1 << 2)
+#define	PINCTRL_DRIVE13_BANK3_PIN08_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE13_BANK3_PIN08_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE14_BANK3_PIN23_V			(1 << 30)
+#define	PINCTRL_DRIVE14_BANK3_PIN23_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE14_BANK3_PIN23_MA_OFFSET		28
+#define	PINCTRL_DRIVE14_BANK3_PIN22_V			(1 << 26)
+#define	PINCTRL_DRIVE14_BANK3_PIN22_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE14_BANK3_PIN22_MA_OFFSET		24
+#define	PINCTRL_DRIVE14_BANK3_PIN21_V			(1 << 22)
+#define	PINCTRL_DRIVE14_BANK3_PIN21_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE14_BANK3_PIN21_MA_OFFSET		20
+#define	PINCTRL_DRIVE14_BANK3_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE14_BANK3_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE14_BANK3_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE14_BANK3_PIN18_V			(1 << 10)
+#define	PINCTRL_DRIVE14_BANK3_PIN18_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE14_BANK3_PIN18_MA_OFFSET		8
+#define	PINCTRL_DRIVE14_BANK3_PIN17_V			(1 << 6)
+#define	PINCTRL_DRIVE14_BANK3_PIN17_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE14_BANK3_PIN17_MA_OFFSET		4
+#define	PINCTRL_DRIVE14_BANK3_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE14_BANK3_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE14_BANK3_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE15_BANK3_PIN30_V			(1 << 26)
+#define	PINCTRL_DRIVE15_BANK3_PIN30_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE15_BANK3_PIN30_MA_OFFSET		24
+#define	PINCTRL_DRIVE15_BANK3_PIN29_V			(1 << 22)
+#define	PINCTRL_DRIVE15_BANK3_PIN29_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE15_BANK3_PIN29_MA_OFFSET		20
+#define	PINCTRL_DRIVE15_BANK3_PIN28_V			(1 << 18)
+#define	PINCTRL_DRIVE15_BANK3_PIN28_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE15_BANK3_PIN28_MA_OFFSET		16
+#define	PINCTRL_DRIVE15_BANK3_PIN27_V			(1 << 14)
+#define	PINCTRL_DRIVE15_BANK3_PIN27_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE15_BANK3_PIN27_MA_OFFSET		12
+#define	PINCTRL_DRIVE15_BANK3_PIN26_V			(1 << 10)
+#define	PINCTRL_DRIVE15_BANK3_PIN26_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE15_BANK3_PIN26_MA_OFFSET		8
+#define	PINCTRL_DRIVE15_BANK3_PIN25_V			(1 << 6)
+#define	PINCTRL_DRIVE15_BANK3_PIN25_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE15_BANK3_PIN25_MA_OFFSET		4
+#define	PINCTRL_DRIVE15_BANK3_PIN24_V			(1 << 2)
+#define	PINCTRL_DRIVE15_BANK3_PIN24_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE15_BANK3_PIN24_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE16_BANK4_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE16_BANK4_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE16_BANK4_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE16_BANK4_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE16_BANK4_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE16_BANK4_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE16_BANK4_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE16_BANK4_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE16_BANK4_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE16_BANK4_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE16_BANK4_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE16_BANK4_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE16_BANK4_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE16_BANK4_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE16_BANK4_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE16_BANK4_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE16_BANK4_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE16_BANK4_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE16_BANK4_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE16_BANK4_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE16_BANK4_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE16_BANK4_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE16_BANK4_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE16_BANK4_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE17_BANK4_PIN15_V			(1 << 30)
+#define	PINCTRL_DRIVE17_BANK4_PIN15_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE17_BANK4_PIN15_MA_OFFSET		28
+#define	PINCTRL_DRIVE17_BANK4_PIN14_V			(1 << 26)
+#define	PINCTRL_DRIVE17_BANK4_PIN14_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE17_BANK4_PIN14_MA_OFFSET		24
+#define	PINCTRL_DRIVE17_BANK4_PIN13_V			(1 << 22)
+#define	PINCTRL_DRIVE17_BANK4_PIN13_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE17_BANK4_PIN13_MA_OFFSET		20
+#define	PINCTRL_DRIVE17_BANK4_PIN12_V			(1 << 18)
+#define	PINCTRL_DRIVE17_BANK4_PIN12_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE17_BANK4_PIN12_MA_OFFSET		16
+#define	PINCTRL_DRIVE17_BANK4_PIN11_V			(1 << 14)
+#define	PINCTRL_DRIVE17_BANK4_PIN11_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE17_BANK4_PIN11_MA_OFFSET		12
+#define	PINCTRL_DRIVE17_BANK4_PIN10_V			(1 << 10)
+#define	PINCTRL_DRIVE17_BANK4_PIN10_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE17_BANK4_PIN10_MA_OFFSET		8
+#define	PINCTRL_DRIVE17_BANK4_PIN09_V			(1 << 6)
+#define	PINCTRL_DRIVE17_BANK4_PIN09_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE17_BANK4_PIN09_MA_OFFSET		4
+#define	PINCTRL_DRIVE17_BANK4_PIN08_V			(1 << 2)
+#define	PINCTRL_DRIVE17_BANK4_PIN08_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE17_BANK4_PIN08_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE18_BANK4_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE18_BANK4_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE18_BANK4_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE18_BANK4_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE18_BANK4_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE18_BANK4_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_PULL0_BANK0_PIN28			(1 << 28)
+#define	PINCTRL_PULL0_BANK0_PIN27			(1 << 27)
+#define	PINCTRL_PULL0_BANK0_PIN26			(1 << 26)
+#define	PINCTRL_PULL0_BANK0_PIN25			(1 << 25)
+#define	PINCTRL_PULL0_BANK0_PIN24			(1 << 24)
+#define	PINCTRL_PULL0_BANK0_PIN23			(1 << 23)
+#define	PINCTRL_PULL0_BANK0_PIN22			(1 << 22)
+#define	PINCTRL_PULL0_BANK0_PIN21			(1 << 21)
+#define	PINCTRL_PULL0_BANK0_PIN20			(1 << 20)
+#define	PINCTRL_PULL0_BANK0_PIN19			(1 << 19)
+#define	PINCTRL_PULL0_BANK0_PIN18			(1 << 18)
+#define	PINCTRL_PULL0_BANK0_PIN17			(1 << 17)
+#define	PINCTRL_PULL0_BANK0_PIN16			(1 << 16)
+#define	PINCTRL_PULL0_BANK0_PIN07			(1 << 7)
+#define	PINCTRL_PULL0_BANK0_PIN06			(1 << 6)
+#define	PINCTRL_PULL0_BANK0_PIN05			(1 << 5)
+#define	PINCTRL_PULL0_BANK0_PIN04			(1 << 4)
+#define	PINCTRL_PULL0_BANK0_PIN03			(1 << 3)
+#define	PINCTRL_PULL0_BANK0_PIN02			(1 << 2)
+#define	PINCTRL_PULL0_BANK0_PIN01			(1 << 1)
+#define	PINCTRL_PULL0_BANK0_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL1_BANK1_PIN31			(1 << 31)
+#define	PINCTRL_PULL1_BANK1_PIN30			(1 << 30)
+#define	PINCTRL_PULL1_BANK1_PIN29			(1 << 29)
+#define	PINCTRL_PULL1_BANK1_PIN28			(1 << 28)
+#define	PINCTRL_PULL1_BANK1_PIN27			(1 << 27)
+#define	PINCTRL_PULL1_BANK1_PIN26			(1 << 26)
+#define	PINCTRL_PULL1_BANK1_PIN25			(1 << 25)
+#define	PINCTRL_PULL1_BANK1_PIN24			(1 << 24)
+#define	PINCTRL_PULL1_BANK1_PIN23			(1 << 23)
+#define	PINCTRL_PULL1_BANK1_PIN22			(1 << 22)
+#define	PINCTRL_PULL1_BANK1_PIN21			(1 << 21)
+#define	PINCTRL_PULL1_BANK1_PIN20			(1 << 20)
+#define	PINCTRL_PULL1_BANK1_PIN19			(1 << 19)
+#define	PINCTRL_PULL1_BANK1_PIN18			(1 << 18)
+#define	PINCTRL_PULL1_BANK1_PIN17			(1 << 17)
+#define	PINCTRL_PULL1_BANK1_PIN16			(1 << 16)
+#define	PINCTRL_PULL1_BANK1_PIN15			(1 << 15)
+#define	PINCTRL_PULL1_BANK1_PIN14			(1 << 14)
+#define	PINCTRL_PULL1_BANK1_PIN13			(1 << 13)
+#define	PINCTRL_PULL1_BANK1_PIN12			(1 << 12)
+#define	PINCTRL_PULL1_BANK1_PIN11			(1 << 11)
+#define	PINCTRL_PULL1_BANK1_PIN10			(1 << 10)
+#define	PINCTRL_PULL1_BANK1_PIN09			(1 << 9)
+#define	PINCTRL_PULL1_BANK1_PIN08			(1 << 8)
+#define	PINCTRL_PULL1_BANK1_PIN07			(1 << 7)
+#define	PINCTRL_PULL1_BANK1_PIN06			(1 << 6)
+#define	PINCTRL_PULL1_BANK1_PIN05			(1 << 5)
+#define	PINCTRL_PULL1_BANK1_PIN04			(1 << 4)
+#define	PINCTRL_PULL1_BANK1_PIN03			(1 << 3)
+#define	PINCTRL_PULL1_BANK1_PIN02			(1 << 2)
+#define	PINCTRL_PULL1_BANK1_PIN01			(1 << 1)
+#define	PINCTRL_PULL1_BANK1_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL2_BANK2_PIN27			(1 << 27)
+#define	PINCTRL_PULL2_BANK2_PIN26			(1 << 26)
+#define	PINCTRL_PULL2_BANK2_PIN25			(1 << 25)
+#define	PINCTRL_PULL2_BANK2_PIN24			(1 << 24)
+#define	PINCTRL_PULL2_BANK2_PIN21			(1 << 21)
+#define	PINCTRL_PULL2_BANK2_PIN20			(1 << 20)
+#define	PINCTRL_PULL2_BANK2_PIN19			(1 << 19)
+#define	PINCTRL_PULL2_BANK2_PIN18			(1 << 18)
+#define	PINCTRL_PULL2_BANK2_PIN17			(1 << 17)
+#define	PINCTRL_PULL2_BANK2_PIN16			(1 << 16)
+#define	PINCTRL_PULL2_BANK2_PIN15			(1 << 15)
+#define	PINCTRL_PULL2_BANK2_PIN14			(1 << 14)
+#define	PINCTRL_PULL2_BANK2_PIN13			(1 << 13)
+#define	PINCTRL_PULL2_BANK2_PIN12			(1 << 12)
+#define	PINCTRL_PULL2_BANK2_PIN10			(1 << 10)
+#define	PINCTRL_PULL2_BANK2_PIN09			(1 << 9)
+#define	PINCTRL_PULL2_BANK2_PIN08			(1 << 8)
+#define	PINCTRL_PULL2_BANK2_PIN07			(1 << 7)
+#define	PINCTRL_PULL2_BANK2_PIN06			(1 << 6)
+#define	PINCTRL_PULL2_BANK2_PIN05			(1 << 5)
+#define	PINCTRL_PULL2_BANK2_PIN04			(1 << 4)
+#define	PINCTRL_PULL2_BANK2_PIN03			(1 << 3)
+#define	PINCTRL_PULL2_BANK2_PIN02			(1 << 2)
+#define	PINCTRL_PULL2_BANK2_PIN01			(1 << 1)
+#define	PINCTRL_PULL2_BANK2_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL3_BANK3_PIN30			(1 << 30)
+#define	PINCTRL_PULL3_BANK3_PIN29			(1 << 29)
+#define	PINCTRL_PULL3_BANK3_PIN28			(1 << 28)
+#define	PINCTRL_PULL3_BANK3_PIN27			(1 << 27)
+#define	PINCTRL_PULL3_BANK3_PIN26			(1 << 26)
+#define	PINCTRL_PULL3_BANK3_PIN25			(1 << 25)
+#define	PINCTRL_PULL3_BANK3_PIN24			(1 << 24)
+#define	PINCTRL_PULL3_BANK3_PIN23			(1 << 23)
+#define	PINCTRL_PULL3_BANK3_PIN22			(1 << 22)
+#define	PINCTRL_PULL3_BANK3_PIN21			(1 << 21)
+#define	PINCTRL_PULL3_BANK3_PIN20			(1 << 20)
+#define	PINCTRL_PULL3_BANK3_PIN18			(1 << 18)
+#define	PINCTRL_PULL3_BANK3_PIN17			(1 << 17)
+#define	PINCTRL_PULL3_BANK3_PIN16			(1 << 16)
+#define	PINCTRL_PULL3_BANK3_PIN15			(1 << 15)
+#define	PINCTRL_PULL3_BANK3_PIN14			(1 << 14)
+#define	PINCTRL_PULL3_BANK3_PIN13			(1 << 13)
+#define	PINCTRL_PULL3_BANK3_PIN12			(1 << 12)
+#define	PINCTRL_PULL3_BANK3_PIN11			(1 << 11)
+#define	PINCTRL_PULL3_BANK3_PIN10			(1 << 10)
+#define	PINCTRL_PULL3_BANK3_PIN09			(1 << 9)
+#define	PINCTRL_PULL3_BANK3_PIN08			(1 << 8)
+#define	PINCTRL_PULL3_BANK3_PIN07			(1 << 7)
+#define	PINCTRL_PULL3_BANK3_PIN06			(1 << 6)
+#define	PINCTRL_PULL3_BANK3_PIN05			(1 << 5)
+#define	PINCTRL_PULL3_BANK3_PIN04			(1 << 4)
+#define	PINCTRL_PULL3_BANK3_PIN03			(1 << 3)
+#define	PINCTRL_PULL3_BANK3_PIN02			(1 << 2)
+#define	PINCTRL_PULL3_BANK3_PIN01			(1 << 1)
+#define	PINCTRL_PULL3_BANK3_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL4_BANK4_PIN20			(1 << 20)
+#define	PINCTRL_PULL4_BANK4_PIN16			(1 << 16)
+#define	PINCTRL_PULL4_BANK4_PIN15			(1 << 15)
+#define	PINCTRL_PULL4_BANK4_PIN14			(1 << 14)
+#define	PINCTRL_PULL4_BANK4_PIN13			(1 << 13)
+#define	PINCTRL_PULL4_BANK4_PIN12			(1 << 12)
+#define	PINCTRL_PULL4_BANK4_PIN11			(1 << 11)
+#define	PINCTRL_PULL4_BANK4_PIN10			(1 << 10)
+#define	PINCTRL_PULL4_BANK4_PIN09			(1 << 9)
+#define	PINCTRL_PULL4_BANK4_PIN08			(1 << 8)
+#define	PINCTRL_PULL4_BANK4_PIN07			(1 << 7)
+#define	PINCTRL_PULL4_BANK4_PIN06			(1 << 6)
+#define	PINCTRL_PULL4_BANK4_PIN05			(1 << 5)
+#define	PINCTRL_PULL4_BANK4_PIN04			(1 << 4)
+#define	PINCTRL_PULL4_BANK4_PIN03			(1 << 3)
+#define	PINCTRL_PULL4_BANK4_PIN02			(1 << 2)
+#define	PINCTRL_PULL4_BANK4_PIN01			(1 << 1)
+#define	PINCTRL_PULL4_BANK4_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL5_BANK5_PIN26			(1 << 26)
+#define	PINCTRL_PULL5_BANK5_PIN23			(1 << 23)
+#define	PINCTRL_PULL5_BANK5_PIN22			(1 << 22)
+#define	PINCTRL_PULL5_BANK5_PIN21			(1 << 21)
+#define	PINCTRL_PULL5_BANK5_PIN20			(1 << 20)
+#define	PINCTRL_PULL5_BANK5_PIN19			(1 << 19)
+#define	PINCTRL_PULL5_BANK5_PIN18			(1 << 18)
+#define	PINCTRL_PULL5_BANK5_PIN17			(1 << 17)
+#define	PINCTRL_PULL5_BANK5_PIN16			(1 << 16)
+#define	PINCTRL_PULL5_BANK5_PIN15			(1 << 15)
+#define	PINCTRL_PULL5_BANK5_PIN14			(1 << 14)
+#define	PINCTRL_PULL5_BANK5_PIN13			(1 << 13)
+#define	PINCTRL_PULL5_BANK5_PIN12			(1 << 12)
+#define	PINCTRL_PULL5_BANK5_PIN11			(1 << 11)
+#define	PINCTRL_PULL5_BANK5_PIN10			(1 << 10)
+#define	PINCTRL_PULL5_BANK5_PIN09			(1 << 9)
+#define	PINCTRL_PULL5_BANK5_PIN08			(1 << 8)
+#define	PINCTRL_PULL5_BANK5_PIN07			(1 << 7)
+#define	PINCTRL_PULL5_BANK5_PIN06			(1 << 6)
+#define	PINCTRL_PULL5_BANK5_PIN05			(1 << 5)
+#define	PINCTRL_PULL5_BANK5_PIN04			(1 << 4)
+#define	PINCTRL_PULL5_BANK5_PIN03			(1 << 3)
+#define	PINCTRL_PULL5_BANK5_PIN02			(1 << 2)
+#define	PINCTRL_PULL5_BANK5_PIN01			(1 << 1)
+#define	PINCTRL_PULL5_BANK5_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL6_BANK6_PIN24			(1 << 24)
+#define	PINCTRL_PULL6_BANK6_PIN23			(1 << 23)
+#define	PINCTRL_PULL6_BANK6_PIN22			(1 << 22)
+#define	PINCTRL_PULL6_BANK6_PIN21			(1 << 21)
+#define	PINCTRL_PULL6_BANK6_PIN20			(1 << 20)
+#define	PINCTRL_PULL6_BANK6_PIN19			(1 << 19)
+#define	PINCTRL_PULL6_BANK6_PIN18			(1 << 18)
+#define	PINCTRL_PULL6_BANK6_PIN17			(1 << 17)
+#define	PINCTRL_PULL6_BANK6_PIN16			(1 << 16)
+#define	PINCTRL_PULL6_BANK6_PIN14			(1 << 14)
+#define	PINCTRL_PULL6_BANK6_PIN13			(1 << 13)
+#define	PINCTRL_PULL6_BANK6_PIN12			(1 << 12)
+#define	PINCTRL_PULL6_BANK6_PIN11			(1 << 11)
+#define	PINCTRL_PULL6_BANK6_PIN10			(1 << 10)
+#define	PINCTRL_PULL6_BANK6_PIN09			(1 << 9)
+#define	PINCTRL_PULL6_BANK6_PIN08			(1 << 8)
+#define	PINCTRL_PULL6_BANK6_PIN07			(1 << 7)
+#define	PINCTRL_PULL6_BANK6_PIN06			(1 << 6)
+#define	PINCTRL_PULL6_BANK6_PIN05			(1 << 5)
+#define	PINCTRL_PULL6_BANK6_PIN04			(1 << 4)
+#define	PINCTRL_PULL6_BANK6_PIN03			(1 << 3)
+#define	PINCTRL_PULL6_BANK6_PIN02			(1 << 2)
+#define	PINCTRL_PULL6_BANK6_PIN01			(1 << 1)
+#define	PINCTRL_PULL6_BANK6_PIN00			(1 << 0)
+
+#define	PINCTRL_DOUT0_DOUT_MASK				0x1fffffff
+#define	PINCTRL_DOUT0_DOUT_OFFSET			0
+
+#define	PINCTRL_DOUT1_DOUT_MASK				0xffffffff
+#define	PINCTRL_DOUT1_DOUT_OFFSET			0
+
+#define	PINCTRL_DOUT2_DOUT_MASK				0xfffffff
+#define	PINCTRL_DOUT2_DOUT_OFFSET			0
+
+#define	PINCTRL_DOUT3_DOUT_MASK				0x7fffffff
+#define	PINCTRL_DOUT3_DOUT_OFFSET			0
+
+#define	PINCTRL_DOUT4_DOUT_MASK				0x1fffff
+#define	PINCTRL_DOUT4_DOUT_OFFSET			0
+
+#define	PINCTRL_DIN0_DIN_MASK				0x1fffffff
+#define	PINCTRL_DIN0_DIN_OFFSET				0
+
+#define	PINCTRL_DIN1_DIN_MASK				0xffffffff
+#define	PINCTRL_DIN1_DIN_OFFSET				0
+
+#define	PINCTRL_DIN2_DIN_MASK				0xfffffff
+#define	PINCTRL_DIN2_DIN_OFFSET				0
+
+#define	PINCTRL_DIN3_DIN_MASK				0x7fffffff
+#define	PINCTRL_DIN3_DIN_OFFSET				0
+
+#define	PINCTRL_DIN4_DIN_MASK				0x1fffff
+#define	PINCTRL_DIN4_DIN_OFFSET				0
+
+#define	PINCTRL_DOE0_DOE_MASK				0x1fffffff
+#define	PINCTRL_DOE0_DOE_OFFSET				0
+
+#define	PINCTRL_DOE1_DOE_MASK				0xffffffff
+#define	PINCTRL_DOE1_DOE_OFFSET				0
+
+#define	PINCTRL_DOE2_DOE_MASK				0xfffffff
+#define	PINCTRL_DOE2_DOE_OFFSET				0
+
+#define	PINCTRL_DOE3_DOE_MASK				0x7fffffff
+#define	PINCTRL_DOE3_DOE_OFFSET				0
+
+#define	PINCTRL_DOE4_DOE_MASK				0x1fffff
+#define	PINCTRL_DOE4_DOE_OFFSET				0
+
+#define	PINCTRL_PIN2IRQ0_PIN2IRQ_MASK			0x1fffffff
+#define	PINCTRL_PIN2IRQ0_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_PIN2IRQ1_PIN2IRQ_MASK			0xffffffff
+#define	PINCTRL_PIN2IRQ1_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_PIN2IRQ2_PIN2IRQ_MASK			0xfffffff
+#define	PINCTRL_PIN2IRQ2_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_PIN2IRQ3_PIN2IRQ_MASK			0x7fffffff
+#define	PINCTRL_PIN2IRQ3_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_PIN2IRQ4_PIN2IRQ_MASK			0x1fffff
+#define	PINCTRL_PIN2IRQ4_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_IRQEN0_IRQEN_MASK			0x1fffffff
+#define	PINCTRL_IRQEN0_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQEN1_IRQEN_MASK			0xffffffff
+#define	PINCTRL_IRQEN1_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQEN2_IRQEN_MASK			0xfffffff
+#define	PINCTRL_IRQEN2_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQEN3_IRQEN_MASK			0x7fffffff
+#define	PINCTRL_IRQEN3_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQEN4_IRQEN_MASK			0x1fffff
+#define	PINCTRL_IRQEN4_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQLEVEL0_IRQLEVEL_MASK			0x1fffffff
+#define	PINCTRL_IRQLEVEL0_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQLEVEL1_IRQLEVEL_MASK			0xffffffff
+#define	PINCTRL_IRQLEVEL1_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQLEVEL2_IRQLEVEL_MASK			0xfffffff
+#define	PINCTRL_IRQLEVEL2_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQLEVEL3_IRQLEVEL_MASK			0x7fffffff
+#define	PINCTRL_IRQLEVEL3_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQLEVEL4_IRQLEVEL_MASK			0x1fffff
+#define	PINCTRL_IRQLEVEL4_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQPOL0_IRQPOL_MASK			0x1fffffff
+#define	PINCTRL_IRQPOL0_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQPOL1_IRQPOL_MASK			0xffffffff
+#define	PINCTRL_IRQPOL1_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQPOL2_IRQPOL_MASK			0xfffffff
+#define	PINCTRL_IRQPOL2_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQPOL3_IRQPOL_MASK			0x7fffffff
+#define	PINCTRL_IRQPOL3_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQPOL4_IRQPOL_MASK			0x1fffff
+#define	PINCTRL_IRQPOL4_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQSTAT0_IRQSTAT_MASK			0x1fffffff
+#define	PINCTRL_IRQSTAT0_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_IRQSTAT1_IRQSTAT_MASK			0xffffffff
+#define	PINCTRL_IRQSTAT1_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_IRQSTAT2_IRQSTAT_MASK			0xfffffff
+#define	PINCTRL_IRQSTAT2_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_IRQSTAT3_IRQSTAT_MASK			0x7fffffff
+#define	PINCTRL_IRQSTAT3_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_IRQSTAT4_IRQSTAT_MASK			0x1fffff
+#define	PINCTRL_IRQSTAT4_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_EMI_ODT_CTRL_ADDRESS_CALIB_MASK		(0x3 << 26)
+#define	PINCTRL_EMI_ODT_CTRL_ADDRESS_CALIB_OFFSET	26
+#define	PINCTRL_EMI_ODT_CTRL_ADDRESS_TLOAD_MASK		(0x3 << 24)
+#define	PINCTRL_EMI_ODT_CTRL_ADDRESS_TLOAD_OFFSET	24
+#define	PINCTRL_EMI_ODT_CTRL_CONTROL_CALIB_MASK		(0x3 << 22)
+#define	PINCTRL_EMI_ODT_CTRL_CONTROL_CALIB_OFFSET	22
+#define	PINCTRL_EMI_ODT_CTRL_CONTROL_TLOAD_MASK		(0x3 << 20)
+#define	PINCTRL_EMI_ODT_CTRL_CONTROL_TLOAD_OFFSET	20
+#define	PINCTRL_EMI_ODT_CTRL_DUALPAD_CALIB_MASK		(0x3 << 18)
+#define	PINCTRL_EMI_ODT_CTRL_DUALPAD_CALIB_OFFSET	18
+#define	PINCTRL_EMI_ODT_CTRL_DUALPAD_TLOAD_MASK		(0x3 << 16)
+#define	PINCTRL_EMI_ODT_CTRL_DUALPAD_TLOAD_OFFSET	16
+#define	PINCTRL_EMI_ODT_CTRL_SLICE3_CALIB_MASK		(0x3 << 14)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE3_CALIB_OFFSET	14
+#define	PINCTRL_EMI_ODT_CTRL_SLICE3_TLOAD_MASK		(0x3 << 12)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE3_TLOAD_OFFSET	12
+#define	PINCTRL_EMI_ODT_CTRL_SLICE2_CALIB_MASK		(0x3 << 10)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE2_CALIB_OFFSET	10
+#define	PINCTRL_EMI_ODT_CTRL_SLICE2_TLOAD_MASK		(0x3 << 8)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE2_TLOAD_OFFSET	8
+#define	PINCTRL_EMI_ODT_CTRL_SLICE1_CALIB_MASK		(0x3 << 6)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE1_CALIB_OFFSET	6
+#define	PINCTRL_EMI_ODT_CTRL_SLICE1_TLOAD_MASK		(0x3 << 4)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE1_TLOAD_OFFSET	4
+#define	PINCTRL_EMI_ODT_CTRL_SLICE0_CALIB_MASK		(0x3 << 2)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE0_CALIB_OFFSET	2
+#define	PINCTRL_EMI_ODT_CTRL_SLICE0_TLOAD_MASK		(0x3 << 0)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE0_TLOAD_OFFSET	0
+
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_MASK		(0x3 << 16)
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_OFFSET		16
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_mDDR		(0x0 << 16)
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_GPIO		(0x1 << 16)
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_LVDDR2		(0x2 << 16)
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2		(0x3 << 16)
+#define	PINCTRL_EMI_DS_CTRL_ADDRESS_MA_MASK		(0x3 << 12)
+#define	PINCTRL_EMI_DS_CTRL_ADDRESS_MA_OFFSET		12
+#define	PINCTRL_EMI_DS_CTRL_CONTROL_MA_MASK		(0x3 << 10)
+#define	PINCTRL_EMI_DS_CTRL_CONTROL_MA_OFFSET		10
+#define	PINCTRL_EMI_DS_CTRL_DUALPAD_MA_MASK		(0x3 << 8)
+#define	PINCTRL_EMI_DS_CTRL_DUALPAD_MA_OFFSET		8
+#define	PINCTRL_EMI_DS_CTRL_SLICE3_MA_MASK		(0x3 << 6)
+#define	PINCTRL_EMI_DS_CTRL_SLICE3_MA_OFFSET		6
+#define	PINCTRL_EMI_DS_CTRL_SLICE2_MA_MASK		(0x3 << 4)
+#define	PINCTRL_EMI_DS_CTRL_SLICE2_MA_OFFSET		4
+#define	PINCTRL_EMI_DS_CTRL_SLICE1_MA_MASK		(0x3 << 2)
+#define	PINCTRL_EMI_DS_CTRL_SLICE1_MA_OFFSET		2
+#define	PINCTRL_EMI_DS_CTRL_SLICE0_MA_MASK		(0x3 << 0)
+#define	PINCTRL_EMI_DS_CTRL_SLICE0_MA_OFFSET		0
+
+#endif /* __MX28_REGS_PINCTRL_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-power.h b/arch/arm/include/asm/arch-mx28/regs-power.h
new file mode 100644
index 0000000..9da63ad
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-power.h
@@ -0,0 +1,413 @@
+/*
+ * Freescale i.MX28 Power Controller Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_POWER_H__
+#define __MX28_REGS_POWER_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_power_regs {
+	mx28_reg(hw_power_ctrl)
+	mx28_reg(hw_power_5vctrl)
+	mx28_reg(hw_power_minpwr)
+	mx28_reg(hw_power_charge)
+	uint32_t	hw_power_vdddctrl;
+	uint32_t	reserved_vddd[3];
+	uint32_t	hw_power_vddactrl;
+	uint32_t	reserved_vdda[3];
+	uint32_t	hw_power_vddioctrl;
+	uint32_t	reserved_vddio[3];
+	uint32_t	hw_power_vddmemctrl;
+	uint32_t	reserved_vddmem[3];
+	uint32_t	hw_power_dcdc4p2;
+	uint32_t	reserved_dcdc4p2[3];
+	uint32_t	hw_power_misc;
+	uint32_t	reserved_misc[3];
+	uint32_t	hw_power_dclimits;
+	uint32_t	reserved_dclimits[3];
+	mx28_reg(hw_power_loopctrl)
+	uint32_t	hw_power_sts;
+	uint32_t	reserved_sts[3];
+	mx28_reg(hw_power_speed)
+	uint32_t	hw_power_battmonitor;
+	uint32_t	reserved_battmonitor[3];
+
+	uint32_t	reserved[4];
+
+	mx28_reg(hw_power_reset)
+	mx28_reg(hw_power_debug)
+	mx28_reg(hw_power_thermal)
+	mx28_reg(hw_power_usb1ctrl)
+	mx28_reg(hw_power_special)
+	mx28_reg(hw_power_version)
+	mx28_reg(hw_power_anaclkctrl)
+	mx28_reg(hw_power_refctrl)
+};
+#endif
+
+#define	POWER_CTRL_PSWITCH_MID_TRAN			(1 << 27)
+#define	POWER_CTRL_DCDC4P2_BO_IRQ			(1 << 24)
+#define	POWER_CTRL_ENIRQ_DCDC4P2_BO			(1 << 23)
+#define	POWER_CTRL_VDD5V_DROOP_IRQ			(1 << 22)
+#define	POWER_CTRL_ENIRQ_VDD5V_DROOP			(1 << 21)
+#define	POWER_CTRL_PSWITCH_IRQ				(1 << 20)
+#define	POWER_CTRL_PSWITCH_IRQ_SRC			(1 << 19)
+#define	POWER_CTRL_POLARITY_PSWITCH			(1 << 18)
+#define	POWER_CTRL_ENIRQ_PSWITCH			(1 << 17)
+#define	POWER_CTRL_POLARITY_DC_OK			(1 << 16)
+#define	POWER_CTRL_DC_OK_IRQ				(1 << 15)
+#define	POWER_CTRL_ENIRQ_DC_OK				(1 << 14)
+#define	POWER_CTRL_BATT_BO_IRQ				(1 << 13)
+#define	POWER_CTRL_ENIRQ_BATT_BO			(1 << 12)
+#define	POWER_CTRL_VDDIO_BO_IRQ				(1 << 11)
+#define	POWER_CTRL_ENIRQ_VDDIO_BO			(1 << 10)
+#define	POWER_CTRL_VDDA_BO_IRQ				(1 << 9)
+#define	POWER_CTRL_ENIRQ_VDDA_BO			(1 << 8)
+#define	POWER_CTRL_VDDD_BO_IRQ				(1 << 7)
+#define	POWER_CTRL_ENIRQ_VDDD_BO			(1 << 6)
+#define	POWER_CTRL_POLARITY_VBUSVALID			(1 << 5)
+#define	POWER_CTRL_VBUS_VALID_IRQ			(1 << 4)
+#define	POWER_CTRL_ENIRQ_VBUS_VALID			(1 << 3)
+#define	POWER_CTRL_POLARITY_VDD5V_GT_VDDIO		(1 << 2)
+#define	POWER_CTRL_VDD5V_GT_VDDIO_IRQ			(1 << 1)
+#define	POWER_CTRL_ENIRQ_VDD5V_GT_VDDIO			(1 << 0)
+
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_MASK		(0x3 << 30)
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_OFFSET		30
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_4V3			(0x0 << 30)
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_4V4			(0x1 << 30)
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_4V5			(0x2 << 30)
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_4V7			(0x3 << 30)
+#define	POWER_5VCTRL_HEADROOM_ADJ_MASK			(0x7 << 24)
+#define	POWER_5VCTRL_HEADROOM_ADJ_OFFSET		24
+#define	POWER_5VCTRL_PWD_CHARGE_4P2_MASK		(0x3 << 20)
+#define	POWER_5VCTRL_PWD_CHARGE_4P2_OFFSET		20
+#define	POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK		(0x3f << 12)
+#define	POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET		12
+#define	POWER_5VCTRL_VBUSVALID_TRSH_MASK		(0x7 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_OFFSET		8
+#define	POWER_5VCTRL_VBUSVALID_TRSH_2V9			(0x0 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V0			(0x1 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V1			(0x2 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V2			(0x3 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V3			(0x4 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V4			(0x5 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V5			(0x6 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V6			(0x7 << 8)
+#define	POWER_5VCTRL_PWDN_5VBRNOUT			(1 << 7)
+#define	POWER_5VCTRL_ENABLE_LINREG_ILIMIT		(1 << 6)
+#define	POWER_5VCTRL_DCDC_XFER				(1 << 5)
+#define	POWER_5VCTRL_VBUSVALID_5VDETECT			(1 << 4)
+#define	POWER_5VCTRL_VBUSVALID_TO_B			(1 << 3)
+#define	POWER_5VCTRL_ILIMIT_EQ_ZERO			(1 << 2)
+#define	POWER_5VCTRL_PWRUP_VBUS_CMPS			(1 << 1)
+#define	POWER_5VCTRL_ENABLE_DCDC			(1 << 0)
+
+#define	POWER_MINPWR_LOWPWR_4P2				(1 << 14)
+#define	POWER_MINPWR_PWD_BO				(1 << 12)
+#define	POWER_MINPWR_USE_VDDXTAL_VBG			(1 << 11)
+#define	POWER_MINPWR_PWD_ANA_CMPS			(1 << 10)
+#define	POWER_MINPWR_ENABLE_OSC				(1 << 9)
+#define	POWER_MINPWR_SELECT_OSC				(1 << 8)
+#define	POWER_MINPWR_FBG_OFF				(1 << 7)
+#define	POWER_MINPWR_DOUBLE_FETS			(1 << 6)
+#define	POWER_MINPWR_HALFFETS				(1 << 5)
+#define	POWER_MINPWR_LESSANA_I				(1 << 4)
+#define	POWER_MINPWR_PWD_XTAL24				(1 << 3)
+#define	POWER_MINPWR_DC_STOPCLK				(1 << 2)
+#define	POWER_MINPWR_EN_DC_PFM				(1 << 1)
+#define	POWER_MINPWR_DC_HALFCLK				(1 << 0)
+
+#define	POWER_CHARGE_ADJ_VOLT_MASK			(0x7 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_OFFSET			24
+#define	POWER_CHARGE_ADJ_VOLT_M025P			(0x1 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_P050P			(0x2 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_M075P			(0x3 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_P025P			(0x4 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_M050P			(0x5 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_P075P			(0x6 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_M100P			(0x7 << 24)
+#define	POWER_CHARGE_ENABLE_LOAD			(1 << 22)
+#define	POWER_CHARGE_ENABLE_FAULT_DETECT		(1 << 20)
+#define	POWER_CHARGE_CHRG_STS_OFF			(1 << 19)
+#define	POWER_CHARGE_LIION_4P1				(1 << 18)
+#define	POWER_CHARGE_PWD_BATTCHRG			(1 << 16)
+#define	POWER_CHARGE_ENABLE_CHARGER_USB1		(1 << 13)
+#define	POWER_CHARGE_ENABLE_CHARGER_USB0		(1 << 12)
+#define	POWER_CHARGE_STOP_ILIMIT_MASK			(0xf << 8)
+#define	POWER_CHARGE_STOP_ILIMIT_OFFSET			8
+#define	POWER_CHARGE_STOP_ILIMIT_10MA			(0x1 << 8)
+#define	POWER_CHARGE_STOP_ILIMIT_20MA			(0x2 << 8)
+#define	POWER_CHARGE_STOP_ILIMIT_50MA			(0x4 << 8)
+#define	POWER_CHARGE_STOP_ILIMIT_100MA			(0x8 << 8)
+#define	POWER_CHARGE_BATTCHRG_I_MASK			0x3f
+#define	POWER_CHARGE_BATTCHRG_I_OFFSET			0
+#define	POWER_CHARGE_BATTCHRG_I_10MA			0x01
+#define	POWER_CHARGE_BATTCHRG_I_20MA			0x02
+#define	POWER_CHARGE_BATTCHRG_I_50MA			0x04
+#define	POWER_CHARGE_BATTCHRG_I_100MA			0x08
+#define	POWER_CHARGE_BATTCHRG_I_200MA			0x10
+#define	POWER_CHARGE_BATTCHRG_I_400MA			0x20
+
+#define	POWER_VDDDCTRL_ADJTN_MASK			(0xf << 28)
+#define	POWER_VDDDCTRL_ADJTN_OFFSET			28
+#define	POWER_VDDDCTRL_PWDN_BRNOUT			(1 << 23)
+#define	POWER_VDDDCTRL_DISABLE_STEPPING			(1 << 22)
+#define	POWER_VDDDCTRL_ENABLE_LINREG			(1 << 21)
+#define	POWER_VDDDCTRL_DISABLE_FET			(1 << 20)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_MASK		(0x3 << 16)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_OFFSET		16
+#define	POWER_VDDDCTRL_LINREG_OFFSET_0STEPS		(0x0 << 16)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_ABOVE	(0x1 << 16)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW	(0x2 << 16)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_2STEPS_BELOW	(0x3 << 16)
+#define	POWER_VDDDCTRL_BO_OFFSET_MASK			(0x7 << 8)
+#define	POWER_VDDDCTRL_BO_OFFSET_OFFSET			8
+#define	POWER_VDDDCTRL_TRG_MASK				0x1f
+#define	POWER_VDDDCTRL_TRG_OFFSET			0
+
+#define	POWER_VDDACTRL_PWDN_BRNOUT			(1 << 19)
+#define	POWER_VDDACTRL_DISABLE_STEPPING			(1 << 18)
+#define	POWER_VDDACTRL_ENABLE_LINREG			(1 << 17)
+#define	POWER_VDDACTRL_DISABLE_FET			(1 << 16)
+#define	POWER_VDDACTRL_LINREG_OFFSET_MASK		(0x3 << 12)
+#define	POWER_VDDACTRL_LINREG_OFFSET_OFFSET		12
+#define	POWER_VDDACTRL_LINREG_OFFSET_0STEPS		(0x0 << 12)
+#define	POWER_VDDACTRL_LINREG_OFFSET_1STEPS_ABOVE	(0x1 << 12)
+#define	POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW	(0x2 << 12)
+#define	POWER_VDDACTRL_LINREG_OFFSET_2STEPS_BELOW	(0x3 << 12)
+#define	POWER_VDDACTRL_BO_OFFSET_MASK			(0x7 << 8)
+#define	POWER_VDDACTRL_BO_OFFSET_OFFSET			8
+#define	POWER_VDDACTRL_TRG_MASK				0x1f
+#define	POWER_VDDACTRL_TRG_OFFSET			0
+
+#define	POWER_VDDIOCTRL_ADJTN_MASK			(0xf << 20)
+#define	POWER_VDDIOCTRL_ADJTN_OFFSET			20
+#define	POWER_VDDIOCTRL_PWDN_BRNOUT			(1 << 18)
+#define	POWER_VDDIOCTRL_DISABLE_STEPPING		(1 << 17)
+#define	POWER_VDDIOCTRL_DISABLE_FET			(1 << 16)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_MASK		(0x3 << 12)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_OFFSET		12
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_0STEPS		(0x0 << 12)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_ABOVE	(0x1 << 12)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW	(0x2 << 12)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_2STEPS_BELOW	(0x3 << 12)
+#define	POWER_VDDIOCTRL_BO_OFFSET_MASK			(0x7 << 8)
+#define	POWER_VDDIOCTRL_BO_OFFSET_OFFSET		8
+#define	POWER_VDDIOCTRL_TRG_MASK			0x1f
+#define	POWER_VDDIOCTRL_TRG_OFFSET			0
+
+#define	POWER_VDDMEMCTRL_PULLDOWN_ACTIVE		(1 << 10)
+#define	POWER_VDDMEMCTRL_ENABLE_ILIMIT			(1 << 9)
+#define	POWER_VDDMEMCTRL_ENABLE_LINREG			(1 << 8)
+#define	POWER_VDDMEMCTRL_BO_OFFSET_MASK			(0x7 << 5)
+#define	POWER_VDDMEMCTRL_BO_OFFSET_OFFSET		5
+#define	POWER_VDDMEMCTRL_TRG_MASK			0x1f
+#define	POWER_VDDMEMCTRL_TRG_OFFSET			0
+
+#define	POWER_DCDC4P2_DROPOUT_CTRL_MASK			(0xf << 28)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_OFFSET		28
+#define	POWER_DCDC4P2_DROPOUT_CTRL_200MV		(0x3 << 30)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_100MV		(0x2 << 30)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_50MV			(0x1 << 30)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_25MV			(0x0 << 30)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_SRC_4P2		(0x0 << 28)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_SRC_4P2_LT_BATT	(0x1 << 28)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL		(0x2 << 28)
+#define	POWER_DCDC4P2_ISTEAL_THRESH_MASK		(0x3 << 24)
+#define	POWER_DCDC4P2_ISTEAL_THRESH_OFFSET		24
+#define	POWER_DCDC4P2_ENABLE_4P2			(1 << 23)
+#define	POWER_DCDC4P2_ENABLE_DCDC			(1 << 22)
+#define	POWER_DCDC4P2_HYST_DIR				(1 << 21)
+#define	POWER_DCDC4P2_HYST_THRESH			(1 << 20)
+#define	POWER_DCDC4P2_TRG_MASK				(0x7 << 16)
+#define	POWER_DCDC4P2_TRG_OFFSET			16
+#define	POWER_DCDC4P2_TRG_4V2				(0x0 << 16)
+#define	POWER_DCDC4P2_TRG_4V1				(0x1 << 16)
+#define	POWER_DCDC4P2_TRG_4V0				(0x2 << 16)
+#define	POWER_DCDC4P2_TRG_3V9				(0x3 << 16)
+#define	POWER_DCDC4P2_TRG_BATT				(0x4 << 16)
+#define	POWER_DCDC4P2_BO_MASK				(0x1f << 8)
+#define	POWER_DCDC4P2_BO_OFFSET				8
+#define	POWER_DCDC4P2_CMPTRIP_MASK			0x1f
+#define	POWER_DCDC4P2_CMPTRIP_OFFSET			0
+
+#define	POWER_MISC_FREQSEL_MASK				(0x7 << 4)
+#define	POWER_MISC_FREQSEL_OFFSET			4
+#define	POWER_MISC_FREQSEL_20MHZ			(0x1 << 4)
+#define	POWER_MISC_FREQSEL_24MHZ			(0x2 << 4)
+#define	POWER_MISC_FREQSEL_19MHZ			(0x3 << 4)
+#define	POWER_MISC_FREQSEL_14MHZ			(0x4 << 4)
+#define	POWER_MISC_FREQSEL_18MHZ			(0x5 << 4)
+#define	POWER_MISC_FREQSEL_21MHZ			(0x6 << 4)
+#define	POWER_MISC_FREQSEL_17MHZ			(0x7 << 4)
+#define	POWER_MISC_DISABLE_FET_BO_LOGIC			(1 << 3)
+#define	POWER_MISC_DELAY_TIMING				(1 << 2)
+#define	POWER_MISC_TEST					(1 << 1)
+#define	POWER_MISC_SEL_PLLCLK				(1 << 0)
+
+#define	POWER_DCLIMITS_POSLIMIT_BUCK_MASK		(0x7f << 8)
+#define	POWER_DCLIMITS_POSLIMIT_BUCK_OFFSET		8
+#define	POWER_DCLIMITS_NEGLIMIT_MASK			0x7f
+#define	POWER_DCLIMITS_NETLIMIT_OFFSET			0
+
+#define	POWER_LOOPCTRL_TOGGLE_DIF			(1 << 20)
+#define	POWER_LOOPCTRL_HYST_SIGN			(1 << 19)
+#define	POWER_LOOPCTRL_EN_CM_HYST			(1 << 18)
+#define	POWER_LOOPCTRL_EN_DF_HYST			(1 << 17)
+#define	POWER_LOOPCTRL_CM_HYST_THRESH			(1 << 16)
+#define	POWER_LOOPCTRL_DF_HYST_THRESH			(1 << 15)
+#define	POWER_LOOPCTRL_RCSCALE_THRESH			(1 << 14)
+#define	POWER_LOOPCTRL_EN_RCSCALE_MASK			(0x3 << 12)
+#define	POWER_LOOPCTRL_EN_RCSCALE_OFFSET		12
+#define	POWER_LOOPCTRL_EN_RCSCALE_DIS			(0x0 << 12)
+#define	POWER_LOOPCTRL_EN_RCSCALE_2X			(0x1 << 12)
+#define	POWER_LOOPCTRL_EN_RCSCALE_4X			(0x2 << 12)
+#define	POWER_LOOPCTRL_EN_RCSCALE_8X			(0x3 << 12)
+#define	POWER_LOOPCTRL_DC_FF_MASK			(0x7 << 8)
+#define	POWER_LOOPCTRL_DC_FF_OFFSET			8
+#define	POWER_LOOPCTRL_DC_R_MASK			(0xf << 4)
+#define	POWER_LOOPCTRL_DC_R_OFFSET			4
+#define	POWER_LOOPCTRL_DC_C_MASK			0x3
+#define	POWER_LOOPCTRL_DC_C_OFFSET			0
+#define	POWER_LOOPCTRL_DC_C_MAX				0x0
+#define	POWER_LOOPCTRL_DC_C_2X				0x1
+#define	POWER_LOOPCTRL_DC_C_4X				0x2
+#define	POWER_LOOPCTRL_DC_C_MIN				0x3
+
+#define	POWER_STS_PWRUP_SOURCE_MASK			(0x3f << 24)
+#define	POWER_STS_PWRUP_SOURCE_OFFSET			24
+#define	POWER_STS_PWRUP_SOURCE_5V			(0x20 << 24)
+#define	POWER_STS_PWRUP_SOURCE_RTC			(0x10 << 24)
+#define	POWER_STS_PWRUP_SOURCE_PSWITCH_HIGH		(0x02 << 24)
+#define	POWER_STS_PWRUP_SOURCE_PSWITCH_MID		(0x01 << 24)
+#define	POWER_STS_PSWITCH_MASK				(0x3 << 20)
+#define	POWER_STS_PSWITCH_OFFSET			20
+#define	POWER_STS_THERMAL_WARNING			(1 << 19)
+#define	POWER_STS_VDDMEM_BO				(1 << 18)
+#define	POWER_STS_AVALID0_STATUS			(1 << 17)
+#define	POWER_STS_BVALID0_STATUS			(1 << 16)
+#define	POWER_STS_VBUSVALID0_STATUS			(1 << 15)
+#define	POWER_STS_SESSEND0_STATUS			(1 << 14)
+#define	POWER_STS_BATT_BO				(1 << 13)
+#define	POWER_STS_VDD5V_FAULT				(1 << 12)
+#define	POWER_STS_CHRGSTS				(1 << 11)
+#define	POWER_STS_DCDC_4P2_BO				(1 << 10)
+#define	POWER_STS_DC_OK					(1 << 9)
+#define	POWER_STS_VDDIO_BO				(1 << 8)
+#define	POWER_STS_VDDA_BO				(1 << 7)
+#define	POWER_STS_VDDD_BO				(1 << 6)
+#define	POWER_STS_VDD5V_GT_VDDIO			(1 << 5)
+#define	POWER_STS_VDD5V_DROOP				(1 << 4)
+#define	POWER_STS_AVALID0				(1 << 3)
+#define	POWER_STS_BVALID0				(1 << 2)
+#define	POWER_STS_VBUSVALID0				(1 << 1)
+#define	POWER_STS_SESSEND0				(1 << 0)
+
+#define	POWER_SPEED_STATUS_MASK				(0xffff << 8)
+#define	POWER_SPEED_STATUS_OFFSET			8
+#define	POWER_SPEED_STATUS_SEL_MASK			(0x3 << 6)
+#define	POWER_SPEED_STATUS_SEL_OFFSET			6
+#define	POWER_SPEED_STATUS_SEL_DCDC_STAT		(0x0 << 6)
+#define	POWER_SPEED_STATUS_SEL_CORE_STAT		(0x1 << 6)
+#define	POWER_SPEED_STATUS_SEL_ARM_STAT			(0x2 << 6)
+#define	POWER_SPEED_CTRL_MASK				0x3
+#define	POWER_SPEED_CTRL_OFFSET				0
+#define	POWER_SPEED_CTRL_SS_OFF				0x0
+#define	POWER_SPEED_CTRL_SS_ON				0x1
+#define	POWER_SPEED_CTRL_SS_ENABLE			0x3
+
+#define	POWER_BATTMONITOR_BATT_VAL_MASK			(0x3ff << 16)
+#define	POWER_BATTMONITOR_BATT_VAL_OFFSET		16
+#define	POWER_BATTMONITOR_PWDN_BATTBRNOUT_5VDETECT_EN	(1 << 11)
+#define	POWER_BATTMONITOR_EN_BATADJ			(1 << 10)
+#define	POWER_BATTMONITOR_PWDN_BATTBRNOUT		(1 << 9)
+#define	POWER_BATTMONITOR_BRWNOUT_PWD			(1 << 8)
+#define	POWER_BATTMONITOR_BRWNOUT_LVL_MASK		0x1f
+#define	POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET		0
+
+#define	POWER_RESET_UNLOCK_MASK				(0xffff << 16)
+#define	POWER_RESET_UNLOCK_OFFSET			16
+#define	POWER_RESET_UNLOCK_KEY				(0x3e77 << 16)
+#define	POWER_RESET_FASTFALL_PSWITCH_OFF		(1 << 2)
+#define	POWER_RESET_PWD_OFF				(1 << 1)
+#define	POWER_RESET_PWD					(1 << 0)
+
+#define	POWER_DEBUG_VBUSVALIDPIOLOCK			(1 << 3)
+#define	POWER_DEBUG_AVALIDPIOLOCK			(1 << 2)
+#define	POWER_DEBUG_BVALIDPIOLOCK			(1 << 1)
+#define	POWER_DEBUG_SESSENDPIOLOCK			(1 << 0)
+
+#define	POWER_THERMAL_TEST				(1 << 8)
+#define	POWER_THERMAL_PWD				(1 << 7)
+#define	POWER_THERMAL_LOW_POWER				(1 << 6)
+#define	POWER_THERMAL_OFFSET_ADJ_MASK			(0x3 << 4)
+#define	POWER_THERMAL_OFFSET_ADJ_OFFSET			4
+#define	POWER_THERMAL_OFFSET_ADJ_ENABLE			(1 << 3)
+#define	POWER_THERMAL_TEMP_THRESHOLD_MASK		0x7
+#define	POWER_THERMAL_TEMP_THRESHOLD_OFFSET		0
+
+#define	POWER_USB1CTRL_AVALID1				(1 << 3)
+#define	POWER_USB1CTRL_BVALID1				(1 << 2)
+#define	POWER_USB1CTRL_VBUSVALID1			(1 << 1)
+#define	POWER_USB1CTRL_SESSEND1				(1 << 0)
+
+#define	POWER_SPECIAL_TEST_MASK				0xffffffff
+#define	POWER_SPECIAL_TEST_OFFSET			0
+
+#define	POWER_VERSION_MAJOR_MASK			(0xff << 24)
+#define	POWER_VERSION_MAJOR_OFFSET			24
+#define	POWER_VERSION_MINOR_MASK			(0xff << 16)
+#define	POWER_VERSION_MINOR_OFFSET			16
+#define	POWER_VERSION_STEP_MASK				0xffff
+#define	POWER_VERSION_STEP_OFFSET			0
+
+#define	POWER_ANACLKCTRL_CLKGATE_0			(1 << 31)
+#define	POWER_ANACLKCTRL_OUTDIV_MASK			(0x7 << 28)
+#define	POWER_ANACLKCTRL_OUTDIV_OFFSET			28
+#define	POWER_ANACLKCTRL_INVERT_OUTCLK			(1 << 27)
+#define	POWER_ANACLKCTRL_CLKGATE_I			(1 << 26)
+#define	POWER_ANACLKCTRL_DITHER_OFF			(1 << 10)
+#define	POWER_ANACLKCTRL_SLOW_DITHER			(1 << 9)
+#define	POWER_ANACLKCTRL_INVERT_INCLK			(1 << 8)
+#define	POWER_ANACLKCTRL_INCLK_SHIFT_MASK		(0x3 << 4)
+#define	POWER_ANACLKCTRL_INCLK_SHIFT_OFFSET		4
+#define	POWER_ANACLKCTRL_INDIV_MASK			0x7
+#define	POWER_ANACLKCTRL_INDIV_OFFSET			0
+
+#define	POWER_REFCTRL_FASTSETTLING			(1 << 26)
+#define	POWER_REFCTRL_RAISE_REF				(1 << 25)
+#define	POWER_REFCTRL_XTAL_BGR_BIAS			(1 << 24)
+#define	POWER_REFCTRL_VBG_ADJ_MASK			(0x7 << 20)
+#define	POWER_REFCTRL_VBG_ADJ_OFFSET			20
+#define	POWER_REFCTRL_LOW_PWR				(1 << 19)
+#define	POWER_REFCTRL_BIAS_CTRL_MASK			(0x3 << 16)
+#define	POWER_REFCTRL_BIAS_CTRL_OFFSET			16
+#define	POWER_REFCTRL_VDDXTAL_TO_VDDD			(1 << 14)
+#define	POWER_REFCTRL_ADJ_ANA				(1 << 13)
+#define	POWER_REFCTRL_ADJ_VAG				(1 << 12)
+#define	POWER_REFCTRL_ANA_REFVAL_MASK			(0xf << 8)
+#define	POWER_REFCTRL_ANA_REFVAL_OFFSET			8
+#define	POWER_REFCTRL_VAG_VAL_MASK			(0xf << 4)
+#define	POWER_REFCTRL_VAG_VAL_OFFSET			4
+
+#endif	/* __MX28_REGS_POWER_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-rtc.h b/arch/arm/include/asm/arch-mx28/regs-rtc.h
new file mode 100644
index 0000000..fe2fda9
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-rtc.h
@@ -0,0 +1,147 @@
+/*
+ * Freescale i.MX28 RTC Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_RTC_H__
+#define __MX28_REGS_RTC_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_rtc_regs {
+	mx28_reg(hw_rtc_ctrl)
+	mx28_reg(hw_rtc_stat)
+	mx28_reg(hw_rtc_milliseconds)
+	mx28_reg(hw_rtc_seconds)
+	mx28_reg(hw_rtc_rtc_alarm)
+	mx28_reg(hw_rtc_watchdog)
+	mx28_reg(hw_rtc_persistent0)
+	mx28_reg(hw_rtc_persistent1)
+	mx28_reg(hw_rtc_persistent2)
+	mx28_reg(hw_rtc_persistent3)
+	mx28_reg(hw_rtc_persistent4)
+	mx28_reg(hw_rtc_persistent5)
+	mx28_reg(hw_rtc_debug)
+	mx28_reg(hw_rtc_version)
+};
+#endif
+
+#define	RTC_CTRL_SFTRST				(1 << 31)
+#define	RTC_CTRL_CLKGATE			(1 << 30)
+#define	RTC_CTRL_SUPPRESS_COPY2ANALOG		(1 << 6)
+#define	RTC_CTRL_FORCE_UPDATE			(1 << 5)
+#define	RTC_CTRL_WATCHDOGEN			(1 << 4)
+#define	RTC_CTRL_ONEMSEC_IRQ			(1 << 3)
+#define	RTC_CTRL_ALARM_IRQ			(1 << 2)
+#define	RTC_CTRL_ONEMSEC_IRQ_EN			(1 << 1)
+#define	RTC_CTRL_ALARM_IRQ_EN			(1 << 0)
+
+#define	RTC_STAT_RTC_PRESENT			(1 << 31)
+#define	RTC_STAT_ALARM_PRESENT			(1 << 30)
+#define	RTC_STAT_WATCHDOG_PRESENT		(1 << 29)
+#define	RTC_STAT_XTAL32000_PRESENT		(1 << 28)
+#define	RTC_STAT_XTAL32768_PRESENT		(1 << 27)
+#define	RTC_STAT_STALE_REGS_MASK		(0xff << 16)
+#define	RTC_STAT_STALE_REGS_OFFSET		16
+#define	RTC_STAT_NEW_REGS_MASK			(0xff << 8)
+#define	RTC_STAT_NEW_REGS_OFFSET		8
+
+#define	RTC_MILLISECONDS_COUNT_MASK		0xffffffff
+#define	RTC_MILLISECONDS_COUNT_OFFSET		0
+
+#define	RTC_SECONDS_COUNT_MASK			0xffffffff
+#define	RTC_SECONDS_COUNT_OFFSET		0
+
+#define	RTC_ALARM_VALUE_MASK			0xffffffff
+#define	RTC_ALARM_VALUE_OFFSET			0
+
+#define	RTC_WATCHDOG_COUNT_MASK			0xffffffff
+#define	RTC_WATCHDOG_COUNT_OFFSET		0
+
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_MASK	(0xf << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_OFFSET	28
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V83	(0x0 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V78	(0x1 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V73	(0x2 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V68	(0x3 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V62	(0x4 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V57	(0x5 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V52	(0x6 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V48	(0x7 << 28)
+#define	RTC_PERSISTENT0_EXTERNAL_RESET		(1 << 21)
+#define	RTC_PERSISTENT0_THERMAL_RESET		(1 << 20)
+#define	RTC_PERSISTENT0_ENABLE_LRADC_PWRUP	(1 << 18)
+#define	RTC_PERSISTENT0_AUTO_RESTART		(1 << 17)
+#define	RTC_PERSISTENT0_DISABLE_PSWITCH		(1 << 16)
+#define	RTC_PERSISTENT0_LOWERBIAS_MASK		(0xf << 14)
+#define	RTC_PERSISTENT0_LOWERBIAS_OFFSET	14
+#define	RTC_PERSISTENT0_LOWERBIAS_NOMINAL	(0x0 << 14)
+#define	RTC_PERSISTENT0_LOWERBIAS_M25P		(0x1 << 14)
+#define	RTC_PERSISTENT0_LOWERBIAS_M50P		(0x3 << 14)
+#define	RTC_PERSISTENT0_DISABLE_XTALOK		(1 << 13)
+#define	RTC_PERSISTENT0_MSEC_RES_MASK		(0x1f << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_OFFSET		8
+#define	RTC_PERSISTENT0_MSEC_RES_1MS		(0x01 << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_2MS		(0x02 << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_4MS		(0x04 << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_8MS		(0x08 << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_16MS		(0x10 << 8)
+#define	RTC_PERSISTENT0_ALARM_WAKE		(1 << 7)
+#define	RTC_PERSISTENT0_XTAL32_FREQ		(1 << 6)
+#define	RTC_PERSISTENT0_XTAL32KHZ_PWRUP		(1 << 5)
+#define	RTC_PERSISTENT0_XTAL24KHZ_PWRUP		(1 << 4)
+#define	RTC_PERSISTENT0_LCK_SECS		(1 << 3)
+#define	RTC_PERSISTENT0_ALARM_EN		(1 << 2)
+#define	RTC_PERSISTENT0_ALARM_WAKE_EN		(1 << 1)
+#define	RTC_PERSISTENT0_CLOCKSOURCE		(1 << 0)
+
+#define	RTC_PERSISTENT1_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT1_GENERAL_OFFSET		0
+#define	RTC_PERSISTENT1_GENERAL_OTG_ALT_ROLE	0x0080
+#define	RTC_PERSISTENT1_GENERAL_OTG_HNP		0x0100
+#define	RTC_PERSISTENT1_GENERAL_USB_LPM		0x0200
+#define	RTC_PERSISTENT1_GENERAL_SKIP_CHECKDISK	0x0400
+#define	RTC_PERSISTENT1_GENERAL_USB_BOOT_PLAYER	0x0800
+#define	RTC_PERSISTENT1_GENERAL_ENUM_500MA_2X	0x1000
+
+#define	RTC_PERSISTENT2_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT2_GENERAL_OFFSET		0
+
+#define	RTC_PERSISTENT3_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT3_GENERAL_OFFSET		0
+
+#define	RTC_PERSISTENT4_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT4_GENERAL_OFFSET		0
+
+#define	RTC_PERSISTENT5_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT5_GENERAL_OFFSET		0
+
+#define	RTC_DEBUG_WATCHDOG_RESET_MASK		(1 << 1)
+#define	RTC_DEBUG_WATCHDOG_RESET		(1 << 0)
+
+#define	RTC_VERSION_MAJOR_MASK			(0xff << 24)
+#define	RTC_VERSION_MAJOR_OFFSET		24
+#define	RTC_VERSION_MINOR_MASK			(0xff << 16)
+#define	RTC_VERSION_MINOR_OFFSET		16
+#define	RTC_VERSION_STEP_MASK			0xffff
+#define	RTC_VERSION_STEP_OFFSET			0
+
+#endif	/* __MX28_REGS_RTC_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-ssp.h b/arch/arm/include/asm/arch-mx28/regs-ssp.h
new file mode 100644
index 0000000..ab3870c
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-ssp.h
@@ -0,0 +1,349 @@
+/*
+ * Freescale i.MX28 SSP Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_SSP_H__
+#define __MX28_REGS_SSP_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_ssp_regs {
+	mx28_reg(hw_ssp_ctrl0)
+	mx28_reg(hw_ssp_cmd0)
+	mx28_reg(hw_ssp_cmd1)
+	mx28_reg(hw_ssp_xfer_size)
+	mx28_reg(hw_ssp_block_size)
+	mx28_reg(hw_ssp_compref)
+	mx28_reg(hw_ssp_compmask)
+	mx28_reg(hw_ssp_timing)
+	mx28_reg(hw_ssp_ctrl1)
+	mx28_reg(hw_ssp_data)
+	mx28_reg(hw_ssp_sdresp0)
+	mx28_reg(hw_ssp_sdresp1)
+	mx28_reg(hw_ssp_sdresp2)
+	mx28_reg(hw_ssp_sdresp3)
+	mx28_reg(hw_ssp_ddr_ctrl)
+	mx28_reg(hw_ssp_dll_ctrl)
+	mx28_reg(hw_ssp_status)
+	mx28_reg(hw_ssp_dll_sts)
+	mx28_reg(hw_ssp_debug)
+	mx28_reg(hw_ssp_version)
+};
+#endif
+
+#define	SSP_CTRL0_SFTRST			(1 << 31)
+#define	SSP_CTRL0_CLKGATE			(1 << 30)
+#define	SSP_CTRL0_RUN				(1 << 29)
+#define	SSP_CTRL0_SDIO_IRQ_CHECK		(1 << 28)
+#define	SSP_CTRL0_LOCK_CS			(1 << 27)
+#define	SSP_CTRL0_IGNORE_CRC			(1 << 26)
+#define	SSP_CTRL0_READ				(1 << 25)
+#define	SSP_CTRL0_DATA_XFER			(1 << 24)
+#define	SSP_CTRL0_BUS_WIDTH_MASK		(0x3 << 22)
+#define	SSP_CTRL0_BUS_WIDTH_OFFSET		22
+#define	SSP_CTRL0_BUS_WIDTH_ONE_BIT		(0x0 << 22)
+#define	SSP_CTRL0_BUS_WIDTH_FOUR_BIT		(0x1 << 22)
+#define	SSP_CTRL0_BUS_WIDTH_EIGHT_BIT		(0x2 << 22)
+#define	SSP_CTRL0_WAIT_FOR_IRQ			(1 << 21)
+#define	SSP_CTRL0_WAIT_FOR_CMD			(1 << 20)
+#define	SSP_CTRL0_LONG_RESP			(1 << 19)
+#define	SSP_CTRL0_CHECK_RESP			(1 << 18)
+#define	SSP_CTRL0_GET_RESP			(1 << 17)
+#define	SSP_CTRL0_ENABLE			(1 << 16)
+
+#define	SSP_CMD0_SOFT_TERMINATE			(1 << 26)
+#define	SSP_CMD0_DBL_DATA_RATE_EN		(1 << 25)
+#define	SSP_CMD0_PRIM_BOOT_OP_EN		(1 << 24)
+#define	SSP_CMD0_BOOT_ACK_EN			(1 << 23)
+#define	SSP_CMD0_SLOW_CLKING_EN			(1 << 22)
+#define	SSP_CMD0_CONT_CLKING_EN			(1 << 21)
+#define	SSP_CMD0_APPEND_8CYC			(1 << 20)
+#define	SSP_CMD0_CMD_MASK			0xff
+#define	SSP_CMD0_CMD_OFFSET			0
+#define	SSP_CMD0_CMD_MMC_GO_IDLE_STATE		0x00
+#define	SSP_CMD0_CMD_MMC_SEND_OP_COND		0x01
+#define	SSP_CMD0_CMD_MMC_ALL_SEND_CID		0x02
+#define	SSP_CMD0_CMD_MMC_SET_RELATIVE_ADDR	0x03
+#define	SSP_CMD0_CMD_MMC_SET_DSR		0x04
+#define	SSP_CMD0_CMD_MMC_RESERVED_5		0x05
+#define	SSP_CMD0_CMD_MMC_SWITCH			0x06
+#define	SSP_CMD0_CMD_MMC_SELECT_DESELECT_CARD	0x07
+#define	SSP_CMD0_CMD_MMC_SEND_EXT_CSD		0x08
+#define	SSP_CMD0_CMD_MMC_SEND_CSD		0x09
+#define	SSP_CMD0_CMD_MMC_SEND_CID		0x0a
+#define	SSP_CMD0_CMD_MMC_READ_DAT_UNTIL_STOP	0x0b
+#define	SSP_CMD0_CMD_MMC_STOP_TRANSMISSION	0x0c
+#define	SSP_CMD0_CMD_MMC_SEND_STATUS		0x0d
+#define	SSP_CMD0_CMD_MMC_BUSTEST_R		0x0e
+#define	SSP_CMD0_CMD_MMC_GO_INACTIVE_STATE	0x0f
+#define	SSP_CMD0_CMD_MMC_SET_BLOCKLEN		0x10
+#define	SSP_CMD0_CMD_MMC_READ_SINGLE_BLOCK	0x11
+#define	SSP_CMD0_CMD_MMC_READ_MULTIPLE_BLOCK	0x12
+#define	SSP_CMD0_CMD_MMC_BUSTEST_W		0x13
+#define	SSP_CMD0_CMD_MMC_WRITE_DAT_UNTIL_STOP	0x14
+#define	SSP_CMD0_CMD_MMC_SET_BLOCK_COUNT	0x17
+#define	SSP_CMD0_CMD_MMC_WRITE_BLOCK		0x18
+#define	SSP_CMD0_CMD_MMC_WRITE_MULTIPLE_BLOCK	0x19
+#define	SSP_CMD0_CMD_MMC_PROGRAM_CID		0x1a
+#define	SSP_CMD0_CMD_MMC_PROGRAM_CSD		0x1b
+#define	SSP_CMD0_CMD_MMC_SET_WRITE_PROT		0x1c
+#define	SSP_CMD0_CMD_MMC_CLR_WRITE_PROT		0x1d
+#define	SSP_CMD0_CMD_MMC_SEND_WRITE_PROT	0x1e
+#define	SSP_CMD0_CMD_MMC_ERASE_GROUP_START	0x23
+#define	SSP_CMD0_CMD_MMC_ERASE_GROUP_END	0x24
+#define	SSP_CMD0_CMD_MMC_ERASE			0x26
+#define	SSP_CMD0_CMD_MMC_FAST_IO		0x27
+#define	SSP_CMD0_CMD_MMC_GO_IRQ_STATE		0x28
+#define	SSP_CMD0_CMD_MMC_LOCK_UNLOCK		0x2a
+#define	SSP_CMD0_CMD_MMC_APP_CMD		0x37
+#define	SSP_CMD0_CMD_MMC_GEN_CMD		0x38
+#define	SSP_CMD0_CMD_SD_GO_IDLE_STATE		0x00
+#define	SSP_CMD0_CMD_SD_ALL_SEND_CID		0x02
+#define	SSP_CMD0_CMD_SD_SEND_RELATIVE_ADDR	0x03
+#define	SSP_CMD0_CMD_SD_SET_DSR			0x04
+#define	SSP_CMD0_CMD_SD_IO_SEND_OP_COND		0x05
+#define	SSP_CMD0_CMD_SD_SELECT_DESELECT_CARD	0x07
+#define	SSP_CMD0_CMD_SD_SEND_CSD		0x09
+#define	SSP_CMD0_CMD_SD_SEND_CID		0x0a
+#define	SSP_CMD0_CMD_SD_STOP_TRANSMISSION	0x0c
+#define	SSP_CMD0_CMD_SD_SEND_STATUS		0x0d
+#define	SSP_CMD0_CMD_SD_GO_INACTIVE_STATE	0x0f
+#define	SSP_CMD0_CMD_SD_SET_BLOCKLEN		0x10
+#define	SSP_CMD0_CMD_SD_READ_SINGLE_BLOCK	0x11
+#define	SSP_CMD0_CMD_SD_READ_MULTIPLE_BLOCK	0x12
+#define	SSP_CMD0_CMD_SD_WRITE_BLOCK		0x18
+#define	SSP_CMD0_CMD_SD_WRITE_MULTIPLE_BLOCK	0x19
+#define	SSP_CMD0_CMD_SD_PROGRAM_CSD		0x1b
+#define	SSP_CMD0_CMD_SD_SET_WRITE_PROT		0x1c
+#define	SSP_CMD0_CMD_SD_CLR_WRITE_PROT		0x1d
+#define	SSP_CMD0_CMD_SD_SEND_WRITE_PROT		0x1e
+#define	SSP_CMD0_CMD_SD_ERASE_WR_BLK_START	0x20
+#define	SSP_CMD0_CMD_SD_ERASE_WR_BLK_END	0x21
+#define	SSP_CMD0_CMD_SD_ERASE_GROUP_START	0x23
+#define	SSP_CMD0_CMD_SD_ERASE_GROUP_END		0x24
+#define	SSP_CMD0_CMD_SD_ERASE			0x26
+#define	SSP_CMD0_CMD_SD_LOCK_UNLOCK		0x2a
+#define	SSP_CMD0_CMD_SD_IO_RW_DIRECT		0x34
+#define	SSP_CMD0_CMD_SD_IO_RW_EXTENDED		0x35
+#define	SSP_CMD0_CMD_SD_APP_CMD			0x37
+#define	SSP_CMD0_CMD_SD_GEN_CMD			0x38
+
+#define	SSP_CMD1_CMD_ARG_MASK			0xffffffff
+#define	SSP_CMD1_CMD_ARG_OFFSET			0
+
+#define	SSP_XFER_SIZE_XFER_COUNT_MASK		0xffffffff
+#define	SSP_XFER_SIZE_XFER_COUNT_OFFSET		0
+
+#define	SSP_BLOCK_SIZE_BLOCK_COUNT_MASK		(0xffffff << 4)
+#define	SSP_BLOCK_SIZE_BLOCK_COUNT_OFFSET	4
+#define	SSP_BLOCK_SIZE_BLOCK_SIZE_MASK		0xf
+#define	SSP_BLOCK_SIZE_BLOCK_SIZE_OFFSET	0
+
+#define	SSP_COMPREF_REFERENCE_MASK		0xffffffff
+#define	SSP_COMPREF_REFERENCE_OFFSET		0
+
+#define	SSP_COMPMASK_MASK_MASK			0xffffffff
+#define	SSP_COMPMASK_MASK_OFFSET		0
+
+#define	SSP_TIMING_TIMEOUT_MASK			(0xffff << 16)
+#define	SSP_TIMING_TIMEOUT_OFFSET		16
+#define	SSP_TIMING_CLOCK_DIVIDE_MASK		(0xff << 8)
+#define	SSP_TIMING_CLOCK_DIVIDE_OFFSET		8
+#define	SSP_TIMING_CLOCK_RATE_MASK		0xff
+#define	SSP_TIMING_CLOCK_RATE_OFFSET		0
+
+#define	SSP_CTRL1_SDIO_IRQ			(1 << 31)
+#define	SSP_CTRL1_SDIO_IRQ_EN			(1 << 30)
+#define	SSP_CTRL1_RESP_ERR_IRQ			(1 << 29)
+#define	SSP_CTRL1_RESP_ERR_IRQ_EN		(1 << 28)
+#define	SSP_CTRL1_RESP_TIMEOUT_IRQ		(1 << 27)
+#define	SSP_CTRL1_RESP_TIMEOUT_IRQ_EN		(1 << 26)
+#define	SSP_CTRL1_DATA_TIMEOUT_IRQ		(1 << 25)
+#define	SSP_CTRL1_DATA_TIMEOUT_IRQ_EN		(1 << 24)
+#define	SSP_CTRL1_DATA_CRC_IRQ			(1 << 23)
+#define	SSP_CTRL1_DATA_CRC_IRQ_EN		(1 << 22)
+#define	SSP_CTRL1_FIFO_UNDERRUN_IRQ		(1 << 21)
+#define	SSP_CTRL1_FIFO_UNDERRUN_EN		(1 << 20)
+#define	SSP_CTRL1_CEATA_CCS_ERR_IRQ		(1 << 19)
+#define	SSP_CTRL1_CEATA_CCS_ERR_IRQ_EN		(1 << 18)
+#define	SSP_CTRL1_RECV_TIMEOUT_IRQ		(1 << 17)
+#define	SSP_CTRL1_RECV_TIMEOUT_IRQ_EN		(1 << 16)
+#define	SSP_CTRL1_FIFO_OVERRUN_IRQ		(1 << 15)
+#define	SSP_CTRL1_FIFO_OVERRUN_IRQ_EN		(1 << 14)
+#define	SSP_CTRL1_DMA_ENABLE			(1 << 13)
+#define	SSP_CTRL1_CEATA_CCS_ERR_EN		(1 << 12)
+#define	SSP_CTRL1_SLAVE_OUT_DISABLE		(1 << 11)
+#define	SSP_CTRL1_PHASE				(1 << 10)
+#define	SSP_CTRL1_POLARITY			(1 << 9)
+#define	SSP_CTRL1_SLAVE_MODE			(1 << 8)
+#define	SSP_CTRL1_WORD_LENGTH_MASK		(0xf << 4)
+#define	SSP_CTRL1_WORD_LENGTH_OFFSET		4
+#define	SSP_CTRL1_WORD_LENGTH_RESERVED0		(0x0 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_RESERVED1		(0x1 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_RESERVED2		(0x2 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_FOUR_BITS		(0x3 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_EIGHT_BITS	(0x7 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_SIXTEEN_BITS	(0xf << 4)
+#define	SSP_CTRL1_SSP_MODE_MASK			0xf
+#define	SSP_CTRL1_SSP_MODE_OFFSET		0
+#define	SSP_CTRL1_SSP_MODE_SPI			0x0
+#define	SSP_CTRL1_SSP_MODE_SSI			0x1
+#define	SSP_CTRL1_SSP_MODE_SD_MMC		0x3
+#define	SSP_CTRL1_SSP_MODE_MS			0x4
+
+#define	SSP_DATA_DATA_MASK			0xffffffff
+#define	SSP_DATA_DATA_OFFSET			0
+
+#define	SSP_SDRESP0_RESP0_MASK			0xffffffff
+#define	SSP_SDRESP0_RESP0_OFFSET		0
+
+#define	SSP_SDRESP1_RESP1_MASK			0xffffffff
+#define	SSP_SDRESP1_RESP1_OFFSET		0
+
+#define	SSP_SDRESP2_RESP2_MASK			0xffffffff
+#define	SSP_SDRESP2_RESP2_OFFSET		0
+
+#define	SSP_SDRESP3_RESP3_MASK			0xffffffff
+#define	SSP_SDRESP3_RESP3_OFFSET		0
+
+#define	SSP_DDR_CTRL_DMA_BURST_TYPE_MASK	(0x3 << 30)
+#define	SSP_DDR_CTRL_DMA_BURST_TYPE_OFFSET	30
+#define	SSP_DDR_CTRL_NIBBLE_POS			(1 << 1)
+#define	SSP_DDR_CTRL_TXCLK_DELAY_TYPE		(1 << 0)
+
+#define	SSP_DLL_CTRL_REF_UPDATE_INT_MASK	(0xf << 28)
+#define	SSP_DLL_CTRL_REF_UPDATE_INT_OFFSET	28
+#define	SSP_DLL_CTRL_SLV_UPDATE_INT_MASK	(0xff << 20)
+#define	SSP_DLL_CTRL_SLV_UPDATE_INT_OFFSET	20
+#define	SSP_DLL_CTRL_SLV_OVERRIDE_VAL_MASK	(0x3f << 10)
+#define	SSP_DLL_CTRL_SLV_OVERRIDE_VAL_OFFSET	10
+#define	SSP_DLL_CTRL_SLV_OVERRIDE		(1 << 9)
+#define	SSP_DLL_CTRL_GATE_UPDATE		(1 << 7)
+#define	SSP_DLL_CTRL_SLV_DLY_TARGET_MASK	(0xf << 3)
+#define	SSP_DLL_CTRL_SLV_DLY_TARGET_OFFSET	3
+#define	SSP_DLL_CTRL_SLV_FORCE_UPD		(1 << 2)
+#define	SSP_DLL_CTRL_RESET			(1 << 1)
+#define	SSP_DLL_CTRL_ENABLE			(1 << 0)
+
+#define	SSP_STATUS_PRESENT			(1 << 31)
+#define	SSP_STATUS_MS_PRESENT			(1 << 30)
+#define	SSP_STATUS_SD_PRESENT			(1 << 29)
+#define	SSP_STATUS_CARD_DETECT			(1 << 28)
+#define	SSP_STATUS_DMABURST			(1 << 22)
+#define	SSP_STATUS_DMASENSE			(1 << 21)
+#define	SSP_STATUS_DMATERM			(1 << 20)
+#define	SSP_STATUS_DMAREQ			(1 << 19)
+#define	SSP_STATUS_DMAEND			(1 << 18)
+#define	SSP_STATUS_SDIO_IRQ			(1 << 17)
+#define	SSP_STATUS_RESP_CRC_ERR			(1 << 16)
+#define	SSP_STATUS_RESP_ERR			(1 << 15)
+#define	SSP_STATUS_RESP_TIMEOUT			(1 << 14)
+#define	SSP_STATUS_DATA_CRC_ERR			(1 << 13)
+#define	SSP_STATUS_TIMEOUT			(1 << 12)
+#define	SSP_STATUS_RECV_TIMEOUT_STAT		(1 << 11)
+#define	SSP_STATUS_CEATA_CCS_ERR		(1 << 10)
+#define	SSP_STATUS_FIFO_OVRFLW			(1 << 9)
+#define	SSP_STATUS_FIFO_FULL			(1 << 8)
+#define	SSP_STATUS_FIFO_EMPTY			(1 << 5)
+#define	SSP_STATUS_FIFO_UNDRFLW			(1 << 4)
+#define	SSP_STATUS_CMD_BUSY			(1 << 3)
+#define	SSP_STATUS_DATA_BUSY			(1 << 2)
+#define	SSP_STATUS_BUSY				(1 << 0)
+
+#define	SSP_DLL_STS_REF_SEL_MASK		(0x3f << 8)
+#define	SSP_DLL_STS_REF_SEL_OFFSET		8
+#define	SSP_DLL_STS_SLV_SEL_MASK		(0x3f << 2)
+#define	SSP_DLL_STS_SLV_SEL_OFFSET		2
+#define	SSP_DLL_STS_REF_LOCK			(1 << 1)
+#define	SSP_DLL_STS_SLV_LOCK			(1 << 0)
+
+#define	SSP_DEBUG_DATACRC_ERR_MASK		(0xf << 28)
+#define	SSP_DEBUG_DATACRC_ERR_OFFSET		28
+#define	SSP_DEBUG_DATA_STALL			(1 << 27)
+#define	SSP_DEBUG_DAT_SM_MASK			(0x7 << 24)
+#define	SSP_DEBUG_DAT_SM_OFFSET			24
+#define	SSP_DEBUG_DAT_SM_DSM_IDLE		(0x0 << 24)
+#define	SSP_DEBUG_DAT_SM_DSM_WORD		(0x2 << 24)
+#define	SSP_DEBUG_DAT_SM_DSM_CRC1		(0x3 << 24)
+#define	SSP_DEBUG_DAT_SM_DSM_CRC2		(0x4 << 24)
+#define	SSP_DEBUG_DAT_SM_DSM_END		(0x5 << 24)
+#define	SSP_DEBUG_MSTK_SM_MASK			(0xf << 20)
+#define	SSP_DEBUG_MSTK_SM_OFFSET		20
+#define	SSP_DEBUG_MSTK_SM_MSTK_IDLE		(0x0 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_CKON		(0x1 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_BS1		(0x2 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_TPC		(0x3 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_BS2		(0x4 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_HDSHK		(0x5 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_BS3		(0x6 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_RW		(0x7 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_CRC1		(0x8 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_CRC2		(0x9 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_BS0		(0xa << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_END1		(0xb << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_END2W		(0xc << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_END2R		(0xd << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_DONE		(0xe << 20)
+#define	SSP_DEBUG_CMD_OE			(1 << 19)
+#define	SSP_DEBUG_DMA_SM_MASK			(0x7 << 16)
+#define	SSP_DEBUG_DMA_SM_OFFSET			16
+#define	SSP_DEBUG_DMA_SM_DMA_IDLE		(0x0 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_DMAREQ		(0x1 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_DMAACK		(0x2 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_STALL		(0x3 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_BUSY		(0x4 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_DONE		(0x5 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_COUNT		(0x6 << 16)
+#define	SSP_DEBUG_MMC_SM_MASK			(0xf << 12)
+#define	SSP_DEBUG_MMC_SM_OFFSET			12
+#define	SSP_DEBUG_MMC_SM_MMC_IDLE		(0x0 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_CMD		(0x1 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_TRC		(0x2 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_RESP		(0x3 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_RPRX		(0x4 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_TX			(0x5 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_CTOK		(0x6 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_RX			(0x7 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_CCS		(0x8 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_PUP		(0x9 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_WAIT		(0xa << 12)
+#define	SSP_DEBUG_CMD_SM_MASK			(0x3 << 10)
+#define	SSP_DEBUG_CMD_SM_OFFSET			10
+#define	SSP_DEBUG_CMD_SM_CSM_IDLE		(0x0 << 10)
+#define	SSP_DEBUG_CMD_SM_CSM_INDEX		(0x1 << 10)
+#define	SSP_DEBUG_CMD_SM_CSM_ARG		(0x2 << 10)
+#define	SSP_DEBUG_CMD_SM_CSM_CRC		(0x3 << 10)
+#define	SSP_DEBUG_SSP_CMD			(1 << 9)
+#define	SSP_DEBUG_SSP_RESP			(1 << 8)
+#define	SSP_DEBUG_SSP_RXD_MASK			0xff
+#define	SSP_DEBUG_SSP_RXD_OFFSET		0
+
+#define	SSP_VERSION_MAJOR_MASK			(0xff << 24)
+#define	SSP_VERSION_MAJOR_OFFSET		24
+#define	SSP_VERSION_MINOR_MASK			(0xff << 16)
+#define	SSP_VERSION_MINOR_OFFSET		16
+#define	SSP_VERSION_STEP_MASK			0xffff
+#define	SSP_VERSION_STEP_OFFSET			0
+
+#endif /* __MX28_REGS_SSP_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-timrot.h b/arch/arm/include/asm/arch-mx28/regs-timrot.h
new file mode 100644
index 0000000..1b941cf
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-timrot.h
@@ -0,0 +1,171 @@
+/*
+ * Freescale i.MX28 TIMROT Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_TIMROT_H__
+#define __MX28_REGS_TIMROT_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_timrot_regs {
+	mx28_reg(hw_timrot_rotctrl)
+	mx28_reg(hw_timrot_rotcount)
+	mx28_reg(hw_timrot_timctrl0)
+	mx28_reg(hw_timrot_running_count0)
+	mx28_reg(hw_timrot_fixed_count0)
+	mx28_reg(hw_timrot_match_count0)
+	mx28_reg(hw_timrot_timctrl1)
+	mx28_reg(hw_timrot_running_count1)
+	mx28_reg(hw_timrot_fixed_count1)
+	mx28_reg(hw_timrot_match_count1)
+	mx28_reg(hw_timrot_timctrl2)
+	mx28_reg(hw_timrot_running_count2)
+	mx28_reg(hw_timrot_fixed_count2)
+	mx28_reg(hw_timrot_match_count2)
+	mx28_reg(hw_timrot_timctrl3)
+	mx28_reg(hw_timrot_running_count3)
+	mx28_reg(hw_timrot_fixed_count3)
+	mx28_reg(hw_timrot_match_count3)
+	mx28_reg(hw_timrot_version)
+};
+#endif
+
+#define	TIMROT_ROTCTRL_SFTRST				(1 << 31)
+#define	TIMROT_ROTCTRL_CLKGATE				(1 << 30)
+#define	TIMROT_ROTCTRL_ROTARY_PRESENT			(1 << 29)
+#define	TIMROT_ROTCTRL_TIM3_PRESENT			(1 << 28)
+#define	TIMROT_ROTCTRL_TIM2_PRESENT			(1 << 27)
+#define	TIMROT_ROTCTRL_TIM1_PRESENT			(1 << 26)
+#define	TIMROT_ROTCTRL_TIM0_PRESENT			(1 << 25)
+#define	TIMROT_ROTCTRL_STATE_MASK			(0x7 << 22)
+#define	TIMROT_ROTCTRL_STATE_OFFSET			22
+#define	TIMROT_ROTCTRL_DIVIDER_MASK			(0x3f << 16)
+#define	TIMROT_ROTCTRL_DIVIDER_OFFSET			16
+#define	TIMROT_ROTCTRL_RELATIVE				(1 << 12)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_MASK			(0x3 << 10)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_OFFSET		10
+#define	TIMROT_ROTCTRL_OVERSAMPLE_8X			(0x0 << 10)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_4X			(0x1 << 10)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_2X			(0x2 << 10)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_1X			(0x3 << 10)
+#define	TIMROT_ROTCTRL_POLARITY_B			(1 << 9)
+#define	TIMROT_ROTCTRL_POLARITY_A			(1 << 8)
+#define	TIMROT_ROTCTRL_SELECT_B_MASK			(0xf << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_OFFSET			4
+#define	TIMROT_ROTCTRL_SELECT_B_NEVER_TICK		(0x0 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM0			(0x1 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM1			(0x2 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM2			(0x3 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM3			(0x4 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM4			(0x5 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM5			(0x6 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM6			(0x7 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM7			(0x8 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_ROTARYA			(0x9 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_ROTARYB			(0xa << 4)
+#define	TIMROT_ROTCTRL_SELECT_A_MASK			0xf
+#define	TIMROT_ROTCTRL_SELECT_A_OFFSET			0
+#define	TIMROT_ROTCTRL_SELECT_A_NEVER_TICK		0x0
+#define	TIMROT_ROTCTRL_SELECT_A_PWM0			0x1
+#define	TIMROT_ROTCTRL_SELECT_A_PWM1			0x2
+#define	TIMROT_ROTCTRL_SELECT_A_PWM2			0x3
+#define	TIMROT_ROTCTRL_SELECT_A_PWM3			0x4
+#define	TIMROT_ROTCTRL_SELECT_A_PWM4			0x5
+#define	TIMROT_ROTCTRL_SELECT_A_PWM5			0x6
+#define	TIMROT_ROTCTRL_SELECT_A_PWM6			0x7
+#define	TIMROT_ROTCTRL_SELECT_A_PWM7			0x8
+#define	TIMROT_ROTCTRL_SELECT_A_ROTARYA			0x9
+#define	TIMROT_ROTCTRL_SELECT_A_ROTARYB			0xa
+
+#define	TIMROT_ROTCOUNT_UPDOWN_MASK			0xffff
+#define	TIMROT_ROTCOUNT_UPDOWN_OFFSET			0
+
+#define	TIMROT_TIMCTRLn_IRQ				(1 << 15)
+#define	TIMROT_TIMCTRLn_IRQ_EN				(1 << 14)
+#define	TIMROT_TIMCTRLn_MATCH_MODE			(1 << 11)
+#define	TIMROT_TIMCTRLn_POLARITY			(1 << 8)
+#define	TIMROT_TIMCTRLn_UPDATE				(1 << 7)
+#define	TIMROT_TIMCTRLn_RELOAD				(1 << 6)
+#define	TIMROT_TIMCTRLn_PRESCALE_MASK			(0x3 << 4)
+#define	TIMROT_TIMCTRLn_PRESCALE_OFFSET			4
+#define	TIMROT_TIMCTRLn_PRESCALE_DIV_BY_1		(0x0 << 4)
+#define	TIMROT_TIMCTRLn_PRESCALE_DIV_BY_2		(0x1 << 4)
+#define	TIMROT_TIMCTRLn_PRESCALE_DIV_BY_4		(0x2 << 4)
+#define	TIMROT_TIMCTRLn_PRESCALE_DIV_BY_8		(0x3 << 4)
+#define	TIMROT_TIMCTRLn_SELECT_MASK			0xf
+#define	TIMROT_TIMCTRLn_SELECT_OFFSET			0
+#define	TIMROT_TIMCTRLn_SELECT_NEVER_TICK		0x0
+#define	TIMROT_TIMCTRLn_SELECT_PWM0			0x1
+#define	TIMROT_TIMCTRLn_SELECT_PWM1			0x2
+#define	TIMROT_TIMCTRLn_SELECT_PWM2			0x3
+#define	TIMROT_TIMCTRLn_SELECT_PWM3			0x4
+#define	TIMROT_TIMCTRLn_SELECT_PWM4			0x5
+#define	TIMROT_TIMCTRLn_SELECT_PWM5			0x6
+#define	TIMROT_TIMCTRLn_SELECT_PWM6			0x7
+#define	TIMROT_TIMCTRLn_SELECT_PWM7			0x8
+#define	TIMROT_TIMCTRLn_SELECT_ROTARYA			0x9
+#define	TIMROT_TIMCTRLn_SELECT_ROTARYB			0xa
+#define	TIMROT_TIMCTRLn_SELECT_32KHZ_XTAL		0xb
+#define	TIMROT_TIMCTRLn_SELECT_8KHZ_XTAL		0xc
+#define	TIMROT_TIMCTRLn_SELECT_4KHZ_XTAL		0xd
+#define	TIMROT_TIMCTRLn_SELECT_1KHZ_XTAL		0xe
+#define	TIMROT_TIMCTRLn_SELECT_TICK_ALWAYS		0xf
+
+#define	TIMROT_RUNNING_COUNTn_RUNNING_COUNT_MASK	0xffffffff
+#define	TIMROT_RUNNING_COUNTn_RUNNING_COUNT_OFFSET	0
+
+#define	TIMROT_FIXED_COUNTn_FIXED_COUNT_MASK		0xffffffff
+#define	TIMROT_FIXED_COUNTn_FIXED_COUNT_OFFSET		0
+
+#define	TIMROT_MATCH_COUNTn_MATCH_COUNT_MASK		0xffffffff
+#define	TIMROT_MATCH_COUNTn_MATCH_COUNT_OFFSET		0
+
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_MASK		(0xf << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_OFFSET		16
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_NEVER_TICK		(0x0 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM0		(0x1 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM1		(0x2 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM2		(0x3 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM3		(0x4 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM4		(0x5 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM5		(0x6 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM6		(0x7 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM7		(0x8 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_ROTARYA		(0x9 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_ROTARYB		(0xa << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_32KHZ_XTAL		(0xb << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_8KHZ_XTAL		(0xc << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_4KHZ_XTAL		(0xd << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_1KHZ_XTAL		(0xe << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_TICK_ALWAYS		(0xf << 16)
+#define	TIMROT_TIMCTRL3_DUTY_CYCLE			(1 << 9)
+
+#define	TIMROT_VERSION_MAJOR_MASK			(0xff << 24)
+#define	TIMROT_VERSION_MAJOR_OFFSET			24
+#define	TIMROT_VERSION_MINOR_MASK			(0xff << 16)
+#define	TIMROT_VERSION_MINOR_OFFSET			16
+#define	TIMROT_VERSION_STEP_MASK			0xffff
+#define	TIMROT_VERSION_STEP_OFFSET			0
+
+#endif /* __MX28_REGS_TIMROT_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/sys_proto.h b/arch/arm/include/asm/arch-mx28/sys_proto.h
new file mode 100644
index 0000000..a262c05
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/sys_proto.h
@@ -0,0 +1,30 @@
+/*
+ * Freescale i.MX28 MX28 specific functions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __MX28_H__
+#define __MX28_H__
+
+int mx28_reset_block(struct mx28_register *reg);
+int mx28_wait_mask_set(struct mx28_register *reg, uint32_t mask, int timeout);
+int mx28_wait_mask_clr(struct mx28_register *reg, uint32_t mask, int timeout);
+
+#endif	/* __MX28_H__ */
-- 
1.7.6.3

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

* [U-Boot] [PATCH 01/15 V3] iMX28: Initial support for iMX28 CPU
  2011-10-13 18:14         ` Marek Vasut
  2011-10-13 20:45           ` Wolfgang Denk
@ 2011-10-14  7:51           ` Stefano Babic
  2011-10-14  7:59             ` Marek Vasut
  1 sibling, 1 reply; 116+ messages in thread
From: Stefano Babic @ 2011-10-14  7:51 UTC (permalink / raw)
  To: u-boot

On 10/13/2011 08:14 PM, Marek Vasut wrote:
> 
> Hi Stefano,
> 
> the patch is big and will need approval to be let into ML. Removing the space in 
> char * const argv[] shall do the trick, can you please do that by hand ?

I have absolutely no intention to push patches without beeing reviewed
by ML, but I would like to prepare a branch with all your M28 patches to
check consistency with the rest of code.

Running checkpatch on your patches I see a lot of issues, and not only a
couple of them.

For example,

WARNING: line over 80 characters
#632: FILE: arch/arm/cpu/arm926ejs/mx28/mx28.c:150:
+int do_mx28_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char *
const argv[])

WARNING: line over 80 characters
#5415: FILE: arch/arm/include/asm/arch-mx28/iomux-mx28.h:23:
+ *
BANK    PIN     MUX

WARNING: line over 80 characters
#5418: FILE: arch/arm/include/asm/arch-mx28/iomux-mx28.h:26:
+#define MX28_PAD_GPMI_D00__GPMI_D0
MXS_IOMUX_PAD_NAKED(0,  0, PAD_MUXSEL_0)

Running checkpatch on all your patches I get 488 warnings. Can you check
and fix them ?

Stefano


-- 
=====================================================================
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de
=====================================================================

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

* [U-Boot] [PATCH 01/15 V3] iMX28: Initial support for iMX28 CPU
  2011-10-14  7:51           ` Stefano Babic
@ 2011-10-14  7:59             ` Marek Vasut
  2011-10-14 21:00               ` Wolfgang Denk
  0 siblings, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-10-14  7:59 UTC (permalink / raw)
  To: u-boot

On Friday, October 14, 2011 09:51:22 AM Stefano Babic wrote:
> On 10/13/2011 08:14 PM, Marek Vasut wrote:
> > Hi Stefano,
> > 
> > the patch is big and will need approval to be let into ML. Removing the
> > space in char * const argv[] shall do the trick, can you please do that
> > by hand ?
> 
> I have absolutely no intention to push patches without beeing reviewed
> by ML, but I would like to prepare a branch with all your M28 patches to
> check consistency with the rest of code.
> 
> Running checkpatch on your patches I see a lot of issues, and not only a
> couple of them.
> 
> For example,
> 
> WARNING: line over 80 characters
> #632: FILE: arch/arm/cpu/arm926ejs/mx28/mx28.c:150:
> +int do_mx28_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char *
> const argv[])
> 
> WARNING: line over 80 characters
> #5415: FILE: arch/arm/include/asm/arch-mx28/iomux-mx28.h:23:
> + *
> BANK    PIN     MUX
> 
> WARNING: line over 80 characters
> #5418: FILE: arch/arm/include/asm/arch-mx28/iomux-mx28.h:26:
> +#define MX28_PAD_GPMI_D00__GPMI_D0
> MXS_IOMUX_PAD_NAKED(0,  0, PAD_MUXSEL_0)
> 
> Running checkpatch on all your patches I get 488 warnings. Can you check
> and fix them ?
> 
> Stefano

Stefano,

those iomux-mx28.h issues were already explained. It's a file taken from linux 
kernel with no modifications, that's why the issues. And if you take a look 
inside, fixing it would make it unreadable.

Cheers

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

* [U-Boot] [PATCH 14/15 V3] M28: Add MMC SPL
  2011-09-30  9:40   ` [U-Boot] [PATCH 14/15 V2] " Marek Vasut
@ 2011-10-14 12:09     ` Marek Vasut
  0 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-10-14 12:09 UTC (permalink / raw)
  To: u-boot

This patch adds SPL code for the M28 board.

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Andy Fleming <afleming@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 board/denx/m28evk/Makefile       |    8 +
 board/denx/m28evk/m28_init.h     |   41 ++
 board/denx/m28evk/mem_init.c     |  213 +++++++++
 board/denx/m28evk/mmc_boot.c     |  274 ++++++++++++
 board/denx/m28evk/power_init.c   |  913 ++++++++++++++++++++++++++++++++++++++
 board/denx/m28evk/start.S        |  396 +++++++++++++++++
 board/denx/m28evk/u-boot-spl.lds |   87 ++++
 board/denx/m28evk/u-boot.bd      |   14 +
 include/configs/m28evk.h         |    8 +
 9 files changed, 1954 insertions(+), 0 deletions(-)
 create mode 100644 board/denx/m28evk/m28_init.h
 create mode 100644 board/denx/m28evk/mem_init.c
 create mode 100644 board/denx/m28evk/mmc_boot.c
 create mode 100644 board/denx/m28evk/power_init.c
 create mode 100644 board/denx/m28evk/start.S
 create mode 100644 board/denx/m28evk/u-boot-spl.lds
 create mode 100644 board/denx/m28evk/u-boot.bd

V2: Make waiting for powerswitch to be pressed configurable
V3: Squash checkpatch warning

diff --git a/board/denx/m28evk/Makefile b/board/denx/m28evk/Makefile
index 4037199..953143a 100644
--- a/board/denx/m28evk/Makefile
+++ b/board/denx/m28evk/Makefile
@@ -25,7 +25,13 @@ include $(TOPDIR)/config.mk
 
 LIB	= $(obj)lib$(BOARD).o
 
+ifndef	CONFIG_SPL_BUILD
 COBJS	:= m28evk.o
+endif
+
+ifdef	CONFIG_SPL_BUILD
+COBJS	:= mem_init.o mmc_boot.o power_init.o
+endif
 
 SRCS	:= $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS))
@@ -33,6 +39,8 @@ OBJS	:= $(addprefix $(obj),$(COBJS))
 $(LIB):	$(obj).depend $(OBJS)
 	$(call cmd_link_o_target, $(OBJS))
 
+all:	$(ALL)
+
 clean:
 	rm -f $(OBJS)
 
diff --git a/board/denx/m28evk/m28_init.h b/board/denx/m28evk/m28_init.h
new file mode 100644
index 0000000..98d3631
--- /dev/null
+++ b/board/denx/m28evk/m28_init.h
@@ -0,0 +1,41 @@
+/*
+ * Freescale i.MX28 SPL functions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef	__M28_INIT_H__
+#define	__M28_INIT_H__
+
+void early_delay(int delay);
+
+void mx28_power_init(void);
+
+#ifdef	CONFIG_SPL_MX28_PSWITCH_WAIT
+void mx28_power_wait_pswitch(void);
+#else
+static inline void mx28_power_wait_pswitch(void) { }
+#endif
+
+void mx28_mem_init(void);
+
+#endif	/* __M28_INIT_H__ */
diff --git a/board/denx/m28evk/mem_init.c b/board/denx/m28evk/mem_init.c
new file mode 100644
index 0000000..066fe0d
--- /dev/null
+++ b/board/denx/m28evk/mem_init.c
@@ -0,0 +1,213 @@
+/*
+ * Freescale i.MX28 RAM init
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/io.h>
+#include <asm/arch/iomux-mx28.h>
+#include <asm/arch/imx-regs.h>
+
+#include "m28_init.h"
+
+uint32_t dram_vals[] = {
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000100, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00010101, 0x01010101, 0x000f0f01, 0x0f02020a,
+	0x00000000, 0x00010101, 0x00000100, 0x00000100, 0x00000000,
+	0x00000002, 0x01010000, 0x05060302, 0x06005003, 0x0a0000c8,
+	0x02009c40, 0x0000030c, 0x0036a609, 0x031a0612, 0x02030202,
+	0x00c8001c, 0x00000000, 0x00000000, 0x00012100, 0xffff0303,
+	0x00012100, 0xffff0303, 0x00012100, 0xffff0303, 0x00012100,
+	0xffff0303, 0x00000003, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000612, 0x01000F02, 0x06120612, 0x00000200,
+	0x00020007, 0xf5014b27, 0xf5014b27, 0xf5014b27, 0xf5014b27,
+	0x07000300, 0x07000300, 0x07000300, 0x07000300, 0x00000006,
+	0x00000000, 0x00000000, 0x01000000, 0x01020408, 0x08040201,
+	0x000f1133, 0x00000000, 0x00001f04, 0x00001f04, 0x00001f04,
+	0x00001f04, 0x00001f04, 0x00001f04, 0x00001f04, 0x00001f04,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00010000, 0x00020304, 0x00000004,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x01010000, 0x01000000, 0x03030000, 0x00010303,
+	0x01020202, 0x00000000, 0x02040303, 0x21002103, 0x00061200,
+	0x06120612, 0x04320432, 0x04320432, 0x00040004, 0x00040004,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00010001
+};
+
+void init_m28_200mhz_ddr2(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dram_vals); i++)
+		writel(dram_vals[i], MXS_DRAM_BASE + (4 * i));
+}
+
+void mx28_mem_init_clock(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/* Gate EMI clock */
+	writel(CLKCTRL_FRAC0_CLKGATEEMI,
+		&clkctrl_regs->hw_clkctrl_frac0_set);
+
+	/* EMI = 205MHz */
+	writel(CLKCTRL_FRAC0_EMIFRAC_MASK,
+		&clkctrl_regs->hw_clkctrl_frac0_set);
+	writel((0x2a << CLKCTRL_FRAC0_EMIFRAC_OFFSET) &
+		CLKCTRL_FRAC0_EMIFRAC_MASK,
+		&clkctrl_regs->hw_clkctrl_frac0_clr);
+
+	/* Ungate EMI clock */
+	writel(CLKCTRL_FRAC0_CLKGATEEMI,
+		&clkctrl_regs->hw_clkctrl_frac0_clr);
+
+	early_delay(11000);
+
+	writel((2 << CLKCTRL_EMI_DIV_EMI_OFFSET) |
+		(1 << CLKCTRL_EMI_DIV_XTAL_OFFSET),
+		&clkctrl_regs->hw_clkctrl_emi);
+
+	/* Unbypass EMI */
+	writel(CLKCTRL_CLKSEQ_BYPASS_EMI,
+		&clkctrl_regs->hw_clkctrl_clkseq_clr);
+
+	early_delay(10000);
+}
+
+void mx28_mem_setup_cpu_and_hbus(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/* CPU = 454MHz and ungate CPU clock */
+	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_frac0,
+		CLKCTRL_FRAC0_CPUFRAC_MASK | CLKCTRL_FRAC0_CLKGATECPU,
+		19 << CLKCTRL_FRAC0_CPUFRAC_OFFSET);
+
+	/* Set CPU bypass */
+	writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
+		&clkctrl_regs->hw_clkctrl_clkseq_set);
+
+	/* HBUS = 151MHz */
+	writel(CLKCTRL_HBUS_DIV_MASK, &clkctrl_regs->hw_clkctrl_hbus_set);
+	writel(((~3) << CLKCTRL_HBUS_DIV_OFFSET) & CLKCTRL_HBUS_DIV_MASK,
+		&clkctrl_regs->hw_clkctrl_hbus_clr);
+
+	early_delay(10000);
+
+	/* CPU clock divider = 1 */
+	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_cpu,
+			CLKCTRL_CPU_DIV_CPU_MASK, 1);
+
+	/* Disable CPU bypass */
+	writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
+		&clkctrl_regs->hw_clkctrl_clkseq_clr);
+}
+
+void mx28_mem_setup_vdda(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	writel((0xc << POWER_VDDACTRL_TRG_OFFSET) |
+		(0x7 << POWER_VDDACTRL_BO_OFFSET_OFFSET) |
+		POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW,
+		&power_regs->hw_power_vddactrl);
+}
+
+void mx28_mem_setup_vddd(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	writel((0x1c << POWER_VDDDCTRL_TRG_OFFSET) |
+		(0x7 << POWER_VDDDCTRL_BO_OFFSET_OFFSET) |
+		POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW,
+		&power_regs->hw_power_vdddctrl);
+}
+
+void mx28_mem_init(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	struct mx28_pinctrl_regs *pinctrl_regs =
+		(struct mx28_pinctrl_regs *)MXS_PINCTRL_BASE;
+
+	/* Set DDR2 mode */
+	writel(PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2,
+		&pinctrl_regs->hw_pinctrl_emi_ds_ctrl_set);
+
+	/* Power up PLL0 */
+	writel(CLKCTRL_PLL0CTRL0_POWER,
+		&clkctrl_regs->hw_clkctrl_pll0ctrl0_set);
+
+	early_delay(11000);
+
+	mx28_mem_init_clock();
+
+	mx28_mem_setup_vdda();
+
+	/*
+	 * Configure the DRAM registers
+	 */
+
+	/* Clear START bit from DRAM_CTL16 */
+	clrbits_le32(MXS_DRAM_BASE + 0x40, 1);
+
+	init_m28_200mhz_ddr2();
+
+	/* Clear SREFRESH bit from DRAM_CTL17 */
+	clrbits_le32(MXS_DRAM_BASE + 0x44, 1);
+
+	/* Set START bit in DRAM_CTL16 */
+	setbits_le32(MXS_DRAM_BASE + 0x40, 1);
+
+	/* Wait for bit 20 (DRAM init complete) in DRAM_CTL58 */
+	while (!(readl(MXS_DRAM_BASE + 0xe8) & (1 << 20)))
+		;
+
+	mx28_mem_setup_vddd();
+
+	early_delay(10000);
+
+	mx28_mem_setup_cpu_and_hbus();
+}
diff --git a/board/denx/m28evk/mmc_boot.c b/board/denx/m28evk/mmc_boot.c
new file mode 100644
index 0000000..e2060ee
--- /dev/null
+++ b/board/denx/m28evk/mmc_boot.c
@@ -0,0 +1,274 @@
+/*
+ * Freescale i.MX28 Boot setup
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/io.h>
+#include <asm/arch/iomux-mx28.h>
+
+#include "m28_init.h"
+
+/*
+ * This delay function is intended to be used only in early stage of boot, where
+ * clock are not set up yet. The timer used here is reset on every boot and
+ * takes a few seconds to roll. The boot doesn't take that long, so to keep the
+ * code simple, it doesn't take rolling into consideration.
+ */
+#define	HW_DIGCTRL_MICROSECONDS	0x8001c0c0
+void early_delay(int delay)
+{
+	uint32_t st = readl(HW_DIGCTRL_MICROSECONDS);
+	st += delay;
+	while (st > readl(HW_DIGCTRL_MICROSECONDS))
+		;
+}
+
+#define	MUX_CONFIG_LED	(MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL)
+#define	MUX_CONFIG_LCD	(MXS_PAD_3V3 | MXS_PAD_4MA)
+#define	MUX_CONFIG_TSC	(MXS_PAD_3V3 | MXS_PAD_8MA | MXS_PAD_PULLUP)
+#define	MUX_CONFIG_SSP0	(MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_PULLUP)
+#define	MUX_CONFIG_SSP2	(MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_PULLUP)
+#define	MUX_CONFIG_GPMI	(MXS_PAD_1V8 | MXS_PAD_4MA | MXS_PAD_NOPULL)
+#define	MUX_CONFIG_ENET	(MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_PULLUP)
+#define	MUX_CONFIG_EMI	(MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_NOPULL)
+
+const iomux_cfg_t iomux_setup[] = {
+	/* LED */
+	MX28_PAD_ENET0_RXD3__GPIO_4_10 | MUX_CONFIG_LED,
+
+	/* framebuffer */
+	MX28_PAD_LCD_D00__LCD_D0 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D01__LCD_D1 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D02__LCD_D2 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D03__LCD_D3 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D04__LCD_D4 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D05__LCD_D5 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D06__LCD_D6 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D07__LCD_D7 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D08__LCD_D8 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D09__LCD_D9 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D10__LCD_D10 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D11__LCD_D11 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D12__LCD_D12 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D13__LCD_D13 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D14__LCD_D14 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D15__LCD_D15 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D16__LCD_D16 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D17__LCD_D17 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D18__LCD_D18 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D19__LCD_D19 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D20__LCD_D20 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D21__LCD_D21 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D22__LCD_D22 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D23__LCD_D23 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_RD_E__LCD_VSYNC | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_WR_RWN__LCD_HSYNC | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_RS__LCD_DOTCLK | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_CS__LCD_CS | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_VSYNC__LCD_VSYNC | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_HSYNC__LCD_HSYNC | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_DOTCLK__LCD_DOTCLK | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_ENABLE__GPIO_1_31 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_RESET__GPIO_3_30 | MUX_CONFIG_LCD,
+	MX28_PAD_PWM0__PWM_0 | MUX_CONFIG_LCD,
+
+	/* UART1 */
+	MX28_PAD_AUART0_CTS__DUART_RX,
+	MX28_PAD_AUART0_RTS__DUART_TX,
+	MX28_PAD_AUART0_TX__DUART_RTS,
+	MX28_PAD_AUART0_RX__DUART_CTS,
+
+	/* UART2 */
+	MX28_PAD_AUART1_RX__AUART1_RX,
+	MX28_PAD_AUART1_TX__AUART1_TX,
+	MX28_PAD_AUART1_RTS__AUART1_RTS,
+	MX28_PAD_AUART1_CTS__AUART1_CTS,
+
+	/* CAN */
+	MX28_PAD_GPMI_RDY2__CAN0_TX,
+	MX28_PAD_GPMI_RDY3__CAN0_RX,
+
+	/* I2C */
+	MX28_PAD_I2C0_SCL__I2C0_SCL,
+	MX28_PAD_I2C0_SDA__I2C0_SDA,
+
+	/* TSC2007 */
+	MX28_PAD_SAIF0_MCLK__GPIO_3_20 | MUX_CONFIG_TSC,
+
+	/* MMC0 */
+	MX28_PAD_SSP0_DATA0__SSP0_D0 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA1__SSP0_D1 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA2__SSP0_D2 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA3__SSP0_D3 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA4__SSP0_D4 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA5__SSP0_D5 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA6__SSP0_D6 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA7__SSP0_D7 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_CMD__SSP0_CMD | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT |
+		(MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_NOPULL),
+	MX28_PAD_SSP0_SCK__SSP0_SCK |
+		(MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_NOPULL),
+	MX28_PAD_PWM3__GPIO_3_28 | MUX_CONFIG_SSP0,	/* Power .. FIXME */
+	MX28_PAD_AUART2_CTS__GPIO_3_10,	/* WP ... FIXME */
+
+	/* GPMI NAND */
+	MX28_PAD_GPMI_D00__GPMI_D0 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D01__GPMI_D1 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D02__GPMI_D2 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D03__GPMI_D3 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D04__GPMI_D4 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D05__GPMI_D5 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D06__GPMI_D6 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D07__GPMI_D7 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_CE0N__GPMI_CE0N | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_RDY0__GPMI_READY0 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_RDN__GPMI_RDN |
+		(MXS_PAD_1V8 | MXS_PAD_8MA | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_WRN__GPMI_WRN | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_ALE__GPMI_ALE | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_CLE__GPMI_CLE | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_RESETN__GPMI_RESETN | MUX_CONFIG_GPMI,
+
+	/* FEC Ethernet */
+	MX28_PAD_ENET0_MDC__ENET0_MDC | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_MDIO__ENET0_MDIO | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_RX_EN__ENET0_RX_EN | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_TX_EN__ENET0_TX_EN | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_RXD0__ENET0_RXD0 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_RXD1__ENET0_RXD1 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_TXD0__ENET0_TXD0 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_TXD1__ENET0_TXD1 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET_CLK__CLKCTRL_ENET | MUX_CONFIG_ENET,
+
+	MX28_PAD_ENET0_COL__ENET1_TX_EN | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_CRS__ENET1_RX_EN | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_RXD2__ENET1_RXD0 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_RXD3__ENET1_RXD1 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_TXD2__ENET1_TXD0 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_TXD3__ENET1_TXD1 | MUX_CONFIG_ENET,
+
+	/* I2C */
+	MX28_PAD_I2C0_SCL__I2C0_SCL,
+	MX28_PAD_I2C0_SDA__I2C0_SDA,
+
+	/* EMI */
+	MX28_PAD_EMI_D00__EMI_DATA0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D01__EMI_DATA1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D02__EMI_DATA2 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D03__EMI_DATA3 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D04__EMI_DATA4 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D05__EMI_DATA5 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D06__EMI_DATA6 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D07__EMI_DATA7 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D08__EMI_DATA8 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D09__EMI_DATA9 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D10__EMI_DATA10 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D11__EMI_DATA11 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D12__EMI_DATA12 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D13__EMI_DATA13 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D14__EMI_DATA14 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D15__EMI_DATA15 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_ODT0__EMI_ODT0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DQM0__EMI_DQM0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_ODT1__EMI_ODT1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DQM1__EMI_DQM1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DDR_OPEN_FB__EMI_DDR_OPEN_FEEDBACK | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_CLK__EMI_CLK | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DQS0__EMI_DQS0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DQS1__EMI_DQS1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DDR_OPEN__EMI_DDR_OPEN | MUX_CONFIG_EMI,
+
+	MX28_PAD_EMI_A00__EMI_ADDR0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A01__EMI_ADDR1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A02__EMI_ADDR2 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A03__EMI_ADDR3 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A04__EMI_ADDR4 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A05__EMI_ADDR5 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A06__EMI_ADDR6 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A07__EMI_ADDR7 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A08__EMI_ADDR8 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A09__EMI_ADDR9 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A10__EMI_ADDR10 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A11__EMI_ADDR11 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A12__EMI_ADDR12 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A13__EMI_ADDR13 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A14__EMI_ADDR14 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_BA0__EMI_BA0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_BA1__EMI_BA1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_BA2__EMI_BA2 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_CASN__EMI_CASN | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_RASN__EMI_RASN | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_WEN__EMI_WEN | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_CE0N__EMI_CE0N | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_CE1N__EMI_CE1N | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_CKE__EMI_CKE | MUX_CONFIG_EMI,
+
+	/* SPI2 (for flash) */
+	MX28_PAD_SSP2_SCK__SSP2_SCK | MUX_CONFIG_SSP2,
+	MX28_PAD_SSP2_MOSI__SSP2_CMD | MUX_CONFIG_SSP2,
+	MX28_PAD_SSP2_MISO__SSP2_D0 | MUX_CONFIG_SSP2,
+	MX28_PAD_SSP2_SS0__SSP2_D3 |
+		(MXS_PAD_3V3 | MXS_PAD_8MA | MXS_PAD_PULLUP),
+};
+
+void board_init_ll(void)
+{
+	mxs_iomux_setup_multiple_pads(iomux_setup, ARRAY_SIZE(iomux_setup));
+	mx28_power_init();
+	mx28_mem_init();
+	mx28_power_wait_pswitch();
+}
+
+/* Support aparatus */
+inline void board_init_f(unsigned long bootflag)
+{
+	for (;;)
+		;
+}
+
+inline void board_init_r(gd_t *id, ulong dest_addr)
+{
+	for (;;)
+		;
+}
+
+inline int printf(const char *fmt, ...)
+{
+	return 0;
+}
+
+inline void __coloured_LED_init(void) {}
+inline void __red_LED_on(void) {}
+void coloured_LED_init(void)
+	__attribute__((weak, alias("__coloured_LED_init")));
+void red_LED_on(void)
+	__attribute__((weak, alias("__red_LED_on")));
+void hang(void) __attribute__ ((noreturn));
+void hang(void)
+{
+	for (;;)
+		;
+}
diff --git a/board/denx/m28evk/power_init.c b/board/denx/m28evk/power_init.c
new file mode 100644
index 0000000..27322b4
--- /dev/null
+++ b/board/denx/m28evk/power_init.c
@@ -0,0 +1,913 @@
+/*
+ * Freescale i.MX28 Boot PMIC init
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+
+#include "m28_init.h"
+
+void mx28_power_clock2xtal(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/* Set XTAL as CPU reference clock */
+	writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
+		&clkctrl_regs->hw_clkctrl_clkseq_set);
+}
+
+void mx28_power_clock2pll(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	writel(CLKCTRL_PLL0CTRL0_POWER,
+		&clkctrl_regs->hw_clkctrl_pll0ctrl0_set);
+	early_delay(100);
+	writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
+		&clkctrl_regs->hw_clkctrl_clkseq_clr);
+}
+
+void mx28_power_clear_auto_restart(void)
+{
+	struct mx28_rtc_regs *rtc_regs =
+		(struct mx28_rtc_regs *)MXS_RTC_BASE;
+
+	writel(RTC_CTRL_SFTRST, &rtc_regs->hw_rtc_ctrl_clr);
+	while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_SFTRST)
+		;
+
+	writel(RTC_CTRL_CLKGATE, &rtc_regs->hw_rtc_ctrl_clr);
+	while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_CLKGATE)
+		;
+
+	/*
+	 * Due to the hardware design bug of mx28 EVK-A
+	 * we need to set the AUTO_RESTART bit.
+	 */
+	if (readl(&rtc_regs->hw_rtc_persistent0) & RTC_PERSISTENT0_AUTO_RESTART)
+		return;
+
+	while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK)
+		;
+
+	setbits_le32(&rtc_regs->hw_rtc_persistent0,
+			RTC_PERSISTENT0_AUTO_RESTART);
+	writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_set);
+	writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_clr);
+	while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK)
+		;
+	while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_STALE_REGS_MASK)
+		;
+}
+
+void mx28_power_set_linreg(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/* Set linear regulator 25mV below switching converter */
+	clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+			POWER_VDDDCTRL_LINREG_OFFSET_MASK,
+			POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
+
+	clrsetbits_le32(&power_regs->hw_power_vddactrl,
+			POWER_VDDACTRL_LINREG_OFFSET_MASK,
+			POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW);
+
+	clrsetbits_le32(&power_regs->hw_power_vddioctrl,
+			POWER_VDDIOCTRL_LINREG_OFFSET_MASK,
+			POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW);
+}
+
+void mx28_power_setup_5v_detect(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/* Start 5V detection */
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+			POWER_5VCTRL_VBUSVALID_TRSH_MASK,
+			POWER_5VCTRL_VBUSVALID_TRSH_4V4 |
+			POWER_5VCTRL_PWRUP_VBUS_CMPS);
+}
+
+void mx28_src_power_init(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/* Improve efficieny and reduce transient ripple */
+	writel(POWER_LOOPCTRL_TOGGLE_DIF | POWER_LOOPCTRL_EN_CM_HYST |
+		POWER_LOOPCTRL_EN_DF_HYST, &power_regs->hw_power_loopctrl_set);
+
+	clrsetbits_le32(&power_regs->hw_power_dclimits,
+			POWER_DCLIMITS_POSLIMIT_BUCK_MASK,
+			0x30 << POWER_DCLIMITS_POSLIMIT_BUCK_OFFSET);
+
+	setbits_le32(&power_regs->hw_power_battmonitor,
+			POWER_BATTMONITOR_EN_BATADJ);
+
+	/* Increase the RCSCALE level for quick DCDC response to dynamic load */
+	clrsetbits_le32(&power_regs->hw_power_loopctrl,
+			POWER_LOOPCTRL_EN_RCSCALE_MASK,
+			POWER_LOOPCTRL_RCSCALE_THRESH |
+			POWER_LOOPCTRL_EN_RCSCALE_8X);
+
+	clrsetbits_le32(&power_regs->hw_power_minpwr,
+			POWER_MINPWR_HALFFETS, POWER_MINPWR_DOUBLE_FETS);
+
+	/* 5V to battery handoff ... FIXME */
+	setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
+	early_delay(30);
+	clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
+}
+
+void mx28_power_init_4p2_params(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/* Setup 4P2 parameters */
+	clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
+		POWER_DCDC4P2_CMPTRIP_MASK | POWER_DCDC4P2_TRG_MASK,
+		POWER_DCDC4P2_TRG_4V2 | (31 << POWER_DCDC4P2_CMPTRIP_OFFSET));
+
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+		POWER_5VCTRL_HEADROOM_ADJ_MASK,
+		0x4 << POWER_5VCTRL_HEADROOM_ADJ_OFFSET);
+
+	clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
+		POWER_DCDC4P2_DROPOUT_CTRL_MASK,
+		POWER_DCDC4P2_DROPOUT_CTRL_100MV |
+		POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL);
+
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+		POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
+		0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
+}
+
+void mx28_enable_4p2_dcdc_input(int xfer)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp, vbus_thresh, vbus_5vdetect, pwd_bo;
+	uint32_t prev_5v_brnout, prev_5v_droop;
+
+	prev_5v_brnout = readl(&power_regs->hw_power_5vctrl) &
+				POWER_5VCTRL_PWDN_5VBRNOUT;
+	prev_5v_droop = readl(&power_regs->hw_power_ctrl) &
+				POWER_CTRL_ENIRQ_VDD5V_DROOP;
+
+	clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_PWDN_5VBRNOUT);
+	writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
+		&power_regs->hw_power_reset);
+
+	clrbits_le32(&power_regs->hw_power_ctrl, POWER_CTRL_ENIRQ_VDD5V_DROOP);
+
+	if (xfer && (readl(&power_regs->hw_power_5vctrl) &
+			POWER_5VCTRL_ENABLE_DCDC)) {
+		return;
+	}
+
+	/*
+	 * Recording orignal values that will be modified temporarlily
+	 * to handle a chip bug. See chip errata for CQ ENGR00115837
+	 */
+	tmp = readl(&power_regs->hw_power_5vctrl);
+	vbus_thresh = tmp & POWER_5VCTRL_VBUSVALID_TRSH_MASK;
+	vbus_5vdetect = tmp & POWER_5VCTRL_VBUSVALID_5VDETECT;
+
+	pwd_bo = readl(&power_regs->hw_power_minpwr) & POWER_MINPWR_PWD_BO;
+
+	/*
+	 * Disable mechanisms that get erroneously tripped by when setting
+	 * the DCDC4P2 EN_DCDC
+	 */
+	clrbits_le32(&power_regs->hw_power_5vctrl,
+		POWER_5VCTRL_VBUSVALID_5VDETECT |
+		POWER_5VCTRL_VBUSVALID_TRSH_MASK);
+
+	writel(POWER_MINPWR_PWD_BO, &power_regs->hw_power_minpwr_set);
+
+	if (xfer) {
+		setbits_le32(&power_regs->hw_power_5vctrl,
+				POWER_5VCTRL_DCDC_XFER);
+		early_delay(20);
+		clrbits_le32(&power_regs->hw_power_5vctrl,
+				POWER_5VCTRL_DCDC_XFER);
+
+		setbits_le32(&power_regs->hw_power_5vctrl,
+				POWER_5VCTRL_ENABLE_DCDC);
+	} else {
+		setbits_le32(&power_regs->hw_power_dcdc4p2,
+				POWER_DCDC4P2_ENABLE_DCDC);
+	}
+
+	early_delay(25);
+
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+			POWER_5VCTRL_VBUSVALID_TRSH_MASK, vbus_thresh);
+
+	if (vbus_5vdetect)
+		writel(vbus_5vdetect, &power_regs->hw_power_5vctrl_set);
+
+	if (!pwd_bo)
+		clrbits_le32(&power_regs->hw_power_minpwr, POWER_MINPWR_PWD_BO);
+
+	while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ)
+		clrbits_le32(&power_regs->hw_power_ctrl,
+				POWER_CTRL_VBUS_VALID_IRQ);
+
+	if (prev_5v_brnout) {
+		writel(POWER_5VCTRL_PWDN_5VBRNOUT,
+			&power_regs->hw_power_5vctrl_set);
+		writel(POWER_RESET_UNLOCK_KEY,
+			&power_regs->hw_power_reset);
+	} else {
+		writel(POWER_5VCTRL_PWDN_5VBRNOUT,
+			&power_regs->hw_power_5vctrl_clr);
+		writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
+			&power_regs->hw_power_reset);
+	}
+
+	while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VDD5V_DROOP_IRQ)
+		clrbits_le32(&power_regs->hw_power_ctrl,
+				POWER_CTRL_VDD5V_DROOP_IRQ);
+
+	if (prev_5v_droop)
+		clrbits_le32(&power_regs->hw_power_ctrl,
+				POWER_CTRL_ENIRQ_VDD5V_DROOP);
+	else
+		setbits_le32(&power_regs->hw_power_ctrl,
+				POWER_CTRL_ENIRQ_VDD5V_DROOP);
+}
+
+void mx28_power_init_4p2_regulator(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp, tmp2;
+
+	setbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_ENABLE_4P2);
+
+	writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_set);
+
+	writel(POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
+		&power_regs->hw_power_5vctrl_clr);
+	clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_TRG_MASK);
+
+	/* Power up the 4p2 rail and logic/control */
+	writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+		&power_regs->hw_power_5vctrl_clr);
+
+	/*
+	 * Start charging up the 4p2 capacitor. We ramp of this charge
+	 * gradually to avoid large inrush current from the 5V cable which can
+	 * cause transients/problems
+	 */
+	mx28_enable_4p2_dcdc_input(0);
+
+	if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) {
+		/*
+		 * If we arrived here, we were unable to recover from mx23 chip
+		 * errata 5837. 4P2 is disabled and sufficient battery power is
+		 * not present. Exiting to not enable DCDC power during 5V
+		 * connected state.
+		 */
+		clrbits_le32(&power_regs->hw_power_dcdc4p2,
+			POWER_DCDC4P2_ENABLE_DCDC);
+		writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+			&power_regs->hw_power_5vctrl_set);
+		hang();
+	}
+
+	/*
+	 * Here we set the 4p2 brownout level to something very close to 4.2V.
+	 * We then check the brownout status. If the brownout status is false,
+	 * the voltage is already close to the target voltage of 4.2V so we
+	 * can go ahead and set the 4P2 current limit to our max target limit.
+	 * If the brownout status is true, we need to ramp us the current limit
+	 * so that we don't cause large inrush current issues. We step up the
+	 * current limit until the brownout status is false or until we've
+	 * reached our maximum defined 4p2 current limit.
+	 */
+	clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
+			POWER_DCDC4P2_BO_MASK,
+			22 << POWER_DCDC4P2_BO_OFFSET);	/* 4.15V */
+
+	if (!(readl(&power_regs->hw_power_sts) & POWER_STS_DCDC_4P2_BO)) {
+		setbits_le32(&power_regs->hw_power_5vctrl,
+			0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
+	} else {
+		tmp = (readl(&power_regs->hw_power_5vctrl) &
+			POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK) >>
+			POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET;
+		while (tmp < 0x3f) {
+			if (!(readl(&power_regs->hw_power_sts) &
+					POWER_STS_DCDC_4P2_BO)) {
+				tmp = readl(&power_regs->hw_power_5vctrl);
+				tmp |= POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK;
+				early_delay(100);
+				writel(tmp, &power_regs->hw_power_5vctrl);
+				break;
+			} else {
+				tmp++;
+				tmp2 = readl(&power_regs->hw_power_5vctrl);
+				tmp2 &= ~POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK;
+				tmp2 |= tmp <<
+					POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET;
+				writel(tmp2, &power_regs->hw_power_5vctrl);
+				early_delay(100);
+			}
+		}
+	}
+
+	clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_BO_MASK);
+	writel(POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+}
+
+void mx28_power_init_dcdc_4p2_source(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	if (!(readl(&power_regs->hw_power_dcdc4p2) &
+		POWER_DCDC4P2_ENABLE_DCDC)) {
+		hang();
+	}
+
+	mx28_enable_4p2_dcdc_input(1);
+
+	if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) {
+		clrbits_le32(&power_regs->hw_power_dcdc4p2,
+			POWER_DCDC4P2_ENABLE_DCDC);
+		writel(POWER_5VCTRL_ENABLE_DCDC,
+			&power_regs->hw_power_5vctrl_clr);
+		writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+			&power_regs->hw_power_5vctrl_set);
+	}
+}
+
+void mx28_power_enable_4p2(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t vdddctrl, vddactrl, vddioctrl;
+	uint32_t tmp;
+
+	vdddctrl = readl(&power_regs->hw_power_vdddctrl);
+	vddactrl = readl(&power_regs->hw_power_vddactrl);
+	vddioctrl = readl(&power_regs->hw_power_vddioctrl);
+
+	setbits_le32(&power_regs->hw_power_vdddctrl,
+		POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG |
+		POWER_VDDDCTRL_PWDN_BRNOUT);
+
+	setbits_le32(&power_regs->hw_power_vddactrl,
+		POWER_VDDACTRL_DISABLE_FET | POWER_VDDACTRL_ENABLE_LINREG |
+		POWER_VDDACTRL_PWDN_BRNOUT);
+
+	setbits_le32(&power_regs->hw_power_vddioctrl,
+		POWER_VDDIOCTRL_DISABLE_FET | POWER_VDDIOCTRL_PWDN_BRNOUT);
+
+	mx28_power_init_4p2_params();
+	mx28_power_init_4p2_regulator();
+
+	/* Shutdown battery (none present) */
+	clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_BO_MASK);
+	writel(POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+	writel(POWER_CTRL_ENIRQ_DCDC4P2_BO, &power_regs->hw_power_ctrl_clr);
+
+	mx28_power_init_dcdc_4p2_source();
+
+	writel(vdddctrl, &power_regs->hw_power_vdddctrl);
+	early_delay(20);
+	writel(vddactrl, &power_regs->hw_power_vddactrl);
+	early_delay(20);
+	writel(vddioctrl, &power_regs->hw_power_vddioctrl);
+
+	/*
+	 * Check if FET is enabled on either powerout and if so,
+	 * disable load.
+	 */
+	tmp = 0;
+	tmp |= !(readl(&power_regs->hw_power_vdddctrl) &
+			POWER_VDDDCTRL_DISABLE_FET);
+	tmp |= !(readl(&power_regs->hw_power_vddactrl) &
+			POWER_VDDACTRL_DISABLE_FET);
+	tmp |= !(readl(&power_regs->hw_power_vddioctrl) &
+			POWER_VDDIOCTRL_DISABLE_FET);
+	if (tmp)
+		writel(POWER_CHARGE_ENABLE_LOAD,
+			&power_regs->hw_power_charge_clr);
+}
+
+void mx28_boot_valid_5v(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/*
+	 * Use VBUSVALID level instead of VDD5V_GT_VDDIO level to trigger a 5V
+	 * disconnect event. FIXME
+	 */
+	writel(POWER_5VCTRL_VBUSVALID_5VDETECT,
+		&power_regs->hw_power_5vctrl_set);
+
+	/* Configure polarity to check for 5V disconnection. */
+	writel(POWER_CTRL_POLARITY_VBUSVALID |
+		POWER_CTRL_POLARITY_VDD5V_GT_VDDIO,
+		&power_regs->hw_power_ctrl_clr);
+
+	writel(POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_VDD5V_GT_VDDIO_IRQ,
+		&power_regs->hw_power_ctrl_clr);
+
+	mx28_power_enable_4p2();
+}
+
+void mx28_powerdown(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	writel(POWER_RESET_UNLOCK_KEY, &power_regs->hw_power_reset);
+	writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
+		&power_regs->hw_power_reset);
+}
+
+void mx28_handle_5v_conflict(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp;
+
+	setbits_le32(&power_regs->hw_power_vddioctrl,
+			POWER_VDDIOCTRL_BO_OFFSET_MASK);
+
+	for (;;) {
+		tmp = readl(&power_regs->hw_power_sts);
+
+		if (tmp & POWER_STS_VDDIO_BO) {
+			mx28_powerdown();
+			break;
+		}
+
+		if (tmp & POWER_STS_VDD5V_GT_VDDIO) {
+			mx28_boot_valid_5v();
+			break;
+		} else {
+			mx28_powerdown();
+			break;
+		}
+	}
+}
+
+int mx28_get_batt_volt(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t volt = readl(&power_regs->hw_power_battmonitor);
+	volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
+	volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
+	volt *= 8;
+	return volt;
+}
+
+int mx28_is_batt_ready(void)
+{
+	return (mx28_get_batt_volt() >= 3600);
+}
+
+void mx28_5v_boot(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/*
+	 * NOTE: In original IMX-Bootlets, this also checks for VBUSVALID,
+	 * but their implementation always returns 1 so we omit it here.
+	 */
+	if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+		mx28_boot_valid_5v();
+		return;
+	}
+
+	early_delay(1000);
+	if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+		mx28_boot_valid_5v();
+		return;
+	}
+
+	mx28_handle_5v_conflict();
+}
+
+void mx28_init_batt_bo(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/* Brownout at 3V */
+	clrsetbits_le32(&power_regs->hw_power_battmonitor,
+		POWER_BATTMONITOR_BRWNOUT_LVL_MASK,
+		15 << POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET);
+
+	writel(POWER_CTRL_BATT_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+	writel(POWER_CTRL_ENIRQ_BATT_BO, &power_regs->hw_power_ctrl_clr);
+}
+
+void mx28_switch_vddd_to_dcdc_source(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+		POWER_VDDDCTRL_LINREG_OFFSET_MASK,
+		POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
+
+	clrbits_le32(&power_regs->hw_power_vdddctrl,
+		POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG |
+		POWER_VDDDCTRL_DISABLE_STEPPING);
+}
+
+int mx28_is_batt_good(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t volt;
+
+	volt = readl(&power_regs->hw_power_battmonitor);
+	volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
+	volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
+	volt *= 8;
+
+	if ((volt >= 2400) && (volt <= 4300))
+		return 1;
+
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+		POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
+		0x3 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
+	writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+		&power_regs->hw_power_5vctrl_clr);
+
+	clrsetbits_le32(&power_regs->hw_power_charge,
+		POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
+		POWER_CHARGE_STOP_ILIMIT_10MA | 0x3);
+
+	writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_clr);
+	writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+		&power_regs->hw_power_5vctrl_clr);
+
+	early_delay(500000);
+
+	volt = readl(&power_regs->hw_power_battmonitor);
+	volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
+	volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
+	volt *= 8;
+
+	if (volt >= 3500)
+		return 0;
+
+	if (volt >= 2400)
+		return 1;
+
+	writel(POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
+		&power_regs->hw_power_charge_clr);
+	writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_set);
+
+	return 0;
+}
+
+void mx28_power_configure_power_source(void)
+{
+	mx28_src_power_init();
+
+	mx28_5v_boot();
+	mx28_power_clock2pll();
+
+	mx28_init_batt_bo();
+	mx28_switch_vddd_to_dcdc_source();
+}
+
+void mx28_enable_output_rail_protection(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
+		POWER_CTRL_VDDIO_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+
+	setbits_le32(&power_regs->hw_power_vdddctrl,
+			POWER_VDDDCTRL_PWDN_BRNOUT);
+
+	setbits_le32(&power_regs->hw_power_vddactrl,
+			POWER_VDDACTRL_PWDN_BRNOUT);
+
+	setbits_le32(&power_regs->hw_power_vddioctrl,
+			POWER_VDDIOCTRL_PWDN_BRNOUT);
+}
+
+int mx28_get_vddio_power_source_off(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp;
+
+	if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+		tmp = readl(&power_regs->hw_power_vddioctrl);
+		if (tmp & POWER_VDDIOCTRL_DISABLE_FET) {
+			if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
+				POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
+				return 1;
+			}
+		}
+
+		if (!(readl(&power_regs->hw_power_5vctrl) &
+			POWER_5VCTRL_ENABLE_DCDC)) {
+			if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
+				POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
+				return 1;
+			}
+		}
+	}
+
+	return 0;
+
+}
+
+int mx28_get_vddd_power_source_off(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp;
+
+	tmp = readl(&power_regs->hw_power_vdddctrl);
+	if (tmp & POWER_VDDDCTRL_DISABLE_FET) {
+		if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
+			POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
+			return 1;
+		}
+	}
+
+	if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+		if (!(readl(&power_regs->hw_power_5vctrl) &
+			POWER_5VCTRL_ENABLE_DCDC)) {
+			return 1;
+		}
+	}
+
+	if (!(tmp & POWER_VDDDCTRL_ENABLE_LINREG)) {
+		if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
+			POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW) {
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+void mx28_power_set_vddio(uint32_t new_target, uint32_t new_brownout)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t cur_target, diff, bo_int = 0;
+	uint32_t powered_by_linreg = 0;
+
+	new_brownout = new_target - new_brownout;
+
+	cur_target = readl(&power_regs->hw_power_vddioctrl);
+	cur_target &= POWER_VDDIOCTRL_TRG_MASK;
+	cur_target *= 50;	/* 50 mV step*/
+	cur_target += 2800;	/* 2800 mV lowest */
+
+	powered_by_linreg = mx28_get_vddio_power_source_off();
+	if (new_target > cur_target) {
+
+		if (powered_by_linreg) {
+			bo_int = readl(&power_regs->hw_power_vddioctrl);
+			clrbits_le32(&power_regs->hw_power_vddioctrl,
+					POWER_CTRL_ENIRQ_VDDIO_BO);
+		}
+
+		setbits_le32(&power_regs->hw_power_vddioctrl,
+				POWER_VDDIOCTRL_BO_OFFSET_MASK);
+		do {
+			if (new_target - cur_target > 100)
+				diff = cur_target + 100;
+			else
+				diff = new_target;
+
+			diff -= 2800;
+			diff /= 50;
+
+			clrsetbits_le32(&power_regs->hw_power_vddioctrl,
+				POWER_VDDIOCTRL_TRG_MASK, diff);
+
+			if (powered_by_linreg)
+				early_delay(1500);
+			else {
+				while (!(readl(&power_regs->hw_power_sts) &
+					POWER_STS_DC_OK))
+					;
+
+			}
+
+			cur_target = readl(&power_regs->hw_power_vddioctrl);
+			cur_target &= POWER_VDDIOCTRL_TRG_MASK;
+			cur_target *= 50;	/* 50 mV step*/
+			cur_target += 2800;	/* 2800 mV lowest */
+		} while (new_target > cur_target);
+
+		if (powered_by_linreg) {
+			writel(POWER_CTRL_VDDIO_BO_IRQ,
+				&power_regs->hw_power_ctrl_clr);
+			if (bo_int & POWER_CTRL_ENIRQ_VDDIO_BO)
+				setbits_le32(&power_regs->hw_power_vddioctrl,
+						POWER_CTRL_ENIRQ_VDDIO_BO);
+		}
+	} else {
+		do {
+			if (cur_target - new_target > 100)
+				diff = cur_target - 100;
+			else
+				diff = new_target;
+
+			diff -= 2800;
+			diff /= 50;
+
+			clrsetbits_le32(&power_regs->hw_power_vddioctrl,
+				POWER_VDDIOCTRL_TRG_MASK, diff);
+
+			if (powered_by_linreg)
+				early_delay(1500);
+			else {
+				while (!(readl(&power_regs->hw_power_sts) &
+					POWER_STS_DC_OK))
+					;
+
+			}
+
+			cur_target = readl(&power_regs->hw_power_vddioctrl);
+			cur_target &= POWER_VDDIOCTRL_TRG_MASK;
+			cur_target *= 50;	/* 50 mV step*/
+			cur_target += 2800;	/* 2800 mV lowest */
+		} while (new_target < cur_target);
+	}
+
+	clrsetbits_le32(&power_regs->hw_power_vddioctrl,
+			POWER_VDDDCTRL_BO_OFFSET_MASK,
+			new_brownout << POWER_VDDDCTRL_BO_OFFSET_OFFSET);
+}
+
+void mx28_power_set_vddd(uint32_t new_target, uint32_t new_brownout)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t cur_target, diff, bo_int = 0;
+	uint32_t powered_by_linreg = 0;
+
+	new_brownout = new_target - new_brownout;
+
+	cur_target = readl(&power_regs->hw_power_vdddctrl);
+	cur_target &= POWER_VDDDCTRL_TRG_MASK;
+	cur_target *= 25;	/* 25 mV step*/
+	cur_target += 800;	/* 800 mV lowest */
+
+	powered_by_linreg = mx28_get_vddd_power_source_off();
+	if (new_target > cur_target) {
+		if (powered_by_linreg) {
+			bo_int = readl(&power_regs->hw_power_vdddctrl);
+			clrbits_le32(&power_regs->hw_power_vdddctrl,
+					POWER_CTRL_ENIRQ_VDDD_BO);
+		}
+
+		setbits_le32(&power_regs->hw_power_vdddctrl,
+				POWER_VDDDCTRL_BO_OFFSET_MASK);
+
+		do {
+			if (new_target - cur_target > 100)
+				diff = cur_target + 100;
+			else
+				diff = new_target;
+
+			diff -= 800;
+			diff /= 25;
+
+			clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+				POWER_VDDDCTRL_TRG_MASK, diff);
+
+			if (powered_by_linreg)
+				early_delay(1500);
+			else {
+				while (!(readl(&power_regs->hw_power_sts) &
+					POWER_STS_DC_OK))
+					;
+
+			}
+
+			cur_target = readl(&power_regs->hw_power_vdddctrl);
+			cur_target &= POWER_VDDDCTRL_TRG_MASK;
+			cur_target *= 25;	/* 25 mV step*/
+			cur_target += 800;	/* 800 mV lowest */
+		} while (new_target > cur_target);
+
+		if (powered_by_linreg) {
+			writel(POWER_CTRL_VDDD_BO_IRQ,
+				&power_regs->hw_power_ctrl_clr);
+			if (bo_int & POWER_CTRL_ENIRQ_VDDD_BO)
+				setbits_le32(&power_regs->hw_power_vdddctrl,
+						POWER_CTRL_ENIRQ_VDDD_BO);
+		}
+	} else {
+		do {
+			if (cur_target - new_target > 100)
+				diff = cur_target - 100;
+			else
+				diff = new_target;
+
+			diff -= 800;
+			diff /= 25;
+
+			clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+					POWER_VDDDCTRL_TRG_MASK, diff);
+
+			if (powered_by_linreg)
+				early_delay(1500);
+			else {
+				while (!(readl(&power_regs->hw_power_sts) &
+					POWER_STS_DC_OK))
+					;
+
+			}
+
+			cur_target = readl(&power_regs->hw_power_vdddctrl);
+			cur_target &= POWER_VDDDCTRL_TRG_MASK;
+			cur_target *= 25;	/* 25 mV step*/
+			cur_target += 800;	/* 800 mV lowest */
+		} while (new_target < cur_target);
+	}
+
+	clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+			POWER_VDDDCTRL_BO_OFFSET_MASK,
+			new_brownout << POWER_VDDDCTRL_BO_OFFSET_OFFSET);
+}
+
+void mx28_power_init(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	mx28_power_clock2xtal();
+	mx28_power_clear_auto_restart();
+	mx28_power_set_linreg();
+	mx28_power_setup_5v_detect();
+	mx28_power_configure_power_source();
+	mx28_enable_output_rail_protection();
+
+	mx28_power_set_vddio(3300, 3150);
+
+	mx28_power_set_vddd(1350, 1200);
+
+	writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
+		POWER_CTRL_VDDIO_BO_IRQ | POWER_CTRL_VDD5V_DROOP_IRQ |
+		POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_BATT_BO_IRQ |
+		POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+
+	writel(POWER_5VCTRL_PWDN_5VBRNOUT, &power_regs->hw_power_5vctrl_set);
+
+	early_delay(1000);
+}
+
+#ifdef	CONFIG_SPL_MX28_PSWITCH_WAIT
+void mx28_power_wait_pswitch(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	while (!(readl(&power_regs->hw_power_sts) & POWER_STS_PSWITCH_MASK))
+		;
+}
+#endif
diff --git a/board/denx/m28evk/start.S b/board/denx/m28evk/start.S
new file mode 100644
index 0000000..cf67599
--- /dev/null
+++ b/board/denx/m28evk/start.S
@@ -0,0 +1,396 @@
+/*
+ *  armboot - Startup Code for ARM926EJS CPU-core
+ *
+ *  Copyright (c) 2003  Texas Instruments
+ *
+ *  ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------
+ *
+ *  Copyright (c) 2001	Marius Groger <mag@sysgo.de>
+ *  Copyright (c) 2002	Alex Zupke <azu@sysgo.de>
+ *  Copyright (c) 2002	Gary Jennejohn <garyj@denx.de>
+ *  Copyright (c) 2003	Richard Woodruff <r-woodruff2@ti.com>
+ *  Copyright (c) 2003	Kshitij <kshitij@ti.com>
+ *  Copyright (c) 2010	Albert Aribaud <albert.u.boot@aribaud.net>
+ *
+ * Change to support call back into iMX28 bootrom
+ * Copyright (c) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <common.h>
+#include <version.h>
+
+#if defined(CONFIG_OMAP1610)
+#include <./configs/omap1510.h>
+#elif defined(CONFIG_OMAP730)
+#include <./configs/omap730.h>
+#endif
+
+/*
+ *************************************************************************
+ *
+ * Jump vector table as in table 3.1 in [1]
+ *
+ *************************************************************************
+ */
+
+
+.globl _start
+_start:
+	b	reset
+#ifdef CONFIG_SPL_BUILD
+/* No exception handlers in preloader */
+	ldr	pc, _hang
+	ldr	pc, _hang
+	ldr	pc, _hang
+	ldr	pc, _hang
+	b	reset
+	ldr	pc, _hang
+	ldr	pc, _hang
+
+_hang:
+	.word	do_hang
+/* pad to 64 byte boundary */
+	.word	0x12345678
+	.word	0x12345678
+	.word	0x12345678
+	.word	0x12345678
+	.word	0x12345678
+	.word	0x12345678
+	.word	0x12345678
+#else
+	ldr	pc, _undefined_instruction
+	ldr	pc, _software_interrupt
+	ldr	pc, _prefetch_abort
+	ldr	pc, _data_abort
+	ldr	pc, _not_used
+	ldr	pc, _irq
+	ldr	pc, _fiq
+
+_undefined_instruction:
+	.word undefined_instruction
+_software_interrupt:
+	.word software_interrupt
+_prefetch_abort:
+	.word prefetch_abort
+_data_abort:
+	.word data_abort
+_not_used:
+	.word not_used
+_irq:
+	.word irq
+_fiq:
+	.word fiq
+
+#endif	/* CONFIG_SPL_BUILD */
+	.balignl 16,0xdeadbeef
+
+
+/*
+ *************************************************************************
+ *
+ * Startup Code (reset vector)
+ *
+ * do important init only if we don't start from memory!
+ * setup Memory and board specific bits prior to relocation.
+ * relocate armboot to ram
+ * setup stack
+ *
+ *************************************************************************
+ */
+
+.globl _TEXT_BASE
+_TEXT_BASE:
+	.word	CONFIG_SYS_TEXT_BASE
+
+/*
+ * These are defined in the board-specific linker script.
+ * Subtracting _start from them lets the linker put their
+ * relative position in the executable instead of leaving
+ * them null.
+ */
+.globl _bss_start_ofs
+_bss_start_ofs:
+	.word __bss_start - _start
+
+.globl _bss_end_ofs
+_bss_end_ofs:
+	.word __bss_end__ - _start
+
+.globl _end_ofs
+_end_ofs:
+	.word _end - _start
+
+#ifdef CONFIG_USE_IRQ
+/* IRQ stack memory (calculated at run-time) */
+.globl IRQ_STACK_START
+IRQ_STACK_START:
+	.word	0x0badc0de
+
+/* IRQ stack memory (calculated at run-time) */
+.globl FIQ_STACK_START
+FIQ_STACK_START:
+	.word 0x0badc0de
+#endif
+
+/* IRQ stack memory (calculated at run-time) + 8 bytes */
+.globl IRQ_STACK_START_IN
+IRQ_STACK_START_IN:
+	.word	0x0badc0de
+
+/*
+ * the actual reset code
+ */
+
+reset:
+	/*
+	 * Store all registers on old stack pointer, this will allow us later to
+	 * return to the BootROM and let the BootROM load U-Boot into RAM.
+	 */
+	push	{r0-r12,r14}
+
+	/*
+	 * set the cpu to SVC32 mode
+	 */
+	mrs	r0,cpsr
+	bic	r0,r0,#0x1f
+	orr	r0,r0,#0xd3
+	msr	cpsr,r0
+
+	/*
+	 * we do sys-critical inits only at reboot,
+	 * not when booting from ram!
+	 */
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+	bl	cpu_init_crit
+#endif
+
+	bl	board_init_ll
+
+	pop	{r0-r12,r14}
+	bx	lr
+
+/*
+ *************************************************************************
+ *
+ * CPU_init_critical registers
+ *
+ * setup important registers
+ * setup memory timing
+ *
+ *************************************************************************
+ */
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+cpu_init_crit:
+	/*
+	 * flush v4 I/D caches
+	 */
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c7, 0	/* flush v3/v4 cache */
+	mcr	p15, 0, r0, c8, c7, 0	/* flush v4 TLB */
+
+	/*
+	 * disable MMU stuff and caches
+	 */
+	mrc	p15, 0, r0, c1, c0, 0
+	bic	r0, r0, #0x00002300	/* clear bits 13, 9:8 (--V- --RS) */
+	bic	r0, r0, #0x00000087	/* clear bits 7, 2:0 (B--- -CAM) */
+	orr	r0, r0, #0x00000002	/* set bit 2 (A) Align */
+	orr	r0, r0, #0x00001000	/* set bit 12 (I) I-Cache */
+	mcr	p15, 0, r0, c1, c0, 0
+
+	mov	pc, lr		/* back to my caller */
+#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
+
+#ifndef CONFIG_SPL_BUILD
+/*
+ *************************************************************************
+ *
+ * Interrupt handling
+ *
+ *************************************************************************
+ */
+
+@
+@ IRQ stack frame.
+@
+#define S_FRAME_SIZE	72
+
+#define S_OLD_R0	68
+#define S_PSR		64
+#define S_PC		60
+#define S_LR		56
+#define S_SP		52
+
+#define S_IP		48
+#define S_FP		44
+#define S_R10		40
+#define S_R9		36
+#define S_R8		32
+#define S_R7		28
+#define S_R6		24
+#define S_R5		20
+#define S_R4		16
+#define S_R3		12
+#define S_R2		8
+#define S_R1		4
+#define S_R0		0
+
+#define MODE_SVC 0x13
+#define I_BIT	 0x80
+
+/*
+ * use bad_save_user_regs for abort/prefetch/undef/swi ...
+ * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
+ */
+
+	.macro	bad_save_user_regs
+	@ carve out a frame on current user stack
+	sub	sp, sp, #S_FRAME_SIZE
+	stmia	sp, {r0 - r12}	@ Save user registers (now in svc mode) r0-r12
+	ldr	r2, IRQ_STACK_START_IN
+	@ get values for "aborted" pc and cpsr (into parm regs)
+	ldmia	r2, {r2 - r3}
+	add	r0, sp, #S_FRAME_SIZE		@ grab pointer to old stack
+	add	r5, sp, #S_SP
+	mov	r1, lr
+	stmia	r5, {r0 - r3}	@ save sp_SVC, lr_SVC, pc, cpsr
+	mov	r0, sp		@ save current stack into r0 (param register)
+	.endm
+
+	.macro	irq_save_user_regs
+	sub	sp, sp, #S_FRAME_SIZE
+	stmia	sp, {r0 - r12}			@ Calling r0-r12
+	@ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
+	add	r8, sp, #S_PC
+	stmdb	r8, {sp, lr}^		@ Calling SP, LR
+	str	lr, [r8, #0]		@ Save calling PC
+	mrs	r6, spsr
+	str	r6, [r8, #4]		@ Save CPSR
+	str	r0, [r8, #8]		@ Save OLD_R0
+	mov	r0, sp
+	.endm
+
+	.macro	irq_restore_user_regs
+	ldmia	sp, {r0 - lr}^			@ Calling r0 - lr
+	mov	r0, r0
+	ldr	lr, [sp, #S_PC]			@ Get PC
+	add	sp, sp, #S_FRAME_SIZE
+	subs	pc, lr, #4		@ return & move spsr_svc into cpsr
+	.endm
+
+	.macro get_bad_stack
+	ldr	r13, IRQ_STACK_START_IN		@ setup our mode stack
+
+	str	lr, [r13]	@ save caller lr in position 0 of saved stack
+	mrs	lr, spsr	@ get the spsr
+	str	lr, [r13, #4]	@ save spsr in position 1 of saved stack
+	mov	r13, #MODE_SVC	@ prepare SVC-Mode
+	@ msr	spsr_c, r13
+	msr	spsr, r13	@ switch modes, make sure moves will execute
+	mov	lr, pc		@ capture return pc
+	movs	pc, lr		@ jump to next instruction & switch modes.
+	.endm
+
+	.macro get_irq_stack			@ setup IRQ stack
+	ldr	sp, IRQ_STACK_START
+	.endm
+
+	.macro get_fiq_stack			@ setup FIQ stack
+	ldr	sp, FIQ_STACK_START
+	.endm
+#endif	/* CONFIG_SPL_BUILD */
+
+/*
+ * exception handlers
+ */
+#ifdef CONFIG_SPL_BUILD
+	.align	5
+do_hang:
+	ldr	sp, _TEXT_BASE			/* switch to abort stack */
+1:
+	bl	1b				/* hang and never return */
+#else	/* !CONFIG_SPL_BUILD */
+	.align  5
+undefined_instruction:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_undefined_instruction
+
+	.align	5
+software_interrupt:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_software_interrupt
+
+	.align	5
+prefetch_abort:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_prefetch_abort
+
+	.align	5
+data_abort:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_data_abort
+
+	.align	5
+not_used:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_not_used
+
+#ifdef CONFIG_USE_IRQ
+
+	.align	5
+irq:
+	get_irq_stack
+	irq_save_user_regs
+	bl	do_irq
+	irq_restore_user_regs
+
+	.align	5
+fiq:
+	get_fiq_stack
+	/* someone ought to write a more effiction fiq_save_user_regs */
+	irq_save_user_regs
+	bl	do_fiq
+	irq_restore_user_regs
+
+#else
+
+	.align	5
+irq:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_irq
+
+	.align	5
+fiq:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_fiq
+
+#endif
+#endif	/* CONFIG_SPL_BUILD */
diff --git a/board/denx/m28evk/u-boot-spl.lds b/board/denx/m28evk/u-boot-spl.lds
new file mode 100644
index 0000000..e296a92
--- /dev/null
+++ b/board/denx/m28evk/u-boot-spl.lds
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * January 2004 - Changed to support H4 device
+ * Copyright (c) 2004-2008 Texas Instruments
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+	. = 0x00000000;
+
+	. = ALIGN(4);
+	.text	:
+	{
+		board/denx/m28evk/start.o	(.text)
+		*(.text)
+	}
+
+	. = ALIGN(4);
+	.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
+
+	. = ALIGN(4);
+	.data : {
+		*(.data)
+	}
+
+	. = ALIGN(4);
+	__u_boot_cmd_start = .;
+	.u_boot_cmd : { *(.u_boot_cmd) }
+	__u_boot_cmd_end = .;
+
+	. = ALIGN(4);
+
+	.rel.dyn : {
+		__rel_dyn_start = .;
+		*(.rel*)
+		__rel_dyn_end = .;
+	}
+
+	.dynsym : {
+		__dynsym_start = .;
+		*(.dynsym)
+	}
+
+	_end = .;
+
+	.bss __rel_dyn_start (OVERLAY) : {
+		__bss_start = .;
+		*(.bss)
+		 . = ALIGN(4);
+		__bss_end__ = .;
+	}
+
+	/DISCARD/ : { *(.bss*) }
+	/DISCARD/ : { *(.dynstr*) }
+	/DISCARD/ : { *(.dynsym*) }
+	/DISCARD/ : { *(.dynamic*) }
+	/DISCARD/ : { *(.hash*) }
+	/DISCARD/ : { *(.plt*) }
+	/DISCARD/ : { *(.interp*) }
+	/DISCARD/ : { *(.gnu*) }
+}
diff --git a/board/denx/m28evk/u-boot.bd b/board/denx/m28evk/u-boot.bd
new file mode 100644
index 0000000..3ce7f92
--- /dev/null
+++ b/board/denx/m28evk/u-boot.bd
@@ -0,0 +1,14 @@
+sources {
+	u_boot_spl="spl/u-boot-spl.bin";
+	u_boot="u-boot.bin";
+}
+
+section (0) {
+        load u_boot_spl > 0x0000;
+        load ivt (entry = 0x0014) > 0x8000;
+	hab call 0x8000;
+
+        load u_boot > 0x40000100;
+        load ivt (entry = 0x40000100) > 0x8000;
+	hab call 0x8000;
+}
diff --git a/include/configs/m28evk.h b/include/configs/m28evk.h
index 44a09a0..89d2938 100644
--- a/include/configs/m28evk.h
+++ b/include/configs/m28evk.h
@@ -43,6 +43,14 @@
 #define	CONFIG_ARCH_CPU_INIT
 
 /*
+ * SPL
+ */
+#define	CONFIG_SPL
+#define	CONFIG_SPL_NO_CPU_SUPPORT_CODE
+#define	CONFIG_SPL_START_S_PATH		"board/denx/m28evk"
+#define	CONFIG_SPL_LDSCRIPT		"board/denx/m28evk/u-boot-spl.lds"
+
+/*
  * U-Boot Commands
  */
 #include <config_cmd_default.h>
-- 
1.7.6.3

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

* [U-Boot] [PATCH 01/15 V3] iMX28: Initial support for iMX28 CPU
  2011-10-14  7:59             ` Marek Vasut
@ 2011-10-14 21:00               ` Wolfgang Denk
  2011-10-14 21:06                 ` Marek Vasut
  0 siblings, 1 reply; 116+ messages in thread
From: Wolfgang Denk @ 2011-10-14 21:00 UTC (permalink / raw)
  To: u-boot

Dear Marek Vasut,

In message <201110140959.42368.marek.vasut@gmail.com> you wrote:
>
> > Running checkpatch on your patches I see a lot of issues, and not only a
> > couple of them.
> > 
> > For example,
> > 
> > WARNING: line over 80 characters
> > #632: FILE: arch/arm/cpu/arm926ejs/mx28/mx28.c:150:
> > +int do_mx28_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char *
> > const argv[])



> those iomux-mx28.h issues were already explained. It's a file taken from linux 
> kernel with no modifications, that's why the issues. And if you take a look 
> inside, fixing it would make it unreadable.

The error above appears to be unrelated. Why did you not fix at least
these?

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Where people stand is not as important as which way they face.
        - Terry Pratchett & Stephen Briggs, _The Discworld Companion_

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

* [U-Boot] [PATCH 01/15 V3] iMX28: Initial support for iMX28 CPU
  2011-09-30  9:42     ` [U-Boot] [PATCH 01/15 V3] " Marek Vasut
  2011-10-13 16:19       ` Stefano Babic
  2011-10-13 23:38       ` [U-Boot] [PATCH 01/15 V4] " Marek Vasut
@ 2011-10-14 21:01       ` Wolfgang Denk
  2011-10-14 21:10         ` Marek Vasut
  2 siblings, 1 reply; 116+ messages in thread
From: Wolfgang Denk @ 2011-10-14 21:01 UTC (permalink / raw)
  To: u-boot

Dear Marek Vasut,

In message <1317375728-23802-1-git-send-email-marek.vasut@gmail.com> you wrote:
> This patch supports:
> - Timers
> - Debug UART
> - Clock
> 
> Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
> Cc: Stefano Babic <sbabic@denx.de>
> Cc: Wolfgang Denk <wd@denx.de>
> Cc: Detlev Zundel <dzu@denx.de>
> ---
>  arch/arm/cpu/arm926ejs/mx28/Makefile          |   46 +
>  arch/arm/cpu/arm926ejs/mx28/clock.c           |  355 +++++++
>  arch/arm/cpu/arm926ejs/mx28/mx28.c            |  194 ++++
>  arch/arm/cpu/arm926ejs/mx28/timer.c           |  141 +++
>  arch/arm/include/asm/arch-mx28/clock.h        |   61 ++
>  arch/arm/include/asm/arch-mx28/imx-regs.h     |   38 +
>  arch/arm/include/asm/arch-mx28/regs-base.h    |   88 ++
>  arch/arm/include/asm/arch-mx28/regs-bch.h     |  230 +++++
>  arch/arm/include/asm/arch-mx28/regs-clkctrl.h |  312 ++++++
>  arch/arm/include/asm/arch-mx28/regs-common.h  |   66 ++
>  arch/arm/include/asm/arch-mx28/regs-gpmi.h    |  222 +++++
>  arch/arm/include/asm/arch-mx28/regs-i2c.h     |  207 ++++
>  arch/arm/include/asm/arch-mx28/regs-ocotp.h   |  173 ++++
>  arch/arm/include/asm/arch-mx28/regs-pinctrl.h | 1284 +++++++++++++++++++++++++
>  arch/arm/include/asm/arch-mx28/regs-power.h   |  413 ++++++++
>  arch/arm/include/asm/arch-mx28/regs-rtc.h     |  147 +++
>  arch/arm/include/asm/arch-mx28/regs-ssp.h     |  349 +++++++
>  arch/arm/include/asm/arch-mx28/regs-timrot.h  |  171 ++++
>  arch/arm/include/asm/arch-mx28/sys_proto.h    |   30 +
>  19 files changed, 4527 insertions(+), 0 deletions(-)
>  create mode 100644 arch/arm/cpu/arm926ejs/mx28/Makefile
>  create mode 100644 arch/arm/cpu/arm926ejs/mx28/clock.c
>  create mode 100644 arch/arm/cpu/arm926ejs/mx28/mx28.c
>  create mode 100644 arch/arm/cpu/arm926ejs/mx28/timer.c
>  create mode 100644 arch/arm/include/asm/arch-mx28/clock.h
>  create mode 100644 arch/arm/include/asm/arch-mx28/imx-regs.h
>  create mode 100644 arch/arm/include/asm/arch-mx28/regs-base.h
>  create mode 100644 arch/arm/include/asm/arch-mx28/regs-bch.h
>  create mode 100644 arch/arm/include/asm/arch-mx28/regs-clkctrl.h
>  create mode 100644 arch/arm/include/asm/arch-mx28/regs-common.h
>  create mode 100644 arch/arm/include/asm/arch-mx28/regs-gpmi.h
>  create mode 100644 arch/arm/include/asm/arch-mx28/regs-i2c.h
>  create mode 100644 arch/arm/include/asm/arch-mx28/regs-ocotp.h
>  create mode 100644 arch/arm/include/asm/arch-mx28/regs-pinctrl.h
>  create mode 100644 arch/arm/include/asm/arch-mx28/regs-power.h
>  create mode 100644 arch/arm/include/asm/arch-mx28/regs-rtc.h
>  create mode 100644 arch/arm/include/asm/arch-mx28/regs-ssp.h
>  create mode 100644 arch/arm/include/asm/arch-mx28/regs-timrot.h
>  create mode 100644 arch/arm/include/asm/arch-mx28/sys_proto.h
...
> +#include <common.h>
> +#include <asm/errno.h>
> +#include <asm/io.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/gpio.h>
> +#include <asm/arch/imx-regs.h>
> +#include <asm/arch/sys_proto.h>
> +#include <asm/arch/iomux-mx28.h>

You include <asm/arch/iomux-mx28.h> here, but add this file only in
patch # 4 of your series.  That means your patches are not bisectable.

Please fix.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Man did not weave the web of life; he  is  merely  a  strand  in  it.
Whatever he does to the web, he does to himself.     - Seattle [1854]

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

* [U-Boot] [PATCH 01/15 V3] iMX28: Initial support for iMX28 CPU
  2011-10-14 21:00               ` Wolfgang Denk
@ 2011-10-14 21:06                 ` Marek Vasut
  0 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-10-14 21:06 UTC (permalink / raw)
  To: u-boot

On Friday, October 14, 2011 11:00:35 PM Wolfgang Denk wrote:
> Dear Marek Vasut,
> 
> In message <201110140959.42368.marek.vasut@gmail.com> you wrote:
> > > Running checkpatch on your patches I see a lot of issues, and not only
> > > a couple of them.
> > > 
> > > For example,
> > > 
> > > WARNING: line over 80 characters
> > > #632: FILE: arch/arm/cpu/arm926ejs/mx28/mx28.c:150:
> > > +int do_mx28_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char *
> > > const argv[])
> > 
> > those iomux-mx28.h issues were already explained. It's a file taken from
> > linux kernel with no modifications, that's why the issues. And if you
> > take a look inside, fixing it would make it unreadable.
> 
> The error above appears to be unrelated. Why did you not fix at least
> these?

I believe the V3 should have that error fixed. The line-over-80 error that is.

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

* [U-Boot] [PATCH 01/15 V3] iMX28: Initial support for iMX28 CPU
  2011-10-14 21:01       ` [U-Boot] [PATCH 01/15 V3] " Wolfgang Denk
@ 2011-10-14 21:10         ` Marek Vasut
  0 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-10-14 21:10 UTC (permalink / raw)
  To: u-boot

On Friday, October 14, 2011 11:01:23 PM Wolfgang Denk wrote:
> Dear Marek Vasut,
> 
> In message <1317375728-23802-1-git-send-email-marek.vasut@gmail.com> you 
wrote:
> > This patch supports:
> > - Timers
> > - Debug UART
> > - Clock
> > 
> > Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
> > Cc: Stefano Babic <sbabic@denx.de>
> > Cc: Wolfgang Denk <wd@denx.de>
> > Cc: Detlev Zundel <dzu@denx.de>
> > ---
> > 
> >  arch/arm/cpu/arm926ejs/mx28/Makefile          |   46 +
> >  arch/arm/cpu/arm926ejs/mx28/clock.c           |  355 +++++++
> >  arch/arm/cpu/arm926ejs/mx28/mx28.c            |  194 ++++
> >  arch/arm/cpu/arm926ejs/mx28/timer.c           |  141 +++
> >  arch/arm/include/asm/arch-mx28/clock.h        |   61 ++
> >  arch/arm/include/asm/arch-mx28/imx-regs.h     |   38 +
> >  arch/arm/include/asm/arch-mx28/regs-base.h    |   88 ++
> >  arch/arm/include/asm/arch-mx28/regs-bch.h     |  230 +++++
> >  arch/arm/include/asm/arch-mx28/regs-clkctrl.h |  312 ++++++
> >  arch/arm/include/asm/arch-mx28/regs-common.h  |   66 ++
> >  arch/arm/include/asm/arch-mx28/regs-gpmi.h    |  222 +++++
> >  arch/arm/include/asm/arch-mx28/regs-i2c.h     |  207 ++++
> >  arch/arm/include/asm/arch-mx28/regs-ocotp.h   |  173 ++++
> >  arch/arm/include/asm/arch-mx28/regs-pinctrl.h | 1284
> >  +++++++++++++++++++++++++ arch/arm/include/asm/arch-mx28/regs-power.h  
> >  |  413 ++++++++
> >  arch/arm/include/asm/arch-mx28/regs-rtc.h     |  147 +++
> >  arch/arm/include/asm/arch-mx28/regs-ssp.h     |  349 +++++++
> >  arch/arm/include/asm/arch-mx28/regs-timrot.h  |  171 ++++
> >  arch/arm/include/asm/arch-mx28/sys_proto.h    |   30 +
> >  19 files changed, 4527 insertions(+), 0 deletions(-)
> >  create mode 100644 arch/arm/cpu/arm926ejs/mx28/Makefile
> >  create mode 100644 arch/arm/cpu/arm926ejs/mx28/clock.c
> >  create mode 100644 arch/arm/cpu/arm926ejs/mx28/mx28.c
> >  create mode 100644 arch/arm/cpu/arm926ejs/mx28/timer.c
> >  create mode 100644 arch/arm/include/asm/arch-mx28/clock.h
> >  create mode 100644 arch/arm/include/asm/arch-mx28/imx-regs.h
> >  create mode 100644 arch/arm/include/asm/arch-mx28/regs-base.h
> >  create mode 100644 arch/arm/include/asm/arch-mx28/regs-bch.h
> >  create mode 100644 arch/arm/include/asm/arch-mx28/regs-clkctrl.h
> >  create mode 100644 arch/arm/include/asm/arch-mx28/regs-common.h
> >  create mode 100644 arch/arm/include/asm/arch-mx28/regs-gpmi.h
> >  create mode 100644 arch/arm/include/asm/arch-mx28/regs-i2c.h
> >  create mode 100644 arch/arm/include/asm/arch-mx28/regs-ocotp.h
> >  create mode 100644 arch/arm/include/asm/arch-mx28/regs-pinctrl.h
> >  create mode 100644 arch/arm/include/asm/arch-mx28/regs-power.h
> >  create mode 100644 arch/arm/include/asm/arch-mx28/regs-rtc.h
> >  create mode 100644 arch/arm/include/asm/arch-mx28/regs-ssp.h
> >  create mode 100644 arch/arm/include/asm/arch-mx28/regs-timrot.h
> >  create mode 100644 arch/arm/include/asm/arch-mx28/sys_proto.h
> 
> ...
> 
> > +#include <common.h>
> > +#include <asm/errno.h>
> > +#include <asm/io.h>
> > +#include <asm/arch/clock.h>
> > +#include <asm/arch/gpio.h>
> > +#include <asm/arch/imx-regs.h>
> > +#include <asm/arch/sys_proto.h>
> > +#include <asm/arch/iomux-mx28.h>
> 
> You include <asm/arch/iomux-mx28.h> here, but add this file only in
> patch # 4 of your series.  That means your patches are not bisectable.

Good catch, it must have crawled in when I was debugging the reset issue. 
Dropping the include does the trick, thanks for your constant torture! ;-)

Fix in V4 on the way!

Cheers

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

* [U-Boot] [PATCH 01/15 V5] iMX28: Initial support for iMX28 CPU
  2011-10-13 23:38       ` [U-Boot] [PATCH 01/15 V4] " Marek Vasut
@ 2011-10-14 21:14         ` Marek Vasut
  0 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-10-14 21:14 UTC (permalink / raw)
  To: u-boot

This patch supports:
- Timers
- Debug UART
- Clock

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 arch/arm/cpu/arm926ejs/mx28/Makefile          |   46 +
 arch/arm/cpu/arm926ejs/mx28/clock.c           |  355 +++++++
 arch/arm/cpu/arm926ejs/mx28/mx28.c            |  193 ++++
 arch/arm/cpu/arm926ejs/mx28/timer.c           |  141 +++
 arch/arm/include/asm/arch-mx28/clock.h        |   61 ++
 arch/arm/include/asm/arch-mx28/imx-regs.h     |   38 +
 arch/arm/include/asm/arch-mx28/regs-base.h    |   88 ++
 arch/arm/include/asm/arch-mx28/regs-bch.h     |  230 +++++
 arch/arm/include/asm/arch-mx28/regs-clkctrl.h |  312 ++++++
 arch/arm/include/asm/arch-mx28/regs-common.h  |   66 ++
 arch/arm/include/asm/arch-mx28/regs-gpmi.h    |  222 +++++
 arch/arm/include/asm/arch-mx28/regs-i2c.h     |  207 ++++
 arch/arm/include/asm/arch-mx28/regs-ocotp.h   |  173 ++++
 arch/arm/include/asm/arch-mx28/regs-pinctrl.h | 1284 +++++++++++++++++++++++++
 arch/arm/include/asm/arch-mx28/regs-power.h   |  413 ++++++++
 arch/arm/include/asm/arch-mx28/regs-rtc.h     |  147 +++
 arch/arm/include/asm/arch-mx28/regs-ssp.h     |  349 +++++++
 arch/arm/include/asm/arch-mx28/regs-timrot.h  |  171 ++++
 arch/arm/include/asm/arch-mx28/sys_proto.h    |   30 +
 19 files changed, 4526 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/Makefile
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/clock.c
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/mx28.c
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/timer.c
 create mode 100644 arch/arm/include/asm/arch-mx28/clock.h
 create mode 100644 arch/arm/include/asm/arch-mx28/imx-regs.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-base.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-bch.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-clkctrl.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-common.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-gpmi.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-i2c.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-ocotp.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-pinctrl.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-power.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-rtc.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-ssp.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-timrot.h
 create mode 100644 arch/arm/include/asm/arch-mx28/sys_proto.h

V2: Use watchdog for reset
V3: Remove redundant power_regs from cpu_reset() (gcc4.6)
V4: Squash checkpatch issue
V5: Drop bogus include directive including so far nonexistent file

diff --git a/arch/arm/cpu/arm926ejs/mx28/Makefile b/arch/arm/cpu/arm926ejs/mx28/Makefile
new file mode 100644
index 0000000..98504f9
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/Makefile
@@ -0,0 +1,46 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(SOC).o
+
+COBJS	= clock.o mx28.o timer.o
+
+SRCS	:= $(START:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+START	:= $(addprefix $(obj),$(START))
+
+all:	$(obj).depend $(LIB)
+
+$(LIB):	$(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/arm/cpu/arm926ejs/mx28/clock.c b/arch/arm/cpu/arm926ejs/mx28/clock.c
new file mode 100644
index 0000000..f698506
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/clock.c
@@ -0,0 +1,355 @@
+/*
+ * Freescale i.MX28 clock setup code
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+
+/* The PLL frequency is always 480MHz, see section 10.2 in iMX28 datasheet. */
+#define	PLL_FREQ_KHZ	480000
+#define	PLL_FREQ_COEF	18
+/* The XTAL frequency is always 24MHz, see section 10.2 in iMX28 datasheet. */
+#define	XTAL_FREQ_KHZ	24000
+
+#define	PLL_FREQ_MHZ	(PLL_FREQ_KHZ / 1000)
+#define	XTAL_FREQ_MHZ	(XTAL_FREQ_KHZ / 1000)
+
+static uint32_t mx28_get_pclk(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	uint32_t clkctrl, clkseq, clkfrac;
+	uint32_t frac, div;
+
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_cpu);
+
+	/* No support of fractional divider calculation */
+	if (clkctrl &
+		(CLKCTRL_CPU_DIV_XTAL_FRAC_EN | CLKCTRL_CPU_DIV_CPU_FRAC_EN)) {
+		return 0;
+	}
+
+	clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+
+	/* XTAL Path */
+	if (clkseq & CLKCTRL_CLKSEQ_BYPASS_CPU) {
+		div = (clkctrl & CLKCTRL_CPU_DIV_XTAL_MASK) >>
+			CLKCTRL_CPU_DIV_XTAL_OFFSET;
+		return XTAL_FREQ_MHZ / div;
+	}
+
+	/* REF Path */
+	clkfrac = readl(&clkctrl_regs->hw_clkctrl_frac0);
+	frac = clkfrac & CLKCTRL_FRAC0_CPUFRAC_MASK;
+	div = clkctrl & CLKCTRL_CPU_DIV_CPU_MASK;
+	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
+}
+
+static uint32_t mx28_get_hclk(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	uint32_t div;
+	uint32_t clkctrl;
+
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_hbus);
+
+	/* No support of fractional divider calculation */
+	if (clkctrl & CLKCTRL_HBUS_DIV_FRAC_EN)
+		return 0;
+
+	div = clkctrl & CLKCTRL_HBUS_DIV_MASK;
+	return mx28_get_pclk() / div;
+}
+
+static uint32_t mx28_get_emiclk(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	uint32_t frac, div;
+	uint32_t clkctrl, clkseq, clkfrac;
+
+	clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_emi);
+
+	/* XTAL Path */
+	if (clkseq & CLKCTRL_CLKSEQ_BYPASS_EMI) {
+		div = (clkctrl & CLKCTRL_EMI_DIV_XTAL_MASK) >>
+			CLKCTRL_EMI_DIV_XTAL_OFFSET;
+		return XTAL_FREQ_MHZ / div;
+	}
+
+	clkfrac = readl(&clkctrl_regs->hw_clkctrl_frac0);
+
+	/* REF Path */
+	frac = (clkfrac & CLKCTRL_FRAC0_EMIFRAC_MASK) >>
+		CLKCTRL_FRAC0_EMIFRAC_OFFSET;
+	div = clkctrl & CLKCTRL_EMI_DIV_EMI_MASK;
+	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
+}
+
+static uint32_t mx28_get_gpmiclk(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	uint32_t frac, div;
+	uint32_t clkctrl, clkseq, clkfrac;
+
+	clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_gpmi);
+
+	/* XTAL Path */
+	if (clkseq & CLKCTRL_CLKSEQ_BYPASS_GPMI) {
+		div = clkctrl & CLKCTRL_GPMI_DIV_MASK;
+		return XTAL_FREQ_MHZ / div;
+	}
+
+	clkfrac = readl(&clkctrl_regs->hw_clkctrl_frac1);
+
+	/* REF Path */
+	frac = (clkfrac & CLKCTRL_FRAC1_GPMIFRAC_MASK) >>
+		CLKCTRL_FRAC1_GPMIFRAC_OFFSET;
+	div = clkctrl & CLKCTRL_GPMI_DIV_MASK;
+	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
+}
+
+/*
+ * Set IO clock frequency, in kHz
+ */
+void mx28_set_ioclk(enum mxs_ioclock io, uint32_t freq)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t div;
+
+	if (freq == 0)
+		return;
+
+	if (io > MXC_IOCLK1)
+		return;
+
+	div = (PLL_FREQ_KHZ * PLL_FREQ_COEF) / freq;
+
+	if (div < 18)
+		div = 18;
+
+	if (div > 35)
+		div = 35;
+
+	if (io == MXC_IOCLK0) {
+		writel(CLKCTRL_FRAC0_CLKGATEIO0,
+			&clkctrl_regs->hw_clkctrl_frac0_set);
+		clrsetbits_le32(&clkctrl_regs->hw_clkctrl_frac0,
+				CLKCTRL_FRAC0_IO0FRAC_MASK,
+				div << CLKCTRL_FRAC0_IO0FRAC_OFFSET);
+		writel(CLKCTRL_FRAC0_CLKGATEIO0,
+			&clkctrl_regs->hw_clkctrl_frac0_clr);
+	} else {
+		writel(CLKCTRL_FRAC0_CLKGATEIO1,
+			&clkctrl_regs->hw_clkctrl_frac0_set);
+		clrsetbits_le32(&clkctrl_regs->hw_clkctrl_frac0,
+				CLKCTRL_FRAC0_IO1FRAC_MASK,
+				div << CLKCTRL_FRAC0_IO1FRAC_OFFSET);
+		writel(CLKCTRL_FRAC0_CLKGATEIO1,
+			&clkctrl_regs->hw_clkctrl_frac0_clr);
+	}
+}
+
+/*
+ * Get IO clock, returns IO clock in kHz
+ */
+static uint32_t mx28_get_ioclk(enum mxs_ioclock io)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t tmp, ret;
+
+	if (io > MXC_IOCLK1)
+		return 0;
+
+	tmp = readl(&clkctrl_regs->hw_clkctrl_frac0);
+
+	if (io == MXC_IOCLK0)
+		ret = (tmp & CLKCTRL_FRAC0_IO0FRAC_MASK) >>
+			CLKCTRL_FRAC0_IO0FRAC_OFFSET;
+	else
+		ret = (tmp & CLKCTRL_FRAC0_IO1FRAC_MASK) >>
+			CLKCTRL_FRAC0_IO1FRAC_OFFSET;
+
+	return (PLL_FREQ_KHZ * PLL_FREQ_COEF) / ret;
+}
+
+/*
+ * Configure SSP clock frequency, in kHz
+ */
+void mx28_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t clk, clkreg;
+
+	if (ssp > MXC_SSPCLK3)
+		return;
+
+	clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) +
+			(ssp * sizeof(struct mx28_register));
+
+	clrbits_le32(clkreg, CLKCTRL_SSP_CLKGATE);
+	while (readl(clkreg) & CLKCTRL_SSP_CLKGATE)
+		;
+
+	if (xtal)
+		clk = XTAL_FREQ_KHZ;
+	else
+		clk = mx28_get_ioclk(ssp >> 1);
+
+	if (freq > clk)
+		return;
+
+	/* Calculate the divider and cap it if necessary */
+	clk /= freq;
+	if (clk > CLKCTRL_SSP_DIV_MASK)
+		clk = CLKCTRL_SSP_DIV_MASK;
+
+	clrsetbits_le32(clkreg, CLKCTRL_SSP_DIV_MASK, clk);
+	while (readl(clkreg) & CLKCTRL_SSP_BUSY)
+		;
+
+	if (xtal)
+		writel(CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp,
+			&clkctrl_regs->hw_clkctrl_clkseq_set);
+	else
+		writel(CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp,
+			&clkctrl_regs->hw_clkctrl_clkseq_clr);
+}
+
+/*
+ * Return SSP frequency, in kHz
+ */
+static uint32_t mx28_get_sspclk(enum mxs_sspclock ssp)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t clkreg;
+	uint32_t clk, tmp;
+
+	if (ssp > MXC_SSPCLK3)
+		return 0;
+
+	tmp = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+	if (tmp & (CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp))
+		return XTAL_FREQ_KHZ;
+
+	clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) +
+			(ssp * sizeof(struct mx28_register));
+
+	tmp = readl(clkreg) & CLKCTRL_SSP_DIV_MASK;
+
+	if (tmp == 0)
+		return 0;
+
+	clk = mx28_get_ioclk(ssp >> 1);
+
+	return clk / tmp;
+}
+
+/*
+ * Set SSP/MMC bus frequency, in kHz)
+ */
+void mx28_set_ssp_busclock(unsigned int bus, uint32_t freq)
+{
+	struct mx28_ssp_regs *ssp_regs;
+	const uint32_t sspclk = mx28_get_sspclk(bus);
+	uint32_t reg;
+	uint32_t divide, rate, tgtclk;
+
+	ssp_regs = (struct mx28_ssp_regs *)(MXS_SSP0_BASE + (bus * 0x2000));
+
+	/*
+	 * SSP bit rate = SSPCLK / (CLOCK_DIVIDE * (1 + CLOCK_RATE)),
+	 * CLOCK_DIVIDE has to be an even value from 2 to 254, and
+	 * CLOCK_RATE could be any integer from 0 to 255.
+	 */
+	for (divide = 2; divide < 254; divide += 2) {
+		rate = sspclk / freq / divide;
+		if (rate <= 256)
+			break;
+	}
+
+	tgtclk = sspclk / divide / rate;
+	while (tgtclk > freq) {
+		rate++;
+		tgtclk = sspclk / divide / rate;
+	}
+	if (rate > 256)
+		rate = 256;
+
+	/* Always set timeout the maximum */
+	reg = SSP_TIMING_TIMEOUT_MASK |
+		(divide << SSP_TIMING_CLOCK_DIVIDE_OFFSET) |
+		((rate - 1) << SSP_TIMING_CLOCK_RATE_OFFSET);
+	writel(reg, &ssp_regs->hw_ssp_timing);
+
+	debug("SPI%d: Set freq rate to %d KHz (requested %d KHz)\n",
+		bus, tgtclk, freq);
+}
+
+uint32_t mxc_get_clock(enum mxc_clock clk)
+{
+	switch (clk) {
+	case MXC_ARM_CLK:
+		return mx28_get_pclk() * 1000000;
+	case MXC_GPMI_CLK:
+		return mx28_get_gpmiclk() * 1000000;
+	case MXC_AHB_CLK:
+	case MXC_IPG_CLK:
+		return mx28_get_hclk() * 1000000;
+	case MXC_EMI_CLK:
+		return mx28_get_emiclk();
+	case MXC_IO0_CLK:
+		return mx28_get_ioclk(MXC_IOCLK0);
+	case MXC_IO1_CLK:
+		return mx28_get_ioclk(MXC_IOCLK1);
+	case MXC_SSP0_CLK:
+		return mx28_get_sspclk(MXC_SSPCLK0);
+	case MXC_SSP1_CLK:
+		return mx28_get_sspclk(MXC_SSPCLK1);
+	case MXC_SSP2_CLK:
+		return mx28_get_sspclk(MXC_SSPCLK2);
+	case MXC_SSP3_CLK:
+		return mx28_get_sspclk(MXC_SSPCLK3);
+	}
+
+	return 0;
+}
diff --git a/arch/arm/cpu/arm926ejs/mx28/mx28.c b/arch/arm/cpu/arm926ejs/mx28/mx28.c
new file mode 100644
index 0000000..446ea8b
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/mx28.c
@@ -0,0 +1,193 @@
+/*
+ * Freescale i.MX28 common code
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+
+/* 1 second delay should be plenty of time for block reset. */
+#define	RESET_MAX_TIMEOUT	1000000
+
+#define	MX28_BLOCK_SFTRST	(1 << 31)
+#define	MX28_BLOCK_CLKGATE	(1 << 30)
+
+/* Lowlevel init isn't used on i.MX28, so just have a dummy here */
+inline void lowlevel_init(void) {}
+
+void reset_cpu(ulong ignored) __attribute__((noreturn));
+
+void reset_cpu(ulong ignored)
+{
+
+	struct mx28_rtc_regs *rtc_regs =
+		(struct mx28_rtc_regs *)MXS_RTC_BASE;
+
+	/* Wait 1 uS before doing the actual watchdog reset */
+	writel(1, &rtc_regs->hw_rtc_watchdog);
+	writel(RTC_CTRL_WATCHDOGEN, &rtc_regs->hw_rtc_ctrl_set);
+
+	/* Endless loop, reset will exit from here */
+	for (;;)
+		;
+}
+
+int mx28_wait_mask_set(struct mx28_register *reg, uint32_t mask, int timeout)
+{
+	while (--timeout) {
+		if ((readl(&reg->reg) & mask) == mask)
+			break;
+		udelay(1);
+	}
+
+	return !timeout;
+}
+
+int mx28_wait_mask_clr(struct mx28_register *reg, uint32_t mask, int timeout)
+{
+	while (--timeout) {
+		if ((readl(&reg->reg) & mask) == 0)
+			break;
+		udelay(1);
+	}
+
+	return !timeout;
+}
+
+int mx28_reset_block(struct mx28_register *reg)
+{
+	/* Clear SFTRST */
+	writel(MX28_BLOCK_SFTRST, &reg->reg_clr);
+
+	if (mx28_wait_mask_clr(reg, MX28_BLOCK_SFTRST, RESET_MAX_TIMEOUT))
+		return 1;
+
+	/* Clear CLKGATE */
+	writel(MX28_BLOCK_CLKGATE, &reg->reg_clr);
+
+	/* Set SFTRST */
+	writel(MX28_BLOCK_SFTRST, &reg->reg_set);
+
+	/* Wait for CLKGATE being set */
+	if (mx28_wait_mask_set(reg, MX28_BLOCK_CLKGATE, RESET_MAX_TIMEOUT))
+		return 1;
+
+	/* Clear SFTRST */
+	writel(MX28_BLOCK_SFTRST, &reg->reg_clr);
+
+	if (mx28_wait_mask_clr(reg, MX28_BLOCK_SFTRST, RESET_MAX_TIMEOUT))
+		return 1;
+
+	/* Clear CLKGATE */
+	writel(MX28_BLOCK_CLKGATE, &reg->reg_clr);
+
+	if (mx28_wait_mask_clr(reg, MX28_BLOCK_CLKGATE, RESET_MAX_TIMEOUT))
+		return 1;
+
+	return 0;
+}
+
+#ifdef	CONFIG_ARCH_CPU_INIT
+int arch_cpu_init(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/*
+	 * Enable NAND clock
+	 */
+	/* Clear bypass bit */
+	writel(CLKCTRL_CLKSEQ_BYPASS_GPMI,
+		&clkctrl_regs->hw_clkctrl_clkseq_set);
+
+	/* Set GPMI clock to ref_gpmi / 12 */
+	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_gpmi,
+		CLKCTRL_GPMI_CLKGATE | CLKCTRL_GPMI_DIV_MASK, 1);
+
+	udelay(1000);
+
+	return 0;
+}
+#endif
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+int print_cpuinfo(void)
+{
+	printf("Freescale i.MX28 family\n");
+	return 0;
+}
+#endif
+
+int do_mx28_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+	printf("CPU:   %3d MHz\n", mxc_get_clock(MXC_ARM_CLK) / 1000000);
+	printf("BUS:   %3d MHz\n", mxc_get_clock(MXC_AHB_CLK) / 1000000);
+	printf("EMI:   %3d MHz\n", mxc_get_clock(MXC_EMI_CLK));
+	printf("GPMI:  %3d MHz\n", mxc_get_clock(MXC_GPMI_CLK) / 1000000);
+	return 0;
+}
+
+/*
+ * Initializes on-chip ethernet controllers.
+ */
+#ifdef	CONFIG_CMD_NET
+int cpu_eth_init(bd_t *bis)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/* Turn on ENET clocks */
+	clrbits_le32(&clkctrl_regs->hw_clkctrl_enet,
+		CLKCTRL_ENET_SLEEP | CLKCTRL_ENET_DISABLE);
+
+	/* Set up ENET PLL for 50 MHz */
+	/* Power on ENET PLL */
+	writel(CLKCTRL_PLL2CTRL0_POWER,
+		&clkctrl_regs->hw_clkctrl_pll2ctrl0_set);
+
+	udelay(10);
+
+	/* Gate on ENET PLL */
+	writel(CLKCTRL_PLL2CTRL0_CLKGATE,
+		&clkctrl_regs->hw_clkctrl_pll2ctrl0_clr);
+
+	/* Enable pad output */
+	setbits_le32(&clkctrl_regs->hw_clkctrl_enet, CLKCTRL_ENET_CLK_OUT_EN);
+
+	return 0;
+}
+#endif
+
+U_BOOT_CMD(
+	clocks,	CONFIG_SYS_MAXARGS, 1, do_mx28_showclocks,
+	"display clocks",
+	""
+);
diff --git a/arch/arm/cpu/arm926ejs/mx28/timer.c b/arch/arm/cpu/arm926ejs/mx28/timer.c
new file mode 100644
index 0000000..dbc904d
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/timer.c
@@ -0,0 +1,141 @@
+/*
+ * Freescale i.MX28 timer driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * (C) Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+
+/* Maximum fixed count */
+#define TIMER_LOAD_VAL	0xffffffff
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define timestamp (gd->tbl)
+#define lastdec (gd->lastinc)
+
+/*
+ * This driver uses 1kHz clock source.
+ */
+#define	MX28_INCREMENTER_HZ		1000
+
+static inline unsigned long tick_to_time(unsigned long tick)
+{
+	return tick / (MX28_INCREMENTER_HZ / CONFIG_SYS_HZ);
+}
+
+static inline unsigned long time_to_tick(unsigned long time)
+{
+	return time * (MX28_INCREMENTER_HZ / CONFIG_SYS_HZ);
+}
+
+/* Calculate how many ticks happen in "us" microseconds */
+static inline unsigned long us_to_tick(unsigned long us)
+{
+	return (us * MX28_INCREMENTER_HZ) / 1000000;
+}
+
+int timer_init(void)
+{
+	struct mx28_timrot_regs *timrot_regs =
+		(struct mx28_timrot_regs *)MXS_TIMROT_BASE;
+
+	/* Reset Timers and Rotary Encoder module */
+	mx28_reset_block(&timrot_regs->hw_timrot_rotctrl_reg);
+
+	/* Set fixed_count to 0 */
+	writel(0, &timrot_regs->hw_timrot_fixed_count0);
+
+	/* Set UPDATE bit and 1Khz frequency */
+	writel(TIMROT_TIMCTRLn_UPDATE | TIMROT_TIMCTRLn_RELOAD |
+		TIMROT_TIMCTRLn_SELECT_1KHZ_XTAL,
+		&timrot_regs->hw_timrot_timctrl0);
+
+	/* Set fixed_count to maximal value */
+	writel(TIMER_LOAD_VAL, &timrot_regs->hw_timrot_fixed_count0);
+
+	return 0;
+}
+
+ulong get_timer(ulong base)
+{
+	struct mx28_timrot_regs *timrot_regs =
+		(struct mx28_timrot_regs *)MXS_TIMROT_BASE;
+
+	/* Current tick value */
+	uint32_t now = readl(&timrot_regs->hw_timrot_running_count0);
+
+	if (lastdec >= now) {
+		/*
+		 * normal mode (non roll)
+		 * move stamp forward with absolut diff ticks
+		 */
+		timestamp += (lastdec - now);
+	} else {
+		/* we have rollover of decrementer */
+		timestamp += (TIMER_LOAD_VAL - now) + lastdec;
+
+	}
+	lastdec = now;
+
+	return tick_to_time(timestamp) - base;
+}
+
+/* We use the HW_DIGCTL_MICROSECONDS register for sub-millisecond timer. */
+#define	MX28_HW_DIGCTL_MICROSECONDS	0x8001c0c0
+
+void __udelay(unsigned long usec)
+{
+	uint32_t old, new, incr;
+	uint32_t counter = 0;
+
+	old = readl(MX28_HW_DIGCTL_MICROSECONDS);
+
+	while (counter < usec) {
+		new = readl(MX28_HW_DIGCTL_MICROSECONDS);
+
+		/* Check if the timer wrapped. */
+		if (new < old) {
+			incr = 0xffffffff - old;
+			incr += new;
+		} else {
+			incr = new - old;
+		}
+
+		/*
+		 * Check if we are close to the maximum time and the counter
+		 * would wrap if incremented. If that's the case, break out
+		 * from the loop as the requested delay time passed.
+		 */
+		if (counter + incr < counter)
+			break;
+
+		counter += incr;
+		old = new;
+	}
+}
diff --git a/arch/arm/include/asm/arch-mx28/clock.h b/arch/arm/include/asm/arch-mx28/clock.h
new file mode 100644
index 0000000..1700fe3
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/clock.h
@@ -0,0 +1,61 @@
+/*
+ * Freescale i.MX28 Clock
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __CLOCK_H__
+#define __CLOCK_H__
+
+enum mxc_clock {
+	MXC_ARM_CLK = 0,
+	MXC_AHB_CLK,
+	MXC_IPG_CLK,
+	MXC_EMI_CLK,
+	MXC_GPMI_CLK,
+	MXC_IO0_CLK,
+	MXC_IO1_CLK,
+	MXC_SSP0_CLK,
+	MXC_SSP1_CLK,
+	MXC_SSP2_CLK,
+	MXC_SSP3_CLK,
+};
+
+enum mxs_ioclock {
+	MXC_IOCLK0 = 0,
+	MXC_IOCLK1,
+};
+
+enum mxs_sspclock {
+	MXC_SSPCLK0 = 0,
+	MXC_SSPCLK1,
+	MXC_SSPCLK2,
+	MXC_SSPCLK3,
+};
+
+uint32_t mxc_get_clock(enum mxc_clock clk);
+
+void mx28_set_ioclk(enum mxs_ioclock io, uint32_t freq);
+void mx28_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal);
+void mx28_set_ssp_busclock(unsigned int bus, uint32_t freq);
+
+/* Compatibility with the FEC Ethernet driver */
+#define	imx_get_fecclk()	mxc_get_clock(MXC_AHB_CLK)
+
+#endif	/* __CLOCK_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/imx-regs.h b/arch/arm/include/asm/arch-mx28/imx-regs.h
new file mode 100644
index 0000000..32bfd7e
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/imx-regs.h
@@ -0,0 +1,38 @@
+/*
+ * Freescale i.MX28 Registers
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __IMX_REGS_H__
+#define __IMX_REGS_H__
+
+#include <asm/arch/regs-base.h>
+#include <asm/arch/regs-bch.h>
+#include <asm/arch/regs-clkctrl.h>
+#include <asm/arch/regs-gpmi.h>
+#include <asm/arch/regs-i2c.h>
+#include <asm/arch/regs-ocotp.h>
+#include <asm/arch/regs-pinctrl.h>
+#include <asm/arch/regs-power.h>
+#include <asm/arch/regs-rtc.h>
+#include <asm/arch/regs-ssp.h>
+#include <asm/arch/regs-timrot.h>
+
+#endif	/* __IMX_REGS_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-base.h b/arch/arm/include/asm/arch-mx28/regs-base.h
new file mode 100644
index 0000000..dbdcc2b
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-base.h
@@ -0,0 +1,88 @@
+/*
+ * Freescale i.MX28 Peripheral Base Addresses
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright (C) 2008 Embedded Alley Solutions Inc.
+ *
+ * (C) Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __MX28_REGS_BASE_H__
+#define __MX28_REGS_BASE_H__
+
+/*
+ * Register base address
+ */
+#define	MXS_ICOL_BASE		0x80000000
+#define	MXS_HSADC_BASE		0x80002000
+#define	MXS_APBH_BASE		0x80004000
+#define	MXS_PERFMON_BASE	0x80006000
+#define	MXS_BCH_BASE		0x8000A000
+#define	MXS_GPMI_BASE		0x8000C000
+#define	MXS_SSP0_BASE		0x80010000
+#define	MXS_SSP1_BASE		0x80012000
+#define	MXS_SSP2_BASE		0x80014000
+#define	MXS_SSP3_BASE		0x80016000
+#define	MXS_PINCTRL_BASE	0x80018000
+#define	MXS_DIGCTL_BASE		0x8001C000
+#define	MXS_ETM_BASE		0x80022000
+#define	MXS_APBX_BASE		0x80024000
+#define	MXS_DCP_BASE		0x80028000
+#define	MXS_PXP_BASE		0x8002A000
+#define	MXS_OCOTP_BASE		0x8002C000
+#define	MXS_AXI_AHB0_BASE	0x8002E000
+#define	MXS_LCDIF_BASE		0x80030000
+#define	MXS_CAN0_BASE		0x80032000
+#define	MXS_CAN1_BASE		0x80034000
+#define	MXS_SIMDBG_BASE		0x8003C000
+#define	MXS_SIMGPMISEL_BASE	0x8003C200
+#define	MXS_SIMSSPSEL_BASE	0x8003C300
+#define	MXS_SIMMEMSEL_BASE	0x8003C400
+#define	MXS_GPIOMON_BASE	0x8003C500
+#define	MXS_SIMENET_BASE	0x8003C700
+#define	MXS_ARMJTAG_BASE	0x8003C800
+#define	MXS_CLKCTRL_BASE	0x80040000
+#define	MXS_SAIF0_BASE		0x80042000
+#define	MXS_POWER_BASE		0x80044000
+#define	MXS_SAIF1_BASE		0x80046000
+#define	MXS_LRADC_BASE		0x80050000
+#define	MXS_SPDIF_BASE		0x80054000
+#define	MXS_RTC_BASE		0x80056000
+#define	MXS_I2C0_BASE		0x80058000
+#define	MXS_I2C1_BASE		0x8005A000
+#define	MXS_PWM_BASE		0x80064000
+#define	MXS_TIMROT_BASE		0x80068000
+#define	MXS_UARTAPP0_BASE	0x8006A000
+#define	MXS_UARTAPP1_BASE	0x8006C000
+#define	MXS_UARTAPP2_BASE	0x8006E000
+#define	MXS_UARTAPP3_BASE	0x80070000
+#define	MXS_UARTAPP4_BASE	0x80072000
+#define	MXS_UARTDBG_BASE	0x80074000
+#define	MXS_USBPHY0_BASE	0x8007C000
+#define	MXS_USBPHY1_BASE	0x8007E000
+#define	MXS_USBCTRL0_BASE	0x80080000
+#define	MXS_USBCTRL1_BASE	0x80090000
+#define	MXS_DFLPT_BASE		0x800C0000
+#define	MXS_DRAM_BASE		0x800E0000
+#define	MXS_ENET0_BASE		0x800F0000
+#define	MXS_ENET1_BASE		0x800F4000
+
+#endif /* __MX28_REGS_BASE_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-bch.h b/arch/arm/include/asm/arch-mx28/regs-bch.h
new file mode 100644
index 0000000..cac0470
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-bch.h
@@ -0,0 +1,230 @@
+/*
+ * Freescale i.MX28 BCH Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_BCH_H__
+#define __MX28_REGS_BCH_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_bch_regs {
+	mx28_reg(hw_bch_ctrl)
+	mx28_reg(hw_bch_status0)
+	mx28_reg(hw_bch_mode)
+	mx28_reg(hw_bch_encodeptr)
+	mx28_reg(hw_bch_dataptr)
+	mx28_reg(hw_bch_metaptr)
+
+	uint32_t	reserved[4];
+
+	mx28_reg(hw_bch_layoutselect)
+	mx28_reg(hw_bch_flash0layout0)
+	mx28_reg(hw_bch_flash0layout1)
+	mx28_reg(hw_bch_flash1layout0)
+	mx28_reg(hw_bch_flash1layout1)
+	mx28_reg(hw_bch_flash2layout0)
+	mx28_reg(hw_bch_flash2layout1)
+	mx28_reg(hw_bch_flash3layout0)
+	mx28_reg(hw_bch_flash3layout1)
+	mx28_reg(hw_bch_dbgkesread)
+	mx28_reg(hw_bch_dbgcsferead)
+	mx28_reg(hw_bch_dbgsyndegread)
+	mx28_reg(hw_bch_dbgahbmread)
+	mx28_reg(hw_bch_blockname)
+	mx28_reg(hw_bch_version)
+};
+#endif
+
+#define	BCH_CTRL_SFTRST					(1 << 31)
+#define	BCH_CTRL_CLKGATE				(1 << 30)
+#define	BCH_CTRL_DEBUGSYNDROME				(1 << 22)
+#define	BCH_CTRL_M2M_LAYOUT_MASK			(0x3 << 18)
+#define	BCH_CTRL_M2M_LAYOUT_OFFSET			18
+#define	BCH_CTRL_M2M_ENCODE				(1 << 17)
+#define	BCH_CTRL_M2M_ENABLE				(1 << 16)
+#define	BCH_CTRL_DEBUG_STALL_IRQ_EN			(1 << 10)
+#define	BCH_CTRL_COMPLETE_IRQ_EN			(1 << 8)
+#define	BCH_CTRL_BM_ERROR_IRQ				(1 << 3)
+#define	BCH_CTRL_DEBUG_STALL_IRQ			(1 << 2)
+#define	BCH_CTRL_COMPLETE_IRQ				(1 << 0)
+
+#define	BCH_STATUS0_HANDLE_MASK				(0xfff << 20)
+#define	BCH_STATUS0_HANDLE_OFFSET			20
+#define	BCH_STATUS0_COMPLETED_CE_MASK			(0xf << 16)
+#define	BCH_STATUS0_COMPLETED_CE_OFFSET			16
+#define	BCH_STATUS0_STATUS_BLK0_MASK			(0xff << 8)
+#define	BCH_STATUS0_STATUS_BLK0_OFFSET			8
+#define	BCH_STATUS0_STATUS_BLK0_ZERO			(0x00 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERROR1			(0x01 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERROR2			(0x02 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERROR3			(0x03 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERROR4			(0x04 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_UNCORRECTABLE		(0xfe << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERASED			(0xff << 8)
+#define	BCH_STATUS0_ALLONES				(1 << 4)
+#define	BCH_STATUS0_CORRECTED				(1 << 3)
+#define	BCH_STATUS0_UNCORRECTABLE			(1 << 2)
+
+#define	BCH_MODE_ERASE_THRESHOLD_MASK			0xff
+#define	BCH_MODE_ERASE_THRESHOLD_OFFSET			0
+
+#define	BCH_ENCODEPTR_ADDR_MASK				0xffffffff
+#define	BCH_ENCODEPTR_ADDR_OFFSET			0
+
+#define	BCH_DATAPTR_ADDR_MASK				0xffffffff
+#define	BCH_DATAPTR_ADDR_OFFSET				0
+
+#define	BCH_METAPTR_ADDR_MASK				0xffffffff
+#define	BCH_METAPTR_ADDR_OFFSET				0
+
+#define	BCH_LAYOUTSELECT_CS15_SELECT_MASK		(0x3 << 30)
+#define	BCH_LAYOUTSELECT_CS15_SELECT_OFFSET		30
+#define	BCH_LAYOUTSELECT_CS14_SELECT_MASK		(0x3 << 28)
+#define	BCH_LAYOUTSELECT_CS14_SELECT_OFFSET		28
+#define	BCH_LAYOUTSELECT_CS13_SELECT_MASK		(0x3 << 26)
+#define	BCH_LAYOUTSELECT_CS13_SELECT_OFFSET		26
+#define	BCH_LAYOUTSELECT_CS12_SELECT_MASK		(0x3 << 24)
+#define	BCH_LAYOUTSELECT_CS12_SELECT_OFFSET		24
+#define	BCH_LAYOUTSELECT_CS11_SELECT_MASK		(0x3 << 22)
+#define	BCH_LAYOUTSELECT_CS11_SELECT_OFFSET		22
+#define	BCH_LAYOUTSELECT_CS10_SELECT_MASK		(0x3 << 20)
+#define	BCH_LAYOUTSELECT_CS10_SELECT_OFFSET		20
+#define	BCH_LAYOUTSELECT_CS9_SELECT_MASK		(0x3 << 18)
+#define	BCH_LAYOUTSELECT_CS9_SELECT_OFFSET		18
+#define	BCH_LAYOUTSELECT_CS8_SELECT_MASK		(0x3 << 16)
+#define	BCH_LAYOUTSELECT_CS8_SELECT_OFFSET		16
+#define	BCH_LAYOUTSELECT_CS7_SELECT_MASK		(0x3 << 14)
+#define	BCH_LAYOUTSELECT_CS7_SELECT_OFFSET		14
+#define	BCH_LAYOUTSELECT_CS6_SELECT_MASK		(0x3 << 12)
+#define	BCH_LAYOUTSELECT_CS6_SELECT_OFFSET		12
+#define	BCH_LAYOUTSELECT_CS5_SELECT_MASK		(0x3 << 10)
+#define	BCH_LAYOUTSELECT_CS5_SELECT_OFFSET		10
+#define	BCH_LAYOUTSELECT_CS4_SELECT_MASK		(0x3 << 8)
+#define	BCH_LAYOUTSELECT_CS4_SELECT_OFFSET		8
+#define	BCH_LAYOUTSELECT_CS3_SELECT_MASK		(0x3 << 6)
+#define	BCH_LAYOUTSELECT_CS3_SELECT_OFFSET		6
+#define	BCH_LAYOUTSELECT_CS2_SELECT_MASK		(0x3 << 4)
+#define	BCH_LAYOUTSELECT_CS2_SELECT_OFFSET		4
+#define	BCH_LAYOUTSELECT_CS1_SELECT_MASK		(0x3 << 2)
+#define	BCH_LAYOUTSELECT_CS1_SELECT_OFFSET		2
+#define	BCH_LAYOUTSELECT_CS0_SELECT_MASK		(0x3 << 0)
+#define	BCH_LAYOUTSELECT_CS0_SELECT_OFFSET		0
+
+#define	BCH_FLASHLAYOUT0_NBLOCKS_MASK			(0xff << 24)
+#define	BCH_FLASHLAYOUT0_NBLOCKS_OFFSET			24
+#define	BCH_FLASHLAYOUT0_META_SIZE_MASK			(0xff << 16)
+#define	BCH_FLASHLAYOUT0_META_SIZE_OFFSET		16
+#define	BCH_FLASHLAYOUT0_ECC0_MASK			(0xf << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_OFFSET			12
+#define	BCH_FLASHLAYOUT0_ECC0_NONE			(0x0 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC2			(0x1 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC4			(0x2 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC6			(0x3 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC8			(0x4 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC10			(0x5 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC12			(0x6 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC14			(0x7 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC16			(0x8 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC18			(0x9 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC20			(0xa << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC22			(0xb << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC24			(0xc << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC26			(0xd << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC28			(0xe << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC30			(0xf << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC32			(0x10 << 12)
+#define	BCH_FLASHLAYOUT0_GF13_0_GF14_1			(1 << 10)
+#define	BCH_FLASHLAYOUT0_DATA0_SIZE_MASK		0xfff
+#define	BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET		0
+
+#define	BCH_FLASHLAYOUT1_PAGE_SIZE_MASK			(0xffff << 16)
+#define	BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET		16
+#define	BCH_FLASHLAYOUT1_ECCN_MASK			(0xf << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_OFFSET			12
+#define	BCH_FLASHLAYOUT1_ECCN_NONE			(0x0 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC2			(0x1 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC4			(0x2 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC6			(0x3 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC8			(0x4 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC10			(0x5 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC12			(0x6 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC14			(0x7 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC16			(0x8 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC18			(0x9 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC20			(0xa << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC22			(0xb << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC24			(0xc << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC26			(0xd << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC28			(0xe << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC30			(0xf << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC32			(0x10 << 12)
+#define	BCH_FLASHLAYOUT1_GF13_0_GF14_1			(1 << 10)
+#define	BCH_FLASHLAYOUT1_DATAN_SIZE_MASK		0xfff
+#define	BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET		0
+
+#define	BCH_DEBUG0_RSVD1_MASK				(0x1f << 27)
+#define	BCH_DEBUG0_RSVD1_OFFSET				27
+#define	BCH_DEBUG0_ROM_BIST_ENABLE			(1 << 26)
+#define	BCH_DEBUG0_ROM_BIST_COMPLETE			(1 << 25)
+#define	BCH_DEBUG0_KES_DEBUG_SYNDROME_SYMBOL_MASK	(0x1ff << 16)
+#define	BCH_DEBUG0_KES_DEBUG_SYNDROME_SYMBOL_OFFSET	16
+#define	BCH_DEBUG0_KES_DEBUG_SYNDROME_SYMBOL_NORMAL	(0x0 << 16)
+#define	BCH_DEBUG0_KES_DEBUG_SYNDROME_SYMBOL_TEST_MODE	(0x1 << 16)
+#define	BCH_DEBUG0_KES_DEBUG_SHIFT_SYND			(1 << 15)
+#define	BCH_DEBUG0_KES_DEBUG_PAYLOAD_FLAG		(1 << 14)
+#define	BCH_DEBUG0_KES_DEBUG_MODE4K			(1 << 13)
+#define	BCH_DEBUG0_KES_DEBUG_KICK			(1 << 12)
+#define	BCH_DEBUG0_KES_STANDALONE			(1 << 11)
+#define	BCH_DEBUG0_KES_DEBUG_STEP			(1 << 10)
+#define	BCH_DEBUG0_KES_DEBUG_STALL			(1 << 9)
+#define	BCH_DEBUG0_BM_KES_TEST_BYPASS			(1 << 8)
+#define	BCH_DEBUG0_RSVD0_MASK				(0x3 << 6)
+#define	BCH_DEBUG0_RSVD0_OFFSET				6
+#define	BCH_DEBUG0_DEBUG_REG_SELECT_MASK		0x3f
+#define	BCH_DEBUG0_DEBUG_REG_SELECT_OFFSET		0
+
+#define	BCH_DBGKESREAD_VALUES_MASK			0xffffffff
+#define	BCH_DBGKESREAD_VALUES_OFFSET			0
+
+#define	BCH_DBGCSFEREAD_VALUES_MASK			0xffffffff
+#define	BCH_DBGCSFEREAD_VALUES_OFFSET			0
+
+#define	BCH_DBGSYNDGENREAD_VALUES_MASK			0xffffffff
+#define	BCH_DBGSYNDGENREAD_VALUES_OFFSET		0
+
+#define	BCH_DBGAHBMREAD_VALUES_MASK			0xffffffff
+#define	BCH_DBGAHBMREAD_VALUES_OFFSET			0
+
+#define	BCH_BLOCKNAME_NAME_MASK				0xffffffff
+#define	BCH_BLOCKNAME_NAME_OFFSET			0
+
+#define	BCH_VERSION_MAJOR_MASK				(0xff << 24)
+#define	BCH_VERSION_MAJOR_OFFSET			24
+#define	BCH_VERSION_MINOR_MASK				(0xff << 16)
+#define	BCH_VERSION_MINOR_OFFSET			16
+#define	BCH_VERSION_STEP_MASK				0xffff
+#define	BCH_VERSION_STEP_OFFSET				0
+
+#endif	/* __MX28_REGS_BCH_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-clkctrl.h b/arch/arm/include/asm/arch-mx28/regs-clkctrl.h
new file mode 100644
index 0000000..93d0397
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-clkctrl.h
@@ -0,0 +1,312 @@
+/*
+ * Freescale i.MX28 CLKCTRL Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_CLKCTRL_H__
+#define __MX28_REGS_CLKCTRL_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_clkctrl_regs {
+	mx28_reg(hw_clkctrl_pll0ctrl0)		/* 0x00 */
+	mx28_reg(hw_clkctrl_pll0ctrl1)		/* 0x10 */
+	mx28_reg(hw_clkctrl_pll1ctrl0)		/* 0x20 */
+	mx28_reg(hw_clkctrl_pll1ctrl1)		/* 0x30 */
+	mx28_reg(hw_clkctrl_pll2ctrl0)		/* 0x40 */
+	mx28_reg(hw_clkctrl_cpu)		/* 0x50 */
+	mx28_reg(hw_clkctrl_hbus)		/* 0x60 */
+	mx28_reg(hw_clkctrl_xbus)		/* 0x70 */
+	mx28_reg(hw_clkctrl_xtal)		/* 0x80 */
+	mx28_reg(hw_clkctrl_ssp0)		/* 0x90 */
+	mx28_reg(hw_clkctrl_ssp1)		/* 0xa0 */
+	mx28_reg(hw_clkctrl_ssp2)		/* 0xb0 */
+	mx28_reg(hw_clkctrl_ssp3)		/* 0xc0 */
+	mx28_reg(hw_clkctrl_gpmi)		/* 0xd0 */
+	mx28_reg(hw_clkctrl_spdif)		/* 0xe0 */
+	mx28_reg(hw_clkctrl_emi)		/* 0xf0 */
+	mx28_reg(hw_clkctrl_saif0)		/* 0x100 */
+	mx28_reg(hw_clkctrl_saif1)		/* 0x110 */
+	mx28_reg(hw_clkctrl_lcdif)		/* 0x120 */
+	mx28_reg(hw_clkctrl_etm)		/* 0x130 */
+	mx28_reg(hw_clkctrl_enet)		/* 0x140 */
+	mx28_reg(hw_clkctrl_hsadc)		/* 0x150 */
+	mx28_reg(hw_clkctrl_flexcan)		/* 0x160 */
+
+	uint32_t	reserved[16];
+
+	mx28_reg(hw_clkctrl_frac0)		/* 0x1b0 */
+	mx28_reg(hw_clkctrl_frac1)		/* 0x1c0 */
+	mx28_reg(hw_clkctrl_clkseq)		/* 0x1d0 */
+	mx28_reg(hw_clkctrl_reset)		/* 0x1e0 */
+	mx28_reg(hw_clkctrl_status)		/* 0x1f0 */
+	mx28_reg(hw_clkctrl_version)		/* 0x200 */
+};
+#endif
+
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_MASK		(0x3 << 28)
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_OFFSET	28
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_DEFAULT	(0x0 << 28)
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_TIMES_2	(0x1 << 28)
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_TIMES_05	(0x2 << 28)
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_UNDEFINED	(0x3 << 28)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_MASK		(0x3 << 24)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_OFFSET		24
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_DEFAULT	(0x0 << 24)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_TIMES_2	(0x1 << 24)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_TIMES_05	(0x2 << 24)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_UNDEFINED	(0x3 << 24)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_MASK		(0x3 << 20)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_OFFSET	20
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_DEFAULT	(0x0 << 20)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_LOWER		(0x1 << 20)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_LOWEST	(0x2 << 20)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_UNDEFINED	(0x3 << 20)
+#define	CLKCTRL_PLL0CTRL0_EN_USB_CLKS		(1 << 18)
+#define	CLKCTRL_PLL0CTRL0_POWER			(1 << 17)
+
+#define	CLKCTRL_PLL0CTRL1_LOCK			(1 << 31)
+#define	CLKCTRL_PLL0CTRL1_FORCE_LOCK		(1 << 30)
+#define	CLKCTRL_PLL0CTRL1_LOCK_COUNT_MASK	0xffff
+#define	CLKCTRL_PLL0CTRL1_LOCK_COUNT_OFFSET	0
+
+#define	CLKCTRL_PLL1CTRL0_CLKGATEEMI		(1 << 31)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_MASK		(0x3 << 28)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_OFFSET	28
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_DEFAULT	(0x0 << 28)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_TIMES_2	(0x1 << 28)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_TIMES_05	(0x2 << 28)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_UNDEFINED	(0x3 << 28)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_MASK		(0x3 << 24)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_OFFSET		24
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_DEFAULT	(0x0 << 24)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_TIMES_2	(0x1 << 24)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_TIMES_05	(0x2 << 24)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_UNDEFINED	(0x3 << 24)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_MASK		(0x3 << 20)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_OFFSET	20
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_DEFAULT	(0x0 << 20)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_LOWER		(0x1 << 20)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_LOWEST	(0x2 << 20)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_UNDEFINED	(0x3 << 20)
+#define	CLKCTRL_PLL1CTRL0_EN_USB_CLKS		(1 << 18)
+#define	CLKCTRL_PLL1CTRL0_POWER			(1 << 17)
+
+#define	CLKCTRL_PLL1CTRL1_LOCK			(1 << 31)
+#define	CLKCTRL_PLL1CTRL1_FORCE_LOCK		(1 << 30)
+#define	CLKCTRL_PLL1CTRL1_LOCK_COUNT_MASK	0xffff
+#define	CLKCTRL_PLL1CTRL1_LOCK_COUNT_OFFSET	0
+
+#define	CLKCTRL_PLL2CTRL0_CLKGATE		(1 << 31)
+#define	CLKCTRL_PLL2CTRL0_LFR_SEL_MASK		(0x3 << 28)
+#define	CLKCTRL_PLL2CTRL0_LFR_SEL_OFFSET	28
+#define	CLKCTRL_PLL2CTRL0_HOLD_RING_OFF_B	(1 << 26)
+#define	CLKCTRL_PLL2CTRL0_CP_SEL_MASK		(0x3 << 24)
+#define	CLKCTRL_PLL2CTRL0_CP_SEL_OFFSET		24
+#define	CLKCTRL_PLL2CTRL0_POWER			(1 << 23)
+
+#define	CLKCTRL_CPU_BUSY_REF_XTAL		(1 << 29)
+#define	CLKCTRL_CPU_BUSY_REF_CPU		(1 << 28)
+#define	CLKCTRL_CPU_DIV_XTAL_FRAC_EN		(1 << 26)
+#define	CLKCTRL_CPU_DIV_XTAL_MASK		(0x3ff << 16)
+#define	CLKCTRL_CPU_DIV_XTAL_OFFSET		16
+#define	CLKCTRL_CPU_INTERRUPT_WAIT		(1 << 12)
+#define	CLKCTRL_CPU_DIV_CPU_FRAC_EN		(1 << 10)
+#define	CLKCTRL_CPU_DIV_CPU_MASK		0x3f
+#define	CLKCTRL_CPU_DIV_CPU_OFFSET		0
+
+#define	CLKCTRL_HBUS_ASM_BUSY			(1 << 31)
+#define	CLKCTRL_HBUS_DCP_AS_ENABLE		(1 << 30)
+#define	CLKCTRL_HBUS_PXP_AS_ENABLE		(1 << 29)
+#define	CLKCTRL_HBUS_ASM_EMIPORT_AS_ENABLE	(1 << 27)
+#define	CLKCTRL_HBUS_APBHDMA_AS_ENABLE		(1 << 26)
+#define	CLKCTRL_HBUS_APBXDMA_AS_ENABLE		(1 << 25)
+#define	CLKCTRL_HBUS_TRAFFIC_JAM_AS_ENABLE	(1 << 24)
+#define	CLKCTRL_HBUS_TRAFFIC_AS_ENABLE		(1 << 23)
+#define	CLKCTRL_HBUS_CPU_DATA_AS_ENABLE		(1 << 22)
+#define	CLKCTRL_HBUS_CPU_INSTR_AS_ENABLE	(1 << 21)
+#define	CLKCTRL_HBUS_ASM_ENABLE			(1 << 20)
+#define	CLKCTRL_HBUS_AUTO_CLEAR_DIV_ENABLE	(1 << 19)
+#define	CLKCTRL_HBUS_SLOW_DIV_MASK		(0x7 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_OFFSET		16
+#define	CLKCTRL_HBUS_SLOW_DIV_BY1		(0x0 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY2		(0x1 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY4		(0x2 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY8		(0x3 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY16		(0x4 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY32		(0x5 << 16)
+#define	CLKCTRL_HBUS_DIV_FRAC_EN		(1 << 5)
+#define	CLKCTRL_HBUS_DIV_MASK			0x1f
+#define	CLKCTRL_HBUS_DIV_OFFSET			0
+
+#define	CLKCTRL_XBUS_BUSY			(1 << 31)
+#define	CLKCTRL_XBUS_AUTO_CLEAR_DIV_ENABLE	(1 << 11)
+#define	CLKCTRL_XBUS_DIV_FRAC_EN		(1 << 10)
+#define	CLKCTRL_XBUS_DIV_MASK			0x3ff
+#define	CLKCTRL_XBUS_DIV_OFFSET			0
+
+#define	CLKCTRL_XTAL_UART_CLK_GATE		(1 << 31)
+#define	CLKCTRL_XTAL_PWM_CLK24M_GATE		(1 << 29)
+#define	CLKCTRL_XTAL_TIMROT_CLK32K_GATE		(1 << 26)
+#define	CLKCTRL_XTAL_DIV_UART_MASK		0x3
+#define	CLKCTRL_XTAL_DIV_UART_OFFSET		0
+
+#define	CLKCTRL_SSP_CLKGATE			(1 << 31)
+#define	CLKCTRL_SSP_BUSY			(1 << 29)
+#define	CLKCTRL_SSP_DIV_FRAC_EN			(1 << 9)
+#define	CLKCTRL_SSP_DIV_MASK			0x1ff
+#define	CLKCTRL_SSP_DIV_OFFSET			0
+
+#define	CLKCTRL_GPMI_CLKGATE			(1 << 31)
+#define	CLKCTRL_GPMI_BUSY			(1 << 29)
+#define	CLKCTRL_GPMI_DIV_FRAC_EN		(1 << 10)
+#define	CLKCTRL_GPMI_DIV_MASK			0x3ff
+#define	CLKCTRL_GPMI_DIV_OFFSET			0
+
+#define	CLKCTRL_SPDIF_CLKGATE			(1 << 31)
+
+#define	CLKCTRL_EMI_CLKGATE			(1 << 31)
+#define	CLKCTRL_EMI_SYNC_MODE_EN		(1 << 30)
+#define	CLKCTRL_EMI_BUSY_REF_XTAL		(1 << 29)
+#define	CLKCTRL_EMI_BUSY_REF_EMI		(1 << 28)
+#define	CLKCTRL_EMI_BUSY_REF_CPU		(1 << 27)
+#define	CLKCTRL_EMI_BUSY_SYNC_MODE		(1 << 26)
+#define	CLKCTRL_EMI_BUSY_DCC_RESYNC		(1 << 17)
+#define	CLKCTRL_EMI_DCC_RESYNC_ENABLE		(1 << 16)
+#define	CLKCTRL_EMI_DIV_XTAL_MASK		(0xf << 8)
+#define	CLKCTRL_EMI_DIV_XTAL_OFFSET		8
+#define	CLKCTRL_EMI_DIV_EMI_MASK		0x3f
+#define	CLKCTRL_EMI_DIV_EMI_OFFSET		0
+
+#define	CLKCTRL_SAIF0_CLKGATE			(1 << 31)
+#define	CLKCTRL_SAIF0_BUSY			(1 << 29)
+#define	CLKCTRL_SAIF0_DIV_FRAC_EN		(1 << 16)
+#define	CLKCTRL_SAIF0_DIV_MASK			0xffff
+#define	CLKCTRL_SAIF0_DIV_OFFSET		0
+
+#define	CLKCTRL_SAIF1_CLKGATE			(1 << 31)
+#define	CLKCTRL_SAIF1_BUSY			(1 << 29)
+#define	CLKCTRL_SAIF1_DIV_FRAC_EN		(1 << 16)
+#define	CLKCTRL_SAIF1_DIV_MASK			0xffff
+#define	CLKCTRL_SAIF1_DIV_OFFSET		0
+
+#define	CLKCTRL_DIS_LCDIF_CLKGATE		(1 << 31)
+#define	CLKCTRL_DIS_LCDIF_BUSY			(1 << 29)
+#define	CLKCTRL_DIS_LCDIF_DIV_FRAC_EN		(1 << 13)
+#define	CLKCTRL_DIS_LCDIF_DIV_MASK		0x1fff
+#define	CLKCTRL_DIS_LCDIF_DIV_OFFSET		0
+
+#define	CLKCTRL_ETM_CLKGATE			(1 << 31)
+#define	CLKCTRL_ETM_BUSY			(1 << 29)
+#define	CLKCTRL_ETM_DIV_FRAC_EN			(1 << 7)
+#define	CLKCTRL_ETM_DIV_MASK			0x7f
+#define	CLKCTRL_ETM_DIV_OFFSET			0
+
+#define	CLKCTRL_ENET_SLEEP			(1 << 31)
+#define	CLKCTRL_ENET_DISABLE			(1 << 30)
+#define	CLKCTRL_ENET_STATUS			(1 << 29)
+#define	CLKCTRL_ENET_BUSY_TIME			(1 << 27)
+#define	CLKCTRL_ENET_DIV_TIME_MASK		(0x3f << 21)
+#define	CLKCTRL_ENET_DIV_TIME_OFFSET		21
+#define	CLKCTRL_ENET_TIME_SEL_MASK		(0x3 << 19)
+#define	CLKCTRL_ENET_TIME_SEL_OFFSET		19
+#define	CLKCTRL_ENET_TIME_SEL_XTAL		(0x0 << 19)
+#define	CLKCTRL_ENET_TIME_SEL_PLL		(0x1 << 19)
+#define	CLKCTRL_ENET_TIME_SEL_RMII_CLK		(0x2 << 19)
+#define	CLKCTRL_ENET_TIME_SEL_UNDEFINED		(0x3 << 19)
+#define	CLKCTRL_ENET_CLK_OUT_EN			(1 << 18)
+#define	CLKCTRL_ENET_RESET_BY_SW_CHIP		(1 << 17)
+#define	CLKCTRL_ENET_RESET_BY_SW		(1 << 16)
+
+#define	CLKCTRL_HSADC_RESETB			(1 << 30)
+#define	CLKCTRL_HSADC_FREQDIV_MASK		(0x3 << 28)
+#define	CLKCTRL_HSADC_FREQDIV_OFFSET		28
+
+#define	CLKCTRL_FLEXCAN_STOP_CAN0		(1 << 30)
+#define	CLKCTRL_FLEXCAN_CAN0_STATUS		(1 << 29)
+#define	CLKCTRL_FLEXCAN_STOP_CAN1		(1 << 28)
+#define	CLKCTRL_FLEXCAN_CAN1_STATUS		(1 << 27)
+
+#define	CLKCTRL_FRAC0_CLKGATEIO0		(1 << 31)
+#define	CLKCTRL_FRAC0_IO0_STABLE		(1 << 30)
+#define	CLKCTRL_FRAC0_IO0FRAC_MASK		(0x3f << 24)
+#define	CLKCTRL_FRAC0_IO0FRAC_OFFSET		24
+#define	CLKCTRL_FRAC0_CLKGATEIO1		(1 << 23)
+#define	CLKCTRL_FRAC0_IO1_STABLE		(1 << 22)
+#define	CLKCTRL_FRAC0_IO1FRAC_MASK		(0x3f << 16)
+#define	CLKCTRL_FRAC0_IO1FRAC_OFFSET		16
+#define	CLKCTRL_FRAC0_CLKGATEEMI		(1 << 15)
+#define	CLKCTRL_FRAC0_EMI_STABLE		(1 << 14)
+#define	CLKCTRL_FRAC0_EMIFRAC_MASK		(0x3f << 8)
+#define	CLKCTRL_FRAC0_EMIFRAC_OFFSET		8
+#define	CLKCTRL_FRAC0_CLKGATECPU		(1 << 7)
+#define	CLKCTRL_FRAC0_CPU_STABLE		(1 << 6)
+#define	CLKCTRL_FRAC0_CPUFRAC_MASK		0x3f
+#define	CLKCTRL_FRAC0_CPUFRAC_OFFSET		0
+
+#define	CLKCTRL_FRAC1_CLKGATEGPMI		(1 << 23)
+#define	CLKCTRL_FRAC1_GPMI_STABLE		(1 << 22)
+#define	CLKCTRL_FRAC1_GPMIFRAC_MASK		(0x3f << 16)
+#define	CLKCTRL_FRAC1_GPMIFRAC_OFFSET		16
+#define	CLKCTRL_FRAC1_CLKGATEHSADC		(1 << 15)
+#define	CLKCTRL_FRAC1_HSADC_STABLE		(1 << 14)
+#define	CLKCTRL_FRAC1_HSADCFRAC_MASK		(0x3f << 8)
+#define	CLKCTRL_FRAC1_HSADCFRAC_OFFSET		8
+#define	CLKCTRL_FRAC1_CLKGATEPIX		(1 << 7)
+#define	CLKCTRL_FRAC1_PIX_STABLE		(1 << 6)
+#define	CLKCTRL_FRAC1_PIXFRAC_MASK		0x3f
+#define	CLKCTRL_FRAC1_PIXFRAC_OFFSET		0
+
+#define	CLKCTRL_CLKSEQ_BYPASS_CPU		(1 << 18)
+#define	CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF		(1 << 14)
+#define	CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF_BYPASS	(0x1 << 14)
+#define	CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF_PFD	(0x0 << 14)
+#define	CLKCTRL_CLKSEQ_BYPASS_ETM		(1 << 8)
+#define	CLKCTRL_CLKSEQ_BYPASS_EMI		(1 << 7)
+#define	CLKCTRL_CLKSEQ_BYPASS_SSP3		(1 << 6)
+#define	CLKCTRL_CLKSEQ_BYPASS_SSP2		(1 << 5)
+#define	CLKCTRL_CLKSEQ_BYPASS_SSP1		(1 << 4)
+#define	CLKCTRL_CLKSEQ_BYPASS_SSP0		(1 << 3)
+#define	CLKCTRL_CLKSEQ_BYPASS_GPMI		(1 << 2)
+#define	CLKCTRL_CLKSEQ_BYPASS_SAIF1		(1 << 1)
+#define	CLKCTRL_CLKSEQ_BYPASS_SAIF0		(1 << 0)
+
+#define	CLKCTRL_RESET_WDOG_POR_DISABLE		(1 << 5)
+#define	CLKCTRL_RESET_EXTERNAL_RESET_ENABLE	(1 << 4)
+#define	CLKCTRL_RESET_THERMAL_RESET_ENABLE	(1 << 3)
+#define	CLKCTRL_RESET_THERMAL_RESET_DEFAULT	(1 << 2)
+#define	CLKCTRL_RESET_CHIP			(1 << 1)
+#define	CLKCTRL_RESET_DIG			(1 << 0)
+
+#define	CLKCTRL_STATUS_CPU_LIMIT_MASK		(0x3 << 30)
+#define	CLKCTRL_STATUS_CPU_LIMIT_OFFSET		30
+
+#define	CLKCTRL_VERSION_MAJOR_MASK		(0xff << 24)
+#define	CLKCTRL_VERSION_MAJOR_OFFSET		24
+#define	CLKCTRL_VERSION_MINOR_MASK		(0xff << 16)
+#define	CLKCTRL_VERSION_MINOR_OFFSET		16
+#define	CLKCTRL_VERSION_STEP_MASK		0xffff
+#define	CLKCTRL_VERSION_STEP_OFFSET		0
+
+#endif /* __MX28_REGS_CLKCTRL_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-common.h b/arch/arm/include/asm/arch-mx28/regs-common.h
new file mode 100644
index 0000000..efe975b
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-common.h
@@ -0,0 +1,66 @@
+/*
+ * Freescale i.MX28 Register Accessors
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_COMMON_H__
+#define __MX28_REGS_COMMON_H__
+
+/*
+ * The i.MX28 has interesting feature when it comes to register access. There
+ * are four kinds of access to one particular register. Those are:
+ *
+ * 1) Common read/write access. To use this mode, just write to the address of
+ *    the register.
+ * 2) Set bits only access. To set bits, write which bits you want to set to the
+ *    address of the register + 0x4.
+ * 3) Clear bits only access. To clear bits, write which bits you want to clear
+ *    to the address of the register + 0x8.
+ * 4) Toggle bits only access. To toggle bits, write which bits you want to
+ *    toggle to the address of the register + 0xc.
+ *
+ * IMPORTANT NOTE: Not all registers support accesses 2-4! Also, not all bits
+ * can be set/cleared by pure write as in access type 1, some need to be
+ * explicitly set/cleared by using access type 2-3.
+ *
+ * The following macros and structures allow the user to either access the
+ * register in all aforementioned modes (by accessing reg_name, reg_name_set,
+ * reg_name_clr, reg_name_tog) or pass the register structure further into
+ * various functions with correct type information (by accessing reg_name_reg).
+ *
+ */
+
+#define	__mx28_reg(name)		\
+	uint32_t name;			\
+	uint32_t name##_set;		\
+	uint32_t name##_clr;		\
+	uint32_t name##_tog;
+
+struct mx28_register {
+	__mx28_reg(reg)
+};
+
+#define	mx28_reg(name)					\
+	union {						\
+		struct { __mx28_reg(name) };		\
+		struct mx28_register name##_reg;	\
+	};
+
+#endif	/* __MX28_REGS_COMMON_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-gpmi.h b/arch/arm/include/asm/arch-mx28/regs-gpmi.h
new file mode 100644
index 0000000..0096793
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-gpmi.h
@@ -0,0 +1,222 @@
+/*
+ * Freescale i.MX28 GPMI Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_GPMI_H__
+#define __MX28_REGS_GPMI_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_gpmi_regs {
+	mx28_reg(hw_gpmi_ctrl0)
+	mx28_reg(hw_gpmi_compare)
+	mx28_reg(hw_gpmi_eccctrl)
+	mx28_reg(hw_gpmi_ecccount)
+	mx28_reg(hw_gpmi_payload)
+	mx28_reg(hw_gpmi_auxiliary)
+	mx28_reg(hw_gpmi_ctrl1)
+	mx28_reg(hw_gpmi_timing0)
+	mx28_reg(hw_gpmi_timing1)
+
+	uint32_t	reserved[4];
+
+	mx28_reg(hw_gpmi_data)
+	mx28_reg(hw_gpmi_stat)
+	mx28_reg(hw_gpmi_debug)
+	mx28_reg(hw_gpmi_version)
+};
+#endif
+
+#define	GPMI_CTRL0_SFTRST				(1 << 31)
+#define	GPMI_CTRL0_CLKGATE				(1 << 30)
+#define	GPMI_CTRL0_RUN					(1 << 29)
+#define	GPMI_CTRL0_DEV_IRQ_EN				(1 << 28)
+#define	GPMI_CTRL0_LOCK_CS				(1 << 27)
+#define	GPMI_CTRL0_UDMA					(1 << 26)
+#define	GPMI_CTRL0_COMMAND_MODE_MASK			(0x3 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_OFFSET			24
+#define	GPMI_CTRL0_COMMAND_MODE_WRITE			(0x0 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_READ			(0x1 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_READ_AND_COMPARE	(0x2 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY		(0x3 << 24)
+#define	GPMI_CTRL0_WORD_LENGTH				(1 << 23)
+#define	GPMI_CTRL0_CS_MASK				(0x7 << 20)
+#define	GPMI_CTRL0_CS_OFFSET				20
+#define	GPMI_CTRL0_ADDRESS_MASK				(0x7 << 17)
+#define	GPMI_CTRL0_ADDRESS_OFFSET			17
+#define	GPMI_CTRL0_ADDRESS_NAND_DATA			(0x0 << 17)
+#define	GPMI_CTRL0_ADDRESS_NAND_CLE			(0x1 << 17)
+#define	GPMI_CTRL0_ADDRESS_NAND_ALE			(0x2 << 17)
+#define	GPMI_CTRL0_ADDRESS_INCREMENT			(1 << 16)
+#define	GPMI_CTRL0_XFER_COUNT_MASK			0xffff
+#define	GPMI_CTRL0_XFER_COUNT_OFFSET			0
+
+#define	GPMI_COMPARE_MASK_MASK				(0xffff << 16)
+#define	GPMI_COMPARE_MASK_OFFSET			16
+#define	GPMI_COMPARE_REFERENCE_MASK			0xffff
+#define	GPMI_COMPARE_REFERENCE_OFFSET			0
+
+#define	GPMI_ECCCTRL_HANDLE_MASK			(0xffff << 16)
+#define	GPMI_ECCCTRL_HANDLE_OFFSET			16
+#define	GPMI_ECCCTRL_ECC_CMD_MASK			(0x3 << 13)
+#define	GPMI_ECCCTRL_ECC_CMD_OFFSET			13
+#define	GPMI_ECCCTRL_ECC_CMD_DECODE			(0x0 << 13)
+#define	GPMI_ECCCTRL_ECC_CMD_ENCODE			(0x1 << 13)
+#define	GPMI_ECCCTRL_ENABLE_ECC				(1 << 12)
+#define	GPMI_ECCCTRL_BUFFER_MASK_MASK			0x1ff
+#define	GPMI_ECCCTRL_BUFFER_MASK_OFFSET			0
+#define	GPMI_ECCCTRL_BUFFER_MASK_BCH_AUXONLY		0x100
+#define	GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE		0x1ff
+
+#define	GPMI_ECCCOUNT_COUNT_MASK			0xffff
+#define	GPMI_ECCCOUNT_COUNT_OFFSET			0
+
+#define	GPMI_PAYLOAD_ADDRESS_MASK			(0x3fffffff << 2)
+#define	GPMI_PAYLOAD_ADDRESS_OFFSET			2
+
+#define	GPMI_AUXILIARY_ADDRESS_MASK			(0x3fffffff << 2)
+#define	GPMI_AUXILIARY_ADDRESS_OFFSET			2
+
+#define	GPMI_CTRL1_DECOUPLE_CS				(1 << 24)
+#define	GPMI_CTRL1_WRN_DLY_SEL_MASK			(0x3 << 22)
+#define	GPMI_CTRL1_WRN_DLY_SEL_OFFSET			22
+#define	GPMI_CTRL1_TIMEOUT_IRQ_EN			(1 << 20)
+#define	GPMI_CTRL1_GANGED_RDYBUSY			(1 << 19)
+#define	GPMI_CTRL1_BCH_MODE				(1 << 18)
+#define	GPMI_CTRL1_DLL_ENABLE				(1 << 17)
+#define	GPMI_CTRL1_HALF_PERIOD				(1 << 16)
+#define	GPMI_CTRL1_RDN_DELAY_MASK			(0xf << 12)
+#define	GPMI_CTRL1_RDN_DELAY_OFFSET			12
+#define	GPMI_CTRL1_DMA2ECC_MODE				(1 << 11)
+#define	GPMI_CTRL1_DEV_IRQ				(1 << 10)
+#define	GPMI_CTRL1_TIMEOUT_IRQ				(1 << 9)
+#define	GPMI_CTRL1_BURST_EN				(1 << 8)
+#define	GPMI_CTRL1_ABORT_WAIT_REQUEST			(1 << 7)
+#define	GPMI_CTRL1_ABORT_WAIT_FOR_READY_CHANNEL_MASK	(0x7 << 4)
+#define	GPMI_CTRL1_ABORT_WAIT_FOR_READY_CHANNEL_OFFSET	4
+#define	GPMI_CTRL1_DEV_RESET				(1 << 3)
+#define	GPMI_CTRL1_ATA_IRQRDY_POLARITY			(1 << 2)
+#define	GPMI_CTRL1_CAMERA_MODE				(1 << 1)
+#define	GPMI_CTRL1_GPMI_MODE				(1 << 0)
+
+#define	GPMI_TIMING0_ADDRESS_SETUP_MASK			(0xff << 16)
+#define	GPMI_TIMING0_ADDRESS_SETUP_OFFSET		16
+#define	GPMI_TIMING0_DATA_HOLD_MASK			(0xff << 8)
+#define	GPMI_TIMING0_DATA_HOLD_OFFSET			8
+#define	GPMI_TIMING0_DATA_SETUP_MASK			0xff
+#define	GPMI_TIMING0_DATA_SETUP_OFFSET			0
+
+#define	GPMI_TIMING1_DEVICE_BUSY_TIMEOUT_MASK		(0xffff << 16)
+#define	GPMI_TIMING1_DEVICE_BUSY_TIMEOUT_OFFSET		16
+
+#define	GPMI_TIMING2_UDMA_TRP_MASK			(0xff << 24)
+#define	GPMI_TIMING2_UDMA_TRP_OFFSET			24
+#define	GPMI_TIMING2_UDMA_ENV_MASK			(0xff << 16)
+#define	GPMI_TIMING2_UDMA_ENV_OFFSET			16
+#define	GPMI_TIMING2_UDMA_HOLD_MASK			(0xff << 8)
+#define	GPMI_TIMING2_UDMA_HOLD_OFFSET			8
+#define	GPMI_TIMING2_UDMA_SETUP_MASK			0xff
+#define	GPMI_TIMING2_UDMA_SETUP_OFFSET			0
+
+#define	GPMI_DATA_DATA_MASK				0xffffffff
+#define	GPMI_DATA_DATA_OFFSET				0
+
+#define	GPMI_STAT_READY_BUSY_MASK			(0xff << 24)
+#define	GPMI_STAT_READY_BUSY_OFFSET			24
+#define	GPMI_STAT_RDY_TIMEOUT_MASK			(0xff << 16)
+#define	GPMI_STAT_RDY_TIMEOUT_OFFSET			16
+#define	GPMI_STAT_DEV7_ERROR				(1 << 15)
+#define	GPMI_STAT_DEV6_ERROR				(1 << 14)
+#define	GPMI_STAT_DEV5_ERROR				(1 << 13)
+#define	GPMI_STAT_DEV4_ERROR				(1 << 12)
+#define	GPMI_STAT_DEV3_ERROR				(1 << 11)
+#define	GPMI_STAT_DEV2_ERROR				(1 << 10)
+#define	GPMI_STAT_DEV1_ERROR				(1 << 9)
+#define	GPMI_STAT_DEV0_ERROR				(1 << 8)
+#define	GPMI_STAT_ATA_IRQ				(1 << 4)
+#define	GPMI_STAT_INVALID_BUFFER_MASK			(1 << 3)
+#define	GPMI_STAT_FIFO_EMPTY				(1 << 2)
+#define	GPMI_STAT_FIFO_FULL				(1 << 1)
+#define	GPMI_STAT_PRESENT				(1 << 0)
+
+#define	GPMI_DEBUG_WAIT_FOR_READY_END_MASK		(0xff << 24)
+#define	GPMI_DEBUG_WAIT_FOR_READY_END_OFFSET		24
+#define	GPMI_DEBUG_DMA_SENSE_MASK			(0xff << 16)
+#define	GPMI_DEBUG_DMA_SENSE_OFFSET			16
+#define	GPMI_DEBUG_DMAREQ_MASK				(0xff << 8)
+#define	GPMI_DEBUG_DMAREQ_OFFSET			8
+#define	GPMI_DEBUG_CMD_END_MASK				0xff
+#define	GPMI_DEBUG_CMD_END_OFFSET			0
+
+#define	GPMI_VERSION_MAJOR_MASK				(0xff << 24)
+#define	GPMI_VERSION_MAJOR_OFFSET			24
+#define	GPMI_VERSION_MINOR_MASK				(0xff << 16)
+#define	GPMI_VERSION_MINOR_OFFSET			16
+#define	GPMI_VERSION_STEP_MASK				0xffff
+#define	GPMI_VERSION_STEP_OFFSET			0
+
+#define	GPMI_DEBUG2_UDMA_STATE_MASK			(0xf << 24)
+#define	GPMI_DEBUG2_UDMA_STATE_OFFSET			24
+#define	GPMI_DEBUG2_BUSY				(1 << 23)
+#define	GPMI_DEBUG2_PIN_STATE_MASK			(0x7 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_OFFSET			20
+#define	GPMI_DEBUG2_PIN_STATE_PSM_IDLE			(0x0 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_BYTCNT		(0x1 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_ADDR			(0x2 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_STALL			(0x3 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_STROBE		(0x4 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_ATARDY		(0x5 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_DHOLD			(0x6 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_DONE			(0x7 << 20)
+#define	GPMI_DEBUG2_MAIN_STATE_MASK			(0xf << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_OFFSET			16
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_IDLE			(0x0 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_BYTCNT		(0x1 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_WAITFE		(0x2 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_WAITFR		(0x3 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_DMAREQ		(0x4 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_DMAACK		(0x5 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_WAITFF		(0x6 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_LDFIFO		(0x7 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_LDDMAR		(0x8 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_RDCMP		(0x9 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_DONE			(0xa << 16)
+#define	GPMI_DEBUG2_SYND2GPMI_BE_MASK			(0xf << 12)
+#define	GPMI_DEBUG2_SYND2GPMI_BE_OFFSET			12
+#define	GPMI_DEBUG2_GPMI2SYND_VALID			(1 << 11)
+#define	GPMI_DEBUG2_GPMI2SYND_READY			(1 << 10)
+#define	GPMI_DEBUG2_SYND2GPMI_VALID			(1 << 9)
+#define	GPMI_DEBUG2_SYND2GPMI_READY			(1 << 8)
+#define	GPMI_DEBUG2_VIEW_DELAYED_RDN			(1 << 7)
+#define	GPMI_DEBUG2_UPDATE_WINDOW			(1 << 6)
+#define	GPMI_DEBUG2_RDN_TAP_MASK			0x3f
+#define	GPMI_DEBUG2_RDN_TAP_OFFSET			0
+
+#define	GPMI_DEBUG3_APB_WORD_CNTR_MASK			(0xffff << 16)
+#define	GPMI_DEBUG3_APB_WORD_CNTR_OFFSET		16
+#define	GPMI_DEBUG3_DEV_WORD_CNTR_MASK			0xffff
+#define	GPMI_DEBUG3_DEV_WORD_CNTR_OFFSET		0
+
+#endif	/* __MX28_REGS_GPMI_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-i2c.h b/arch/arm/include/asm/arch-mx28/regs-i2c.h
new file mode 100644
index 0000000..30e0ed7
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-i2c.h
@@ -0,0 +1,207 @@
+/*
+ * Freescale i.MX28 I2C Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_I2C_H__
+#define __MX28_REGS_I2C_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_i2c_regs {
+	mx28_reg(hw_i2c_ctrl0)
+	mx28_reg(hw_i2c_timing0)
+	mx28_reg(hw_i2c_timing1)
+	mx28_reg(hw_i2c_timing2)
+	mx28_reg(hw_i2c_ctrl1)
+	mx28_reg(hw_i2c_stat)
+	mx28_reg(hw_i2c_queuectrl)
+	mx28_reg(hw_i2c_queuestat)
+	mx28_reg(hw_i2c_queuecmd)
+	mx28_reg(hw_i2c_queuedata)
+	mx28_reg(hw_i2c_data)
+	mx28_reg(hw_i2c_debug0)
+	mx28_reg(hw_i2c_debug1)
+	mx28_reg(hw_i2c_version)
+};
+#endif
+
+#define	I2C_CTRL_SFTRST				(1 << 31)
+#define	I2C_CTRL_CLKGATE			(1 << 30)
+#define	I2C_CTRL_RUN				(1 << 29)
+#define	I2C_CTRL_PREACK				(1 << 27)
+#define	I2C_CTRL_ACKNOWLEDGE			(1 << 26)
+#define	I2C_CTRL_SEND_NAK_ON_LAST		(1 << 25)
+#define	I2C_CTRL_MULTI_MASTER			(1 << 23)
+#define	I2C_CTRL_CLOCK_HELD			(1 << 22)
+#define	I2C_CTRL_RETAIN_CLOCK			(1 << 21)
+#define	I2C_CTRL_POST_SEND_STOP			(1 << 20)
+#define	I2C_CTRL_PRE_SEND_START			(1 << 19)
+#define	I2C_CTRL_SLAVE_ADDRESS_ENABLE		(1 << 18)
+#define	I2C_CTRL_MASTER_MODE			(1 << 17)
+#define	I2C_CTRL_DIRECTION			(1 << 16)
+#define	I2C_CTRL_XFER_COUNT_MASK		0xffff
+#define	I2C_CTRL_XFER_COUNT_OFFSET		0
+
+#define	I2C_TIMING0_HIGH_COUNT_MASK		(0x3ff << 16)
+#define	I2C_TIMING0_HIGH_COUNT_OFFSET		16
+#define	I2C_TIMING0_RCV_COUNT_MASK		0x3ff
+#define	I2C_TIMING0_RCV_COUNT_OFFSET		0
+
+#define	I2C_TIMING1_LOW_COUNT_MASK		(0x3ff << 16)
+#define	I2C_TIMING1_LOW_COUNT_OFFSET		16
+#define	I2C_TIMING1_XMIT_COUNT_MASK		0x3ff
+#define	I2C_TIMING1_XMIT_COUNT_OFFSET		0
+
+#define	I2C_TIMING2_BUS_FREE_MASK		(0x3ff << 16)
+#define	I2C_TIMING2_BUS_FREE_OFFSET		16
+#define	I2C_TIMING2_LEADIN_COUNT_MASK		0x3ff
+#define	I2C_TIMING2_LEADIN_COUNT_OFFSET		0
+
+#define	I2C_CTRL1_RD_QUEUE_IRQ			(1 << 30)
+#define	I2C_CTRL1_WR_QUEUE_IRQ			(1 << 29)
+#define	I2C_CTRL1_CLR_GOT_A_NAK			(1 << 28)
+#define	I2C_CTRL1_ACK_MODE			(1 << 27)
+#define	I2C_CTRL1_FORCE_DATA_IDLE		(1 << 26)
+#define	I2C_CTRL1_FORCE_CLK_IDLE		(1 << 25)
+#define	I2C_CTRL1_BCAST_SLAVE_EN		(1 << 24)
+#define	I2C_CTRL1_SLAVE_ADDRESS_BYTE_MASK	(0xff << 16)
+#define	I2C_CTRL1_SLAVE_ADDRESS_BYTE_OFFSET	16
+#define	I2C_CTRL1_BUS_FREE_IRQ_EN		(1 << 15)
+#define	I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ_EN	(1 << 14)
+#define	I2C_CTRL1_NO_SLAVE_ACK_IRQ_EN		(1 << 13)
+#define	I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ_EN	(1 << 12)
+#define	I2C_CTRL1_EARLY_TERM_IRQ_EN		(1 << 11)
+#define	I2C_CTRL1_MASTER_LOSS_IRQ_EN		(1 << 10)
+#define	I2C_CTRL1_SLAVE_STOP_IRQ_EN		(1 << 9)
+#define	I2C_CTRL1_SLAVE_IRQ_EN			(1 << 8)
+#define	I2C_CTRL1_BUS_FREE_IRQ			(1 << 7)
+#define	I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ		(1 << 6)
+#define	I2C_CTRL1_NO_SLAVE_ACK_IRQ		(1 << 5)
+#define	I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ	(1 << 4)
+#define	I2C_CTRL1_EARLY_TERM_IRQ		(1 << 3)
+#define	I2C_CTRL1_MASTER_LOSS_IRQ		(1 << 2)
+#define	I2C_CTRL1_SLAVE_STOP_IRQ		(1 << 1)
+#define	I2C_CTRL1_SLAVE_IRQ			(1 << 0)
+
+#define	I2C_STAT_MASTER_PRESENT			(1 << 31)
+#define	I2C_STAT_SLAVE_PRESENT			(1 << 30)
+#define	I2C_STAT_ANY_ENABLED_IRQ		(1 << 29)
+#define	I2C_STAT_GOT_A_NAK			(1 << 28)
+#define	I2C_STAT_RCVD_SLAVE_ADDR_MASK		(0xff << 16)
+#define	I2C_STAT_RCVD_SLAVE_ADDR_OFFSET		16
+#define	I2C_STAT_SLAVE_ADDR_EQ_ZERO		(1 << 15)
+#define	I2C_STAT_SLAVE_FOUND			(1 << 14)
+#define	I2C_STAT_SLAVE_SEARCHING		(1 << 13)
+#define	I2C_STAT_DATA_ENGING_DMA_WAIT		(1 << 12)
+#define	I2C_STAT_BUS_BUSY			(1 << 11)
+#define	I2C_STAT_CLK_GEN_BUSY			(1 << 10)
+#define	I2C_STAT_DATA_ENGINE_BUSY		(1 << 9)
+#define	I2C_STAT_SLAVE_BUSY			(1 << 8)
+#define	I2C_STAT_BUS_FREE_IRQ_SUMMARY		(1 << 7)
+#define	I2C_STAT_DATA_ENGINE_CMPLT_IRQ_SUMMARY	(1 << 6)
+#define	I2C_STAT_NO_SLAVE_ACK_IRQ_SUMMARY	(1 << 5)
+#define	I2C_STAT_OVERSIZE_XFER_TERM_IRQ_SUMMARY	(1 << 4)
+#define	I2C_STAT_EARLY_TERM_IRQ_SUMMARY		(1 << 3)
+#define	I2C_STAT_MASTER_LOSS_IRQ_SUMMARY	(1 << 2)
+#define	I2C_STAT_SLAVE_STOP_IRQ_SUMMARY		(1 << 1)
+#define	I2C_STAT_SLAVE_IRQ_SUMMARY		(1 << 0)
+
+#define	I2C_QUEUECTRL_RD_THRESH_MASK		(0x1f << 16)
+#define	I2C_QUEUECTRL_RD_THRESH_OFFSET		16
+#define	I2C_QUEUECTRL_WR_THRESH_MASK		(0x1f << 8)
+#define	I2C_QUEUECTRL_WR_THRESH_OFFSET		8
+#define	I2C_QUEUECTRL_QUEUE_RUN			(1 << 5)
+#define	I2C_QUEUECTRL_RD_CLEAR			(1 << 4)
+#define	I2C_QUEUECTRL_WR_CLEAR			(1 << 3)
+#define	I2C_QUEUECTRL_PIO_QUEUE_MODE		(1 << 2)
+#define	I2C_QUEUECTRL_RD_QUEUE_IRQ_EN		(1 << 1)
+#define	I2C_QUEUECTRL_WR_QUEUE_IRQ_EN		(1 << 0)
+
+#define	I2C_QUEUESTAT_RD_QUEUE_FULL		(1 << 14)
+#define	I2C_QUEUESTAT_RD_QUEUE_EMPTY		(1 << 13)
+#define	I2C_QUEUESTAT_RD_QUEUE_CNT_MASK		(0x1f << 8)
+#define	I2C_QUEUESTAT_RD_QUEUE_CNT_OFFSET	8
+#define	I2C_QUEUESTAT_WR_QUEUE_FULL		(1 << 6)
+#define	I2C_QUEUESTAT_WR_QUEUE_EMPTY		(1 << 5)
+#define	I2C_QUEUESTAT_WR_QUEUE_CNT_MASK		0x1f
+#define	I2C_QUEUESTAT_WR_QUEUE_CNT_OFFSET	0
+
+#define	I2C_QUEUECMD_PREACK			(1 << 27)
+#define	I2C_QUEUECMD_ACKNOWLEDGE		(1 << 26)
+#define	I2C_QUEUECMD_SEND_NAK_ON_LAST		(1 << 25)
+#define	I2C_QUEUECMD_MULTI_MASTER		(1 << 23)
+#define	I2C_QUEUECMD_CLOCK_HELD			(1 << 22)
+#define	I2C_QUEUECMD_RETAIN_CLOCK		(1 << 21)
+#define	I2C_QUEUECMD_POST_SEND_STOP		(1 << 20)
+#define	I2C_QUEUECMD_PRE_SEND_START		(1 << 19)
+#define	I2C_QUEUECMD_SLAVE_ADDRESS_ENABLE	(1 << 18)
+#define	I2C_QUEUECMD_MASTER_MODE		(1 << 17)
+#define	I2C_QUEUECMD_DIRECTION			(1 << 16)
+#define	I2C_QUEUECMD_XFER_COUNT_MASK		0xffff
+#define	I2C_QUEUECMD_XFER_COUNT_OFFSET		0
+
+#define	I2C_QUEUEDATA_DATA_MASK			0xffffffff
+#define	I2C_QUEUEDATA_DATA_OFFSET		0
+
+#define	I2C_DATA_DATA_MASK			0xffffffff
+#define	I2C_DATA_DATA_OFFSET			0
+
+#define	I2C_DEBUG0_DMAREQ			(1 << 31)
+#define	I2C_DEBUG0_DMAENDCMD			(1 << 30)
+#define	I2C_DEBUG0_DMAKICK			(1 << 29)
+#define	I2C_DEBUG0_DMATERMINATE			(1 << 28)
+#define	I2C_DEBUG0_STATE_VALUE_MASK		(0x3 << 26)
+#define	I2C_DEBUG0_STATE_VALUE_OFFSET		26
+#define	I2C_DEBUG0_DMA_STATE_MASK		(0x3ff << 16)
+#define	I2C_DEBUG0_DMA_STATE_OFFSET		16
+#define	I2C_DEBUG0_START_TOGGLE			(1 << 15)
+#define	I2C_DEBUG0_STOP_TOGGLE			(1 << 14)
+#define	I2C_DEBUG0_GRAB_TOGGLE			(1 << 13)
+#define	I2C_DEBUG0_CHANGE_TOGGLE		(1 << 12)
+#define	I2C_DEBUG0_STATE_LATCH			(1 << 11)
+#define	I2C_DEBUG0_SLAVE_HOLD_CLK		(1 << 10)
+#define	I2C_DEBUG0_STATE_STATE_MASK		0x3ff
+#define	I2C_DEBUG0_STATE_STATE_OFFSET		0
+
+#define	I2C_DEBUG1_I2C_CLK_IN			(1 << 31)
+#define	I2C_DEBUG1_I2C_DATA_IN			(1 << 30)
+#define	I2C_DEBUG1_DMA_BYTE_ENABLES_MASK	(0xf << 24)
+#define	I2C_DEBUG1_DMA_BYTE_ENABLES_OFFSET	24
+#define	I2C_DEBUG1_CLK_GEN_STATE_MASK		(0xff << 16)
+#define	I2C_DEBUG1_CLK_GEN_STATE_OFFSET		16
+#define	I2C_DEBUG1_LST_MODE_MASK		(0x3 << 9)
+#define	I2C_DEBUG1_LST_MODE_OFFSET		9
+#define	I2C_DEBUG1_LOCAL_SLAVE_TEST		(1 << 8)
+#define	I2C_DEBUG1_FORCE_CLK_ON			(1 << 4)
+#define	I2C_DEBUG1_FORCE_ABR_LOSS		(1 << 3)
+#define	I2C_DEBUG1_FORCE_RCV_ACK		(1 << 2)
+#define	I2C_DEBUG1_FORCE_I2C_DATA_OE		(1 << 1)
+#define	I2C_DEBUG1_FORCE_I2C_CLK_OE		(1 << 0)
+
+#define	I2C_VERSION_MAJOR_MASK			(0xff << 24)
+#define	I2C_VERSION_MAJOR_OFFSET		24
+#define	I2C_VERSION_MINOR_MASK			(0xff << 16)
+#define	I2C_VERSION_MINOR_OFFSET		16
+#define	I2C_VERSION_STEP_MASK			0xffff
+#define	I2C_VERSION_STEP_OFFSET			0
+
+#endif	/* __MX28_REGS_I2C_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-ocotp.h b/arch/arm/include/asm/arch-mx28/regs-ocotp.h
new file mode 100644
index 0000000..ea2fd7b
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-ocotp.h
@@ -0,0 +1,173 @@
+/*
+ * Freescale i.MX28 OCOTP Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_OCOTP_H__
+#define __MX28_REGS_OCOTP_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_ocotp_regs {
+	mx28_reg(hw_ocotp_ctrl)		/* 0x0 */
+	mx28_reg(hw_ocotp_data)		/* 0x10 */
+	mx28_reg(hw_ocotp_cust0)	/* 0x20 */
+	mx28_reg(hw_ocotp_cust1)	/* 0x30 */
+	mx28_reg(hw_ocotp_cust2)	/* 0x40 */
+	mx28_reg(hw_ocotp_cust3)	/* 0x50 */
+	mx28_reg(hw_ocotp_crypto0)	/* 0x60 */
+	mx28_reg(hw_ocotp_crypto1)	/* 0x70 */
+	mx28_reg(hw_ocotp_crypto2)	/* 0x80 */
+	mx28_reg(hw_ocotp_crypto3)	/* 0x90 */
+	mx28_reg(hw_ocotp_hwcap0)	/* 0xa0 */
+	mx28_reg(hw_ocotp_hwcap1)	/* 0xb0 */
+	mx28_reg(hw_ocotp_hwcap2)	/* 0xc0 */
+	mx28_reg(hw_ocotp_hwcap3)	/* 0xd0 */
+	mx28_reg(hw_ocotp_hwcap4)	/* 0xe0 */
+	mx28_reg(hw_ocotp_hwcap5)	/* 0xf0 */
+	mx28_reg(hw_ocotp_swcap)	/* 0x100 */
+	mx28_reg(hw_ocotp_custcap)	/* 0x110 */
+	mx28_reg(hw_ocotp_lock)		/* 0x120 */
+	mx28_reg(hw_ocotp_ops0)		/* 0x130 */
+	mx28_reg(hw_ocotp_ops1)		/* 0x140 */
+	mx28_reg(hw_ocotp_ops2)		/* 0x150 */
+	mx28_reg(hw_ocotp_ops3)		/* 0x160 */
+	mx28_reg(hw_ocotp_un0)		/* 0x170 */
+	mx28_reg(hw_ocotp_un1)		/* 0x180 */
+	mx28_reg(hw_ocotp_un2)		/* 0x190 */
+	mx28_reg(hw_ocotp_rom0)		/* 0x1a0 */
+	mx28_reg(hw_ocotp_rom1)		/* 0x1b0 */
+	mx28_reg(hw_ocotp_rom2)		/* 0x1c0 */
+	mx28_reg(hw_ocotp_rom3)		/* 0x1d0 */
+	mx28_reg(hw_ocotp_rom4)		/* 0x1e0 */
+	mx28_reg(hw_ocotp_rom5)		/* 0x1f0 */
+	mx28_reg(hw_ocotp_rom6)		/* 0x200 */
+	mx28_reg(hw_ocotp_rom7)		/* 0x210 */
+	mx28_reg(hw_ocotp_srk0)		/* 0x220 */
+	mx28_reg(hw_ocotp_srk1)		/* 0x230 */
+	mx28_reg(hw_ocotp_srk2)		/* 0x240 */
+	mx28_reg(hw_ocotp_srk3)		/* 0x250 */
+	mx28_reg(hw_ocotp_srk4)		/* 0x260 */
+	mx28_reg(hw_ocotp_srk5)		/* 0x270 */
+	mx28_reg(hw_ocotp_srk6)		/* 0x280 */
+	mx28_reg(hw_ocotp_srk7)		/* 0x290 */
+	mx28_reg(hw_ocotp_version)	/* 0x2a0 */
+};
+#endif
+
+#define	OCOTP_CTRL_WR_UNLOCK_MASK		(0xffff << 16)
+#define	OCOTP_CTRL_WR_UNLOCK_OFFSET		16
+#define	OCOTP_CTRL_WR_UNLOCK_KEY		(0x3e77 << 16)
+#define	OCOTP_CTRL_RELOAD_SHADOWS		(1 << 13)
+#define	OCOTP_CTRL_RD_BANK_OPEN			(1 << 12)
+#define	OCOTP_CTRL_ERROR			(1 << 9)
+#define	OCOTP_CTRL_BUSY				(1 << 8)
+#define	OCOTP_CTRL_ADDR_MASK			0x3f
+#define	OCOTP_CTRL_ADDR_OFFSET			0
+
+#define	OCOTP_DATA_DATA_MASK			0xffffffff
+#define	OCOTP_DATA_DATA_OFFSET			0
+
+#define	OCOTP_CUST_BITS_MASK			0xffffffff
+#define	OCOTP_CUST_BITS_OFFSET			0
+
+#define	OCOTP_CRYPTO_BITS_MASK			0xffffffff
+#define	OCOTP_CRYPTO_BITS_OFFSET		0
+
+#define	OCOTP_HWCAP_BITS_MASK			0xffffffff
+#define	OCOTP_HWCAP_BITS_OFFSET			0
+
+#define	OCOTP_SWCAP_BITS_MASK			0xffffffff
+#define	OCOTP_SWCAP_BITS_OFFSET			0
+
+#define	OCOTP_CUSTCAP_RTC_XTAL_32768_PRESENT	(1 << 2)
+#define	OCOTP_CUSTCAP_RTC_XTAL_32000_PRESENT	(1 << 1)
+
+#define	OCOTP_LOCK_ROM7				(1 << 31)
+#define	OCOTP_LOCK_ROM6				(1 << 30)
+#define	OCOTP_LOCK_ROM5				(1 << 29)
+#define	OCOTP_LOCK_ROM4				(1 << 28)
+#define	OCOTP_LOCK_ROM3				(1 << 27)
+#define	OCOTP_LOCK_ROM2				(1 << 26)
+#define	OCOTP_LOCK_ROM1				(1 << 25)
+#define	OCOTP_LOCK_ROM0				(1 << 24)
+#define	OCOTP_LOCK_HWSW_SHADOW_ALT		(1 << 23)
+#define	OCOTP_LOCK_CRYPTODCP_ALT		(1 << 22)
+#define	OCOTP_LOCK_CRYPTOKEY_ALT		(1 << 21)
+#define	OCOTP_LOCK_PIN				(1 << 20)
+#define	OCOTP_LOCK_OPS				(1 << 19)
+#define	OCOTP_LOCK_UN2				(1 << 18)
+#define	OCOTP_LOCK_UN1				(1 << 17)
+#define	OCOTP_LOCK_UN0				(1 << 16)
+#define	OCOTP_LOCK_SRK				(1 << 15)
+#define	OCOTP_LOCK_UNALLOCATED_MASK		(0x7 << 12)
+#define	OCOTP_LOCK_UNALLOCATED_OFFSET		12
+#define	OCOTP_LOCK_SRK_SHADOW			(1 << 11)
+#define	OCOTP_LOCK_ROM_SHADOW			(1 << 10)
+#define	OCOTP_LOCK_CUSTCAP			(1 << 9)
+#define	OCOTP_LOCK_HWSW				(1 << 8)
+#define	OCOTP_LOCK_CUSTCAP_SHADOW		(1 << 7)
+#define	OCOTP_LOCK_HWSW_SHADOW			(1 << 6)
+#define	OCOTP_LOCK_CRYPTODCP			(1 << 5)
+#define	OCOTP_LOCK_CRYPTOKEY			(1 << 4)
+#define	OCOTP_LOCK_CUST3			(1 << 3)
+#define	OCOTP_LOCK_CUST2			(1 << 2)
+#define	OCOTP_LOCK_CUST1			(1 << 1)
+#define	OCOTP_LOCK_CUST0			(1 << 0)
+
+#define	OCOTP_OPS_BITS_MASK			0xffffffff
+#define	OCOTP_OPS_BITS_OFFSET			0
+
+#define	OCOTP_UN_BITS_MASK			0xffffffff
+#define	OCOTP_UN_BITS_OFFSET			0
+
+#define	OCOTP_ROM_BOOT_MODE_MASK		(0xff << 24)
+#define	OCOTP_ROM_BOOT_MODE_OFFSET		24
+#define	OCOTP_ROM_SD_MMC_MODE_MASK		(0x3 << 22)
+#define	OCOTP_ROM_SD_MMC_MODE_OFFSET		22
+#define	OCOTP_ROM_SD_POWER_GATE_GPIO_MASK	(0x3 << 20)
+#define	OCOTP_ROM_SD_POWER_GATE_GPIO_OFFSET	20
+#define	OCOTP_ROM_SD_POWER_UP_DELAY_MASK	(0x3f << 14)
+#define	OCOTP_ROM_SD_POWER_UP_DELAY_OFFSET	14
+#define	OCOTP_ROM_SD_BUS_WIDTH_MASK		(0x3 << 12)
+#define	OCOTP_ROM_SD_BUS_WIDTH_OFFSET		12
+#define	OCOTP_ROM_SSP_SCK_INDEX_MASK		(0xf << 8)
+#define	OCOTP_ROM_SSP_SCK_INDEX_OFFSET		8
+#define	OCOTP_ROM_EMMC_USE_DDR			(1 << 7)
+#define	OCOTP_ROM_DISABLE_SPI_NOR_FAST_READ	(1 << 6)
+#define	OCOTP_ROM_ENABLE_USB_BOOT_SERIAL_NUM	(1 << 5)
+#define	OCOTP_ROM_ENABLE_UNENCRYPTED_BOOT	(1 << 4)
+#define	OCOTP_ROM_SD_MBR_BOOT			(1 << 3)
+
+#define	OCOTP_SRK_BITS_MASK			0xffffffff
+#define	OCOTP_SRK_BITS_OFFSET			0
+
+#define	OCOTP_VERSION_MAJOR_MASK		(0xff << 24)
+#define	OCOTP_VERSION_MAJOR_OFFSET		24
+#define	OCOTP_VERSION_MINOR_MASK		(0xff << 16)
+#define	OCOTP_VERSION_MINOR_OFFSET		16
+#define	OCOTP_VERSION_STEP_MASK			0xffff
+#define	OCOTP_VERSION_STEP_OFFSET		0
+
+#endif /* __MX28_REGS_OCOTP_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-pinctrl.h b/arch/arm/include/asm/arch-mx28/regs-pinctrl.h
new file mode 100644
index 0000000..73739ca
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-pinctrl.h
@@ -0,0 +1,1284 @@
+/*
+ * Freescale i.MX28 PINCTRL Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_PINCTRL_H__
+#define __MX28_REGS_PINCTRL_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_pinctrl_regs {
+	mx28_reg(hw_pinctrl_ctrl)		/* 0x0 */
+
+	uint32_t	reserved1[60];
+
+	mx28_reg(hw_pinctrl_muxsel0)		/* 0x100 */
+	mx28_reg(hw_pinctrl_muxsel1)		/* 0x110 */
+	mx28_reg(hw_pinctrl_muxsel2)		/* 0x120 */
+	mx28_reg(hw_pinctrl_muxsel3)		/* 0x130 */
+	mx28_reg(hw_pinctrl_muxsel4)		/* 0x140 */
+	mx28_reg(hw_pinctrl_muxsel5)		/* 0x150 */
+	mx28_reg(hw_pinctrl_muxsel6)		/* 0x160 */
+	mx28_reg(hw_pinctrl_muxsel7)		/* 0x170 */
+	mx28_reg(hw_pinctrl_muxsel8)		/* 0x180 */
+	mx28_reg(hw_pinctrl_muxsel9)		/* 0x190 */
+	mx28_reg(hw_pinctrl_muxsel10)		/* 0x1a0 */
+	mx28_reg(hw_pinctrl_muxsel11)		/* 0x1b0 */
+	mx28_reg(hw_pinctrl_muxsel12)		/* 0x1c0 */
+	mx28_reg(hw_pinctrl_muxsel13)		/* 0x1d0 */
+
+	uint32_t	reserved2[72];
+
+	mx28_reg(hw_pinctrl_drive0)		/* 0x300 */
+	mx28_reg(hw_pinctrl_drive1)		/* 0x310 */
+	mx28_reg(hw_pinctrl_drive2)		/* 0x320 */
+	mx28_reg(hw_pinctrl_drive3)		/* 0x330 */
+	mx28_reg(hw_pinctrl_drive4)		/* 0x340 */
+	mx28_reg(hw_pinctrl_drive5)		/* 0x350 */
+	mx28_reg(hw_pinctrl_drive6)		/* 0x360 */
+	mx28_reg(hw_pinctrl_drive7)		/* 0x370 */
+	mx28_reg(hw_pinctrl_drive8)		/* 0x380 */
+	mx28_reg(hw_pinctrl_drive9)		/* 0x390 */
+	mx28_reg(hw_pinctrl_drive10)		/* 0x3a0 */
+	mx28_reg(hw_pinctrl_drive11)		/* 0x3b0 */
+	mx28_reg(hw_pinctrl_drive12)		/* 0x3c0 */
+	mx28_reg(hw_pinctrl_drive13)		/* 0x3d0 */
+	mx28_reg(hw_pinctrl_drive14)		/* 0x3e0 */
+	mx28_reg(hw_pinctrl_drive15)		/* 0x3f0 */
+	mx28_reg(hw_pinctrl_drive16)		/* 0x400 */
+	mx28_reg(hw_pinctrl_drive17)		/* 0x410 */
+	mx28_reg(hw_pinctrl_drive18)		/* 0x420 */
+	mx28_reg(hw_pinctrl_drive19)		/* 0x430 */
+
+	uint32_t	reserved3[112];
+
+	mx28_reg(hw_pinctrl_pull0)		/* 0x600 */
+	mx28_reg(hw_pinctrl_pull1)		/* 0x610 */
+	mx28_reg(hw_pinctrl_pull2)		/* 0x620 */
+	mx28_reg(hw_pinctrl_pull3)		/* 0x630 */
+	mx28_reg(hw_pinctrl_pull4)		/* 0x640 */
+	mx28_reg(hw_pinctrl_pull5)		/* 0x650 */
+	mx28_reg(hw_pinctrl_pull6)		/* 0x660 */
+
+	uint32_t	reserved4[36];
+
+	mx28_reg(hw_pinctrl_dout0)		/* 0x700 */
+	mx28_reg(hw_pinctrl_dout1)		/* 0x710 */
+	mx28_reg(hw_pinctrl_dout2)		/* 0x720 */
+	mx28_reg(hw_pinctrl_dout3)		/* 0x730 */
+	mx28_reg(hw_pinctrl_dout4)		/* 0x740 */
+
+	uint32_t	reserved5[108];
+
+	mx28_reg(hw_pinctrl_din0)		/* 0x900 */
+	mx28_reg(hw_pinctrl_din1)		/* 0x910 */
+	mx28_reg(hw_pinctrl_din2)		/* 0x920 */
+	mx28_reg(hw_pinctrl_din3)		/* 0x930 */
+	mx28_reg(hw_pinctrl_din4)		/* 0x940 */
+
+	uint32_t	reserved6[108];
+
+	mx28_reg(hw_pinctrl_doe0)		/* 0xb00 */
+	mx28_reg(hw_pinctrl_doe1)		/* 0xb10 */
+	mx28_reg(hw_pinctrl_doe2)		/* 0xb20 */
+	mx28_reg(hw_pinctrl_doe3)		/* 0xb30 */
+	mx28_reg(hw_pinctrl_doe4)		/* 0xb40 */
+
+	uint32_t	reserved7[300];
+
+	mx28_reg(hw_pinctrl_pin2irq0)		/* 0x1000 */
+	mx28_reg(hw_pinctrl_pin2irq1)		/* 0x1010 */
+	mx28_reg(hw_pinctrl_pin2irq2)		/* 0x1020 */
+	mx28_reg(hw_pinctrl_pin2irq3)		/* 0x1030 */
+	mx28_reg(hw_pinctrl_pin2irq4)		/* 0x1040 */
+
+	uint32_t	reserved8[44];
+
+	mx28_reg(hw_pinctrl_irqen0)		/* 0x1100 */
+	mx28_reg(hw_pinctrl_irqen1)		/* 0x1110 */
+	mx28_reg(hw_pinctrl_irqen2)		/* 0x1120 */
+	mx28_reg(hw_pinctrl_irqen3)		/* 0x1130 */
+	mx28_reg(hw_pinctrl_irqen4)		/* 0x1140 */
+
+	uint32_t	reserved9[44];
+
+	mx28_reg(hw_pinctrl_irqlevel0)		/* 0x1200 */
+	mx28_reg(hw_pinctrl_irqlevel1)		/* 0x1210 */
+	mx28_reg(hw_pinctrl_irqlevel2)		/* 0x1220 */
+	mx28_reg(hw_pinctrl_irqlevel3)		/* 0x1230 */
+	mx28_reg(hw_pinctrl_irqlevel4)		/* 0x1240 */
+
+	uint32_t	reserved10[44];
+
+	mx28_reg(hw_pinctrl_irqpol0)		/* 0x1300 */
+	mx28_reg(hw_pinctrl_irqpol1)		/* 0x1310 */
+	mx28_reg(hw_pinctrl_irqpol2)		/* 0x1320 */
+	mx28_reg(hw_pinctrl_irqpol3)		/* 0x1330 */
+	mx28_reg(hw_pinctrl_irqpol4)		/* 0x1340 */
+
+	uint32_t	reserved11[44];
+
+	mx28_reg(hw_pinctrl_irqstat0)		/* 0x1400 */
+	mx28_reg(hw_pinctrl_irqstat1)		/* 0x1410 */
+	mx28_reg(hw_pinctrl_irqstat2)		/* 0x1420 */
+	mx28_reg(hw_pinctrl_irqstat3)		/* 0x1430 */
+	mx28_reg(hw_pinctrl_irqstat4)		/* 0x1440 */
+
+	uint32_t	reserved12[380];
+
+	mx28_reg(hw_pinctrl_emi_odt_ctrl)	/* 0x1a40 */
+
+	uint32_t	reserved13[76];
+
+	mx28_reg(hw_pinctrl_emi_ds_ctrl)	/* 0x1b80 */
+};
+#endif
+
+#define	PINCTRL_CTRL_SFTRST				(1 << 31)
+#define	PINCTRL_CTRL_CLKGATE				(1 << 30)
+#define	PINCTRL_CTRL_PRESENT4				(1 << 24)
+#define	PINCTRL_CTRL_PRESENT3				(1 << 23)
+#define	PINCTRL_CTRL_PRESENT2				(1 << 22)
+#define	PINCTRL_CTRL_PRESENT1				(1 << 21)
+#define	PINCTRL_CTRL_PRESENT0				(1 << 20)
+#define	PINCTRL_CTRL_IRQOUT4				(1 << 4)
+#define	PINCTRL_CTRL_IRQOUT3				(1 << 3)
+#define	PINCTRL_CTRL_IRQOUT2				(1 << 2)
+#define	PINCTRL_CTRL_IRQOUT1				(1 << 1)
+#define	PINCTRL_CTRL_IRQOUT0				(1 << 0)
+
+#define	PINCTRL_MUXSEL0_BANK0_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL0_BANK0_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL0_BANK0_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL0_BANK0_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL0_BANK0_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL0_BANK0_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL0_BANK0_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL0_BANK0_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL0_BANK0_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL0_BANK0_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL0_BANK0_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL0_BANK0_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL0_BANK0_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL0_BANK0_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL0_BANK0_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL0_BANK0_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL1_BANK0_PIN28_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL1_BANK0_PIN28_OFFSET		24
+#define	PINCTRL_MUXSEL1_BANK0_PIN27_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL1_BANK0_PIN27_OFFSET		22
+#define	PINCTRL_MUXSEL1_BANK0_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL1_BANK0_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL1_BANK0_PIN25_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL1_BANK0_PIN25_OFFSET		18
+#define	PINCTRL_MUXSEL1_BANK0_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL1_BANK0_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL1_BANK0_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL1_BANK0_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL1_BANK0_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL1_BANK0_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL1_BANK0_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL1_BANK0_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL1_BANK0_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL1_BANK0_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL1_BANK0_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL1_BANK0_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL1_BANK0_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL1_BANK0_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL1_BANK0_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL1_BANK0_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL1_BANK0_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL1_BANK0_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL2_BANK1_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL2_BANK1_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL2_BANK1_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL2_BANK1_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL2_BANK1_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL2_BANK1_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL2_BANK1_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL2_BANK1_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL2_BANK1_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL2_BANK1_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL2_BANK1_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL2_BANK1_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL2_BANK1_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL2_BANK1_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL2_BANK1_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL2_BANK1_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL2_BANK1_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL2_BANK1_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL2_BANK1_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL2_BANK1_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL2_BANK1_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL2_BANK1_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL2_BANK1_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL2_BANK1_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL2_BANK1_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL2_BANK1_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL2_BANK1_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL2_BANK1_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL2_BANK1_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL2_BANK1_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL2_BANK1_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL2_BANK1_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL3_BANK1_PIN31_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL3_BANK1_PIN31_OFFSET		30
+#define	PINCTRL_MUXSEL3_BANK1_PIN30_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL3_BANK1_PIN30_OFFSET		28
+#define	PINCTRL_MUXSEL3_BANK1_PIN29_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL3_BANK1_PIN29_OFFSET		26
+#define	PINCTRL_MUXSEL3_BANK1_PIN28_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL3_BANK1_PIN28_OFFSET		24
+#define	PINCTRL_MUXSEL3_BANK1_PIN27_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL3_BANK1_PIN27_OFFSET		22
+#define	PINCTRL_MUXSEL3_BANK1_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL3_BANK1_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL3_BANK1_PIN25_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL3_BANK1_PIN25_OFFSET		18
+#define	PINCTRL_MUXSEL3_BANK1_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL3_BANK1_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL3_BANK1_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL3_BANK1_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL3_BANK1_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL3_BANK1_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL3_BANK1_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL3_BANK1_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL3_BANK1_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL3_BANK1_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL3_BANK1_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL3_BANK1_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL3_BANK1_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL3_BANK1_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL3_BANK1_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL3_BANK1_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL3_BANK1_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL3_BANK1_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL4_BANK2_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL4_BANK2_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL4_BANK2_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL4_BANK2_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL4_BANK2_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL4_BANK2_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL4_BANK2_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL4_BANK2_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL4_BANK2_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL4_BANK2_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL4_BANK2_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL4_BANK2_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL4_BANK2_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL4_BANK2_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL4_BANK2_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL4_BANK2_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL4_BANK2_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL4_BANK2_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL4_BANK2_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL4_BANK2_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL4_BANK2_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL4_BANK2_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL4_BANK2_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL4_BANK2_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL4_BANK2_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL4_BANK2_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL4_BANK2_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL4_BANK2_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL4_BANK2_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL4_BANK2_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL5_BANK2_PIN27_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL5_BANK2_PIN27_OFFSET		22
+#define	PINCTRL_MUXSEL5_BANK2_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL5_BANK2_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL5_BANK2_PIN25_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL5_BANK2_PIN25_OFFSET		18
+#define	PINCTRL_MUXSEL5_BANK2_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL5_BANK2_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL5_BANK2_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL5_BANK2_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL5_BANK2_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL5_BANK2_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL5_BANK2_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL5_BANK2_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL5_BANK2_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL5_BANK2_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL5_BANK2_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL5_BANK2_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL5_BANK2_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL5_BANK2_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL6_BANK3_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL6_BANK3_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL6_BANK3_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL6_BANK3_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL6_BANK3_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL6_BANK3_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL6_BANK3_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL6_BANK3_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL6_BANK3_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL6_BANK3_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL6_BANK3_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL6_BANK3_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL6_BANK3_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL6_BANK3_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL6_BANK3_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL6_BANK3_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL6_BANK3_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL6_BANK3_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL6_BANK3_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL6_BANK3_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL6_BANK3_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL6_BANK3_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL6_BANK3_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL6_BANK3_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL6_BANK3_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL6_BANK3_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL6_BANK3_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL6_BANK3_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL6_BANK3_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL6_BANK3_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL6_BANK3_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL6_BANK3_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL7_BANK3_PIN30_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL7_BANK3_PIN30_OFFSET		28
+#define	PINCTRL_MUXSEL7_BANK3_PIN29_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL7_BANK3_PIN29_OFFSET		26
+#define	PINCTRL_MUXSEL7_BANK3_PIN28_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL7_BANK3_PIN28_OFFSET		24
+#define	PINCTRL_MUXSEL7_BANK3_PIN27_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL7_BANK3_PIN27_OFFSET		22
+#define	PINCTRL_MUXSEL7_BANK3_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL7_BANK3_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL7_BANK3_PIN25_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL7_BANK3_PIN25_OFFSET		18
+#define	PINCTRL_MUXSEL7_BANK3_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL7_BANK3_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL7_BANK3_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL7_BANK3_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL7_BANK3_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL7_BANK3_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL7_BANK3_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL7_BANK3_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL7_BANK3_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL7_BANK3_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL7_BANK3_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL7_BANK3_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL7_BANK3_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL7_BANK3_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL7_BANK3_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL7_BANK3_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL8_BANK4_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL8_BANK4_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL8_BANK4_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL8_BANK4_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL8_BANK4_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL8_BANK4_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL8_BANK4_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL8_BANK4_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL8_BANK4_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL8_BANK4_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL8_BANK4_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL8_BANK4_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL8_BANK4_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL8_BANK4_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL8_BANK4_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL8_BANK4_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL8_BANK4_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL8_BANK4_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL8_BANK4_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL8_BANK4_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL8_BANK4_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL8_BANK4_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL8_BANK4_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL8_BANK4_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL8_BANK4_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL8_BANK4_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL8_BANK4_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL8_BANK4_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL8_BANK4_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL8_BANK4_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL8_BANK4_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL8_BANK4_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL9_BANK4_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL9_BANK4_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL9_BANK4_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL9_BANK4_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL10_BANK5_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL10_BANK5_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL10_BANK5_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL10_BANK5_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL10_BANK5_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL10_BANK5_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL10_BANK5_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL10_BANK5_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL10_BANK5_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL10_BANK5_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL10_BANK5_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL10_BANK5_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL10_BANK5_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL10_BANK5_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL10_BANK5_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL10_BANK5_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL10_BANK5_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL10_BANK5_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL10_BANK5_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL10_BANK5_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL10_BANK5_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL10_BANK5_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL10_BANK5_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL10_BANK5_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL10_BANK5_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL10_BANK5_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL10_BANK5_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL10_BANK5_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL10_BANK5_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL10_BANK5_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL10_BANK5_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL10_BANK5_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL11_BANK5_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL11_BANK5_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL11_BANK5_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL11_BANK5_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL11_BANK5_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL11_BANK5_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL11_BANK5_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL11_BANK5_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL11_BANK5_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL11_BANK5_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL11_BANK5_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL11_BANK5_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL11_BANK5_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL11_BANK5_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL11_BANK5_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL11_BANK5_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL11_BANK5_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL11_BANK5_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL12_BANK6_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL12_BANK6_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL12_BANK6_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL12_BANK6_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL12_BANK6_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL12_BANK6_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL12_BANK6_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL12_BANK6_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL12_BANK6_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL12_BANK6_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL12_BANK6_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL12_BANK6_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL12_BANK6_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL12_BANK6_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL12_BANK6_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL12_BANK6_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL12_BANK6_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL12_BANK6_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL12_BANK6_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL12_BANK6_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL12_BANK6_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL12_BANK6_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL12_BANK6_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL12_BANK6_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL12_BANK6_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL12_BANK6_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL12_BANK6_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL12_BANK6_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL12_BANK6_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL12_BANK6_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL13_BANK6_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL13_BANK6_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL13_BANK6_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL13_BANK6_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL13_BANK6_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL13_BANK6_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL13_BANK6_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL13_BANK6_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL13_BANK6_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL13_BANK6_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL13_BANK6_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL13_BANK6_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL13_BANK6_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL13_BANK6_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL13_BANK6_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL13_BANK6_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL13_BANK6_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL13_BANK6_PIN16_OFFSET		0
+
+#define	PINCTRL_DRIVE0_BANK0_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE0_BANK0_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE0_BANK0_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE0_BANK0_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE0_BANK0_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE0_BANK0_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE0_BANK0_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE0_BANK0_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE0_BANK0_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE0_BANK0_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE0_BANK0_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE0_BANK0_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE0_BANK0_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE0_BANK0_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE0_BANK0_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE0_BANK0_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE0_BANK0_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE0_BANK0_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE0_BANK0_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE0_BANK0_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE0_BANK0_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE0_BANK0_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE0_BANK0_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE0_BANK0_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE2_BANK0_PIN23_V			(1 << 30)
+#define	PINCTRL_DRIVE2_BANK0_PIN23_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE2_BANK0_PIN23_MA_OFFSET		28
+#define	PINCTRL_DRIVE2_BANK0_PIN22_V			(1 << 26)
+#define	PINCTRL_DRIVE2_BANK0_PIN22_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE2_BANK0_PIN22_MA_OFFSET		24
+#define	PINCTRL_DRIVE2_BANK0_PIN21_V			(1 << 22)
+#define	PINCTRL_DRIVE2_BANK0_PIN21_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE2_BANK0_PIN21_MA_OFFSET		20
+#define	PINCTRL_DRIVE2_BANK0_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE2_BANK0_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE2_BANK0_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE2_BANK0_PIN19_V			(1 << 14)
+#define	PINCTRL_DRIVE2_BANK0_PIN19_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE2_BANK0_PIN19_MA_OFFSET		12
+#define	PINCTRL_DRIVE2_BANK0_PIN18_V			(1 << 10)
+#define	PINCTRL_DRIVE2_BANK0_PIN18_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE2_BANK0_PIN18_MA_OFFSET		8
+#define	PINCTRL_DRIVE2_BANK0_PIN17_V			(1 << 6)
+#define	PINCTRL_DRIVE2_BANK0_PIN17_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE2_BANK0_PIN17_MA_OFFSET		4
+#define	PINCTRL_DRIVE2_BANK0_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE2_BANK0_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE2_BANK0_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE3_BANK0_PIN28_V			(1 << 18)
+#define	PINCTRL_DRIVE3_BANK0_PIN28_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE3_BANK0_PIN28_MA_OFFSET		16
+#define	PINCTRL_DRIVE3_BANK0_PIN27_V			(1 << 14)
+#define	PINCTRL_DRIVE3_BANK0_PIN27_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE3_BANK0_PIN27_MA_OFFSET		12
+#define	PINCTRL_DRIVE3_BANK0_PIN26_V			(1 << 10)
+#define	PINCTRL_DRIVE3_BANK0_PIN26_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE3_BANK0_PIN26_MA_OFFSET		8
+#define	PINCTRL_DRIVE3_BANK0_PIN25_V			(1 << 6)
+#define	PINCTRL_DRIVE3_BANK0_PIN25_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE3_BANK0_PIN25_MA_OFFSET		4
+#define	PINCTRL_DRIVE3_BANK0_PIN24_V			(1 << 2)
+#define	PINCTRL_DRIVE3_BANK0_PIN24_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE3_BANK0_PIN24_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE4_BANK1_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE4_BANK1_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE4_BANK1_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE4_BANK1_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE4_BANK1_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE4_BANK1_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE4_BANK1_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE4_BANK1_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE4_BANK1_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE4_BANK1_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE4_BANK1_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE4_BANK1_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE4_BANK1_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE4_BANK1_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE4_BANK1_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE4_BANK1_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE4_BANK1_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE4_BANK1_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE4_BANK1_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE4_BANK1_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE4_BANK1_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE4_BANK1_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE4_BANK1_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE4_BANK1_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE5_BANK1_PIN15_V			(1 << 30)
+#define	PINCTRL_DRIVE5_BANK1_PIN15_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE5_BANK1_PIN15_MA_OFFSET		28
+#define	PINCTRL_DRIVE5_BANK1_PIN14_V			(1 << 26)
+#define	PINCTRL_DRIVE5_BANK1_PIN14_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE5_BANK1_PIN14_MA_OFFSET		24
+#define	PINCTRL_DRIVE5_BANK1_PIN13_V			(1 << 22)
+#define	PINCTRL_DRIVE5_BANK1_PIN13_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE5_BANK1_PIN13_MA_OFFSET		20
+#define	PINCTRL_DRIVE5_BANK1_PIN12_V			(1 << 18)
+#define	PINCTRL_DRIVE5_BANK1_PIN12_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE5_BANK1_PIN12_MA_OFFSET		16
+#define	PINCTRL_DRIVE5_BANK1_PIN11_V			(1 << 14)
+#define	PINCTRL_DRIVE5_BANK1_PIN11_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE5_BANK1_PIN11_MA_OFFSET		12
+#define	PINCTRL_DRIVE5_BANK1_PIN10_V			(1 << 10)
+#define	PINCTRL_DRIVE5_BANK1_PIN10_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE5_BANK1_PIN10_MA_OFFSET		8
+#define	PINCTRL_DRIVE5_BANK1_PIN09_V			(1 << 6)
+#define	PINCTRL_DRIVE5_BANK1_PIN09_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE5_BANK1_PIN09_MA_OFFSET		4
+#define	PINCTRL_DRIVE5_BANK1_PIN08_V			(1 << 2)
+#define	PINCTRL_DRIVE5_BANK1_PIN08_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE5_BANK1_PIN08_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE6_BANK1_PIN23_V			(1 << 30)
+#define	PINCTRL_DRIVE6_BANK1_PIN23_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE6_BANK1_PIN23_MA_OFFSET		28
+#define	PINCTRL_DRIVE6_BANK1_PIN22_V			(1 << 26)
+#define	PINCTRL_DRIVE6_BANK1_PIN22_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE6_BANK1_PIN22_MA_OFFSET		24
+#define	PINCTRL_DRIVE6_BANK1_PIN21_V			(1 << 22)
+#define	PINCTRL_DRIVE6_BANK1_PIN21_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE6_BANK1_PIN21_MA_OFFSET		20
+#define	PINCTRL_DRIVE6_BANK1_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE6_BANK1_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE6_BANK1_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE6_BANK1_PIN19_V			(1 << 14)
+#define	PINCTRL_DRIVE6_BANK1_PIN19_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE6_BANK1_PIN19_MA_OFFSET		12
+#define	PINCTRL_DRIVE6_BANK1_PIN18_V			(1 << 10)
+#define	PINCTRL_DRIVE6_BANK1_PIN18_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE6_BANK1_PIN18_MA_OFFSET		8
+#define	PINCTRL_DRIVE6_BANK1_PIN17_V			(1 << 6)
+#define	PINCTRL_DRIVE6_BANK1_PIN17_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE6_BANK1_PIN17_MA_OFFSET		4
+#define	PINCTRL_DRIVE6_BANK1_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE6_BANK1_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE6_BANK1_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE7_BANK1_PIN31_V			(1 << 30)
+#define	PINCTRL_DRIVE7_BANK1_PIN31_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE7_BANK1_PIN31_MA_OFFSET		28
+#define	PINCTRL_DRIVE7_BANK1_PIN30_V			(1 << 26)
+#define	PINCTRL_DRIVE7_BANK1_PIN30_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE7_BANK1_PIN30_MA_OFFSET		24
+#define	PINCTRL_DRIVE7_BANK1_PIN29_V			(1 << 22)
+#define	PINCTRL_DRIVE7_BANK1_PIN29_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE7_BANK1_PIN29_MA_OFFSET		20
+#define	PINCTRL_DRIVE7_BANK1_PIN28_V			(1 << 18)
+#define	PINCTRL_DRIVE7_BANK1_PIN28_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE7_BANK1_PIN28_MA_OFFSET		16
+#define	PINCTRL_DRIVE7_BANK1_PIN27_V			(1 << 14)
+#define	PINCTRL_DRIVE7_BANK1_PIN27_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE7_BANK1_PIN27_MA_OFFSET		12
+#define	PINCTRL_DRIVE7_BANK1_PIN26_V			(1 << 10)
+#define	PINCTRL_DRIVE7_BANK1_PIN26_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE7_BANK1_PIN26_MA_OFFSET		8
+#define	PINCTRL_DRIVE7_BANK1_PIN25_V			(1 << 6)
+#define	PINCTRL_DRIVE7_BANK1_PIN25_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE7_BANK1_PIN25_MA_OFFSET		4
+#define	PINCTRL_DRIVE7_BANK1_PIN24_V			(1 << 2)
+#define	PINCTRL_DRIVE7_BANK1_PIN24_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE7_BANK1_PIN24_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE8_BANK2_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE8_BANK2_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE8_BANK2_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE8_BANK2_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE8_BANK2_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE8_BANK2_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE8_BANK2_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE8_BANK2_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE8_BANK2_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE8_BANK2_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE8_BANK2_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE8_BANK2_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE8_BANK2_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE8_BANK2_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE8_BANK2_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE8_BANK2_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE8_BANK2_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE8_BANK2_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE8_BANK2_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE8_BANK2_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE8_BANK2_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE8_BANK2_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE8_BANK2_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE8_BANK2_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE9_BANK2_PIN15_V			(1 << 30)
+#define	PINCTRL_DRIVE9_BANK2_PIN15_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE9_BANK2_PIN15_MA_OFFSET		28
+#define	PINCTRL_DRIVE9_BANK2_PIN14_V			(1 << 26)
+#define	PINCTRL_DRIVE9_BANK2_PIN14_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE9_BANK2_PIN14_MA_OFFSET		24
+#define	PINCTRL_DRIVE9_BANK2_PIN13_V			(1 << 22)
+#define	PINCTRL_DRIVE9_BANK2_PIN13_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE9_BANK2_PIN13_MA_OFFSET		20
+#define	PINCTRL_DRIVE9_BANK2_PIN12_V			(1 << 18)
+#define	PINCTRL_DRIVE9_BANK2_PIN12_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE9_BANK2_PIN12_MA_OFFSET		16
+#define	PINCTRL_DRIVE9_BANK2_PIN10_V			(1 << 10)
+#define	PINCTRL_DRIVE9_BANK2_PIN10_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE9_BANK2_PIN10_MA_OFFSET		8
+#define	PINCTRL_DRIVE9_BANK2_PIN09_V			(1 << 6)
+#define	PINCTRL_DRIVE9_BANK2_PIN09_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE9_BANK2_PIN09_MA_OFFSET		4
+#define	PINCTRL_DRIVE9_BANK2_PIN08_V			(1 << 2)
+#define	PINCTRL_DRIVE9_BANK2_PIN08_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE9_BANK2_PIN08_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE10_BANK2_PIN21_V			(1 << 22)
+#define	PINCTRL_DRIVE10_BANK2_PIN21_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE10_BANK2_PIN21_MA_OFFSET		20
+#define	PINCTRL_DRIVE10_BANK2_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE10_BANK2_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE10_BANK2_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE10_BANK2_PIN19_V			(1 << 14)
+#define	PINCTRL_DRIVE10_BANK2_PIN19_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE10_BANK2_PIN19_MA_OFFSET		12
+#define	PINCTRL_DRIVE10_BANK2_PIN18_V			(1 << 10)
+#define	PINCTRL_DRIVE10_BANK2_PIN18_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE10_BANK2_PIN18_MA_OFFSET		8
+#define	PINCTRL_DRIVE10_BANK2_PIN17_V			(1 << 6)
+#define	PINCTRL_DRIVE10_BANK2_PIN17_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE10_BANK2_PIN17_MA_OFFSET		4
+#define	PINCTRL_DRIVE10_BANK2_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE10_BANK2_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE10_BANK2_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE11_BANK2_PIN27_V			(1 << 14)
+#define	PINCTRL_DRIVE11_BANK2_PIN27_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE11_BANK2_PIN27_MA_OFFSET		12
+#define	PINCTRL_DRIVE11_BANK2_PIN26_V			(1 << 10)
+#define	PINCTRL_DRIVE11_BANK2_PIN26_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE11_BANK2_PIN26_MA_OFFSET		8
+#define	PINCTRL_DRIVE11_BANK2_PIN25_V			(1 << 6)
+#define	PINCTRL_DRIVE11_BANK2_PIN25_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE11_BANK2_PIN25_MA_OFFSET		4
+#define	PINCTRL_DRIVE11_BANK2_PIN24_V			(1 << 2)
+#define	PINCTRL_DRIVE11_BANK2_PIN24_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE11_BANK2_PIN24_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE12_BANK3_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE12_BANK3_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE12_BANK3_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE12_BANK3_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE12_BANK3_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE12_BANK3_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE12_BANK3_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE12_BANK3_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE12_BANK3_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE12_BANK3_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE12_BANK3_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE12_BANK3_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE12_BANK3_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE12_BANK3_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE12_BANK3_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE12_BANK3_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE12_BANK3_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE12_BANK3_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE12_BANK3_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE12_BANK3_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE12_BANK3_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE12_BANK3_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE12_BANK3_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE12_BANK3_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE13_BANK3_PIN15_V			(1 << 30)
+#define	PINCTRL_DRIVE13_BANK3_PIN15_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE13_BANK3_PIN15_MA_OFFSET		28
+#define	PINCTRL_DRIVE13_BANK3_PIN14_V			(1 << 26)
+#define	PINCTRL_DRIVE13_BANK3_PIN14_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE13_BANK3_PIN14_MA_OFFSET		24
+#define	PINCTRL_DRIVE13_BANK3_PIN13_V			(1 << 22)
+#define	PINCTRL_DRIVE13_BANK3_PIN13_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE13_BANK3_PIN13_MA_OFFSET		20
+#define	PINCTRL_DRIVE13_BANK3_PIN12_V			(1 << 18)
+#define	PINCTRL_DRIVE13_BANK3_PIN12_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE13_BANK3_PIN12_MA_OFFSET		16
+#define	PINCTRL_DRIVE13_BANK3_PIN11_V			(1 << 14)
+#define	PINCTRL_DRIVE13_BANK3_PIN11_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE13_BANK3_PIN11_MA_OFFSET		12
+#define	PINCTRL_DRIVE13_BANK3_PIN10_V			(1 << 10)
+#define	PINCTRL_DRIVE13_BANK3_PIN10_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE13_BANK3_PIN10_MA_OFFSET		8
+#define	PINCTRL_DRIVE13_BANK3_PIN09_V			(1 << 6)
+#define	PINCTRL_DRIVE13_BANK3_PIN09_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE13_BANK3_PIN09_MA_OFFSET		4
+#define	PINCTRL_DRIVE13_BANK3_PIN08_V			(1 << 2)
+#define	PINCTRL_DRIVE13_BANK3_PIN08_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE13_BANK3_PIN08_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE14_BANK3_PIN23_V			(1 << 30)
+#define	PINCTRL_DRIVE14_BANK3_PIN23_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE14_BANK3_PIN23_MA_OFFSET		28
+#define	PINCTRL_DRIVE14_BANK3_PIN22_V			(1 << 26)
+#define	PINCTRL_DRIVE14_BANK3_PIN22_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE14_BANK3_PIN22_MA_OFFSET		24
+#define	PINCTRL_DRIVE14_BANK3_PIN21_V			(1 << 22)
+#define	PINCTRL_DRIVE14_BANK3_PIN21_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE14_BANK3_PIN21_MA_OFFSET		20
+#define	PINCTRL_DRIVE14_BANK3_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE14_BANK3_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE14_BANK3_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE14_BANK3_PIN18_V			(1 << 10)
+#define	PINCTRL_DRIVE14_BANK3_PIN18_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE14_BANK3_PIN18_MA_OFFSET		8
+#define	PINCTRL_DRIVE14_BANK3_PIN17_V			(1 << 6)
+#define	PINCTRL_DRIVE14_BANK3_PIN17_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE14_BANK3_PIN17_MA_OFFSET		4
+#define	PINCTRL_DRIVE14_BANK3_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE14_BANK3_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE14_BANK3_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE15_BANK3_PIN30_V			(1 << 26)
+#define	PINCTRL_DRIVE15_BANK3_PIN30_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE15_BANK3_PIN30_MA_OFFSET		24
+#define	PINCTRL_DRIVE15_BANK3_PIN29_V			(1 << 22)
+#define	PINCTRL_DRIVE15_BANK3_PIN29_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE15_BANK3_PIN29_MA_OFFSET		20
+#define	PINCTRL_DRIVE15_BANK3_PIN28_V			(1 << 18)
+#define	PINCTRL_DRIVE15_BANK3_PIN28_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE15_BANK3_PIN28_MA_OFFSET		16
+#define	PINCTRL_DRIVE15_BANK3_PIN27_V			(1 << 14)
+#define	PINCTRL_DRIVE15_BANK3_PIN27_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE15_BANK3_PIN27_MA_OFFSET		12
+#define	PINCTRL_DRIVE15_BANK3_PIN26_V			(1 << 10)
+#define	PINCTRL_DRIVE15_BANK3_PIN26_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE15_BANK3_PIN26_MA_OFFSET		8
+#define	PINCTRL_DRIVE15_BANK3_PIN25_V			(1 << 6)
+#define	PINCTRL_DRIVE15_BANK3_PIN25_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE15_BANK3_PIN25_MA_OFFSET		4
+#define	PINCTRL_DRIVE15_BANK3_PIN24_V			(1 << 2)
+#define	PINCTRL_DRIVE15_BANK3_PIN24_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE15_BANK3_PIN24_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE16_BANK4_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE16_BANK4_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE16_BANK4_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE16_BANK4_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE16_BANK4_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE16_BANK4_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE16_BANK4_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE16_BANK4_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE16_BANK4_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE16_BANK4_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE16_BANK4_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE16_BANK4_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE16_BANK4_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE16_BANK4_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE16_BANK4_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE16_BANK4_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE16_BANK4_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE16_BANK4_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE16_BANK4_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE16_BANK4_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE16_BANK4_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE16_BANK4_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE16_BANK4_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE16_BANK4_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE17_BANK4_PIN15_V			(1 << 30)
+#define	PINCTRL_DRIVE17_BANK4_PIN15_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE17_BANK4_PIN15_MA_OFFSET		28
+#define	PINCTRL_DRIVE17_BANK4_PIN14_V			(1 << 26)
+#define	PINCTRL_DRIVE17_BANK4_PIN14_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE17_BANK4_PIN14_MA_OFFSET		24
+#define	PINCTRL_DRIVE17_BANK4_PIN13_V			(1 << 22)
+#define	PINCTRL_DRIVE17_BANK4_PIN13_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE17_BANK4_PIN13_MA_OFFSET		20
+#define	PINCTRL_DRIVE17_BANK4_PIN12_V			(1 << 18)
+#define	PINCTRL_DRIVE17_BANK4_PIN12_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE17_BANK4_PIN12_MA_OFFSET		16
+#define	PINCTRL_DRIVE17_BANK4_PIN11_V			(1 << 14)
+#define	PINCTRL_DRIVE17_BANK4_PIN11_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE17_BANK4_PIN11_MA_OFFSET		12
+#define	PINCTRL_DRIVE17_BANK4_PIN10_V			(1 << 10)
+#define	PINCTRL_DRIVE17_BANK4_PIN10_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE17_BANK4_PIN10_MA_OFFSET		8
+#define	PINCTRL_DRIVE17_BANK4_PIN09_V			(1 << 6)
+#define	PINCTRL_DRIVE17_BANK4_PIN09_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE17_BANK4_PIN09_MA_OFFSET		4
+#define	PINCTRL_DRIVE17_BANK4_PIN08_V			(1 << 2)
+#define	PINCTRL_DRIVE17_BANK4_PIN08_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE17_BANK4_PIN08_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE18_BANK4_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE18_BANK4_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE18_BANK4_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE18_BANK4_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE18_BANK4_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE18_BANK4_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_PULL0_BANK0_PIN28			(1 << 28)
+#define	PINCTRL_PULL0_BANK0_PIN27			(1 << 27)
+#define	PINCTRL_PULL0_BANK0_PIN26			(1 << 26)
+#define	PINCTRL_PULL0_BANK0_PIN25			(1 << 25)
+#define	PINCTRL_PULL0_BANK0_PIN24			(1 << 24)
+#define	PINCTRL_PULL0_BANK0_PIN23			(1 << 23)
+#define	PINCTRL_PULL0_BANK0_PIN22			(1 << 22)
+#define	PINCTRL_PULL0_BANK0_PIN21			(1 << 21)
+#define	PINCTRL_PULL0_BANK0_PIN20			(1 << 20)
+#define	PINCTRL_PULL0_BANK0_PIN19			(1 << 19)
+#define	PINCTRL_PULL0_BANK0_PIN18			(1 << 18)
+#define	PINCTRL_PULL0_BANK0_PIN17			(1 << 17)
+#define	PINCTRL_PULL0_BANK0_PIN16			(1 << 16)
+#define	PINCTRL_PULL0_BANK0_PIN07			(1 << 7)
+#define	PINCTRL_PULL0_BANK0_PIN06			(1 << 6)
+#define	PINCTRL_PULL0_BANK0_PIN05			(1 << 5)
+#define	PINCTRL_PULL0_BANK0_PIN04			(1 << 4)
+#define	PINCTRL_PULL0_BANK0_PIN03			(1 << 3)
+#define	PINCTRL_PULL0_BANK0_PIN02			(1 << 2)
+#define	PINCTRL_PULL0_BANK0_PIN01			(1 << 1)
+#define	PINCTRL_PULL0_BANK0_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL1_BANK1_PIN31			(1 << 31)
+#define	PINCTRL_PULL1_BANK1_PIN30			(1 << 30)
+#define	PINCTRL_PULL1_BANK1_PIN29			(1 << 29)
+#define	PINCTRL_PULL1_BANK1_PIN28			(1 << 28)
+#define	PINCTRL_PULL1_BANK1_PIN27			(1 << 27)
+#define	PINCTRL_PULL1_BANK1_PIN26			(1 << 26)
+#define	PINCTRL_PULL1_BANK1_PIN25			(1 << 25)
+#define	PINCTRL_PULL1_BANK1_PIN24			(1 << 24)
+#define	PINCTRL_PULL1_BANK1_PIN23			(1 << 23)
+#define	PINCTRL_PULL1_BANK1_PIN22			(1 << 22)
+#define	PINCTRL_PULL1_BANK1_PIN21			(1 << 21)
+#define	PINCTRL_PULL1_BANK1_PIN20			(1 << 20)
+#define	PINCTRL_PULL1_BANK1_PIN19			(1 << 19)
+#define	PINCTRL_PULL1_BANK1_PIN18			(1 << 18)
+#define	PINCTRL_PULL1_BANK1_PIN17			(1 << 17)
+#define	PINCTRL_PULL1_BANK1_PIN16			(1 << 16)
+#define	PINCTRL_PULL1_BANK1_PIN15			(1 << 15)
+#define	PINCTRL_PULL1_BANK1_PIN14			(1 << 14)
+#define	PINCTRL_PULL1_BANK1_PIN13			(1 << 13)
+#define	PINCTRL_PULL1_BANK1_PIN12			(1 << 12)
+#define	PINCTRL_PULL1_BANK1_PIN11			(1 << 11)
+#define	PINCTRL_PULL1_BANK1_PIN10			(1 << 10)
+#define	PINCTRL_PULL1_BANK1_PIN09			(1 << 9)
+#define	PINCTRL_PULL1_BANK1_PIN08			(1 << 8)
+#define	PINCTRL_PULL1_BANK1_PIN07			(1 << 7)
+#define	PINCTRL_PULL1_BANK1_PIN06			(1 << 6)
+#define	PINCTRL_PULL1_BANK1_PIN05			(1 << 5)
+#define	PINCTRL_PULL1_BANK1_PIN04			(1 << 4)
+#define	PINCTRL_PULL1_BANK1_PIN03			(1 << 3)
+#define	PINCTRL_PULL1_BANK1_PIN02			(1 << 2)
+#define	PINCTRL_PULL1_BANK1_PIN01			(1 << 1)
+#define	PINCTRL_PULL1_BANK1_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL2_BANK2_PIN27			(1 << 27)
+#define	PINCTRL_PULL2_BANK2_PIN26			(1 << 26)
+#define	PINCTRL_PULL2_BANK2_PIN25			(1 << 25)
+#define	PINCTRL_PULL2_BANK2_PIN24			(1 << 24)
+#define	PINCTRL_PULL2_BANK2_PIN21			(1 << 21)
+#define	PINCTRL_PULL2_BANK2_PIN20			(1 << 20)
+#define	PINCTRL_PULL2_BANK2_PIN19			(1 << 19)
+#define	PINCTRL_PULL2_BANK2_PIN18			(1 << 18)
+#define	PINCTRL_PULL2_BANK2_PIN17			(1 << 17)
+#define	PINCTRL_PULL2_BANK2_PIN16			(1 << 16)
+#define	PINCTRL_PULL2_BANK2_PIN15			(1 << 15)
+#define	PINCTRL_PULL2_BANK2_PIN14			(1 << 14)
+#define	PINCTRL_PULL2_BANK2_PIN13			(1 << 13)
+#define	PINCTRL_PULL2_BANK2_PIN12			(1 << 12)
+#define	PINCTRL_PULL2_BANK2_PIN10			(1 << 10)
+#define	PINCTRL_PULL2_BANK2_PIN09			(1 << 9)
+#define	PINCTRL_PULL2_BANK2_PIN08			(1 << 8)
+#define	PINCTRL_PULL2_BANK2_PIN07			(1 << 7)
+#define	PINCTRL_PULL2_BANK2_PIN06			(1 << 6)
+#define	PINCTRL_PULL2_BANK2_PIN05			(1 << 5)
+#define	PINCTRL_PULL2_BANK2_PIN04			(1 << 4)
+#define	PINCTRL_PULL2_BANK2_PIN03			(1 << 3)
+#define	PINCTRL_PULL2_BANK2_PIN02			(1 << 2)
+#define	PINCTRL_PULL2_BANK2_PIN01			(1 << 1)
+#define	PINCTRL_PULL2_BANK2_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL3_BANK3_PIN30			(1 << 30)
+#define	PINCTRL_PULL3_BANK3_PIN29			(1 << 29)
+#define	PINCTRL_PULL3_BANK3_PIN28			(1 << 28)
+#define	PINCTRL_PULL3_BANK3_PIN27			(1 << 27)
+#define	PINCTRL_PULL3_BANK3_PIN26			(1 << 26)
+#define	PINCTRL_PULL3_BANK3_PIN25			(1 << 25)
+#define	PINCTRL_PULL3_BANK3_PIN24			(1 << 24)
+#define	PINCTRL_PULL3_BANK3_PIN23			(1 << 23)
+#define	PINCTRL_PULL3_BANK3_PIN22			(1 << 22)
+#define	PINCTRL_PULL3_BANK3_PIN21			(1 << 21)
+#define	PINCTRL_PULL3_BANK3_PIN20			(1 << 20)
+#define	PINCTRL_PULL3_BANK3_PIN18			(1 << 18)
+#define	PINCTRL_PULL3_BANK3_PIN17			(1 << 17)
+#define	PINCTRL_PULL3_BANK3_PIN16			(1 << 16)
+#define	PINCTRL_PULL3_BANK3_PIN15			(1 << 15)
+#define	PINCTRL_PULL3_BANK3_PIN14			(1 << 14)
+#define	PINCTRL_PULL3_BANK3_PIN13			(1 << 13)
+#define	PINCTRL_PULL3_BANK3_PIN12			(1 << 12)
+#define	PINCTRL_PULL3_BANK3_PIN11			(1 << 11)
+#define	PINCTRL_PULL3_BANK3_PIN10			(1 << 10)
+#define	PINCTRL_PULL3_BANK3_PIN09			(1 << 9)
+#define	PINCTRL_PULL3_BANK3_PIN08			(1 << 8)
+#define	PINCTRL_PULL3_BANK3_PIN07			(1 << 7)
+#define	PINCTRL_PULL3_BANK3_PIN06			(1 << 6)
+#define	PINCTRL_PULL3_BANK3_PIN05			(1 << 5)
+#define	PINCTRL_PULL3_BANK3_PIN04			(1 << 4)
+#define	PINCTRL_PULL3_BANK3_PIN03			(1 << 3)
+#define	PINCTRL_PULL3_BANK3_PIN02			(1 << 2)
+#define	PINCTRL_PULL3_BANK3_PIN01			(1 << 1)
+#define	PINCTRL_PULL3_BANK3_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL4_BANK4_PIN20			(1 << 20)
+#define	PINCTRL_PULL4_BANK4_PIN16			(1 << 16)
+#define	PINCTRL_PULL4_BANK4_PIN15			(1 << 15)
+#define	PINCTRL_PULL4_BANK4_PIN14			(1 << 14)
+#define	PINCTRL_PULL4_BANK4_PIN13			(1 << 13)
+#define	PINCTRL_PULL4_BANK4_PIN12			(1 << 12)
+#define	PINCTRL_PULL4_BANK4_PIN11			(1 << 11)
+#define	PINCTRL_PULL4_BANK4_PIN10			(1 << 10)
+#define	PINCTRL_PULL4_BANK4_PIN09			(1 << 9)
+#define	PINCTRL_PULL4_BANK4_PIN08			(1 << 8)
+#define	PINCTRL_PULL4_BANK4_PIN07			(1 << 7)
+#define	PINCTRL_PULL4_BANK4_PIN06			(1 << 6)
+#define	PINCTRL_PULL4_BANK4_PIN05			(1 << 5)
+#define	PINCTRL_PULL4_BANK4_PIN04			(1 << 4)
+#define	PINCTRL_PULL4_BANK4_PIN03			(1 << 3)
+#define	PINCTRL_PULL4_BANK4_PIN02			(1 << 2)
+#define	PINCTRL_PULL4_BANK4_PIN01			(1 << 1)
+#define	PINCTRL_PULL4_BANK4_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL5_BANK5_PIN26			(1 << 26)
+#define	PINCTRL_PULL5_BANK5_PIN23			(1 << 23)
+#define	PINCTRL_PULL5_BANK5_PIN22			(1 << 22)
+#define	PINCTRL_PULL5_BANK5_PIN21			(1 << 21)
+#define	PINCTRL_PULL5_BANK5_PIN20			(1 << 20)
+#define	PINCTRL_PULL5_BANK5_PIN19			(1 << 19)
+#define	PINCTRL_PULL5_BANK5_PIN18			(1 << 18)
+#define	PINCTRL_PULL5_BANK5_PIN17			(1 << 17)
+#define	PINCTRL_PULL5_BANK5_PIN16			(1 << 16)
+#define	PINCTRL_PULL5_BANK5_PIN15			(1 << 15)
+#define	PINCTRL_PULL5_BANK5_PIN14			(1 << 14)
+#define	PINCTRL_PULL5_BANK5_PIN13			(1 << 13)
+#define	PINCTRL_PULL5_BANK5_PIN12			(1 << 12)
+#define	PINCTRL_PULL5_BANK5_PIN11			(1 << 11)
+#define	PINCTRL_PULL5_BANK5_PIN10			(1 << 10)
+#define	PINCTRL_PULL5_BANK5_PIN09			(1 << 9)
+#define	PINCTRL_PULL5_BANK5_PIN08			(1 << 8)
+#define	PINCTRL_PULL5_BANK5_PIN07			(1 << 7)
+#define	PINCTRL_PULL5_BANK5_PIN06			(1 << 6)
+#define	PINCTRL_PULL5_BANK5_PIN05			(1 << 5)
+#define	PINCTRL_PULL5_BANK5_PIN04			(1 << 4)
+#define	PINCTRL_PULL5_BANK5_PIN03			(1 << 3)
+#define	PINCTRL_PULL5_BANK5_PIN02			(1 << 2)
+#define	PINCTRL_PULL5_BANK5_PIN01			(1 << 1)
+#define	PINCTRL_PULL5_BANK5_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL6_BANK6_PIN24			(1 << 24)
+#define	PINCTRL_PULL6_BANK6_PIN23			(1 << 23)
+#define	PINCTRL_PULL6_BANK6_PIN22			(1 << 22)
+#define	PINCTRL_PULL6_BANK6_PIN21			(1 << 21)
+#define	PINCTRL_PULL6_BANK6_PIN20			(1 << 20)
+#define	PINCTRL_PULL6_BANK6_PIN19			(1 << 19)
+#define	PINCTRL_PULL6_BANK6_PIN18			(1 << 18)
+#define	PINCTRL_PULL6_BANK6_PIN17			(1 << 17)
+#define	PINCTRL_PULL6_BANK6_PIN16			(1 << 16)
+#define	PINCTRL_PULL6_BANK6_PIN14			(1 << 14)
+#define	PINCTRL_PULL6_BANK6_PIN13			(1 << 13)
+#define	PINCTRL_PULL6_BANK6_PIN12			(1 << 12)
+#define	PINCTRL_PULL6_BANK6_PIN11			(1 << 11)
+#define	PINCTRL_PULL6_BANK6_PIN10			(1 << 10)
+#define	PINCTRL_PULL6_BANK6_PIN09			(1 << 9)
+#define	PINCTRL_PULL6_BANK6_PIN08			(1 << 8)
+#define	PINCTRL_PULL6_BANK6_PIN07			(1 << 7)
+#define	PINCTRL_PULL6_BANK6_PIN06			(1 << 6)
+#define	PINCTRL_PULL6_BANK6_PIN05			(1 << 5)
+#define	PINCTRL_PULL6_BANK6_PIN04			(1 << 4)
+#define	PINCTRL_PULL6_BANK6_PIN03			(1 << 3)
+#define	PINCTRL_PULL6_BANK6_PIN02			(1 << 2)
+#define	PINCTRL_PULL6_BANK6_PIN01			(1 << 1)
+#define	PINCTRL_PULL6_BANK6_PIN00			(1 << 0)
+
+#define	PINCTRL_DOUT0_DOUT_MASK				0x1fffffff
+#define	PINCTRL_DOUT0_DOUT_OFFSET			0
+
+#define	PINCTRL_DOUT1_DOUT_MASK				0xffffffff
+#define	PINCTRL_DOUT1_DOUT_OFFSET			0
+
+#define	PINCTRL_DOUT2_DOUT_MASK				0xfffffff
+#define	PINCTRL_DOUT2_DOUT_OFFSET			0
+
+#define	PINCTRL_DOUT3_DOUT_MASK				0x7fffffff
+#define	PINCTRL_DOUT3_DOUT_OFFSET			0
+
+#define	PINCTRL_DOUT4_DOUT_MASK				0x1fffff
+#define	PINCTRL_DOUT4_DOUT_OFFSET			0
+
+#define	PINCTRL_DIN0_DIN_MASK				0x1fffffff
+#define	PINCTRL_DIN0_DIN_OFFSET				0
+
+#define	PINCTRL_DIN1_DIN_MASK				0xffffffff
+#define	PINCTRL_DIN1_DIN_OFFSET				0
+
+#define	PINCTRL_DIN2_DIN_MASK				0xfffffff
+#define	PINCTRL_DIN2_DIN_OFFSET				0
+
+#define	PINCTRL_DIN3_DIN_MASK				0x7fffffff
+#define	PINCTRL_DIN3_DIN_OFFSET				0
+
+#define	PINCTRL_DIN4_DIN_MASK				0x1fffff
+#define	PINCTRL_DIN4_DIN_OFFSET				0
+
+#define	PINCTRL_DOE0_DOE_MASK				0x1fffffff
+#define	PINCTRL_DOE0_DOE_OFFSET				0
+
+#define	PINCTRL_DOE1_DOE_MASK				0xffffffff
+#define	PINCTRL_DOE1_DOE_OFFSET				0
+
+#define	PINCTRL_DOE2_DOE_MASK				0xfffffff
+#define	PINCTRL_DOE2_DOE_OFFSET				0
+
+#define	PINCTRL_DOE3_DOE_MASK				0x7fffffff
+#define	PINCTRL_DOE3_DOE_OFFSET				0
+
+#define	PINCTRL_DOE4_DOE_MASK				0x1fffff
+#define	PINCTRL_DOE4_DOE_OFFSET				0
+
+#define	PINCTRL_PIN2IRQ0_PIN2IRQ_MASK			0x1fffffff
+#define	PINCTRL_PIN2IRQ0_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_PIN2IRQ1_PIN2IRQ_MASK			0xffffffff
+#define	PINCTRL_PIN2IRQ1_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_PIN2IRQ2_PIN2IRQ_MASK			0xfffffff
+#define	PINCTRL_PIN2IRQ2_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_PIN2IRQ3_PIN2IRQ_MASK			0x7fffffff
+#define	PINCTRL_PIN2IRQ3_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_PIN2IRQ4_PIN2IRQ_MASK			0x1fffff
+#define	PINCTRL_PIN2IRQ4_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_IRQEN0_IRQEN_MASK			0x1fffffff
+#define	PINCTRL_IRQEN0_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQEN1_IRQEN_MASK			0xffffffff
+#define	PINCTRL_IRQEN1_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQEN2_IRQEN_MASK			0xfffffff
+#define	PINCTRL_IRQEN2_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQEN3_IRQEN_MASK			0x7fffffff
+#define	PINCTRL_IRQEN3_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQEN4_IRQEN_MASK			0x1fffff
+#define	PINCTRL_IRQEN4_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQLEVEL0_IRQLEVEL_MASK			0x1fffffff
+#define	PINCTRL_IRQLEVEL0_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQLEVEL1_IRQLEVEL_MASK			0xffffffff
+#define	PINCTRL_IRQLEVEL1_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQLEVEL2_IRQLEVEL_MASK			0xfffffff
+#define	PINCTRL_IRQLEVEL2_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQLEVEL3_IRQLEVEL_MASK			0x7fffffff
+#define	PINCTRL_IRQLEVEL3_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQLEVEL4_IRQLEVEL_MASK			0x1fffff
+#define	PINCTRL_IRQLEVEL4_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQPOL0_IRQPOL_MASK			0x1fffffff
+#define	PINCTRL_IRQPOL0_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQPOL1_IRQPOL_MASK			0xffffffff
+#define	PINCTRL_IRQPOL1_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQPOL2_IRQPOL_MASK			0xfffffff
+#define	PINCTRL_IRQPOL2_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQPOL3_IRQPOL_MASK			0x7fffffff
+#define	PINCTRL_IRQPOL3_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQPOL4_IRQPOL_MASK			0x1fffff
+#define	PINCTRL_IRQPOL4_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQSTAT0_IRQSTAT_MASK			0x1fffffff
+#define	PINCTRL_IRQSTAT0_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_IRQSTAT1_IRQSTAT_MASK			0xffffffff
+#define	PINCTRL_IRQSTAT1_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_IRQSTAT2_IRQSTAT_MASK			0xfffffff
+#define	PINCTRL_IRQSTAT2_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_IRQSTAT3_IRQSTAT_MASK			0x7fffffff
+#define	PINCTRL_IRQSTAT3_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_IRQSTAT4_IRQSTAT_MASK			0x1fffff
+#define	PINCTRL_IRQSTAT4_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_EMI_ODT_CTRL_ADDRESS_CALIB_MASK		(0x3 << 26)
+#define	PINCTRL_EMI_ODT_CTRL_ADDRESS_CALIB_OFFSET	26
+#define	PINCTRL_EMI_ODT_CTRL_ADDRESS_TLOAD_MASK		(0x3 << 24)
+#define	PINCTRL_EMI_ODT_CTRL_ADDRESS_TLOAD_OFFSET	24
+#define	PINCTRL_EMI_ODT_CTRL_CONTROL_CALIB_MASK		(0x3 << 22)
+#define	PINCTRL_EMI_ODT_CTRL_CONTROL_CALIB_OFFSET	22
+#define	PINCTRL_EMI_ODT_CTRL_CONTROL_TLOAD_MASK		(0x3 << 20)
+#define	PINCTRL_EMI_ODT_CTRL_CONTROL_TLOAD_OFFSET	20
+#define	PINCTRL_EMI_ODT_CTRL_DUALPAD_CALIB_MASK		(0x3 << 18)
+#define	PINCTRL_EMI_ODT_CTRL_DUALPAD_CALIB_OFFSET	18
+#define	PINCTRL_EMI_ODT_CTRL_DUALPAD_TLOAD_MASK		(0x3 << 16)
+#define	PINCTRL_EMI_ODT_CTRL_DUALPAD_TLOAD_OFFSET	16
+#define	PINCTRL_EMI_ODT_CTRL_SLICE3_CALIB_MASK		(0x3 << 14)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE3_CALIB_OFFSET	14
+#define	PINCTRL_EMI_ODT_CTRL_SLICE3_TLOAD_MASK		(0x3 << 12)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE3_TLOAD_OFFSET	12
+#define	PINCTRL_EMI_ODT_CTRL_SLICE2_CALIB_MASK		(0x3 << 10)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE2_CALIB_OFFSET	10
+#define	PINCTRL_EMI_ODT_CTRL_SLICE2_TLOAD_MASK		(0x3 << 8)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE2_TLOAD_OFFSET	8
+#define	PINCTRL_EMI_ODT_CTRL_SLICE1_CALIB_MASK		(0x3 << 6)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE1_CALIB_OFFSET	6
+#define	PINCTRL_EMI_ODT_CTRL_SLICE1_TLOAD_MASK		(0x3 << 4)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE1_TLOAD_OFFSET	4
+#define	PINCTRL_EMI_ODT_CTRL_SLICE0_CALIB_MASK		(0x3 << 2)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE0_CALIB_OFFSET	2
+#define	PINCTRL_EMI_ODT_CTRL_SLICE0_TLOAD_MASK		(0x3 << 0)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE0_TLOAD_OFFSET	0
+
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_MASK		(0x3 << 16)
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_OFFSET		16
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_mDDR		(0x0 << 16)
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_GPIO		(0x1 << 16)
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_LVDDR2		(0x2 << 16)
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2		(0x3 << 16)
+#define	PINCTRL_EMI_DS_CTRL_ADDRESS_MA_MASK		(0x3 << 12)
+#define	PINCTRL_EMI_DS_CTRL_ADDRESS_MA_OFFSET		12
+#define	PINCTRL_EMI_DS_CTRL_CONTROL_MA_MASK		(0x3 << 10)
+#define	PINCTRL_EMI_DS_CTRL_CONTROL_MA_OFFSET		10
+#define	PINCTRL_EMI_DS_CTRL_DUALPAD_MA_MASK		(0x3 << 8)
+#define	PINCTRL_EMI_DS_CTRL_DUALPAD_MA_OFFSET		8
+#define	PINCTRL_EMI_DS_CTRL_SLICE3_MA_MASK		(0x3 << 6)
+#define	PINCTRL_EMI_DS_CTRL_SLICE3_MA_OFFSET		6
+#define	PINCTRL_EMI_DS_CTRL_SLICE2_MA_MASK		(0x3 << 4)
+#define	PINCTRL_EMI_DS_CTRL_SLICE2_MA_OFFSET		4
+#define	PINCTRL_EMI_DS_CTRL_SLICE1_MA_MASK		(0x3 << 2)
+#define	PINCTRL_EMI_DS_CTRL_SLICE1_MA_OFFSET		2
+#define	PINCTRL_EMI_DS_CTRL_SLICE0_MA_MASK		(0x3 << 0)
+#define	PINCTRL_EMI_DS_CTRL_SLICE0_MA_OFFSET		0
+
+#endif /* __MX28_REGS_PINCTRL_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-power.h b/arch/arm/include/asm/arch-mx28/regs-power.h
new file mode 100644
index 0000000..9da63ad
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-power.h
@@ -0,0 +1,413 @@
+/*
+ * Freescale i.MX28 Power Controller Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_POWER_H__
+#define __MX28_REGS_POWER_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_power_regs {
+	mx28_reg(hw_power_ctrl)
+	mx28_reg(hw_power_5vctrl)
+	mx28_reg(hw_power_minpwr)
+	mx28_reg(hw_power_charge)
+	uint32_t	hw_power_vdddctrl;
+	uint32_t	reserved_vddd[3];
+	uint32_t	hw_power_vddactrl;
+	uint32_t	reserved_vdda[3];
+	uint32_t	hw_power_vddioctrl;
+	uint32_t	reserved_vddio[3];
+	uint32_t	hw_power_vddmemctrl;
+	uint32_t	reserved_vddmem[3];
+	uint32_t	hw_power_dcdc4p2;
+	uint32_t	reserved_dcdc4p2[3];
+	uint32_t	hw_power_misc;
+	uint32_t	reserved_misc[3];
+	uint32_t	hw_power_dclimits;
+	uint32_t	reserved_dclimits[3];
+	mx28_reg(hw_power_loopctrl)
+	uint32_t	hw_power_sts;
+	uint32_t	reserved_sts[3];
+	mx28_reg(hw_power_speed)
+	uint32_t	hw_power_battmonitor;
+	uint32_t	reserved_battmonitor[3];
+
+	uint32_t	reserved[4];
+
+	mx28_reg(hw_power_reset)
+	mx28_reg(hw_power_debug)
+	mx28_reg(hw_power_thermal)
+	mx28_reg(hw_power_usb1ctrl)
+	mx28_reg(hw_power_special)
+	mx28_reg(hw_power_version)
+	mx28_reg(hw_power_anaclkctrl)
+	mx28_reg(hw_power_refctrl)
+};
+#endif
+
+#define	POWER_CTRL_PSWITCH_MID_TRAN			(1 << 27)
+#define	POWER_CTRL_DCDC4P2_BO_IRQ			(1 << 24)
+#define	POWER_CTRL_ENIRQ_DCDC4P2_BO			(1 << 23)
+#define	POWER_CTRL_VDD5V_DROOP_IRQ			(1 << 22)
+#define	POWER_CTRL_ENIRQ_VDD5V_DROOP			(1 << 21)
+#define	POWER_CTRL_PSWITCH_IRQ				(1 << 20)
+#define	POWER_CTRL_PSWITCH_IRQ_SRC			(1 << 19)
+#define	POWER_CTRL_POLARITY_PSWITCH			(1 << 18)
+#define	POWER_CTRL_ENIRQ_PSWITCH			(1 << 17)
+#define	POWER_CTRL_POLARITY_DC_OK			(1 << 16)
+#define	POWER_CTRL_DC_OK_IRQ				(1 << 15)
+#define	POWER_CTRL_ENIRQ_DC_OK				(1 << 14)
+#define	POWER_CTRL_BATT_BO_IRQ				(1 << 13)
+#define	POWER_CTRL_ENIRQ_BATT_BO			(1 << 12)
+#define	POWER_CTRL_VDDIO_BO_IRQ				(1 << 11)
+#define	POWER_CTRL_ENIRQ_VDDIO_BO			(1 << 10)
+#define	POWER_CTRL_VDDA_BO_IRQ				(1 << 9)
+#define	POWER_CTRL_ENIRQ_VDDA_BO			(1 << 8)
+#define	POWER_CTRL_VDDD_BO_IRQ				(1 << 7)
+#define	POWER_CTRL_ENIRQ_VDDD_BO			(1 << 6)
+#define	POWER_CTRL_POLARITY_VBUSVALID			(1 << 5)
+#define	POWER_CTRL_VBUS_VALID_IRQ			(1 << 4)
+#define	POWER_CTRL_ENIRQ_VBUS_VALID			(1 << 3)
+#define	POWER_CTRL_POLARITY_VDD5V_GT_VDDIO		(1 << 2)
+#define	POWER_CTRL_VDD5V_GT_VDDIO_IRQ			(1 << 1)
+#define	POWER_CTRL_ENIRQ_VDD5V_GT_VDDIO			(1 << 0)
+
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_MASK		(0x3 << 30)
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_OFFSET		30
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_4V3			(0x0 << 30)
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_4V4			(0x1 << 30)
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_4V5			(0x2 << 30)
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_4V7			(0x3 << 30)
+#define	POWER_5VCTRL_HEADROOM_ADJ_MASK			(0x7 << 24)
+#define	POWER_5VCTRL_HEADROOM_ADJ_OFFSET		24
+#define	POWER_5VCTRL_PWD_CHARGE_4P2_MASK		(0x3 << 20)
+#define	POWER_5VCTRL_PWD_CHARGE_4P2_OFFSET		20
+#define	POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK		(0x3f << 12)
+#define	POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET		12
+#define	POWER_5VCTRL_VBUSVALID_TRSH_MASK		(0x7 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_OFFSET		8
+#define	POWER_5VCTRL_VBUSVALID_TRSH_2V9			(0x0 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V0			(0x1 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V1			(0x2 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V2			(0x3 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V3			(0x4 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V4			(0x5 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V5			(0x6 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V6			(0x7 << 8)
+#define	POWER_5VCTRL_PWDN_5VBRNOUT			(1 << 7)
+#define	POWER_5VCTRL_ENABLE_LINREG_ILIMIT		(1 << 6)
+#define	POWER_5VCTRL_DCDC_XFER				(1 << 5)
+#define	POWER_5VCTRL_VBUSVALID_5VDETECT			(1 << 4)
+#define	POWER_5VCTRL_VBUSVALID_TO_B			(1 << 3)
+#define	POWER_5VCTRL_ILIMIT_EQ_ZERO			(1 << 2)
+#define	POWER_5VCTRL_PWRUP_VBUS_CMPS			(1 << 1)
+#define	POWER_5VCTRL_ENABLE_DCDC			(1 << 0)
+
+#define	POWER_MINPWR_LOWPWR_4P2				(1 << 14)
+#define	POWER_MINPWR_PWD_BO				(1 << 12)
+#define	POWER_MINPWR_USE_VDDXTAL_VBG			(1 << 11)
+#define	POWER_MINPWR_PWD_ANA_CMPS			(1 << 10)
+#define	POWER_MINPWR_ENABLE_OSC				(1 << 9)
+#define	POWER_MINPWR_SELECT_OSC				(1 << 8)
+#define	POWER_MINPWR_FBG_OFF				(1 << 7)
+#define	POWER_MINPWR_DOUBLE_FETS			(1 << 6)
+#define	POWER_MINPWR_HALFFETS				(1 << 5)
+#define	POWER_MINPWR_LESSANA_I				(1 << 4)
+#define	POWER_MINPWR_PWD_XTAL24				(1 << 3)
+#define	POWER_MINPWR_DC_STOPCLK				(1 << 2)
+#define	POWER_MINPWR_EN_DC_PFM				(1 << 1)
+#define	POWER_MINPWR_DC_HALFCLK				(1 << 0)
+
+#define	POWER_CHARGE_ADJ_VOLT_MASK			(0x7 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_OFFSET			24
+#define	POWER_CHARGE_ADJ_VOLT_M025P			(0x1 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_P050P			(0x2 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_M075P			(0x3 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_P025P			(0x4 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_M050P			(0x5 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_P075P			(0x6 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_M100P			(0x7 << 24)
+#define	POWER_CHARGE_ENABLE_LOAD			(1 << 22)
+#define	POWER_CHARGE_ENABLE_FAULT_DETECT		(1 << 20)
+#define	POWER_CHARGE_CHRG_STS_OFF			(1 << 19)
+#define	POWER_CHARGE_LIION_4P1				(1 << 18)
+#define	POWER_CHARGE_PWD_BATTCHRG			(1 << 16)
+#define	POWER_CHARGE_ENABLE_CHARGER_USB1		(1 << 13)
+#define	POWER_CHARGE_ENABLE_CHARGER_USB0		(1 << 12)
+#define	POWER_CHARGE_STOP_ILIMIT_MASK			(0xf << 8)
+#define	POWER_CHARGE_STOP_ILIMIT_OFFSET			8
+#define	POWER_CHARGE_STOP_ILIMIT_10MA			(0x1 << 8)
+#define	POWER_CHARGE_STOP_ILIMIT_20MA			(0x2 << 8)
+#define	POWER_CHARGE_STOP_ILIMIT_50MA			(0x4 << 8)
+#define	POWER_CHARGE_STOP_ILIMIT_100MA			(0x8 << 8)
+#define	POWER_CHARGE_BATTCHRG_I_MASK			0x3f
+#define	POWER_CHARGE_BATTCHRG_I_OFFSET			0
+#define	POWER_CHARGE_BATTCHRG_I_10MA			0x01
+#define	POWER_CHARGE_BATTCHRG_I_20MA			0x02
+#define	POWER_CHARGE_BATTCHRG_I_50MA			0x04
+#define	POWER_CHARGE_BATTCHRG_I_100MA			0x08
+#define	POWER_CHARGE_BATTCHRG_I_200MA			0x10
+#define	POWER_CHARGE_BATTCHRG_I_400MA			0x20
+
+#define	POWER_VDDDCTRL_ADJTN_MASK			(0xf << 28)
+#define	POWER_VDDDCTRL_ADJTN_OFFSET			28
+#define	POWER_VDDDCTRL_PWDN_BRNOUT			(1 << 23)
+#define	POWER_VDDDCTRL_DISABLE_STEPPING			(1 << 22)
+#define	POWER_VDDDCTRL_ENABLE_LINREG			(1 << 21)
+#define	POWER_VDDDCTRL_DISABLE_FET			(1 << 20)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_MASK		(0x3 << 16)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_OFFSET		16
+#define	POWER_VDDDCTRL_LINREG_OFFSET_0STEPS		(0x0 << 16)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_ABOVE	(0x1 << 16)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW	(0x2 << 16)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_2STEPS_BELOW	(0x3 << 16)
+#define	POWER_VDDDCTRL_BO_OFFSET_MASK			(0x7 << 8)
+#define	POWER_VDDDCTRL_BO_OFFSET_OFFSET			8
+#define	POWER_VDDDCTRL_TRG_MASK				0x1f
+#define	POWER_VDDDCTRL_TRG_OFFSET			0
+
+#define	POWER_VDDACTRL_PWDN_BRNOUT			(1 << 19)
+#define	POWER_VDDACTRL_DISABLE_STEPPING			(1 << 18)
+#define	POWER_VDDACTRL_ENABLE_LINREG			(1 << 17)
+#define	POWER_VDDACTRL_DISABLE_FET			(1 << 16)
+#define	POWER_VDDACTRL_LINREG_OFFSET_MASK		(0x3 << 12)
+#define	POWER_VDDACTRL_LINREG_OFFSET_OFFSET		12
+#define	POWER_VDDACTRL_LINREG_OFFSET_0STEPS		(0x0 << 12)
+#define	POWER_VDDACTRL_LINREG_OFFSET_1STEPS_ABOVE	(0x1 << 12)
+#define	POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW	(0x2 << 12)
+#define	POWER_VDDACTRL_LINREG_OFFSET_2STEPS_BELOW	(0x3 << 12)
+#define	POWER_VDDACTRL_BO_OFFSET_MASK			(0x7 << 8)
+#define	POWER_VDDACTRL_BO_OFFSET_OFFSET			8
+#define	POWER_VDDACTRL_TRG_MASK				0x1f
+#define	POWER_VDDACTRL_TRG_OFFSET			0
+
+#define	POWER_VDDIOCTRL_ADJTN_MASK			(0xf << 20)
+#define	POWER_VDDIOCTRL_ADJTN_OFFSET			20
+#define	POWER_VDDIOCTRL_PWDN_BRNOUT			(1 << 18)
+#define	POWER_VDDIOCTRL_DISABLE_STEPPING		(1 << 17)
+#define	POWER_VDDIOCTRL_DISABLE_FET			(1 << 16)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_MASK		(0x3 << 12)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_OFFSET		12
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_0STEPS		(0x0 << 12)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_ABOVE	(0x1 << 12)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW	(0x2 << 12)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_2STEPS_BELOW	(0x3 << 12)
+#define	POWER_VDDIOCTRL_BO_OFFSET_MASK			(0x7 << 8)
+#define	POWER_VDDIOCTRL_BO_OFFSET_OFFSET		8
+#define	POWER_VDDIOCTRL_TRG_MASK			0x1f
+#define	POWER_VDDIOCTRL_TRG_OFFSET			0
+
+#define	POWER_VDDMEMCTRL_PULLDOWN_ACTIVE		(1 << 10)
+#define	POWER_VDDMEMCTRL_ENABLE_ILIMIT			(1 << 9)
+#define	POWER_VDDMEMCTRL_ENABLE_LINREG			(1 << 8)
+#define	POWER_VDDMEMCTRL_BO_OFFSET_MASK			(0x7 << 5)
+#define	POWER_VDDMEMCTRL_BO_OFFSET_OFFSET		5
+#define	POWER_VDDMEMCTRL_TRG_MASK			0x1f
+#define	POWER_VDDMEMCTRL_TRG_OFFSET			0
+
+#define	POWER_DCDC4P2_DROPOUT_CTRL_MASK			(0xf << 28)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_OFFSET		28
+#define	POWER_DCDC4P2_DROPOUT_CTRL_200MV		(0x3 << 30)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_100MV		(0x2 << 30)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_50MV			(0x1 << 30)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_25MV			(0x0 << 30)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_SRC_4P2		(0x0 << 28)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_SRC_4P2_LT_BATT	(0x1 << 28)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL		(0x2 << 28)
+#define	POWER_DCDC4P2_ISTEAL_THRESH_MASK		(0x3 << 24)
+#define	POWER_DCDC4P2_ISTEAL_THRESH_OFFSET		24
+#define	POWER_DCDC4P2_ENABLE_4P2			(1 << 23)
+#define	POWER_DCDC4P2_ENABLE_DCDC			(1 << 22)
+#define	POWER_DCDC4P2_HYST_DIR				(1 << 21)
+#define	POWER_DCDC4P2_HYST_THRESH			(1 << 20)
+#define	POWER_DCDC4P2_TRG_MASK				(0x7 << 16)
+#define	POWER_DCDC4P2_TRG_OFFSET			16
+#define	POWER_DCDC4P2_TRG_4V2				(0x0 << 16)
+#define	POWER_DCDC4P2_TRG_4V1				(0x1 << 16)
+#define	POWER_DCDC4P2_TRG_4V0				(0x2 << 16)
+#define	POWER_DCDC4P2_TRG_3V9				(0x3 << 16)
+#define	POWER_DCDC4P2_TRG_BATT				(0x4 << 16)
+#define	POWER_DCDC4P2_BO_MASK				(0x1f << 8)
+#define	POWER_DCDC4P2_BO_OFFSET				8
+#define	POWER_DCDC4P2_CMPTRIP_MASK			0x1f
+#define	POWER_DCDC4P2_CMPTRIP_OFFSET			0
+
+#define	POWER_MISC_FREQSEL_MASK				(0x7 << 4)
+#define	POWER_MISC_FREQSEL_OFFSET			4
+#define	POWER_MISC_FREQSEL_20MHZ			(0x1 << 4)
+#define	POWER_MISC_FREQSEL_24MHZ			(0x2 << 4)
+#define	POWER_MISC_FREQSEL_19MHZ			(0x3 << 4)
+#define	POWER_MISC_FREQSEL_14MHZ			(0x4 << 4)
+#define	POWER_MISC_FREQSEL_18MHZ			(0x5 << 4)
+#define	POWER_MISC_FREQSEL_21MHZ			(0x6 << 4)
+#define	POWER_MISC_FREQSEL_17MHZ			(0x7 << 4)
+#define	POWER_MISC_DISABLE_FET_BO_LOGIC			(1 << 3)
+#define	POWER_MISC_DELAY_TIMING				(1 << 2)
+#define	POWER_MISC_TEST					(1 << 1)
+#define	POWER_MISC_SEL_PLLCLK				(1 << 0)
+
+#define	POWER_DCLIMITS_POSLIMIT_BUCK_MASK		(0x7f << 8)
+#define	POWER_DCLIMITS_POSLIMIT_BUCK_OFFSET		8
+#define	POWER_DCLIMITS_NEGLIMIT_MASK			0x7f
+#define	POWER_DCLIMITS_NETLIMIT_OFFSET			0
+
+#define	POWER_LOOPCTRL_TOGGLE_DIF			(1 << 20)
+#define	POWER_LOOPCTRL_HYST_SIGN			(1 << 19)
+#define	POWER_LOOPCTRL_EN_CM_HYST			(1 << 18)
+#define	POWER_LOOPCTRL_EN_DF_HYST			(1 << 17)
+#define	POWER_LOOPCTRL_CM_HYST_THRESH			(1 << 16)
+#define	POWER_LOOPCTRL_DF_HYST_THRESH			(1 << 15)
+#define	POWER_LOOPCTRL_RCSCALE_THRESH			(1 << 14)
+#define	POWER_LOOPCTRL_EN_RCSCALE_MASK			(0x3 << 12)
+#define	POWER_LOOPCTRL_EN_RCSCALE_OFFSET		12
+#define	POWER_LOOPCTRL_EN_RCSCALE_DIS			(0x0 << 12)
+#define	POWER_LOOPCTRL_EN_RCSCALE_2X			(0x1 << 12)
+#define	POWER_LOOPCTRL_EN_RCSCALE_4X			(0x2 << 12)
+#define	POWER_LOOPCTRL_EN_RCSCALE_8X			(0x3 << 12)
+#define	POWER_LOOPCTRL_DC_FF_MASK			(0x7 << 8)
+#define	POWER_LOOPCTRL_DC_FF_OFFSET			8
+#define	POWER_LOOPCTRL_DC_R_MASK			(0xf << 4)
+#define	POWER_LOOPCTRL_DC_R_OFFSET			4
+#define	POWER_LOOPCTRL_DC_C_MASK			0x3
+#define	POWER_LOOPCTRL_DC_C_OFFSET			0
+#define	POWER_LOOPCTRL_DC_C_MAX				0x0
+#define	POWER_LOOPCTRL_DC_C_2X				0x1
+#define	POWER_LOOPCTRL_DC_C_4X				0x2
+#define	POWER_LOOPCTRL_DC_C_MIN				0x3
+
+#define	POWER_STS_PWRUP_SOURCE_MASK			(0x3f << 24)
+#define	POWER_STS_PWRUP_SOURCE_OFFSET			24
+#define	POWER_STS_PWRUP_SOURCE_5V			(0x20 << 24)
+#define	POWER_STS_PWRUP_SOURCE_RTC			(0x10 << 24)
+#define	POWER_STS_PWRUP_SOURCE_PSWITCH_HIGH		(0x02 << 24)
+#define	POWER_STS_PWRUP_SOURCE_PSWITCH_MID		(0x01 << 24)
+#define	POWER_STS_PSWITCH_MASK				(0x3 << 20)
+#define	POWER_STS_PSWITCH_OFFSET			20
+#define	POWER_STS_THERMAL_WARNING			(1 << 19)
+#define	POWER_STS_VDDMEM_BO				(1 << 18)
+#define	POWER_STS_AVALID0_STATUS			(1 << 17)
+#define	POWER_STS_BVALID0_STATUS			(1 << 16)
+#define	POWER_STS_VBUSVALID0_STATUS			(1 << 15)
+#define	POWER_STS_SESSEND0_STATUS			(1 << 14)
+#define	POWER_STS_BATT_BO				(1 << 13)
+#define	POWER_STS_VDD5V_FAULT				(1 << 12)
+#define	POWER_STS_CHRGSTS				(1 << 11)
+#define	POWER_STS_DCDC_4P2_BO				(1 << 10)
+#define	POWER_STS_DC_OK					(1 << 9)
+#define	POWER_STS_VDDIO_BO				(1 << 8)
+#define	POWER_STS_VDDA_BO				(1 << 7)
+#define	POWER_STS_VDDD_BO				(1 << 6)
+#define	POWER_STS_VDD5V_GT_VDDIO			(1 << 5)
+#define	POWER_STS_VDD5V_DROOP				(1 << 4)
+#define	POWER_STS_AVALID0				(1 << 3)
+#define	POWER_STS_BVALID0				(1 << 2)
+#define	POWER_STS_VBUSVALID0				(1 << 1)
+#define	POWER_STS_SESSEND0				(1 << 0)
+
+#define	POWER_SPEED_STATUS_MASK				(0xffff << 8)
+#define	POWER_SPEED_STATUS_OFFSET			8
+#define	POWER_SPEED_STATUS_SEL_MASK			(0x3 << 6)
+#define	POWER_SPEED_STATUS_SEL_OFFSET			6
+#define	POWER_SPEED_STATUS_SEL_DCDC_STAT		(0x0 << 6)
+#define	POWER_SPEED_STATUS_SEL_CORE_STAT		(0x1 << 6)
+#define	POWER_SPEED_STATUS_SEL_ARM_STAT			(0x2 << 6)
+#define	POWER_SPEED_CTRL_MASK				0x3
+#define	POWER_SPEED_CTRL_OFFSET				0
+#define	POWER_SPEED_CTRL_SS_OFF				0x0
+#define	POWER_SPEED_CTRL_SS_ON				0x1
+#define	POWER_SPEED_CTRL_SS_ENABLE			0x3
+
+#define	POWER_BATTMONITOR_BATT_VAL_MASK			(0x3ff << 16)
+#define	POWER_BATTMONITOR_BATT_VAL_OFFSET		16
+#define	POWER_BATTMONITOR_PWDN_BATTBRNOUT_5VDETECT_EN	(1 << 11)
+#define	POWER_BATTMONITOR_EN_BATADJ			(1 << 10)
+#define	POWER_BATTMONITOR_PWDN_BATTBRNOUT		(1 << 9)
+#define	POWER_BATTMONITOR_BRWNOUT_PWD			(1 << 8)
+#define	POWER_BATTMONITOR_BRWNOUT_LVL_MASK		0x1f
+#define	POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET		0
+
+#define	POWER_RESET_UNLOCK_MASK				(0xffff << 16)
+#define	POWER_RESET_UNLOCK_OFFSET			16
+#define	POWER_RESET_UNLOCK_KEY				(0x3e77 << 16)
+#define	POWER_RESET_FASTFALL_PSWITCH_OFF		(1 << 2)
+#define	POWER_RESET_PWD_OFF				(1 << 1)
+#define	POWER_RESET_PWD					(1 << 0)
+
+#define	POWER_DEBUG_VBUSVALIDPIOLOCK			(1 << 3)
+#define	POWER_DEBUG_AVALIDPIOLOCK			(1 << 2)
+#define	POWER_DEBUG_BVALIDPIOLOCK			(1 << 1)
+#define	POWER_DEBUG_SESSENDPIOLOCK			(1 << 0)
+
+#define	POWER_THERMAL_TEST				(1 << 8)
+#define	POWER_THERMAL_PWD				(1 << 7)
+#define	POWER_THERMAL_LOW_POWER				(1 << 6)
+#define	POWER_THERMAL_OFFSET_ADJ_MASK			(0x3 << 4)
+#define	POWER_THERMAL_OFFSET_ADJ_OFFSET			4
+#define	POWER_THERMAL_OFFSET_ADJ_ENABLE			(1 << 3)
+#define	POWER_THERMAL_TEMP_THRESHOLD_MASK		0x7
+#define	POWER_THERMAL_TEMP_THRESHOLD_OFFSET		0
+
+#define	POWER_USB1CTRL_AVALID1				(1 << 3)
+#define	POWER_USB1CTRL_BVALID1				(1 << 2)
+#define	POWER_USB1CTRL_VBUSVALID1			(1 << 1)
+#define	POWER_USB1CTRL_SESSEND1				(1 << 0)
+
+#define	POWER_SPECIAL_TEST_MASK				0xffffffff
+#define	POWER_SPECIAL_TEST_OFFSET			0
+
+#define	POWER_VERSION_MAJOR_MASK			(0xff << 24)
+#define	POWER_VERSION_MAJOR_OFFSET			24
+#define	POWER_VERSION_MINOR_MASK			(0xff << 16)
+#define	POWER_VERSION_MINOR_OFFSET			16
+#define	POWER_VERSION_STEP_MASK				0xffff
+#define	POWER_VERSION_STEP_OFFSET			0
+
+#define	POWER_ANACLKCTRL_CLKGATE_0			(1 << 31)
+#define	POWER_ANACLKCTRL_OUTDIV_MASK			(0x7 << 28)
+#define	POWER_ANACLKCTRL_OUTDIV_OFFSET			28
+#define	POWER_ANACLKCTRL_INVERT_OUTCLK			(1 << 27)
+#define	POWER_ANACLKCTRL_CLKGATE_I			(1 << 26)
+#define	POWER_ANACLKCTRL_DITHER_OFF			(1 << 10)
+#define	POWER_ANACLKCTRL_SLOW_DITHER			(1 << 9)
+#define	POWER_ANACLKCTRL_INVERT_INCLK			(1 << 8)
+#define	POWER_ANACLKCTRL_INCLK_SHIFT_MASK		(0x3 << 4)
+#define	POWER_ANACLKCTRL_INCLK_SHIFT_OFFSET		4
+#define	POWER_ANACLKCTRL_INDIV_MASK			0x7
+#define	POWER_ANACLKCTRL_INDIV_OFFSET			0
+
+#define	POWER_REFCTRL_FASTSETTLING			(1 << 26)
+#define	POWER_REFCTRL_RAISE_REF				(1 << 25)
+#define	POWER_REFCTRL_XTAL_BGR_BIAS			(1 << 24)
+#define	POWER_REFCTRL_VBG_ADJ_MASK			(0x7 << 20)
+#define	POWER_REFCTRL_VBG_ADJ_OFFSET			20
+#define	POWER_REFCTRL_LOW_PWR				(1 << 19)
+#define	POWER_REFCTRL_BIAS_CTRL_MASK			(0x3 << 16)
+#define	POWER_REFCTRL_BIAS_CTRL_OFFSET			16
+#define	POWER_REFCTRL_VDDXTAL_TO_VDDD			(1 << 14)
+#define	POWER_REFCTRL_ADJ_ANA				(1 << 13)
+#define	POWER_REFCTRL_ADJ_VAG				(1 << 12)
+#define	POWER_REFCTRL_ANA_REFVAL_MASK			(0xf << 8)
+#define	POWER_REFCTRL_ANA_REFVAL_OFFSET			8
+#define	POWER_REFCTRL_VAG_VAL_MASK			(0xf << 4)
+#define	POWER_REFCTRL_VAG_VAL_OFFSET			4
+
+#endif	/* __MX28_REGS_POWER_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-rtc.h b/arch/arm/include/asm/arch-mx28/regs-rtc.h
new file mode 100644
index 0000000..fe2fda9
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-rtc.h
@@ -0,0 +1,147 @@
+/*
+ * Freescale i.MX28 RTC Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_RTC_H__
+#define __MX28_REGS_RTC_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_rtc_regs {
+	mx28_reg(hw_rtc_ctrl)
+	mx28_reg(hw_rtc_stat)
+	mx28_reg(hw_rtc_milliseconds)
+	mx28_reg(hw_rtc_seconds)
+	mx28_reg(hw_rtc_rtc_alarm)
+	mx28_reg(hw_rtc_watchdog)
+	mx28_reg(hw_rtc_persistent0)
+	mx28_reg(hw_rtc_persistent1)
+	mx28_reg(hw_rtc_persistent2)
+	mx28_reg(hw_rtc_persistent3)
+	mx28_reg(hw_rtc_persistent4)
+	mx28_reg(hw_rtc_persistent5)
+	mx28_reg(hw_rtc_debug)
+	mx28_reg(hw_rtc_version)
+};
+#endif
+
+#define	RTC_CTRL_SFTRST				(1 << 31)
+#define	RTC_CTRL_CLKGATE			(1 << 30)
+#define	RTC_CTRL_SUPPRESS_COPY2ANALOG		(1 << 6)
+#define	RTC_CTRL_FORCE_UPDATE			(1 << 5)
+#define	RTC_CTRL_WATCHDOGEN			(1 << 4)
+#define	RTC_CTRL_ONEMSEC_IRQ			(1 << 3)
+#define	RTC_CTRL_ALARM_IRQ			(1 << 2)
+#define	RTC_CTRL_ONEMSEC_IRQ_EN			(1 << 1)
+#define	RTC_CTRL_ALARM_IRQ_EN			(1 << 0)
+
+#define	RTC_STAT_RTC_PRESENT			(1 << 31)
+#define	RTC_STAT_ALARM_PRESENT			(1 << 30)
+#define	RTC_STAT_WATCHDOG_PRESENT		(1 << 29)
+#define	RTC_STAT_XTAL32000_PRESENT		(1 << 28)
+#define	RTC_STAT_XTAL32768_PRESENT		(1 << 27)
+#define	RTC_STAT_STALE_REGS_MASK		(0xff << 16)
+#define	RTC_STAT_STALE_REGS_OFFSET		16
+#define	RTC_STAT_NEW_REGS_MASK			(0xff << 8)
+#define	RTC_STAT_NEW_REGS_OFFSET		8
+
+#define	RTC_MILLISECONDS_COUNT_MASK		0xffffffff
+#define	RTC_MILLISECONDS_COUNT_OFFSET		0
+
+#define	RTC_SECONDS_COUNT_MASK			0xffffffff
+#define	RTC_SECONDS_COUNT_OFFSET		0
+
+#define	RTC_ALARM_VALUE_MASK			0xffffffff
+#define	RTC_ALARM_VALUE_OFFSET			0
+
+#define	RTC_WATCHDOG_COUNT_MASK			0xffffffff
+#define	RTC_WATCHDOG_COUNT_OFFSET		0
+
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_MASK	(0xf << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_OFFSET	28
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V83	(0x0 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V78	(0x1 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V73	(0x2 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V68	(0x3 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V62	(0x4 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V57	(0x5 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V52	(0x6 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V48	(0x7 << 28)
+#define	RTC_PERSISTENT0_EXTERNAL_RESET		(1 << 21)
+#define	RTC_PERSISTENT0_THERMAL_RESET		(1 << 20)
+#define	RTC_PERSISTENT0_ENABLE_LRADC_PWRUP	(1 << 18)
+#define	RTC_PERSISTENT0_AUTO_RESTART		(1 << 17)
+#define	RTC_PERSISTENT0_DISABLE_PSWITCH		(1 << 16)
+#define	RTC_PERSISTENT0_LOWERBIAS_MASK		(0xf << 14)
+#define	RTC_PERSISTENT0_LOWERBIAS_OFFSET	14
+#define	RTC_PERSISTENT0_LOWERBIAS_NOMINAL	(0x0 << 14)
+#define	RTC_PERSISTENT0_LOWERBIAS_M25P		(0x1 << 14)
+#define	RTC_PERSISTENT0_LOWERBIAS_M50P		(0x3 << 14)
+#define	RTC_PERSISTENT0_DISABLE_XTALOK		(1 << 13)
+#define	RTC_PERSISTENT0_MSEC_RES_MASK		(0x1f << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_OFFSET		8
+#define	RTC_PERSISTENT0_MSEC_RES_1MS		(0x01 << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_2MS		(0x02 << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_4MS		(0x04 << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_8MS		(0x08 << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_16MS		(0x10 << 8)
+#define	RTC_PERSISTENT0_ALARM_WAKE		(1 << 7)
+#define	RTC_PERSISTENT0_XTAL32_FREQ		(1 << 6)
+#define	RTC_PERSISTENT0_XTAL32KHZ_PWRUP		(1 << 5)
+#define	RTC_PERSISTENT0_XTAL24KHZ_PWRUP		(1 << 4)
+#define	RTC_PERSISTENT0_LCK_SECS		(1 << 3)
+#define	RTC_PERSISTENT0_ALARM_EN		(1 << 2)
+#define	RTC_PERSISTENT0_ALARM_WAKE_EN		(1 << 1)
+#define	RTC_PERSISTENT0_CLOCKSOURCE		(1 << 0)
+
+#define	RTC_PERSISTENT1_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT1_GENERAL_OFFSET		0
+#define	RTC_PERSISTENT1_GENERAL_OTG_ALT_ROLE	0x0080
+#define	RTC_PERSISTENT1_GENERAL_OTG_HNP		0x0100
+#define	RTC_PERSISTENT1_GENERAL_USB_LPM		0x0200
+#define	RTC_PERSISTENT1_GENERAL_SKIP_CHECKDISK	0x0400
+#define	RTC_PERSISTENT1_GENERAL_USB_BOOT_PLAYER	0x0800
+#define	RTC_PERSISTENT1_GENERAL_ENUM_500MA_2X	0x1000
+
+#define	RTC_PERSISTENT2_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT2_GENERAL_OFFSET		0
+
+#define	RTC_PERSISTENT3_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT3_GENERAL_OFFSET		0
+
+#define	RTC_PERSISTENT4_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT4_GENERAL_OFFSET		0
+
+#define	RTC_PERSISTENT5_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT5_GENERAL_OFFSET		0
+
+#define	RTC_DEBUG_WATCHDOG_RESET_MASK		(1 << 1)
+#define	RTC_DEBUG_WATCHDOG_RESET		(1 << 0)
+
+#define	RTC_VERSION_MAJOR_MASK			(0xff << 24)
+#define	RTC_VERSION_MAJOR_OFFSET		24
+#define	RTC_VERSION_MINOR_MASK			(0xff << 16)
+#define	RTC_VERSION_MINOR_OFFSET		16
+#define	RTC_VERSION_STEP_MASK			0xffff
+#define	RTC_VERSION_STEP_OFFSET			0
+
+#endif	/* __MX28_REGS_RTC_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-ssp.h b/arch/arm/include/asm/arch-mx28/regs-ssp.h
new file mode 100644
index 0000000..ab3870c
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-ssp.h
@@ -0,0 +1,349 @@
+/*
+ * Freescale i.MX28 SSP Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_SSP_H__
+#define __MX28_REGS_SSP_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_ssp_regs {
+	mx28_reg(hw_ssp_ctrl0)
+	mx28_reg(hw_ssp_cmd0)
+	mx28_reg(hw_ssp_cmd1)
+	mx28_reg(hw_ssp_xfer_size)
+	mx28_reg(hw_ssp_block_size)
+	mx28_reg(hw_ssp_compref)
+	mx28_reg(hw_ssp_compmask)
+	mx28_reg(hw_ssp_timing)
+	mx28_reg(hw_ssp_ctrl1)
+	mx28_reg(hw_ssp_data)
+	mx28_reg(hw_ssp_sdresp0)
+	mx28_reg(hw_ssp_sdresp1)
+	mx28_reg(hw_ssp_sdresp2)
+	mx28_reg(hw_ssp_sdresp3)
+	mx28_reg(hw_ssp_ddr_ctrl)
+	mx28_reg(hw_ssp_dll_ctrl)
+	mx28_reg(hw_ssp_status)
+	mx28_reg(hw_ssp_dll_sts)
+	mx28_reg(hw_ssp_debug)
+	mx28_reg(hw_ssp_version)
+};
+#endif
+
+#define	SSP_CTRL0_SFTRST			(1 << 31)
+#define	SSP_CTRL0_CLKGATE			(1 << 30)
+#define	SSP_CTRL0_RUN				(1 << 29)
+#define	SSP_CTRL0_SDIO_IRQ_CHECK		(1 << 28)
+#define	SSP_CTRL0_LOCK_CS			(1 << 27)
+#define	SSP_CTRL0_IGNORE_CRC			(1 << 26)
+#define	SSP_CTRL0_READ				(1 << 25)
+#define	SSP_CTRL0_DATA_XFER			(1 << 24)
+#define	SSP_CTRL0_BUS_WIDTH_MASK		(0x3 << 22)
+#define	SSP_CTRL0_BUS_WIDTH_OFFSET		22
+#define	SSP_CTRL0_BUS_WIDTH_ONE_BIT		(0x0 << 22)
+#define	SSP_CTRL0_BUS_WIDTH_FOUR_BIT		(0x1 << 22)
+#define	SSP_CTRL0_BUS_WIDTH_EIGHT_BIT		(0x2 << 22)
+#define	SSP_CTRL0_WAIT_FOR_IRQ			(1 << 21)
+#define	SSP_CTRL0_WAIT_FOR_CMD			(1 << 20)
+#define	SSP_CTRL0_LONG_RESP			(1 << 19)
+#define	SSP_CTRL0_CHECK_RESP			(1 << 18)
+#define	SSP_CTRL0_GET_RESP			(1 << 17)
+#define	SSP_CTRL0_ENABLE			(1 << 16)
+
+#define	SSP_CMD0_SOFT_TERMINATE			(1 << 26)
+#define	SSP_CMD0_DBL_DATA_RATE_EN		(1 << 25)
+#define	SSP_CMD0_PRIM_BOOT_OP_EN		(1 << 24)
+#define	SSP_CMD0_BOOT_ACK_EN			(1 << 23)
+#define	SSP_CMD0_SLOW_CLKING_EN			(1 << 22)
+#define	SSP_CMD0_CONT_CLKING_EN			(1 << 21)
+#define	SSP_CMD0_APPEND_8CYC			(1 << 20)
+#define	SSP_CMD0_CMD_MASK			0xff
+#define	SSP_CMD0_CMD_OFFSET			0
+#define	SSP_CMD0_CMD_MMC_GO_IDLE_STATE		0x00
+#define	SSP_CMD0_CMD_MMC_SEND_OP_COND		0x01
+#define	SSP_CMD0_CMD_MMC_ALL_SEND_CID		0x02
+#define	SSP_CMD0_CMD_MMC_SET_RELATIVE_ADDR	0x03
+#define	SSP_CMD0_CMD_MMC_SET_DSR		0x04
+#define	SSP_CMD0_CMD_MMC_RESERVED_5		0x05
+#define	SSP_CMD0_CMD_MMC_SWITCH			0x06
+#define	SSP_CMD0_CMD_MMC_SELECT_DESELECT_CARD	0x07
+#define	SSP_CMD0_CMD_MMC_SEND_EXT_CSD		0x08
+#define	SSP_CMD0_CMD_MMC_SEND_CSD		0x09
+#define	SSP_CMD0_CMD_MMC_SEND_CID		0x0a
+#define	SSP_CMD0_CMD_MMC_READ_DAT_UNTIL_STOP	0x0b
+#define	SSP_CMD0_CMD_MMC_STOP_TRANSMISSION	0x0c
+#define	SSP_CMD0_CMD_MMC_SEND_STATUS		0x0d
+#define	SSP_CMD0_CMD_MMC_BUSTEST_R		0x0e
+#define	SSP_CMD0_CMD_MMC_GO_INACTIVE_STATE	0x0f
+#define	SSP_CMD0_CMD_MMC_SET_BLOCKLEN		0x10
+#define	SSP_CMD0_CMD_MMC_READ_SINGLE_BLOCK	0x11
+#define	SSP_CMD0_CMD_MMC_READ_MULTIPLE_BLOCK	0x12
+#define	SSP_CMD0_CMD_MMC_BUSTEST_W		0x13
+#define	SSP_CMD0_CMD_MMC_WRITE_DAT_UNTIL_STOP	0x14
+#define	SSP_CMD0_CMD_MMC_SET_BLOCK_COUNT	0x17
+#define	SSP_CMD0_CMD_MMC_WRITE_BLOCK		0x18
+#define	SSP_CMD0_CMD_MMC_WRITE_MULTIPLE_BLOCK	0x19
+#define	SSP_CMD0_CMD_MMC_PROGRAM_CID		0x1a
+#define	SSP_CMD0_CMD_MMC_PROGRAM_CSD		0x1b
+#define	SSP_CMD0_CMD_MMC_SET_WRITE_PROT		0x1c
+#define	SSP_CMD0_CMD_MMC_CLR_WRITE_PROT		0x1d
+#define	SSP_CMD0_CMD_MMC_SEND_WRITE_PROT	0x1e
+#define	SSP_CMD0_CMD_MMC_ERASE_GROUP_START	0x23
+#define	SSP_CMD0_CMD_MMC_ERASE_GROUP_END	0x24
+#define	SSP_CMD0_CMD_MMC_ERASE			0x26
+#define	SSP_CMD0_CMD_MMC_FAST_IO		0x27
+#define	SSP_CMD0_CMD_MMC_GO_IRQ_STATE		0x28
+#define	SSP_CMD0_CMD_MMC_LOCK_UNLOCK		0x2a
+#define	SSP_CMD0_CMD_MMC_APP_CMD		0x37
+#define	SSP_CMD0_CMD_MMC_GEN_CMD		0x38
+#define	SSP_CMD0_CMD_SD_GO_IDLE_STATE		0x00
+#define	SSP_CMD0_CMD_SD_ALL_SEND_CID		0x02
+#define	SSP_CMD0_CMD_SD_SEND_RELATIVE_ADDR	0x03
+#define	SSP_CMD0_CMD_SD_SET_DSR			0x04
+#define	SSP_CMD0_CMD_SD_IO_SEND_OP_COND		0x05
+#define	SSP_CMD0_CMD_SD_SELECT_DESELECT_CARD	0x07
+#define	SSP_CMD0_CMD_SD_SEND_CSD		0x09
+#define	SSP_CMD0_CMD_SD_SEND_CID		0x0a
+#define	SSP_CMD0_CMD_SD_STOP_TRANSMISSION	0x0c
+#define	SSP_CMD0_CMD_SD_SEND_STATUS		0x0d
+#define	SSP_CMD0_CMD_SD_GO_INACTIVE_STATE	0x0f
+#define	SSP_CMD0_CMD_SD_SET_BLOCKLEN		0x10
+#define	SSP_CMD0_CMD_SD_READ_SINGLE_BLOCK	0x11
+#define	SSP_CMD0_CMD_SD_READ_MULTIPLE_BLOCK	0x12
+#define	SSP_CMD0_CMD_SD_WRITE_BLOCK		0x18
+#define	SSP_CMD0_CMD_SD_WRITE_MULTIPLE_BLOCK	0x19
+#define	SSP_CMD0_CMD_SD_PROGRAM_CSD		0x1b
+#define	SSP_CMD0_CMD_SD_SET_WRITE_PROT		0x1c
+#define	SSP_CMD0_CMD_SD_CLR_WRITE_PROT		0x1d
+#define	SSP_CMD0_CMD_SD_SEND_WRITE_PROT		0x1e
+#define	SSP_CMD0_CMD_SD_ERASE_WR_BLK_START	0x20
+#define	SSP_CMD0_CMD_SD_ERASE_WR_BLK_END	0x21
+#define	SSP_CMD0_CMD_SD_ERASE_GROUP_START	0x23
+#define	SSP_CMD0_CMD_SD_ERASE_GROUP_END		0x24
+#define	SSP_CMD0_CMD_SD_ERASE			0x26
+#define	SSP_CMD0_CMD_SD_LOCK_UNLOCK		0x2a
+#define	SSP_CMD0_CMD_SD_IO_RW_DIRECT		0x34
+#define	SSP_CMD0_CMD_SD_IO_RW_EXTENDED		0x35
+#define	SSP_CMD0_CMD_SD_APP_CMD			0x37
+#define	SSP_CMD0_CMD_SD_GEN_CMD			0x38
+
+#define	SSP_CMD1_CMD_ARG_MASK			0xffffffff
+#define	SSP_CMD1_CMD_ARG_OFFSET			0
+
+#define	SSP_XFER_SIZE_XFER_COUNT_MASK		0xffffffff
+#define	SSP_XFER_SIZE_XFER_COUNT_OFFSET		0
+
+#define	SSP_BLOCK_SIZE_BLOCK_COUNT_MASK		(0xffffff << 4)
+#define	SSP_BLOCK_SIZE_BLOCK_COUNT_OFFSET	4
+#define	SSP_BLOCK_SIZE_BLOCK_SIZE_MASK		0xf
+#define	SSP_BLOCK_SIZE_BLOCK_SIZE_OFFSET	0
+
+#define	SSP_COMPREF_REFERENCE_MASK		0xffffffff
+#define	SSP_COMPREF_REFERENCE_OFFSET		0
+
+#define	SSP_COMPMASK_MASK_MASK			0xffffffff
+#define	SSP_COMPMASK_MASK_OFFSET		0
+
+#define	SSP_TIMING_TIMEOUT_MASK			(0xffff << 16)
+#define	SSP_TIMING_TIMEOUT_OFFSET		16
+#define	SSP_TIMING_CLOCK_DIVIDE_MASK		(0xff << 8)
+#define	SSP_TIMING_CLOCK_DIVIDE_OFFSET		8
+#define	SSP_TIMING_CLOCK_RATE_MASK		0xff
+#define	SSP_TIMING_CLOCK_RATE_OFFSET		0
+
+#define	SSP_CTRL1_SDIO_IRQ			(1 << 31)
+#define	SSP_CTRL1_SDIO_IRQ_EN			(1 << 30)
+#define	SSP_CTRL1_RESP_ERR_IRQ			(1 << 29)
+#define	SSP_CTRL1_RESP_ERR_IRQ_EN		(1 << 28)
+#define	SSP_CTRL1_RESP_TIMEOUT_IRQ		(1 << 27)
+#define	SSP_CTRL1_RESP_TIMEOUT_IRQ_EN		(1 << 26)
+#define	SSP_CTRL1_DATA_TIMEOUT_IRQ		(1 << 25)
+#define	SSP_CTRL1_DATA_TIMEOUT_IRQ_EN		(1 << 24)
+#define	SSP_CTRL1_DATA_CRC_IRQ			(1 << 23)
+#define	SSP_CTRL1_DATA_CRC_IRQ_EN		(1 << 22)
+#define	SSP_CTRL1_FIFO_UNDERRUN_IRQ		(1 << 21)
+#define	SSP_CTRL1_FIFO_UNDERRUN_EN		(1 << 20)
+#define	SSP_CTRL1_CEATA_CCS_ERR_IRQ		(1 << 19)
+#define	SSP_CTRL1_CEATA_CCS_ERR_IRQ_EN		(1 << 18)
+#define	SSP_CTRL1_RECV_TIMEOUT_IRQ		(1 << 17)
+#define	SSP_CTRL1_RECV_TIMEOUT_IRQ_EN		(1 << 16)
+#define	SSP_CTRL1_FIFO_OVERRUN_IRQ		(1 << 15)
+#define	SSP_CTRL1_FIFO_OVERRUN_IRQ_EN		(1 << 14)
+#define	SSP_CTRL1_DMA_ENABLE			(1 << 13)
+#define	SSP_CTRL1_CEATA_CCS_ERR_EN		(1 << 12)
+#define	SSP_CTRL1_SLAVE_OUT_DISABLE		(1 << 11)
+#define	SSP_CTRL1_PHASE				(1 << 10)
+#define	SSP_CTRL1_POLARITY			(1 << 9)
+#define	SSP_CTRL1_SLAVE_MODE			(1 << 8)
+#define	SSP_CTRL1_WORD_LENGTH_MASK		(0xf << 4)
+#define	SSP_CTRL1_WORD_LENGTH_OFFSET		4
+#define	SSP_CTRL1_WORD_LENGTH_RESERVED0		(0x0 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_RESERVED1		(0x1 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_RESERVED2		(0x2 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_FOUR_BITS		(0x3 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_EIGHT_BITS	(0x7 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_SIXTEEN_BITS	(0xf << 4)
+#define	SSP_CTRL1_SSP_MODE_MASK			0xf
+#define	SSP_CTRL1_SSP_MODE_OFFSET		0
+#define	SSP_CTRL1_SSP_MODE_SPI			0x0
+#define	SSP_CTRL1_SSP_MODE_SSI			0x1
+#define	SSP_CTRL1_SSP_MODE_SD_MMC		0x3
+#define	SSP_CTRL1_SSP_MODE_MS			0x4
+
+#define	SSP_DATA_DATA_MASK			0xffffffff
+#define	SSP_DATA_DATA_OFFSET			0
+
+#define	SSP_SDRESP0_RESP0_MASK			0xffffffff
+#define	SSP_SDRESP0_RESP0_OFFSET		0
+
+#define	SSP_SDRESP1_RESP1_MASK			0xffffffff
+#define	SSP_SDRESP1_RESP1_OFFSET		0
+
+#define	SSP_SDRESP2_RESP2_MASK			0xffffffff
+#define	SSP_SDRESP2_RESP2_OFFSET		0
+
+#define	SSP_SDRESP3_RESP3_MASK			0xffffffff
+#define	SSP_SDRESP3_RESP3_OFFSET		0
+
+#define	SSP_DDR_CTRL_DMA_BURST_TYPE_MASK	(0x3 << 30)
+#define	SSP_DDR_CTRL_DMA_BURST_TYPE_OFFSET	30
+#define	SSP_DDR_CTRL_NIBBLE_POS			(1 << 1)
+#define	SSP_DDR_CTRL_TXCLK_DELAY_TYPE		(1 << 0)
+
+#define	SSP_DLL_CTRL_REF_UPDATE_INT_MASK	(0xf << 28)
+#define	SSP_DLL_CTRL_REF_UPDATE_INT_OFFSET	28
+#define	SSP_DLL_CTRL_SLV_UPDATE_INT_MASK	(0xff << 20)
+#define	SSP_DLL_CTRL_SLV_UPDATE_INT_OFFSET	20
+#define	SSP_DLL_CTRL_SLV_OVERRIDE_VAL_MASK	(0x3f << 10)
+#define	SSP_DLL_CTRL_SLV_OVERRIDE_VAL_OFFSET	10
+#define	SSP_DLL_CTRL_SLV_OVERRIDE		(1 << 9)
+#define	SSP_DLL_CTRL_GATE_UPDATE		(1 << 7)
+#define	SSP_DLL_CTRL_SLV_DLY_TARGET_MASK	(0xf << 3)
+#define	SSP_DLL_CTRL_SLV_DLY_TARGET_OFFSET	3
+#define	SSP_DLL_CTRL_SLV_FORCE_UPD		(1 << 2)
+#define	SSP_DLL_CTRL_RESET			(1 << 1)
+#define	SSP_DLL_CTRL_ENABLE			(1 << 0)
+
+#define	SSP_STATUS_PRESENT			(1 << 31)
+#define	SSP_STATUS_MS_PRESENT			(1 << 30)
+#define	SSP_STATUS_SD_PRESENT			(1 << 29)
+#define	SSP_STATUS_CARD_DETECT			(1 << 28)
+#define	SSP_STATUS_DMABURST			(1 << 22)
+#define	SSP_STATUS_DMASENSE			(1 << 21)
+#define	SSP_STATUS_DMATERM			(1 << 20)
+#define	SSP_STATUS_DMAREQ			(1 << 19)
+#define	SSP_STATUS_DMAEND			(1 << 18)
+#define	SSP_STATUS_SDIO_IRQ			(1 << 17)
+#define	SSP_STATUS_RESP_CRC_ERR			(1 << 16)
+#define	SSP_STATUS_RESP_ERR			(1 << 15)
+#define	SSP_STATUS_RESP_TIMEOUT			(1 << 14)
+#define	SSP_STATUS_DATA_CRC_ERR			(1 << 13)
+#define	SSP_STATUS_TIMEOUT			(1 << 12)
+#define	SSP_STATUS_RECV_TIMEOUT_STAT		(1 << 11)
+#define	SSP_STATUS_CEATA_CCS_ERR		(1 << 10)
+#define	SSP_STATUS_FIFO_OVRFLW			(1 << 9)
+#define	SSP_STATUS_FIFO_FULL			(1 << 8)
+#define	SSP_STATUS_FIFO_EMPTY			(1 << 5)
+#define	SSP_STATUS_FIFO_UNDRFLW			(1 << 4)
+#define	SSP_STATUS_CMD_BUSY			(1 << 3)
+#define	SSP_STATUS_DATA_BUSY			(1 << 2)
+#define	SSP_STATUS_BUSY				(1 << 0)
+
+#define	SSP_DLL_STS_REF_SEL_MASK		(0x3f << 8)
+#define	SSP_DLL_STS_REF_SEL_OFFSET		8
+#define	SSP_DLL_STS_SLV_SEL_MASK		(0x3f << 2)
+#define	SSP_DLL_STS_SLV_SEL_OFFSET		2
+#define	SSP_DLL_STS_REF_LOCK			(1 << 1)
+#define	SSP_DLL_STS_SLV_LOCK			(1 << 0)
+
+#define	SSP_DEBUG_DATACRC_ERR_MASK		(0xf << 28)
+#define	SSP_DEBUG_DATACRC_ERR_OFFSET		28
+#define	SSP_DEBUG_DATA_STALL			(1 << 27)
+#define	SSP_DEBUG_DAT_SM_MASK			(0x7 << 24)
+#define	SSP_DEBUG_DAT_SM_OFFSET			24
+#define	SSP_DEBUG_DAT_SM_DSM_IDLE		(0x0 << 24)
+#define	SSP_DEBUG_DAT_SM_DSM_WORD		(0x2 << 24)
+#define	SSP_DEBUG_DAT_SM_DSM_CRC1		(0x3 << 24)
+#define	SSP_DEBUG_DAT_SM_DSM_CRC2		(0x4 << 24)
+#define	SSP_DEBUG_DAT_SM_DSM_END		(0x5 << 24)
+#define	SSP_DEBUG_MSTK_SM_MASK			(0xf << 20)
+#define	SSP_DEBUG_MSTK_SM_OFFSET		20
+#define	SSP_DEBUG_MSTK_SM_MSTK_IDLE		(0x0 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_CKON		(0x1 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_BS1		(0x2 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_TPC		(0x3 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_BS2		(0x4 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_HDSHK		(0x5 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_BS3		(0x6 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_RW		(0x7 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_CRC1		(0x8 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_CRC2		(0x9 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_BS0		(0xa << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_END1		(0xb << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_END2W		(0xc << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_END2R		(0xd << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_DONE		(0xe << 20)
+#define	SSP_DEBUG_CMD_OE			(1 << 19)
+#define	SSP_DEBUG_DMA_SM_MASK			(0x7 << 16)
+#define	SSP_DEBUG_DMA_SM_OFFSET			16
+#define	SSP_DEBUG_DMA_SM_DMA_IDLE		(0x0 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_DMAREQ		(0x1 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_DMAACK		(0x2 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_STALL		(0x3 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_BUSY		(0x4 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_DONE		(0x5 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_COUNT		(0x6 << 16)
+#define	SSP_DEBUG_MMC_SM_MASK			(0xf << 12)
+#define	SSP_DEBUG_MMC_SM_OFFSET			12
+#define	SSP_DEBUG_MMC_SM_MMC_IDLE		(0x0 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_CMD		(0x1 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_TRC		(0x2 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_RESP		(0x3 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_RPRX		(0x4 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_TX			(0x5 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_CTOK		(0x6 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_RX			(0x7 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_CCS		(0x8 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_PUP		(0x9 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_WAIT		(0xa << 12)
+#define	SSP_DEBUG_CMD_SM_MASK			(0x3 << 10)
+#define	SSP_DEBUG_CMD_SM_OFFSET			10
+#define	SSP_DEBUG_CMD_SM_CSM_IDLE		(0x0 << 10)
+#define	SSP_DEBUG_CMD_SM_CSM_INDEX		(0x1 << 10)
+#define	SSP_DEBUG_CMD_SM_CSM_ARG		(0x2 << 10)
+#define	SSP_DEBUG_CMD_SM_CSM_CRC		(0x3 << 10)
+#define	SSP_DEBUG_SSP_CMD			(1 << 9)
+#define	SSP_DEBUG_SSP_RESP			(1 << 8)
+#define	SSP_DEBUG_SSP_RXD_MASK			0xff
+#define	SSP_DEBUG_SSP_RXD_OFFSET		0
+
+#define	SSP_VERSION_MAJOR_MASK			(0xff << 24)
+#define	SSP_VERSION_MAJOR_OFFSET		24
+#define	SSP_VERSION_MINOR_MASK			(0xff << 16)
+#define	SSP_VERSION_MINOR_OFFSET		16
+#define	SSP_VERSION_STEP_MASK			0xffff
+#define	SSP_VERSION_STEP_OFFSET			0
+
+#endif /* __MX28_REGS_SSP_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-timrot.h b/arch/arm/include/asm/arch-mx28/regs-timrot.h
new file mode 100644
index 0000000..1b941cf
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-timrot.h
@@ -0,0 +1,171 @@
+/*
+ * Freescale i.MX28 TIMROT Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_TIMROT_H__
+#define __MX28_REGS_TIMROT_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_timrot_regs {
+	mx28_reg(hw_timrot_rotctrl)
+	mx28_reg(hw_timrot_rotcount)
+	mx28_reg(hw_timrot_timctrl0)
+	mx28_reg(hw_timrot_running_count0)
+	mx28_reg(hw_timrot_fixed_count0)
+	mx28_reg(hw_timrot_match_count0)
+	mx28_reg(hw_timrot_timctrl1)
+	mx28_reg(hw_timrot_running_count1)
+	mx28_reg(hw_timrot_fixed_count1)
+	mx28_reg(hw_timrot_match_count1)
+	mx28_reg(hw_timrot_timctrl2)
+	mx28_reg(hw_timrot_running_count2)
+	mx28_reg(hw_timrot_fixed_count2)
+	mx28_reg(hw_timrot_match_count2)
+	mx28_reg(hw_timrot_timctrl3)
+	mx28_reg(hw_timrot_running_count3)
+	mx28_reg(hw_timrot_fixed_count3)
+	mx28_reg(hw_timrot_match_count3)
+	mx28_reg(hw_timrot_version)
+};
+#endif
+
+#define	TIMROT_ROTCTRL_SFTRST				(1 << 31)
+#define	TIMROT_ROTCTRL_CLKGATE				(1 << 30)
+#define	TIMROT_ROTCTRL_ROTARY_PRESENT			(1 << 29)
+#define	TIMROT_ROTCTRL_TIM3_PRESENT			(1 << 28)
+#define	TIMROT_ROTCTRL_TIM2_PRESENT			(1 << 27)
+#define	TIMROT_ROTCTRL_TIM1_PRESENT			(1 << 26)
+#define	TIMROT_ROTCTRL_TIM0_PRESENT			(1 << 25)
+#define	TIMROT_ROTCTRL_STATE_MASK			(0x7 << 22)
+#define	TIMROT_ROTCTRL_STATE_OFFSET			22
+#define	TIMROT_ROTCTRL_DIVIDER_MASK			(0x3f << 16)
+#define	TIMROT_ROTCTRL_DIVIDER_OFFSET			16
+#define	TIMROT_ROTCTRL_RELATIVE				(1 << 12)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_MASK			(0x3 << 10)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_OFFSET		10
+#define	TIMROT_ROTCTRL_OVERSAMPLE_8X			(0x0 << 10)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_4X			(0x1 << 10)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_2X			(0x2 << 10)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_1X			(0x3 << 10)
+#define	TIMROT_ROTCTRL_POLARITY_B			(1 << 9)
+#define	TIMROT_ROTCTRL_POLARITY_A			(1 << 8)
+#define	TIMROT_ROTCTRL_SELECT_B_MASK			(0xf << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_OFFSET			4
+#define	TIMROT_ROTCTRL_SELECT_B_NEVER_TICK		(0x0 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM0			(0x1 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM1			(0x2 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM2			(0x3 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM3			(0x4 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM4			(0x5 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM5			(0x6 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM6			(0x7 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM7			(0x8 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_ROTARYA			(0x9 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_ROTARYB			(0xa << 4)
+#define	TIMROT_ROTCTRL_SELECT_A_MASK			0xf
+#define	TIMROT_ROTCTRL_SELECT_A_OFFSET			0
+#define	TIMROT_ROTCTRL_SELECT_A_NEVER_TICK		0x0
+#define	TIMROT_ROTCTRL_SELECT_A_PWM0			0x1
+#define	TIMROT_ROTCTRL_SELECT_A_PWM1			0x2
+#define	TIMROT_ROTCTRL_SELECT_A_PWM2			0x3
+#define	TIMROT_ROTCTRL_SELECT_A_PWM3			0x4
+#define	TIMROT_ROTCTRL_SELECT_A_PWM4			0x5
+#define	TIMROT_ROTCTRL_SELECT_A_PWM5			0x6
+#define	TIMROT_ROTCTRL_SELECT_A_PWM6			0x7
+#define	TIMROT_ROTCTRL_SELECT_A_PWM7			0x8
+#define	TIMROT_ROTCTRL_SELECT_A_ROTARYA			0x9
+#define	TIMROT_ROTCTRL_SELECT_A_ROTARYB			0xa
+
+#define	TIMROT_ROTCOUNT_UPDOWN_MASK			0xffff
+#define	TIMROT_ROTCOUNT_UPDOWN_OFFSET			0
+
+#define	TIMROT_TIMCTRLn_IRQ				(1 << 15)
+#define	TIMROT_TIMCTRLn_IRQ_EN				(1 << 14)
+#define	TIMROT_TIMCTRLn_MATCH_MODE			(1 << 11)
+#define	TIMROT_TIMCTRLn_POLARITY			(1 << 8)
+#define	TIMROT_TIMCTRLn_UPDATE				(1 << 7)
+#define	TIMROT_TIMCTRLn_RELOAD				(1 << 6)
+#define	TIMROT_TIMCTRLn_PRESCALE_MASK			(0x3 << 4)
+#define	TIMROT_TIMCTRLn_PRESCALE_OFFSET			4
+#define	TIMROT_TIMCTRLn_PRESCALE_DIV_BY_1		(0x0 << 4)
+#define	TIMROT_TIMCTRLn_PRESCALE_DIV_BY_2		(0x1 << 4)
+#define	TIMROT_TIMCTRLn_PRESCALE_DIV_BY_4		(0x2 << 4)
+#define	TIMROT_TIMCTRLn_PRESCALE_DIV_BY_8		(0x3 << 4)
+#define	TIMROT_TIMCTRLn_SELECT_MASK			0xf
+#define	TIMROT_TIMCTRLn_SELECT_OFFSET			0
+#define	TIMROT_TIMCTRLn_SELECT_NEVER_TICK		0x0
+#define	TIMROT_TIMCTRLn_SELECT_PWM0			0x1
+#define	TIMROT_TIMCTRLn_SELECT_PWM1			0x2
+#define	TIMROT_TIMCTRLn_SELECT_PWM2			0x3
+#define	TIMROT_TIMCTRLn_SELECT_PWM3			0x4
+#define	TIMROT_TIMCTRLn_SELECT_PWM4			0x5
+#define	TIMROT_TIMCTRLn_SELECT_PWM5			0x6
+#define	TIMROT_TIMCTRLn_SELECT_PWM6			0x7
+#define	TIMROT_TIMCTRLn_SELECT_PWM7			0x8
+#define	TIMROT_TIMCTRLn_SELECT_ROTARYA			0x9
+#define	TIMROT_TIMCTRLn_SELECT_ROTARYB			0xa
+#define	TIMROT_TIMCTRLn_SELECT_32KHZ_XTAL		0xb
+#define	TIMROT_TIMCTRLn_SELECT_8KHZ_XTAL		0xc
+#define	TIMROT_TIMCTRLn_SELECT_4KHZ_XTAL		0xd
+#define	TIMROT_TIMCTRLn_SELECT_1KHZ_XTAL		0xe
+#define	TIMROT_TIMCTRLn_SELECT_TICK_ALWAYS		0xf
+
+#define	TIMROT_RUNNING_COUNTn_RUNNING_COUNT_MASK	0xffffffff
+#define	TIMROT_RUNNING_COUNTn_RUNNING_COUNT_OFFSET	0
+
+#define	TIMROT_FIXED_COUNTn_FIXED_COUNT_MASK		0xffffffff
+#define	TIMROT_FIXED_COUNTn_FIXED_COUNT_OFFSET		0
+
+#define	TIMROT_MATCH_COUNTn_MATCH_COUNT_MASK		0xffffffff
+#define	TIMROT_MATCH_COUNTn_MATCH_COUNT_OFFSET		0
+
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_MASK		(0xf << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_OFFSET		16
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_NEVER_TICK		(0x0 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM0		(0x1 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM1		(0x2 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM2		(0x3 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM3		(0x4 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM4		(0x5 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM5		(0x6 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM6		(0x7 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM7		(0x8 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_ROTARYA		(0x9 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_ROTARYB		(0xa << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_32KHZ_XTAL		(0xb << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_8KHZ_XTAL		(0xc << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_4KHZ_XTAL		(0xd << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_1KHZ_XTAL		(0xe << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_TICK_ALWAYS		(0xf << 16)
+#define	TIMROT_TIMCTRL3_DUTY_CYCLE			(1 << 9)
+
+#define	TIMROT_VERSION_MAJOR_MASK			(0xff << 24)
+#define	TIMROT_VERSION_MAJOR_OFFSET			24
+#define	TIMROT_VERSION_MINOR_MASK			(0xff << 16)
+#define	TIMROT_VERSION_MINOR_OFFSET			16
+#define	TIMROT_VERSION_STEP_MASK			0xffff
+#define	TIMROT_VERSION_STEP_OFFSET			0
+
+#endif /* __MX28_REGS_TIMROT_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/sys_proto.h b/arch/arm/include/asm/arch-mx28/sys_proto.h
new file mode 100644
index 0000000..a262c05
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/sys_proto.h
@@ -0,0 +1,30 @@
+/*
+ * Freescale i.MX28 MX28 specific functions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __MX28_H__
+#define __MX28_H__
+
+int mx28_reset_block(struct mx28_register *reg);
+int mx28_wait_mask_set(struct mx28_register *reg, uint32_t mask, int timeout);
+int mx28_wait_mask_clr(struct mx28_register *reg, uint32_t mask, int timeout);
+
+#endif	/* __MX28_H__ */
-- 
1.7.6.3

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

* [U-Boot] [PATCH 00/17 V3] Support for the DENX M28 SoM
  2011-09-12  4:06 [U-Boot] [PATCH 00/15 V2] Support for the DENX M28 SoM Marek Vasut
                   ` (14 preceding siblings ...)
  2011-09-12  4:06 ` [U-Boot] [PATCH 15/15] M28: Add doc/README.m28 documentation Marek Vasut
@ 2011-10-21 22:44 ` Marek Vasut
  2011-10-21 22:44   ` [U-Boot] [PATCH 01/17 RESEND V5] iMX28: Initial support for iMX28 CPU Marek Vasut
                     ` (16 more replies)
  15 siblings, 17 replies; 116+ messages in thread
From: Marek Vasut @ 2011-10-21 22:44 UTC (permalink / raw)
  To: u-boot

This series adds support for DENX M28 SoM and M28EVK kit.

This series depends on previous series:
* Support for both FEC interfaces on i.MX28
* Random NAND fixes and improvements
* SPL modifications

V2: * Convert to SPL framework
    * Squash patches together
    * Fix pointed out issues

V3: * Add vector handling
    * Add memory size detection for i.MX28
    * Fix i.MX28 reset issues
    * Squash errors in the GPMI NAND driver
    * Support M28 V1.1 module
    * Rebase to current u-boot-imx/master
      9bf11bb55137618bc75aadb59810883bc02bab00

Marek Vasut (17):
  iMX28: Initial support for iMX28 CPU
  iMX28: Add SSP MMC driver
  FEC: Add support for iMX28 quirks
  iMX28: Add PINMUX control
  iMX28: Add I2C bus driver
  iMX28: Add GPIO control
  iMX28: Add SPI driver
  iMX28: Add APBH DMA driver
  iMX28: Add GPMI NAND driver
  iMX28: Add driver for internal RTC
  iMX28: Add image header generator tool
  iMX28: Add u-boot.sb target to Makefile
  iMX28: Add support for DENX M28EVK board
  M28: Add MMC SPL
  M28: Add doc/README.m28 documentation
  iMX28: Fix ARM vector handling
  M28: Add memory detection into SPL

 .gitignore                                    |    1 +
 MAINTAINERS                                   |    1 +
 Makefile                                      |    5 +
 arch/arm/cpu/arm926ejs/mx28/Makefile          |   46 +
 arch/arm/cpu/arm926ejs/mx28/clock.c           |  355 +++++++
 arch/arm/cpu/arm926ejs/mx28/iomux.c           |  109 +++
 arch/arm/cpu/arm926ejs/mx28/mx28.c            |  221 +++++
 arch/arm/cpu/arm926ejs/mx28/timer.c           |  141 +++
 arch/arm/include/asm/arch-mx28/clock.h        |   61 ++
 arch/arm/include/asm/arch-mx28/dma.h          |  170 ++++
 arch/arm/include/asm/arch-mx28/gpio.h         |   32 +
 arch/arm/include/asm/arch-mx28/imx-regs.h     |   39 +
 arch/arm/include/asm/arch-mx28/iomux-mx28.h   |  537 +++++++++++
 arch/arm/include/asm/arch-mx28/iomux.h        |  168 ++++
 arch/arm/include/asm/arch-mx28/regs-apbh.h    |  466 +++++++++
 arch/arm/include/asm/arch-mx28/regs-base.h    |   88 ++
 arch/arm/include/asm/arch-mx28/regs-bch.h     |  230 +++++
 arch/arm/include/asm/arch-mx28/regs-clkctrl.h |  312 ++++++
 arch/arm/include/asm/arch-mx28/regs-common.h  |   66 ++
 arch/arm/include/asm/arch-mx28/regs-gpmi.h    |  222 +++++
 arch/arm/include/asm/arch-mx28/regs-i2c.h     |  207 ++++
 arch/arm/include/asm/arch-mx28/regs-ocotp.h   |  173 ++++
 arch/arm/include/asm/arch-mx28/regs-pinctrl.h | 1284 +++++++++++++++++++++++++
 arch/arm/include/asm/arch-mx28/regs-power.h   |  413 ++++++++
 arch/arm/include/asm/arch-mx28/regs-rtc.h     |  147 +++
 arch/arm/include/asm/arch-mx28/regs-ssp.h     |  349 +++++++
 arch/arm/include/asm/arch-mx28/regs-timrot.h  |  171 ++++
 arch/arm/include/asm/arch-mx28/sys_proto.h    |   32 +
 board/denx/m28evk/Makefile                    |   62 ++
 board/denx/m28evk/m28_init.h                  |   41 +
 board/denx/m28evk/m28evk.c                    |  209 ++++
 board/denx/m28evk/mem_init.c                  |  240 +++++
 board/denx/m28evk/mmc_boot.c                  |  273 ++++++
 board/denx/m28evk/power_init.c                |  913 ++++++++++++++++++
 board/denx/m28evk/start.S                     |  234 +++++
 board/denx/m28evk/u-boot-spl.lds              |   87 ++
 board/denx/m28evk/u-boot.bd                   |   14 +
 boards.cfg                                    |    1 +
 doc/README.m28                                |  223 +++++
 drivers/dma/Makefile                          |    1 +
 drivers/dma/apbh_dma.c                        |  691 +++++++++++++
 drivers/gpio/Makefile                         |    1 +
 drivers/gpio/mxs_gpio.c                       |  136 +++
 drivers/i2c/Makefile                          |    1 +
 drivers/i2c/mxs_i2c.c                         |  246 +++++
 drivers/mmc/Makefile                          |    1 +
 drivers/mmc/mxsmmc.c                          |  351 +++++++
 drivers/mtd/nand/Makefile                     |    1 +
 drivers/mtd/nand/mxs_nand.c                   | 1118 +++++++++++++++++++++
 drivers/net/fec_mxc.c                         |   44 +-
 drivers/rtc/Makefile                          |    1 +
 drivers/rtc/mxsrtc.c                          |   86 ++
 drivers/spi/Makefile                          |    1 +
 drivers/spi/mxs_spi.c                         |  186 ++++
 include/configs/m28evk.h                      |  291 ++++++
 tools/.gitignore                              |    1 +
 tools/Makefile                                |    6 +
 tools/mxsboot.c                               |  684 +++++++++++++
 58 files changed, 12188 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/Makefile
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/clock.c
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/iomux.c
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/mx28.c
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/timer.c
 create mode 100644 arch/arm/include/asm/arch-mx28/clock.h
 create mode 100644 arch/arm/include/asm/arch-mx28/dma.h
 create mode 100644 arch/arm/include/asm/arch-mx28/gpio.h
 create mode 100644 arch/arm/include/asm/arch-mx28/imx-regs.h
 create mode 100644 arch/arm/include/asm/arch-mx28/iomux-mx28.h
 create mode 100644 arch/arm/include/asm/arch-mx28/iomux.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-apbh.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-base.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-bch.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-clkctrl.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-common.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-gpmi.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-i2c.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-ocotp.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-pinctrl.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-power.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-rtc.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-ssp.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-timrot.h
 create mode 100644 arch/arm/include/asm/arch-mx28/sys_proto.h
 create mode 100644 board/denx/m28evk/Makefile
 create mode 100644 board/denx/m28evk/m28_init.h
 create mode 100644 board/denx/m28evk/m28evk.c
 create mode 100644 board/denx/m28evk/mem_init.c
 create mode 100644 board/denx/m28evk/mmc_boot.c
 create mode 100644 board/denx/m28evk/power_init.c
 create mode 100644 board/denx/m28evk/start.S
 create mode 100644 board/denx/m28evk/u-boot-spl.lds
 create mode 100644 board/denx/m28evk/u-boot.bd
 create mode 100644 doc/README.m28
 create mode 100644 drivers/dma/apbh_dma.c
 create mode 100644 drivers/gpio/mxs_gpio.c
 create mode 100644 drivers/i2c/mxs_i2c.c
 create mode 100644 drivers/mmc/mxsmmc.c
 create mode 100644 drivers/mtd/nand/mxs_nand.c
 create mode 100644 drivers/rtc/mxsrtc.c
 create mode 100644 drivers/spi/mxs_spi.c
 create mode 100644 include/configs/m28evk.h
 create mode 100644 tools/mxsboot.c

-- 
1.7.6.3

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

* [U-Boot] [PATCH 01/17 RESEND V5] iMX28: Initial support for iMX28 CPU
  2011-10-21 22:44 ` [U-Boot] [PATCH 00/17 V3] Support for the DENX M28 SoM Marek Vasut
@ 2011-10-21 22:44   ` Marek Vasut
  2011-10-21 22:44   ` [U-Boot] [PATCH 02/17 RESEND] iMX28: Add SSP MMC driver Marek Vasut
                     ` (15 subsequent siblings)
  16 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-10-21 22:44 UTC (permalink / raw)
  To: u-boot

This patch supports:
- Timers
- Debug UART
- Clock

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 arch/arm/cpu/arm926ejs/mx28/Makefile          |   46 +
 arch/arm/cpu/arm926ejs/mx28/clock.c           |  355 +++++++
 arch/arm/cpu/arm926ejs/mx28/mx28.c            |  193 ++++
 arch/arm/cpu/arm926ejs/mx28/timer.c           |  141 +++
 arch/arm/include/asm/arch-mx28/clock.h        |   61 ++
 arch/arm/include/asm/arch-mx28/imx-regs.h     |   38 +
 arch/arm/include/asm/arch-mx28/regs-base.h    |   88 ++
 arch/arm/include/asm/arch-mx28/regs-bch.h     |  230 +++++
 arch/arm/include/asm/arch-mx28/regs-clkctrl.h |  312 ++++++
 arch/arm/include/asm/arch-mx28/regs-common.h  |   66 ++
 arch/arm/include/asm/arch-mx28/regs-gpmi.h    |  222 +++++
 arch/arm/include/asm/arch-mx28/regs-i2c.h     |  207 ++++
 arch/arm/include/asm/arch-mx28/regs-ocotp.h   |  173 ++++
 arch/arm/include/asm/arch-mx28/regs-pinctrl.h | 1284 +++++++++++++++++++++++++
 arch/arm/include/asm/arch-mx28/regs-power.h   |  413 ++++++++
 arch/arm/include/asm/arch-mx28/regs-rtc.h     |  147 +++
 arch/arm/include/asm/arch-mx28/regs-ssp.h     |  349 +++++++
 arch/arm/include/asm/arch-mx28/regs-timrot.h  |  171 ++++
 arch/arm/include/asm/arch-mx28/sys_proto.h    |   30 +
 19 files changed, 4526 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/Makefile
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/clock.c
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/mx28.c
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/timer.c
 create mode 100644 arch/arm/include/asm/arch-mx28/clock.h
 create mode 100644 arch/arm/include/asm/arch-mx28/imx-regs.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-base.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-bch.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-clkctrl.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-common.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-gpmi.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-i2c.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-ocotp.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-pinctrl.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-power.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-rtc.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-ssp.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-timrot.h
 create mode 100644 arch/arm/include/asm/arch-mx28/sys_proto.h

V2: Use watchdog for reset
V3: Remove redundant power_regs from cpu_reset() (gcc4.6)
V4: Squash checkpatch issue
V5: Drop bogus include directive including so far nonexistent file

diff --git a/arch/arm/cpu/arm926ejs/mx28/Makefile b/arch/arm/cpu/arm926ejs/mx28/Makefile
new file mode 100644
index 0000000..98504f9
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/Makefile
@@ -0,0 +1,46 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(SOC).o
+
+COBJS	= clock.o mx28.o timer.o
+
+SRCS	:= $(START:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+START	:= $(addprefix $(obj),$(START))
+
+all:	$(obj).depend $(LIB)
+
+$(LIB):	$(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/arm/cpu/arm926ejs/mx28/clock.c b/arch/arm/cpu/arm926ejs/mx28/clock.c
new file mode 100644
index 0000000..f698506
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/clock.c
@@ -0,0 +1,355 @@
+/*
+ * Freescale i.MX28 clock setup code
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+
+/* The PLL frequency is always 480MHz, see section 10.2 in iMX28 datasheet. */
+#define	PLL_FREQ_KHZ	480000
+#define	PLL_FREQ_COEF	18
+/* The XTAL frequency is always 24MHz, see section 10.2 in iMX28 datasheet. */
+#define	XTAL_FREQ_KHZ	24000
+
+#define	PLL_FREQ_MHZ	(PLL_FREQ_KHZ / 1000)
+#define	XTAL_FREQ_MHZ	(XTAL_FREQ_KHZ / 1000)
+
+static uint32_t mx28_get_pclk(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	uint32_t clkctrl, clkseq, clkfrac;
+	uint32_t frac, div;
+
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_cpu);
+
+	/* No support of fractional divider calculation */
+	if (clkctrl &
+		(CLKCTRL_CPU_DIV_XTAL_FRAC_EN | CLKCTRL_CPU_DIV_CPU_FRAC_EN)) {
+		return 0;
+	}
+
+	clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+
+	/* XTAL Path */
+	if (clkseq & CLKCTRL_CLKSEQ_BYPASS_CPU) {
+		div = (clkctrl & CLKCTRL_CPU_DIV_XTAL_MASK) >>
+			CLKCTRL_CPU_DIV_XTAL_OFFSET;
+		return XTAL_FREQ_MHZ / div;
+	}
+
+	/* REF Path */
+	clkfrac = readl(&clkctrl_regs->hw_clkctrl_frac0);
+	frac = clkfrac & CLKCTRL_FRAC0_CPUFRAC_MASK;
+	div = clkctrl & CLKCTRL_CPU_DIV_CPU_MASK;
+	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
+}
+
+static uint32_t mx28_get_hclk(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	uint32_t div;
+	uint32_t clkctrl;
+
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_hbus);
+
+	/* No support of fractional divider calculation */
+	if (clkctrl & CLKCTRL_HBUS_DIV_FRAC_EN)
+		return 0;
+
+	div = clkctrl & CLKCTRL_HBUS_DIV_MASK;
+	return mx28_get_pclk() / div;
+}
+
+static uint32_t mx28_get_emiclk(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	uint32_t frac, div;
+	uint32_t clkctrl, clkseq, clkfrac;
+
+	clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_emi);
+
+	/* XTAL Path */
+	if (clkseq & CLKCTRL_CLKSEQ_BYPASS_EMI) {
+		div = (clkctrl & CLKCTRL_EMI_DIV_XTAL_MASK) >>
+			CLKCTRL_EMI_DIV_XTAL_OFFSET;
+		return XTAL_FREQ_MHZ / div;
+	}
+
+	clkfrac = readl(&clkctrl_regs->hw_clkctrl_frac0);
+
+	/* REF Path */
+	frac = (clkfrac & CLKCTRL_FRAC0_EMIFRAC_MASK) >>
+		CLKCTRL_FRAC0_EMIFRAC_OFFSET;
+	div = clkctrl & CLKCTRL_EMI_DIV_EMI_MASK;
+	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
+}
+
+static uint32_t mx28_get_gpmiclk(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	uint32_t frac, div;
+	uint32_t clkctrl, clkseq, clkfrac;
+
+	clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+	clkctrl = readl(&clkctrl_regs->hw_clkctrl_gpmi);
+
+	/* XTAL Path */
+	if (clkseq & CLKCTRL_CLKSEQ_BYPASS_GPMI) {
+		div = clkctrl & CLKCTRL_GPMI_DIV_MASK;
+		return XTAL_FREQ_MHZ / div;
+	}
+
+	clkfrac = readl(&clkctrl_regs->hw_clkctrl_frac1);
+
+	/* REF Path */
+	frac = (clkfrac & CLKCTRL_FRAC1_GPMIFRAC_MASK) >>
+		CLKCTRL_FRAC1_GPMIFRAC_OFFSET;
+	div = clkctrl & CLKCTRL_GPMI_DIV_MASK;
+	return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
+}
+
+/*
+ * Set IO clock frequency, in kHz
+ */
+void mx28_set_ioclk(enum mxs_ioclock io, uint32_t freq)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t div;
+
+	if (freq == 0)
+		return;
+
+	if (io > MXC_IOCLK1)
+		return;
+
+	div = (PLL_FREQ_KHZ * PLL_FREQ_COEF) / freq;
+
+	if (div < 18)
+		div = 18;
+
+	if (div > 35)
+		div = 35;
+
+	if (io == MXC_IOCLK0) {
+		writel(CLKCTRL_FRAC0_CLKGATEIO0,
+			&clkctrl_regs->hw_clkctrl_frac0_set);
+		clrsetbits_le32(&clkctrl_regs->hw_clkctrl_frac0,
+				CLKCTRL_FRAC0_IO0FRAC_MASK,
+				div << CLKCTRL_FRAC0_IO0FRAC_OFFSET);
+		writel(CLKCTRL_FRAC0_CLKGATEIO0,
+			&clkctrl_regs->hw_clkctrl_frac0_clr);
+	} else {
+		writel(CLKCTRL_FRAC0_CLKGATEIO1,
+			&clkctrl_regs->hw_clkctrl_frac0_set);
+		clrsetbits_le32(&clkctrl_regs->hw_clkctrl_frac0,
+				CLKCTRL_FRAC0_IO1FRAC_MASK,
+				div << CLKCTRL_FRAC0_IO1FRAC_OFFSET);
+		writel(CLKCTRL_FRAC0_CLKGATEIO1,
+			&clkctrl_regs->hw_clkctrl_frac0_clr);
+	}
+}
+
+/*
+ * Get IO clock, returns IO clock in kHz
+ */
+static uint32_t mx28_get_ioclk(enum mxs_ioclock io)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t tmp, ret;
+
+	if (io > MXC_IOCLK1)
+		return 0;
+
+	tmp = readl(&clkctrl_regs->hw_clkctrl_frac0);
+
+	if (io == MXC_IOCLK0)
+		ret = (tmp & CLKCTRL_FRAC0_IO0FRAC_MASK) >>
+			CLKCTRL_FRAC0_IO0FRAC_OFFSET;
+	else
+		ret = (tmp & CLKCTRL_FRAC0_IO1FRAC_MASK) >>
+			CLKCTRL_FRAC0_IO1FRAC_OFFSET;
+
+	return (PLL_FREQ_KHZ * PLL_FREQ_COEF) / ret;
+}
+
+/*
+ * Configure SSP clock frequency, in kHz
+ */
+void mx28_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t clk, clkreg;
+
+	if (ssp > MXC_SSPCLK3)
+		return;
+
+	clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) +
+			(ssp * sizeof(struct mx28_register));
+
+	clrbits_le32(clkreg, CLKCTRL_SSP_CLKGATE);
+	while (readl(clkreg) & CLKCTRL_SSP_CLKGATE)
+		;
+
+	if (xtal)
+		clk = XTAL_FREQ_KHZ;
+	else
+		clk = mx28_get_ioclk(ssp >> 1);
+
+	if (freq > clk)
+		return;
+
+	/* Calculate the divider and cap it if necessary */
+	clk /= freq;
+	if (clk > CLKCTRL_SSP_DIV_MASK)
+		clk = CLKCTRL_SSP_DIV_MASK;
+
+	clrsetbits_le32(clkreg, CLKCTRL_SSP_DIV_MASK, clk);
+	while (readl(clkreg) & CLKCTRL_SSP_BUSY)
+		;
+
+	if (xtal)
+		writel(CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp,
+			&clkctrl_regs->hw_clkctrl_clkseq_set);
+	else
+		writel(CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp,
+			&clkctrl_regs->hw_clkctrl_clkseq_clr);
+}
+
+/*
+ * Return SSP frequency, in kHz
+ */
+static uint32_t mx28_get_sspclk(enum mxs_sspclock ssp)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	uint32_t clkreg;
+	uint32_t clk, tmp;
+
+	if (ssp > MXC_SSPCLK3)
+		return 0;
+
+	tmp = readl(&clkctrl_regs->hw_clkctrl_clkseq);
+	if (tmp & (CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp))
+		return XTAL_FREQ_KHZ;
+
+	clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) +
+			(ssp * sizeof(struct mx28_register));
+
+	tmp = readl(clkreg) & CLKCTRL_SSP_DIV_MASK;
+
+	if (tmp == 0)
+		return 0;
+
+	clk = mx28_get_ioclk(ssp >> 1);
+
+	return clk / tmp;
+}
+
+/*
+ * Set SSP/MMC bus frequency, in kHz)
+ */
+void mx28_set_ssp_busclock(unsigned int bus, uint32_t freq)
+{
+	struct mx28_ssp_regs *ssp_regs;
+	const uint32_t sspclk = mx28_get_sspclk(bus);
+	uint32_t reg;
+	uint32_t divide, rate, tgtclk;
+
+	ssp_regs = (struct mx28_ssp_regs *)(MXS_SSP0_BASE + (bus * 0x2000));
+
+	/*
+	 * SSP bit rate = SSPCLK / (CLOCK_DIVIDE * (1 + CLOCK_RATE)),
+	 * CLOCK_DIVIDE has to be an even value from 2 to 254, and
+	 * CLOCK_RATE could be any integer from 0 to 255.
+	 */
+	for (divide = 2; divide < 254; divide += 2) {
+		rate = sspclk / freq / divide;
+		if (rate <= 256)
+			break;
+	}
+
+	tgtclk = sspclk / divide / rate;
+	while (tgtclk > freq) {
+		rate++;
+		tgtclk = sspclk / divide / rate;
+	}
+	if (rate > 256)
+		rate = 256;
+
+	/* Always set timeout the maximum */
+	reg = SSP_TIMING_TIMEOUT_MASK |
+		(divide << SSP_TIMING_CLOCK_DIVIDE_OFFSET) |
+		((rate - 1) << SSP_TIMING_CLOCK_RATE_OFFSET);
+	writel(reg, &ssp_regs->hw_ssp_timing);
+
+	debug("SPI%d: Set freq rate to %d KHz (requested %d KHz)\n",
+		bus, tgtclk, freq);
+}
+
+uint32_t mxc_get_clock(enum mxc_clock clk)
+{
+	switch (clk) {
+	case MXC_ARM_CLK:
+		return mx28_get_pclk() * 1000000;
+	case MXC_GPMI_CLK:
+		return mx28_get_gpmiclk() * 1000000;
+	case MXC_AHB_CLK:
+	case MXC_IPG_CLK:
+		return mx28_get_hclk() * 1000000;
+	case MXC_EMI_CLK:
+		return mx28_get_emiclk();
+	case MXC_IO0_CLK:
+		return mx28_get_ioclk(MXC_IOCLK0);
+	case MXC_IO1_CLK:
+		return mx28_get_ioclk(MXC_IOCLK1);
+	case MXC_SSP0_CLK:
+		return mx28_get_sspclk(MXC_SSPCLK0);
+	case MXC_SSP1_CLK:
+		return mx28_get_sspclk(MXC_SSPCLK1);
+	case MXC_SSP2_CLK:
+		return mx28_get_sspclk(MXC_SSPCLK2);
+	case MXC_SSP3_CLK:
+		return mx28_get_sspclk(MXC_SSPCLK3);
+	}
+
+	return 0;
+}
diff --git a/arch/arm/cpu/arm926ejs/mx28/mx28.c b/arch/arm/cpu/arm926ejs/mx28/mx28.c
new file mode 100644
index 0000000..446ea8b
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/mx28.c
@@ -0,0 +1,193 @@
+/*
+ * Freescale i.MX28 common code
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+
+/* 1 second delay should be plenty of time for block reset. */
+#define	RESET_MAX_TIMEOUT	1000000
+
+#define	MX28_BLOCK_SFTRST	(1 << 31)
+#define	MX28_BLOCK_CLKGATE	(1 << 30)
+
+/* Lowlevel init isn't used on i.MX28, so just have a dummy here */
+inline void lowlevel_init(void) {}
+
+void reset_cpu(ulong ignored) __attribute__((noreturn));
+
+void reset_cpu(ulong ignored)
+{
+
+	struct mx28_rtc_regs *rtc_regs =
+		(struct mx28_rtc_regs *)MXS_RTC_BASE;
+
+	/* Wait 1 uS before doing the actual watchdog reset */
+	writel(1, &rtc_regs->hw_rtc_watchdog);
+	writel(RTC_CTRL_WATCHDOGEN, &rtc_regs->hw_rtc_ctrl_set);
+
+	/* Endless loop, reset will exit from here */
+	for (;;)
+		;
+}
+
+int mx28_wait_mask_set(struct mx28_register *reg, uint32_t mask, int timeout)
+{
+	while (--timeout) {
+		if ((readl(&reg->reg) & mask) == mask)
+			break;
+		udelay(1);
+	}
+
+	return !timeout;
+}
+
+int mx28_wait_mask_clr(struct mx28_register *reg, uint32_t mask, int timeout)
+{
+	while (--timeout) {
+		if ((readl(&reg->reg) & mask) == 0)
+			break;
+		udelay(1);
+	}
+
+	return !timeout;
+}
+
+int mx28_reset_block(struct mx28_register *reg)
+{
+	/* Clear SFTRST */
+	writel(MX28_BLOCK_SFTRST, &reg->reg_clr);
+
+	if (mx28_wait_mask_clr(reg, MX28_BLOCK_SFTRST, RESET_MAX_TIMEOUT))
+		return 1;
+
+	/* Clear CLKGATE */
+	writel(MX28_BLOCK_CLKGATE, &reg->reg_clr);
+
+	/* Set SFTRST */
+	writel(MX28_BLOCK_SFTRST, &reg->reg_set);
+
+	/* Wait for CLKGATE being set */
+	if (mx28_wait_mask_set(reg, MX28_BLOCK_CLKGATE, RESET_MAX_TIMEOUT))
+		return 1;
+
+	/* Clear SFTRST */
+	writel(MX28_BLOCK_SFTRST, &reg->reg_clr);
+
+	if (mx28_wait_mask_clr(reg, MX28_BLOCK_SFTRST, RESET_MAX_TIMEOUT))
+		return 1;
+
+	/* Clear CLKGATE */
+	writel(MX28_BLOCK_CLKGATE, &reg->reg_clr);
+
+	if (mx28_wait_mask_clr(reg, MX28_BLOCK_CLKGATE, RESET_MAX_TIMEOUT))
+		return 1;
+
+	return 0;
+}
+
+#ifdef	CONFIG_ARCH_CPU_INIT
+int arch_cpu_init(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/*
+	 * Enable NAND clock
+	 */
+	/* Clear bypass bit */
+	writel(CLKCTRL_CLKSEQ_BYPASS_GPMI,
+		&clkctrl_regs->hw_clkctrl_clkseq_set);
+
+	/* Set GPMI clock to ref_gpmi / 12 */
+	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_gpmi,
+		CLKCTRL_GPMI_CLKGATE | CLKCTRL_GPMI_DIV_MASK, 1);
+
+	udelay(1000);
+
+	return 0;
+}
+#endif
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+int print_cpuinfo(void)
+{
+	printf("Freescale i.MX28 family\n");
+	return 0;
+}
+#endif
+
+int do_mx28_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+	printf("CPU:   %3d MHz\n", mxc_get_clock(MXC_ARM_CLK) / 1000000);
+	printf("BUS:   %3d MHz\n", mxc_get_clock(MXC_AHB_CLK) / 1000000);
+	printf("EMI:   %3d MHz\n", mxc_get_clock(MXC_EMI_CLK));
+	printf("GPMI:  %3d MHz\n", mxc_get_clock(MXC_GPMI_CLK) / 1000000);
+	return 0;
+}
+
+/*
+ * Initializes on-chip ethernet controllers.
+ */
+#ifdef	CONFIG_CMD_NET
+int cpu_eth_init(bd_t *bis)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/* Turn on ENET clocks */
+	clrbits_le32(&clkctrl_regs->hw_clkctrl_enet,
+		CLKCTRL_ENET_SLEEP | CLKCTRL_ENET_DISABLE);
+
+	/* Set up ENET PLL for 50 MHz */
+	/* Power on ENET PLL */
+	writel(CLKCTRL_PLL2CTRL0_POWER,
+		&clkctrl_regs->hw_clkctrl_pll2ctrl0_set);
+
+	udelay(10);
+
+	/* Gate on ENET PLL */
+	writel(CLKCTRL_PLL2CTRL0_CLKGATE,
+		&clkctrl_regs->hw_clkctrl_pll2ctrl0_clr);
+
+	/* Enable pad output */
+	setbits_le32(&clkctrl_regs->hw_clkctrl_enet, CLKCTRL_ENET_CLK_OUT_EN);
+
+	return 0;
+}
+#endif
+
+U_BOOT_CMD(
+	clocks,	CONFIG_SYS_MAXARGS, 1, do_mx28_showclocks,
+	"display clocks",
+	""
+);
diff --git a/arch/arm/cpu/arm926ejs/mx28/timer.c b/arch/arm/cpu/arm926ejs/mx28/timer.c
new file mode 100644
index 0000000..dbc904d
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/timer.c
@@ -0,0 +1,141 @@
+/*
+ * Freescale i.MX28 timer driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * (C) Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+
+/* Maximum fixed count */
+#define TIMER_LOAD_VAL	0xffffffff
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define timestamp (gd->tbl)
+#define lastdec (gd->lastinc)
+
+/*
+ * This driver uses 1kHz clock source.
+ */
+#define	MX28_INCREMENTER_HZ		1000
+
+static inline unsigned long tick_to_time(unsigned long tick)
+{
+	return tick / (MX28_INCREMENTER_HZ / CONFIG_SYS_HZ);
+}
+
+static inline unsigned long time_to_tick(unsigned long time)
+{
+	return time * (MX28_INCREMENTER_HZ / CONFIG_SYS_HZ);
+}
+
+/* Calculate how many ticks happen in "us" microseconds */
+static inline unsigned long us_to_tick(unsigned long us)
+{
+	return (us * MX28_INCREMENTER_HZ) / 1000000;
+}
+
+int timer_init(void)
+{
+	struct mx28_timrot_regs *timrot_regs =
+		(struct mx28_timrot_regs *)MXS_TIMROT_BASE;
+
+	/* Reset Timers and Rotary Encoder module */
+	mx28_reset_block(&timrot_regs->hw_timrot_rotctrl_reg);
+
+	/* Set fixed_count to 0 */
+	writel(0, &timrot_regs->hw_timrot_fixed_count0);
+
+	/* Set UPDATE bit and 1Khz frequency */
+	writel(TIMROT_TIMCTRLn_UPDATE | TIMROT_TIMCTRLn_RELOAD |
+		TIMROT_TIMCTRLn_SELECT_1KHZ_XTAL,
+		&timrot_regs->hw_timrot_timctrl0);
+
+	/* Set fixed_count to maximal value */
+	writel(TIMER_LOAD_VAL, &timrot_regs->hw_timrot_fixed_count0);
+
+	return 0;
+}
+
+ulong get_timer(ulong base)
+{
+	struct mx28_timrot_regs *timrot_regs =
+		(struct mx28_timrot_regs *)MXS_TIMROT_BASE;
+
+	/* Current tick value */
+	uint32_t now = readl(&timrot_regs->hw_timrot_running_count0);
+
+	if (lastdec >= now) {
+		/*
+		 * normal mode (non roll)
+		 * move stamp forward with absolut diff ticks
+		 */
+		timestamp += (lastdec - now);
+	} else {
+		/* we have rollover of decrementer */
+		timestamp += (TIMER_LOAD_VAL - now) + lastdec;
+
+	}
+	lastdec = now;
+
+	return tick_to_time(timestamp) - base;
+}
+
+/* We use the HW_DIGCTL_MICROSECONDS register for sub-millisecond timer. */
+#define	MX28_HW_DIGCTL_MICROSECONDS	0x8001c0c0
+
+void __udelay(unsigned long usec)
+{
+	uint32_t old, new, incr;
+	uint32_t counter = 0;
+
+	old = readl(MX28_HW_DIGCTL_MICROSECONDS);
+
+	while (counter < usec) {
+		new = readl(MX28_HW_DIGCTL_MICROSECONDS);
+
+		/* Check if the timer wrapped. */
+		if (new < old) {
+			incr = 0xffffffff - old;
+			incr += new;
+		} else {
+			incr = new - old;
+		}
+
+		/*
+		 * Check if we are close to the maximum time and the counter
+		 * would wrap if incremented. If that's the case, break out
+		 * from the loop as the requested delay time passed.
+		 */
+		if (counter + incr < counter)
+			break;
+
+		counter += incr;
+		old = new;
+	}
+}
diff --git a/arch/arm/include/asm/arch-mx28/clock.h b/arch/arm/include/asm/arch-mx28/clock.h
new file mode 100644
index 0000000..1700fe3
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/clock.h
@@ -0,0 +1,61 @@
+/*
+ * Freescale i.MX28 Clock
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __CLOCK_H__
+#define __CLOCK_H__
+
+enum mxc_clock {
+	MXC_ARM_CLK = 0,
+	MXC_AHB_CLK,
+	MXC_IPG_CLK,
+	MXC_EMI_CLK,
+	MXC_GPMI_CLK,
+	MXC_IO0_CLK,
+	MXC_IO1_CLK,
+	MXC_SSP0_CLK,
+	MXC_SSP1_CLK,
+	MXC_SSP2_CLK,
+	MXC_SSP3_CLK,
+};
+
+enum mxs_ioclock {
+	MXC_IOCLK0 = 0,
+	MXC_IOCLK1,
+};
+
+enum mxs_sspclock {
+	MXC_SSPCLK0 = 0,
+	MXC_SSPCLK1,
+	MXC_SSPCLK2,
+	MXC_SSPCLK3,
+};
+
+uint32_t mxc_get_clock(enum mxc_clock clk);
+
+void mx28_set_ioclk(enum mxs_ioclock io, uint32_t freq);
+void mx28_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal);
+void mx28_set_ssp_busclock(unsigned int bus, uint32_t freq);
+
+/* Compatibility with the FEC Ethernet driver */
+#define	imx_get_fecclk()	mxc_get_clock(MXC_AHB_CLK)
+
+#endif	/* __CLOCK_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/imx-regs.h b/arch/arm/include/asm/arch-mx28/imx-regs.h
new file mode 100644
index 0000000..32bfd7e
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/imx-regs.h
@@ -0,0 +1,38 @@
+/*
+ * Freescale i.MX28 Registers
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __IMX_REGS_H__
+#define __IMX_REGS_H__
+
+#include <asm/arch/regs-base.h>
+#include <asm/arch/regs-bch.h>
+#include <asm/arch/regs-clkctrl.h>
+#include <asm/arch/regs-gpmi.h>
+#include <asm/arch/regs-i2c.h>
+#include <asm/arch/regs-ocotp.h>
+#include <asm/arch/regs-pinctrl.h>
+#include <asm/arch/regs-power.h>
+#include <asm/arch/regs-rtc.h>
+#include <asm/arch/regs-ssp.h>
+#include <asm/arch/regs-timrot.h>
+
+#endif	/* __IMX_REGS_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-base.h b/arch/arm/include/asm/arch-mx28/regs-base.h
new file mode 100644
index 0000000..dbdcc2b
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-base.h
@@ -0,0 +1,88 @@
+/*
+ * Freescale i.MX28 Peripheral Base Addresses
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright (C) 2008 Embedded Alley Solutions Inc.
+ *
+ * (C) Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __MX28_REGS_BASE_H__
+#define __MX28_REGS_BASE_H__
+
+/*
+ * Register base address
+ */
+#define	MXS_ICOL_BASE		0x80000000
+#define	MXS_HSADC_BASE		0x80002000
+#define	MXS_APBH_BASE		0x80004000
+#define	MXS_PERFMON_BASE	0x80006000
+#define	MXS_BCH_BASE		0x8000A000
+#define	MXS_GPMI_BASE		0x8000C000
+#define	MXS_SSP0_BASE		0x80010000
+#define	MXS_SSP1_BASE		0x80012000
+#define	MXS_SSP2_BASE		0x80014000
+#define	MXS_SSP3_BASE		0x80016000
+#define	MXS_PINCTRL_BASE	0x80018000
+#define	MXS_DIGCTL_BASE		0x8001C000
+#define	MXS_ETM_BASE		0x80022000
+#define	MXS_APBX_BASE		0x80024000
+#define	MXS_DCP_BASE		0x80028000
+#define	MXS_PXP_BASE		0x8002A000
+#define	MXS_OCOTP_BASE		0x8002C000
+#define	MXS_AXI_AHB0_BASE	0x8002E000
+#define	MXS_LCDIF_BASE		0x80030000
+#define	MXS_CAN0_BASE		0x80032000
+#define	MXS_CAN1_BASE		0x80034000
+#define	MXS_SIMDBG_BASE		0x8003C000
+#define	MXS_SIMGPMISEL_BASE	0x8003C200
+#define	MXS_SIMSSPSEL_BASE	0x8003C300
+#define	MXS_SIMMEMSEL_BASE	0x8003C400
+#define	MXS_GPIOMON_BASE	0x8003C500
+#define	MXS_SIMENET_BASE	0x8003C700
+#define	MXS_ARMJTAG_BASE	0x8003C800
+#define	MXS_CLKCTRL_BASE	0x80040000
+#define	MXS_SAIF0_BASE		0x80042000
+#define	MXS_POWER_BASE		0x80044000
+#define	MXS_SAIF1_BASE		0x80046000
+#define	MXS_LRADC_BASE		0x80050000
+#define	MXS_SPDIF_BASE		0x80054000
+#define	MXS_RTC_BASE		0x80056000
+#define	MXS_I2C0_BASE		0x80058000
+#define	MXS_I2C1_BASE		0x8005A000
+#define	MXS_PWM_BASE		0x80064000
+#define	MXS_TIMROT_BASE		0x80068000
+#define	MXS_UARTAPP0_BASE	0x8006A000
+#define	MXS_UARTAPP1_BASE	0x8006C000
+#define	MXS_UARTAPP2_BASE	0x8006E000
+#define	MXS_UARTAPP3_BASE	0x80070000
+#define	MXS_UARTAPP4_BASE	0x80072000
+#define	MXS_UARTDBG_BASE	0x80074000
+#define	MXS_USBPHY0_BASE	0x8007C000
+#define	MXS_USBPHY1_BASE	0x8007E000
+#define	MXS_USBCTRL0_BASE	0x80080000
+#define	MXS_USBCTRL1_BASE	0x80090000
+#define	MXS_DFLPT_BASE		0x800C0000
+#define	MXS_DRAM_BASE		0x800E0000
+#define	MXS_ENET0_BASE		0x800F0000
+#define	MXS_ENET1_BASE		0x800F4000
+
+#endif /* __MX28_REGS_BASE_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-bch.h b/arch/arm/include/asm/arch-mx28/regs-bch.h
new file mode 100644
index 0000000..cac0470
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-bch.h
@@ -0,0 +1,230 @@
+/*
+ * Freescale i.MX28 BCH Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_BCH_H__
+#define __MX28_REGS_BCH_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_bch_regs {
+	mx28_reg(hw_bch_ctrl)
+	mx28_reg(hw_bch_status0)
+	mx28_reg(hw_bch_mode)
+	mx28_reg(hw_bch_encodeptr)
+	mx28_reg(hw_bch_dataptr)
+	mx28_reg(hw_bch_metaptr)
+
+	uint32_t	reserved[4];
+
+	mx28_reg(hw_bch_layoutselect)
+	mx28_reg(hw_bch_flash0layout0)
+	mx28_reg(hw_bch_flash0layout1)
+	mx28_reg(hw_bch_flash1layout0)
+	mx28_reg(hw_bch_flash1layout1)
+	mx28_reg(hw_bch_flash2layout0)
+	mx28_reg(hw_bch_flash2layout1)
+	mx28_reg(hw_bch_flash3layout0)
+	mx28_reg(hw_bch_flash3layout1)
+	mx28_reg(hw_bch_dbgkesread)
+	mx28_reg(hw_bch_dbgcsferead)
+	mx28_reg(hw_bch_dbgsyndegread)
+	mx28_reg(hw_bch_dbgahbmread)
+	mx28_reg(hw_bch_blockname)
+	mx28_reg(hw_bch_version)
+};
+#endif
+
+#define	BCH_CTRL_SFTRST					(1 << 31)
+#define	BCH_CTRL_CLKGATE				(1 << 30)
+#define	BCH_CTRL_DEBUGSYNDROME				(1 << 22)
+#define	BCH_CTRL_M2M_LAYOUT_MASK			(0x3 << 18)
+#define	BCH_CTRL_M2M_LAYOUT_OFFSET			18
+#define	BCH_CTRL_M2M_ENCODE				(1 << 17)
+#define	BCH_CTRL_M2M_ENABLE				(1 << 16)
+#define	BCH_CTRL_DEBUG_STALL_IRQ_EN			(1 << 10)
+#define	BCH_CTRL_COMPLETE_IRQ_EN			(1 << 8)
+#define	BCH_CTRL_BM_ERROR_IRQ				(1 << 3)
+#define	BCH_CTRL_DEBUG_STALL_IRQ			(1 << 2)
+#define	BCH_CTRL_COMPLETE_IRQ				(1 << 0)
+
+#define	BCH_STATUS0_HANDLE_MASK				(0xfff << 20)
+#define	BCH_STATUS0_HANDLE_OFFSET			20
+#define	BCH_STATUS0_COMPLETED_CE_MASK			(0xf << 16)
+#define	BCH_STATUS0_COMPLETED_CE_OFFSET			16
+#define	BCH_STATUS0_STATUS_BLK0_MASK			(0xff << 8)
+#define	BCH_STATUS0_STATUS_BLK0_OFFSET			8
+#define	BCH_STATUS0_STATUS_BLK0_ZERO			(0x00 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERROR1			(0x01 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERROR2			(0x02 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERROR3			(0x03 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERROR4			(0x04 << 8)
+#define	BCH_STATUS0_STATUS_BLK0_UNCORRECTABLE		(0xfe << 8)
+#define	BCH_STATUS0_STATUS_BLK0_ERASED			(0xff << 8)
+#define	BCH_STATUS0_ALLONES				(1 << 4)
+#define	BCH_STATUS0_CORRECTED				(1 << 3)
+#define	BCH_STATUS0_UNCORRECTABLE			(1 << 2)
+
+#define	BCH_MODE_ERASE_THRESHOLD_MASK			0xff
+#define	BCH_MODE_ERASE_THRESHOLD_OFFSET			0
+
+#define	BCH_ENCODEPTR_ADDR_MASK				0xffffffff
+#define	BCH_ENCODEPTR_ADDR_OFFSET			0
+
+#define	BCH_DATAPTR_ADDR_MASK				0xffffffff
+#define	BCH_DATAPTR_ADDR_OFFSET				0
+
+#define	BCH_METAPTR_ADDR_MASK				0xffffffff
+#define	BCH_METAPTR_ADDR_OFFSET				0
+
+#define	BCH_LAYOUTSELECT_CS15_SELECT_MASK		(0x3 << 30)
+#define	BCH_LAYOUTSELECT_CS15_SELECT_OFFSET		30
+#define	BCH_LAYOUTSELECT_CS14_SELECT_MASK		(0x3 << 28)
+#define	BCH_LAYOUTSELECT_CS14_SELECT_OFFSET		28
+#define	BCH_LAYOUTSELECT_CS13_SELECT_MASK		(0x3 << 26)
+#define	BCH_LAYOUTSELECT_CS13_SELECT_OFFSET		26
+#define	BCH_LAYOUTSELECT_CS12_SELECT_MASK		(0x3 << 24)
+#define	BCH_LAYOUTSELECT_CS12_SELECT_OFFSET		24
+#define	BCH_LAYOUTSELECT_CS11_SELECT_MASK		(0x3 << 22)
+#define	BCH_LAYOUTSELECT_CS11_SELECT_OFFSET		22
+#define	BCH_LAYOUTSELECT_CS10_SELECT_MASK		(0x3 << 20)
+#define	BCH_LAYOUTSELECT_CS10_SELECT_OFFSET		20
+#define	BCH_LAYOUTSELECT_CS9_SELECT_MASK		(0x3 << 18)
+#define	BCH_LAYOUTSELECT_CS9_SELECT_OFFSET		18
+#define	BCH_LAYOUTSELECT_CS8_SELECT_MASK		(0x3 << 16)
+#define	BCH_LAYOUTSELECT_CS8_SELECT_OFFSET		16
+#define	BCH_LAYOUTSELECT_CS7_SELECT_MASK		(0x3 << 14)
+#define	BCH_LAYOUTSELECT_CS7_SELECT_OFFSET		14
+#define	BCH_LAYOUTSELECT_CS6_SELECT_MASK		(0x3 << 12)
+#define	BCH_LAYOUTSELECT_CS6_SELECT_OFFSET		12
+#define	BCH_LAYOUTSELECT_CS5_SELECT_MASK		(0x3 << 10)
+#define	BCH_LAYOUTSELECT_CS5_SELECT_OFFSET		10
+#define	BCH_LAYOUTSELECT_CS4_SELECT_MASK		(0x3 << 8)
+#define	BCH_LAYOUTSELECT_CS4_SELECT_OFFSET		8
+#define	BCH_LAYOUTSELECT_CS3_SELECT_MASK		(0x3 << 6)
+#define	BCH_LAYOUTSELECT_CS3_SELECT_OFFSET		6
+#define	BCH_LAYOUTSELECT_CS2_SELECT_MASK		(0x3 << 4)
+#define	BCH_LAYOUTSELECT_CS2_SELECT_OFFSET		4
+#define	BCH_LAYOUTSELECT_CS1_SELECT_MASK		(0x3 << 2)
+#define	BCH_LAYOUTSELECT_CS1_SELECT_OFFSET		2
+#define	BCH_LAYOUTSELECT_CS0_SELECT_MASK		(0x3 << 0)
+#define	BCH_LAYOUTSELECT_CS0_SELECT_OFFSET		0
+
+#define	BCH_FLASHLAYOUT0_NBLOCKS_MASK			(0xff << 24)
+#define	BCH_FLASHLAYOUT0_NBLOCKS_OFFSET			24
+#define	BCH_FLASHLAYOUT0_META_SIZE_MASK			(0xff << 16)
+#define	BCH_FLASHLAYOUT0_META_SIZE_OFFSET		16
+#define	BCH_FLASHLAYOUT0_ECC0_MASK			(0xf << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_OFFSET			12
+#define	BCH_FLASHLAYOUT0_ECC0_NONE			(0x0 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC2			(0x1 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC4			(0x2 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC6			(0x3 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC8			(0x4 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC10			(0x5 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC12			(0x6 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC14			(0x7 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC16			(0x8 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC18			(0x9 << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC20			(0xa << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC22			(0xb << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC24			(0xc << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC26			(0xd << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC28			(0xe << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC30			(0xf << 12)
+#define	BCH_FLASHLAYOUT0_ECC0_ECC32			(0x10 << 12)
+#define	BCH_FLASHLAYOUT0_GF13_0_GF14_1			(1 << 10)
+#define	BCH_FLASHLAYOUT0_DATA0_SIZE_MASK		0xfff
+#define	BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET		0
+
+#define	BCH_FLASHLAYOUT1_PAGE_SIZE_MASK			(0xffff << 16)
+#define	BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET		16
+#define	BCH_FLASHLAYOUT1_ECCN_MASK			(0xf << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_OFFSET			12
+#define	BCH_FLASHLAYOUT1_ECCN_NONE			(0x0 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC2			(0x1 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC4			(0x2 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC6			(0x3 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC8			(0x4 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC10			(0x5 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC12			(0x6 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC14			(0x7 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC16			(0x8 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC18			(0x9 << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC20			(0xa << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC22			(0xb << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC24			(0xc << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC26			(0xd << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC28			(0xe << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC30			(0xf << 12)
+#define	BCH_FLASHLAYOUT1_ECCN_ECC32			(0x10 << 12)
+#define	BCH_FLASHLAYOUT1_GF13_0_GF14_1			(1 << 10)
+#define	BCH_FLASHLAYOUT1_DATAN_SIZE_MASK		0xfff
+#define	BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET		0
+
+#define	BCH_DEBUG0_RSVD1_MASK				(0x1f << 27)
+#define	BCH_DEBUG0_RSVD1_OFFSET				27
+#define	BCH_DEBUG0_ROM_BIST_ENABLE			(1 << 26)
+#define	BCH_DEBUG0_ROM_BIST_COMPLETE			(1 << 25)
+#define	BCH_DEBUG0_KES_DEBUG_SYNDROME_SYMBOL_MASK	(0x1ff << 16)
+#define	BCH_DEBUG0_KES_DEBUG_SYNDROME_SYMBOL_OFFSET	16
+#define	BCH_DEBUG0_KES_DEBUG_SYNDROME_SYMBOL_NORMAL	(0x0 << 16)
+#define	BCH_DEBUG0_KES_DEBUG_SYNDROME_SYMBOL_TEST_MODE	(0x1 << 16)
+#define	BCH_DEBUG0_KES_DEBUG_SHIFT_SYND			(1 << 15)
+#define	BCH_DEBUG0_KES_DEBUG_PAYLOAD_FLAG		(1 << 14)
+#define	BCH_DEBUG0_KES_DEBUG_MODE4K			(1 << 13)
+#define	BCH_DEBUG0_KES_DEBUG_KICK			(1 << 12)
+#define	BCH_DEBUG0_KES_STANDALONE			(1 << 11)
+#define	BCH_DEBUG0_KES_DEBUG_STEP			(1 << 10)
+#define	BCH_DEBUG0_KES_DEBUG_STALL			(1 << 9)
+#define	BCH_DEBUG0_BM_KES_TEST_BYPASS			(1 << 8)
+#define	BCH_DEBUG0_RSVD0_MASK				(0x3 << 6)
+#define	BCH_DEBUG0_RSVD0_OFFSET				6
+#define	BCH_DEBUG0_DEBUG_REG_SELECT_MASK		0x3f
+#define	BCH_DEBUG0_DEBUG_REG_SELECT_OFFSET		0
+
+#define	BCH_DBGKESREAD_VALUES_MASK			0xffffffff
+#define	BCH_DBGKESREAD_VALUES_OFFSET			0
+
+#define	BCH_DBGCSFEREAD_VALUES_MASK			0xffffffff
+#define	BCH_DBGCSFEREAD_VALUES_OFFSET			0
+
+#define	BCH_DBGSYNDGENREAD_VALUES_MASK			0xffffffff
+#define	BCH_DBGSYNDGENREAD_VALUES_OFFSET		0
+
+#define	BCH_DBGAHBMREAD_VALUES_MASK			0xffffffff
+#define	BCH_DBGAHBMREAD_VALUES_OFFSET			0
+
+#define	BCH_BLOCKNAME_NAME_MASK				0xffffffff
+#define	BCH_BLOCKNAME_NAME_OFFSET			0
+
+#define	BCH_VERSION_MAJOR_MASK				(0xff << 24)
+#define	BCH_VERSION_MAJOR_OFFSET			24
+#define	BCH_VERSION_MINOR_MASK				(0xff << 16)
+#define	BCH_VERSION_MINOR_OFFSET			16
+#define	BCH_VERSION_STEP_MASK				0xffff
+#define	BCH_VERSION_STEP_OFFSET				0
+
+#endif	/* __MX28_REGS_BCH_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-clkctrl.h b/arch/arm/include/asm/arch-mx28/regs-clkctrl.h
new file mode 100644
index 0000000..93d0397
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-clkctrl.h
@@ -0,0 +1,312 @@
+/*
+ * Freescale i.MX28 CLKCTRL Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_CLKCTRL_H__
+#define __MX28_REGS_CLKCTRL_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_clkctrl_regs {
+	mx28_reg(hw_clkctrl_pll0ctrl0)		/* 0x00 */
+	mx28_reg(hw_clkctrl_pll0ctrl1)		/* 0x10 */
+	mx28_reg(hw_clkctrl_pll1ctrl0)		/* 0x20 */
+	mx28_reg(hw_clkctrl_pll1ctrl1)		/* 0x30 */
+	mx28_reg(hw_clkctrl_pll2ctrl0)		/* 0x40 */
+	mx28_reg(hw_clkctrl_cpu)		/* 0x50 */
+	mx28_reg(hw_clkctrl_hbus)		/* 0x60 */
+	mx28_reg(hw_clkctrl_xbus)		/* 0x70 */
+	mx28_reg(hw_clkctrl_xtal)		/* 0x80 */
+	mx28_reg(hw_clkctrl_ssp0)		/* 0x90 */
+	mx28_reg(hw_clkctrl_ssp1)		/* 0xa0 */
+	mx28_reg(hw_clkctrl_ssp2)		/* 0xb0 */
+	mx28_reg(hw_clkctrl_ssp3)		/* 0xc0 */
+	mx28_reg(hw_clkctrl_gpmi)		/* 0xd0 */
+	mx28_reg(hw_clkctrl_spdif)		/* 0xe0 */
+	mx28_reg(hw_clkctrl_emi)		/* 0xf0 */
+	mx28_reg(hw_clkctrl_saif0)		/* 0x100 */
+	mx28_reg(hw_clkctrl_saif1)		/* 0x110 */
+	mx28_reg(hw_clkctrl_lcdif)		/* 0x120 */
+	mx28_reg(hw_clkctrl_etm)		/* 0x130 */
+	mx28_reg(hw_clkctrl_enet)		/* 0x140 */
+	mx28_reg(hw_clkctrl_hsadc)		/* 0x150 */
+	mx28_reg(hw_clkctrl_flexcan)		/* 0x160 */
+
+	uint32_t	reserved[16];
+
+	mx28_reg(hw_clkctrl_frac0)		/* 0x1b0 */
+	mx28_reg(hw_clkctrl_frac1)		/* 0x1c0 */
+	mx28_reg(hw_clkctrl_clkseq)		/* 0x1d0 */
+	mx28_reg(hw_clkctrl_reset)		/* 0x1e0 */
+	mx28_reg(hw_clkctrl_status)		/* 0x1f0 */
+	mx28_reg(hw_clkctrl_version)		/* 0x200 */
+};
+#endif
+
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_MASK		(0x3 << 28)
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_OFFSET	28
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_DEFAULT	(0x0 << 28)
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_TIMES_2	(0x1 << 28)
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_TIMES_05	(0x2 << 28)
+#define	CLKCTRL_PLL0CTRL0_LFR_SEL_UNDEFINED	(0x3 << 28)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_MASK		(0x3 << 24)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_OFFSET		24
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_DEFAULT	(0x0 << 24)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_TIMES_2	(0x1 << 24)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_TIMES_05	(0x2 << 24)
+#define	CLKCTRL_PLL0CTRL0_CP_SEL_UNDEFINED	(0x3 << 24)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_MASK		(0x3 << 20)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_OFFSET	20
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_DEFAULT	(0x0 << 20)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_LOWER		(0x1 << 20)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_LOWEST	(0x2 << 20)
+#define	CLKCTRL_PLL0CTRL0_DIV_SEL_UNDEFINED	(0x3 << 20)
+#define	CLKCTRL_PLL0CTRL0_EN_USB_CLKS		(1 << 18)
+#define	CLKCTRL_PLL0CTRL0_POWER			(1 << 17)
+
+#define	CLKCTRL_PLL0CTRL1_LOCK			(1 << 31)
+#define	CLKCTRL_PLL0CTRL1_FORCE_LOCK		(1 << 30)
+#define	CLKCTRL_PLL0CTRL1_LOCK_COUNT_MASK	0xffff
+#define	CLKCTRL_PLL0CTRL1_LOCK_COUNT_OFFSET	0
+
+#define	CLKCTRL_PLL1CTRL0_CLKGATEEMI		(1 << 31)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_MASK		(0x3 << 28)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_OFFSET	28
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_DEFAULT	(0x0 << 28)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_TIMES_2	(0x1 << 28)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_TIMES_05	(0x2 << 28)
+#define	CLKCTRL_PLL1CTRL0_LFR_SEL_UNDEFINED	(0x3 << 28)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_MASK		(0x3 << 24)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_OFFSET		24
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_DEFAULT	(0x0 << 24)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_TIMES_2	(0x1 << 24)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_TIMES_05	(0x2 << 24)
+#define	CLKCTRL_PLL1CTRL0_CP_SEL_UNDEFINED	(0x3 << 24)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_MASK		(0x3 << 20)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_OFFSET	20
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_DEFAULT	(0x0 << 20)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_LOWER		(0x1 << 20)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_LOWEST	(0x2 << 20)
+#define	CLKCTRL_PLL1CTRL0_DIV_SEL_UNDEFINED	(0x3 << 20)
+#define	CLKCTRL_PLL1CTRL0_EN_USB_CLKS		(1 << 18)
+#define	CLKCTRL_PLL1CTRL0_POWER			(1 << 17)
+
+#define	CLKCTRL_PLL1CTRL1_LOCK			(1 << 31)
+#define	CLKCTRL_PLL1CTRL1_FORCE_LOCK		(1 << 30)
+#define	CLKCTRL_PLL1CTRL1_LOCK_COUNT_MASK	0xffff
+#define	CLKCTRL_PLL1CTRL1_LOCK_COUNT_OFFSET	0
+
+#define	CLKCTRL_PLL2CTRL0_CLKGATE		(1 << 31)
+#define	CLKCTRL_PLL2CTRL0_LFR_SEL_MASK		(0x3 << 28)
+#define	CLKCTRL_PLL2CTRL0_LFR_SEL_OFFSET	28
+#define	CLKCTRL_PLL2CTRL0_HOLD_RING_OFF_B	(1 << 26)
+#define	CLKCTRL_PLL2CTRL0_CP_SEL_MASK		(0x3 << 24)
+#define	CLKCTRL_PLL2CTRL0_CP_SEL_OFFSET		24
+#define	CLKCTRL_PLL2CTRL0_POWER			(1 << 23)
+
+#define	CLKCTRL_CPU_BUSY_REF_XTAL		(1 << 29)
+#define	CLKCTRL_CPU_BUSY_REF_CPU		(1 << 28)
+#define	CLKCTRL_CPU_DIV_XTAL_FRAC_EN		(1 << 26)
+#define	CLKCTRL_CPU_DIV_XTAL_MASK		(0x3ff << 16)
+#define	CLKCTRL_CPU_DIV_XTAL_OFFSET		16
+#define	CLKCTRL_CPU_INTERRUPT_WAIT		(1 << 12)
+#define	CLKCTRL_CPU_DIV_CPU_FRAC_EN		(1 << 10)
+#define	CLKCTRL_CPU_DIV_CPU_MASK		0x3f
+#define	CLKCTRL_CPU_DIV_CPU_OFFSET		0
+
+#define	CLKCTRL_HBUS_ASM_BUSY			(1 << 31)
+#define	CLKCTRL_HBUS_DCP_AS_ENABLE		(1 << 30)
+#define	CLKCTRL_HBUS_PXP_AS_ENABLE		(1 << 29)
+#define	CLKCTRL_HBUS_ASM_EMIPORT_AS_ENABLE	(1 << 27)
+#define	CLKCTRL_HBUS_APBHDMA_AS_ENABLE		(1 << 26)
+#define	CLKCTRL_HBUS_APBXDMA_AS_ENABLE		(1 << 25)
+#define	CLKCTRL_HBUS_TRAFFIC_JAM_AS_ENABLE	(1 << 24)
+#define	CLKCTRL_HBUS_TRAFFIC_AS_ENABLE		(1 << 23)
+#define	CLKCTRL_HBUS_CPU_DATA_AS_ENABLE		(1 << 22)
+#define	CLKCTRL_HBUS_CPU_INSTR_AS_ENABLE	(1 << 21)
+#define	CLKCTRL_HBUS_ASM_ENABLE			(1 << 20)
+#define	CLKCTRL_HBUS_AUTO_CLEAR_DIV_ENABLE	(1 << 19)
+#define	CLKCTRL_HBUS_SLOW_DIV_MASK		(0x7 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_OFFSET		16
+#define	CLKCTRL_HBUS_SLOW_DIV_BY1		(0x0 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY2		(0x1 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY4		(0x2 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY8		(0x3 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY16		(0x4 << 16)
+#define	CLKCTRL_HBUS_SLOW_DIV_BY32		(0x5 << 16)
+#define	CLKCTRL_HBUS_DIV_FRAC_EN		(1 << 5)
+#define	CLKCTRL_HBUS_DIV_MASK			0x1f
+#define	CLKCTRL_HBUS_DIV_OFFSET			0
+
+#define	CLKCTRL_XBUS_BUSY			(1 << 31)
+#define	CLKCTRL_XBUS_AUTO_CLEAR_DIV_ENABLE	(1 << 11)
+#define	CLKCTRL_XBUS_DIV_FRAC_EN		(1 << 10)
+#define	CLKCTRL_XBUS_DIV_MASK			0x3ff
+#define	CLKCTRL_XBUS_DIV_OFFSET			0
+
+#define	CLKCTRL_XTAL_UART_CLK_GATE		(1 << 31)
+#define	CLKCTRL_XTAL_PWM_CLK24M_GATE		(1 << 29)
+#define	CLKCTRL_XTAL_TIMROT_CLK32K_GATE		(1 << 26)
+#define	CLKCTRL_XTAL_DIV_UART_MASK		0x3
+#define	CLKCTRL_XTAL_DIV_UART_OFFSET		0
+
+#define	CLKCTRL_SSP_CLKGATE			(1 << 31)
+#define	CLKCTRL_SSP_BUSY			(1 << 29)
+#define	CLKCTRL_SSP_DIV_FRAC_EN			(1 << 9)
+#define	CLKCTRL_SSP_DIV_MASK			0x1ff
+#define	CLKCTRL_SSP_DIV_OFFSET			0
+
+#define	CLKCTRL_GPMI_CLKGATE			(1 << 31)
+#define	CLKCTRL_GPMI_BUSY			(1 << 29)
+#define	CLKCTRL_GPMI_DIV_FRAC_EN		(1 << 10)
+#define	CLKCTRL_GPMI_DIV_MASK			0x3ff
+#define	CLKCTRL_GPMI_DIV_OFFSET			0
+
+#define	CLKCTRL_SPDIF_CLKGATE			(1 << 31)
+
+#define	CLKCTRL_EMI_CLKGATE			(1 << 31)
+#define	CLKCTRL_EMI_SYNC_MODE_EN		(1 << 30)
+#define	CLKCTRL_EMI_BUSY_REF_XTAL		(1 << 29)
+#define	CLKCTRL_EMI_BUSY_REF_EMI		(1 << 28)
+#define	CLKCTRL_EMI_BUSY_REF_CPU		(1 << 27)
+#define	CLKCTRL_EMI_BUSY_SYNC_MODE		(1 << 26)
+#define	CLKCTRL_EMI_BUSY_DCC_RESYNC		(1 << 17)
+#define	CLKCTRL_EMI_DCC_RESYNC_ENABLE		(1 << 16)
+#define	CLKCTRL_EMI_DIV_XTAL_MASK		(0xf << 8)
+#define	CLKCTRL_EMI_DIV_XTAL_OFFSET		8
+#define	CLKCTRL_EMI_DIV_EMI_MASK		0x3f
+#define	CLKCTRL_EMI_DIV_EMI_OFFSET		0
+
+#define	CLKCTRL_SAIF0_CLKGATE			(1 << 31)
+#define	CLKCTRL_SAIF0_BUSY			(1 << 29)
+#define	CLKCTRL_SAIF0_DIV_FRAC_EN		(1 << 16)
+#define	CLKCTRL_SAIF0_DIV_MASK			0xffff
+#define	CLKCTRL_SAIF0_DIV_OFFSET		0
+
+#define	CLKCTRL_SAIF1_CLKGATE			(1 << 31)
+#define	CLKCTRL_SAIF1_BUSY			(1 << 29)
+#define	CLKCTRL_SAIF1_DIV_FRAC_EN		(1 << 16)
+#define	CLKCTRL_SAIF1_DIV_MASK			0xffff
+#define	CLKCTRL_SAIF1_DIV_OFFSET		0
+
+#define	CLKCTRL_DIS_LCDIF_CLKGATE		(1 << 31)
+#define	CLKCTRL_DIS_LCDIF_BUSY			(1 << 29)
+#define	CLKCTRL_DIS_LCDIF_DIV_FRAC_EN		(1 << 13)
+#define	CLKCTRL_DIS_LCDIF_DIV_MASK		0x1fff
+#define	CLKCTRL_DIS_LCDIF_DIV_OFFSET		0
+
+#define	CLKCTRL_ETM_CLKGATE			(1 << 31)
+#define	CLKCTRL_ETM_BUSY			(1 << 29)
+#define	CLKCTRL_ETM_DIV_FRAC_EN			(1 << 7)
+#define	CLKCTRL_ETM_DIV_MASK			0x7f
+#define	CLKCTRL_ETM_DIV_OFFSET			0
+
+#define	CLKCTRL_ENET_SLEEP			(1 << 31)
+#define	CLKCTRL_ENET_DISABLE			(1 << 30)
+#define	CLKCTRL_ENET_STATUS			(1 << 29)
+#define	CLKCTRL_ENET_BUSY_TIME			(1 << 27)
+#define	CLKCTRL_ENET_DIV_TIME_MASK		(0x3f << 21)
+#define	CLKCTRL_ENET_DIV_TIME_OFFSET		21
+#define	CLKCTRL_ENET_TIME_SEL_MASK		(0x3 << 19)
+#define	CLKCTRL_ENET_TIME_SEL_OFFSET		19
+#define	CLKCTRL_ENET_TIME_SEL_XTAL		(0x0 << 19)
+#define	CLKCTRL_ENET_TIME_SEL_PLL		(0x1 << 19)
+#define	CLKCTRL_ENET_TIME_SEL_RMII_CLK		(0x2 << 19)
+#define	CLKCTRL_ENET_TIME_SEL_UNDEFINED		(0x3 << 19)
+#define	CLKCTRL_ENET_CLK_OUT_EN			(1 << 18)
+#define	CLKCTRL_ENET_RESET_BY_SW_CHIP		(1 << 17)
+#define	CLKCTRL_ENET_RESET_BY_SW		(1 << 16)
+
+#define	CLKCTRL_HSADC_RESETB			(1 << 30)
+#define	CLKCTRL_HSADC_FREQDIV_MASK		(0x3 << 28)
+#define	CLKCTRL_HSADC_FREQDIV_OFFSET		28
+
+#define	CLKCTRL_FLEXCAN_STOP_CAN0		(1 << 30)
+#define	CLKCTRL_FLEXCAN_CAN0_STATUS		(1 << 29)
+#define	CLKCTRL_FLEXCAN_STOP_CAN1		(1 << 28)
+#define	CLKCTRL_FLEXCAN_CAN1_STATUS		(1 << 27)
+
+#define	CLKCTRL_FRAC0_CLKGATEIO0		(1 << 31)
+#define	CLKCTRL_FRAC0_IO0_STABLE		(1 << 30)
+#define	CLKCTRL_FRAC0_IO0FRAC_MASK		(0x3f << 24)
+#define	CLKCTRL_FRAC0_IO0FRAC_OFFSET		24
+#define	CLKCTRL_FRAC0_CLKGATEIO1		(1 << 23)
+#define	CLKCTRL_FRAC0_IO1_STABLE		(1 << 22)
+#define	CLKCTRL_FRAC0_IO1FRAC_MASK		(0x3f << 16)
+#define	CLKCTRL_FRAC0_IO1FRAC_OFFSET		16
+#define	CLKCTRL_FRAC0_CLKGATEEMI		(1 << 15)
+#define	CLKCTRL_FRAC0_EMI_STABLE		(1 << 14)
+#define	CLKCTRL_FRAC0_EMIFRAC_MASK		(0x3f << 8)
+#define	CLKCTRL_FRAC0_EMIFRAC_OFFSET		8
+#define	CLKCTRL_FRAC0_CLKGATECPU		(1 << 7)
+#define	CLKCTRL_FRAC0_CPU_STABLE		(1 << 6)
+#define	CLKCTRL_FRAC0_CPUFRAC_MASK		0x3f
+#define	CLKCTRL_FRAC0_CPUFRAC_OFFSET		0
+
+#define	CLKCTRL_FRAC1_CLKGATEGPMI		(1 << 23)
+#define	CLKCTRL_FRAC1_GPMI_STABLE		(1 << 22)
+#define	CLKCTRL_FRAC1_GPMIFRAC_MASK		(0x3f << 16)
+#define	CLKCTRL_FRAC1_GPMIFRAC_OFFSET		16
+#define	CLKCTRL_FRAC1_CLKGATEHSADC		(1 << 15)
+#define	CLKCTRL_FRAC1_HSADC_STABLE		(1 << 14)
+#define	CLKCTRL_FRAC1_HSADCFRAC_MASK		(0x3f << 8)
+#define	CLKCTRL_FRAC1_HSADCFRAC_OFFSET		8
+#define	CLKCTRL_FRAC1_CLKGATEPIX		(1 << 7)
+#define	CLKCTRL_FRAC1_PIX_STABLE		(1 << 6)
+#define	CLKCTRL_FRAC1_PIXFRAC_MASK		0x3f
+#define	CLKCTRL_FRAC1_PIXFRAC_OFFSET		0
+
+#define	CLKCTRL_CLKSEQ_BYPASS_CPU		(1 << 18)
+#define	CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF		(1 << 14)
+#define	CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF_BYPASS	(0x1 << 14)
+#define	CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF_PFD	(0x0 << 14)
+#define	CLKCTRL_CLKSEQ_BYPASS_ETM		(1 << 8)
+#define	CLKCTRL_CLKSEQ_BYPASS_EMI		(1 << 7)
+#define	CLKCTRL_CLKSEQ_BYPASS_SSP3		(1 << 6)
+#define	CLKCTRL_CLKSEQ_BYPASS_SSP2		(1 << 5)
+#define	CLKCTRL_CLKSEQ_BYPASS_SSP1		(1 << 4)
+#define	CLKCTRL_CLKSEQ_BYPASS_SSP0		(1 << 3)
+#define	CLKCTRL_CLKSEQ_BYPASS_GPMI		(1 << 2)
+#define	CLKCTRL_CLKSEQ_BYPASS_SAIF1		(1 << 1)
+#define	CLKCTRL_CLKSEQ_BYPASS_SAIF0		(1 << 0)
+
+#define	CLKCTRL_RESET_WDOG_POR_DISABLE		(1 << 5)
+#define	CLKCTRL_RESET_EXTERNAL_RESET_ENABLE	(1 << 4)
+#define	CLKCTRL_RESET_THERMAL_RESET_ENABLE	(1 << 3)
+#define	CLKCTRL_RESET_THERMAL_RESET_DEFAULT	(1 << 2)
+#define	CLKCTRL_RESET_CHIP			(1 << 1)
+#define	CLKCTRL_RESET_DIG			(1 << 0)
+
+#define	CLKCTRL_STATUS_CPU_LIMIT_MASK		(0x3 << 30)
+#define	CLKCTRL_STATUS_CPU_LIMIT_OFFSET		30
+
+#define	CLKCTRL_VERSION_MAJOR_MASK		(0xff << 24)
+#define	CLKCTRL_VERSION_MAJOR_OFFSET		24
+#define	CLKCTRL_VERSION_MINOR_MASK		(0xff << 16)
+#define	CLKCTRL_VERSION_MINOR_OFFSET		16
+#define	CLKCTRL_VERSION_STEP_MASK		0xffff
+#define	CLKCTRL_VERSION_STEP_OFFSET		0
+
+#endif /* __MX28_REGS_CLKCTRL_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-common.h b/arch/arm/include/asm/arch-mx28/regs-common.h
new file mode 100644
index 0000000..efe975b
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-common.h
@@ -0,0 +1,66 @@
+/*
+ * Freescale i.MX28 Register Accessors
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_COMMON_H__
+#define __MX28_REGS_COMMON_H__
+
+/*
+ * The i.MX28 has interesting feature when it comes to register access. There
+ * are four kinds of access to one particular register. Those are:
+ *
+ * 1) Common read/write access. To use this mode, just write to the address of
+ *    the register.
+ * 2) Set bits only access. To set bits, write which bits you want to set to the
+ *    address of the register + 0x4.
+ * 3) Clear bits only access. To clear bits, write which bits you want to clear
+ *    to the address of the register + 0x8.
+ * 4) Toggle bits only access. To toggle bits, write which bits you want to
+ *    toggle to the address of the register + 0xc.
+ *
+ * IMPORTANT NOTE: Not all registers support accesses 2-4! Also, not all bits
+ * can be set/cleared by pure write as in access type 1, some need to be
+ * explicitly set/cleared by using access type 2-3.
+ *
+ * The following macros and structures allow the user to either access the
+ * register in all aforementioned modes (by accessing reg_name, reg_name_set,
+ * reg_name_clr, reg_name_tog) or pass the register structure further into
+ * various functions with correct type information (by accessing reg_name_reg).
+ *
+ */
+
+#define	__mx28_reg(name)		\
+	uint32_t name;			\
+	uint32_t name##_set;		\
+	uint32_t name##_clr;		\
+	uint32_t name##_tog;
+
+struct mx28_register {
+	__mx28_reg(reg)
+};
+
+#define	mx28_reg(name)					\
+	union {						\
+		struct { __mx28_reg(name) };		\
+		struct mx28_register name##_reg;	\
+	};
+
+#endif	/* __MX28_REGS_COMMON_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-gpmi.h b/arch/arm/include/asm/arch-mx28/regs-gpmi.h
new file mode 100644
index 0000000..0096793
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-gpmi.h
@@ -0,0 +1,222 @@
+/*
+ * Freescale i.MX28 GPMI Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_GPMI_H__
+#define __MX28_REGS_GPMI_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_gpmi_regs {
+	mx28_reg(hw_gpmi_ctrl0)
+	mx28_reg(hw_gpmi_compare)
+	mx28_reg(hw_gpmi_eccctrl)
+	mx28_reg(hw_gpmi_ecccount)
+	mx28_reg(hw_gpmi_payload)
+	mx28_reg(hw_gpmi_auxiliary)
+	mx28_reg(hw_gpmi_ctrl1)
+	mx28_reg(hw_gpmi_timing0)
+	mx28_reg(hw_gpmi_timing1)
+
+	uint32_t	reserved[4];
+
+	mx28_reg(hw_gpmi_data)
+	mx28_reg(hw_gpmi_stat)
+	mx28_reg(hw_gpmi_debug)
+	mx28_reg(hw_gpmi_version)
+};
+#endif
+
+#define	GPMI_CTRL0_SFTRST				(1 << 31)
+#define	GPMI_CTRL0_CLKGATE				(1 << 30)
+#define	GPMI_CTRL0_RUN					(1 << 29)
+#define	GPMI_CTRL0_DEV_IRQ_EN				(1 << 28)
+#define	GPMI_CTRL0_LOCK_CS				(1 << 27)
+#define	GPMI_CTRL0_UDMA					(1 << 26)
+#define	GPMI_CTRL0_COMMAND_MODE_MASK			(0x3 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_OFFSET			24
+#define	GPMI_CTRL0_COMMAND_MODE_WRITE			(0x0 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_READ			(0x1 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_READ_AND_COMPARE	(0x2 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY		(0x3 << 24)
+#define	GPMI_CTRL0_WORD_LENGTH				(1 << 23)
+#define	GPMI_CTRL0_CS_MASK				(0x7 << 20)
+#define	GPMI_CTRL0_CS_OFFSET				20
+#define	GPMI_CTRL0_ADDRESS_MASK				(0x7 << 17)
+#define	GPMI_CTRL0_ADDRESS_OFFSET			17
+#define	GPMI_CTRL0_ADDRESS_NAND_DATA			(0x0 << 17)
+#define	GPMI_CTRL0_ADDRESS_NAND_CLE			(0x1 << 17)
+#define	GPMI_CTRL0_ADDRESS_NAND_ALE			(0x2 << 17)
+#define	GPMI_CTRL0_ADDRESS_INCREMENT			(1 << 16)
+#define	GPMI_CTRL0_XFER_COUNT_MASK			0xffff
+#define	GPMI_CTRL0_XFER_COUNT_OFFSET			0
+
+#define	GPMI_COMPARE_MASK_MASK				(0xffff << 16)
+#define	GPMI_COMPARE_MASK_OFFSET			16
+#define	GPMI_COMPARE_REFERENCE_MASK			0xffff
+#define	GPMI_COMPARE_REFERENCE_OFFSET			0
+
+#define	GPMI_ECCCTRL_HANDLE_MASK			(0xffff << 16)
+#define	GPMI_ECCCTRL_HANDLE_OFFSET			16
+#define	GPMI_ECCCTRL_ECC_CMD_MASK			(0x3 << 13)
+#define	GPMI_ECCCTRL_ECC_CMD_OFFSET			13
+#define	GPMI_ECCCTRL_ECC_CMD_DECODE			(0x0 << 13)
+#define	GPMI_ECCCTRL_ECC_CMD_ENCODE			(0x1 << 13)
+#define	GPMI_ECCCTRL_ENABLE_ECC				(1 << 12)
+#define	GPMI_ECCCTRL_BUFFER_MASK_MASK			0x1ff
+#define	GPMI_ECCCTRL_BUFFER_MASK_OFFSET			0
+#define	GPMI_ECCCTRL_BUFFER_MASK_BCH_AUXONLY		0x100
+#define	GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE		0x1ff
+
+#define	GPMI_ECCCOUNT_COUNT_MASK			0xffff
+#define	GPMI_ECCCOUNT_COUNT_OFFSET			0
+
+#define	GPMI_PAYLOAD_ADDRESS_MASK			(0x3fffffff << 2)
+#define	GPMI_PAYLOAD_ADDRESS_OFFSET			2
+
+#define	GPMI_AUXILIARY_ADDRESS_MASK			(0x3fffffff << 2)
+#define	GPMI_AUXILIARY_ADDRESS_OFFSET			2
+
+#define	GPMI_CTRL1_DECOUPLE_CS				(1 << 24)
+#define	GPMI_CTRL1_WRN_DLY_SEL_MASK			(0x3 << 22)
+#define	GPMI_CTRL1_WRN_DLY_SEL_OFFSET			22
+#define	GPMI_CTRL1_TIMEOUT_IRQ_EN			(1 << 20)
+#define	GPMI_CTRL1_GANGED_RDYBUSY			(1 << 19)
+#define	GPMI_CTRL1_BCH_MODE				(1 << 18)
+#define	GPMI_CTRL1_DLL_ENABLE				(1 << 17)
+#define	GPMI_CTRL1_HALF_PERIOD				(1 << 16)
+#define	GPMI_CTRL1_RDN_DELAY_MASK			(0xf << 12)
+#define	GPMI_CTRL1_RDN_DELAY_OFFSET			12
+#define	GPMI_CTRL1_DMA2ECC_MODE				(1 << 11)
+#define	GPMI_CTRL1_DEV_IRQ				(1 << 10)
+#define	GPMI_CTRL1_TIMEOUT_IRQ				(1 << 9)
+#define	GPMI_CTRL1_BURST_EN				(1 << 8)
+#define	GPMI_CTRL1_ABORT_WAIT_REQUEST			(1 << 7)
+#define	GPMI_CTRL1_ABORT_WAIT_FOR_READY_CHANNEL_MASK	(0x7 << 4)
+#define	GPMI_CTRL1_ABORT_WAIT_FOR_READY_CHANNEL_OFFSET	4
+#define	GPMI_CTRL1_DEV_RESET				(1 << 3)
+#define	GPMI_CTRL1_ATA_IRQRDY_POLARITY			(1 << 2)
+#define	GPMI_CTRL1_CAMERA_MODE				(1 << 1)
+#define	GPMI_CTRL1_GPMI_MODE				(1 << 0)
+
+#define	GPMI_TIMING0_ADDRESS_SETUP_MASK			(0xff << 16)
+#define	GPMI_TIMING0_ADDRESS_SETUP_OFFSET		16
+#define	GPMI_TIMING0_DATA_HOLD_MASK			(0xff << 8)
+#define	GPMI_TIMING0_DATA_HOLD_OFFSET			8
+#define	GPMI_TIMING0_DATA_SETUP_MASK			0xff
+#define	GPMI_TIMING0_DATA_SETUP_OFFSET			0
+
+#define	GPMI_TIMING1_DEVICE_BUSY_TIMEOUT_MASK		(0xffff << 16)
+#define	GPMI_TIMING1_DEVICE_BUSY_TIMEOUT_OFFSET		16
+
+#define	GPMI_TIMING2_UDMA_TRP_MASK			(0xff << 24)
+#define	GPMI_TIMING2_UDMA_TRP_OFFSET			24
+#define	GPMI_TIMING2_UDMA_ENV_MASK			(0xff << 16)
+#define	GPMI_TIMING2_UDMA_ENV_OFFSET			16
+#define	GPMI_TIMING2_UDMA_HOLD_MASK			(0xff << 8)
+#define	GPMI_TIMING2_UDMA_HOLD_OFFSET			8
+#define	GPMI_TIMING2_UDMA_SETUP_MASK			0xff
+#define	GPMI_TIMING2_UDMA_SETUP_OFFSET			0
+
+#define	GPMI_DATA_DATA_MASK				0xffffffff
+#define	GPMI_DATA_DATA_OFFSET				0
+
+#define	GPMI_STAT_READY_BUSY_MASK			(0xff << 24)
+#define	GPMI_STAT_READY_BUSY_OFFSET			24
+#define	GPMI_STAT_RDY_TIMEOUT_MASK			(0xff << 16)
+#define	GPMI_STAT_RDY_TIMEOUT_OFFSET			16
+#define	GPMI_STAT_DEV7_ERROR				(1 << 15)
+#define	GPMI_STAT_DEV6_ERROR				(1 << 14)
+#define	GPMI_STAT_DEV5_ERROR				(1 << 13)
+#define	GPMI_STAT_DEV4_ERROR				(1 << 12)
+#define	GPMI_STAT_DEV3_ERROR				(1 << 11)
+#define	GPMI_STAT_DEV2_ERROR				(1 << 10)
+#define	GPMI_STAT_DEV1_ERROR				(1 << 9)
+#define	GPMI_STAT_DEV0_ERROR				(1 << 8)
+#define	GPMI_STAT_ATA_IRQ				(1 << 4)
+#define	GPMI_STAT_INVALID_BUFFER_MASK			(1 << 3)
+#define	GPMI_STAT_FIFO_EMPTY				(1 << 2)
+#define	GPMI_STAT_FIFO_FULL				(1 << 1)
+#define	GPMI_STAT_PRESENT				(1 << 0)
+
+#define	GPMI_DEBUG_WAIT_FOR_READY_END_MASK		(0xff << 24)
+#define	GPMI_DEBUG_WAIT_FOR_READY_END_OFFSET		24
+#define	GPMI_DEBUG_DMA_SENSE_MASK			(0xff << 16)
+#define	GPMI_DEBUG_DMA_SENSE_OFFSET			16
+#define	GPMI_DEBUG_DMAREQ_MASK				(0xff << 8)
+#define	GPMI_DEBUG_DMAREQ_OFFSET			8
+#define	GPMI_DEBUG_CMD_END_MASK				0xff
+#define	GPMI_DEBUG_CMD_END_OFFSET			0
+
+#define	GPMI_VERSION_MAJOR_MASK				(0xff << 24)
+#define	GPMI_VERSION_MAJOR_OFFSET			24
+#define	GPMI_VERSION_MINOR_MASK				(0xff << 16)
+#define	GPMI_VERSION_MINOR_OFFSET			16
+#define	GPMI_VERSION_STEP_MASK				0xffff
+#define	GPMI_VERSION_STEP_OFFSET			0
+
+#define	GPMI_DEBUG2_UDMA_STATE_MASK			(0xf << 24)
+#define	GPMI_DEBUG2_UDMA_STATE_OFFSET			24
+#define	GPMI_DEBUG2_BUSY				(1 << 23)
+#define	GPMI_DEBUG2_PIN_STATE_MASK			(0x7 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_OFFSET			20
+#define	GPMI_DEBUG2_PIN_STATE_PSM_IDLE			(0x0 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_BYTCNT		(0x1 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_ADDR			(0x2 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_STALL			(0x3 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_STROBE		(0x4 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_ATARDY		(0x5 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_DHOLD			(0x6 << 20)
+#define	GPMI_DEBUG2_PIN_STATE_PSM_DONE			(0x7 << 20)
+#define	GPMI_DEBUG2_MAIN_STATE_MASK			(0xf << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_OFFSET			16
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_IDLE			(0x0 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_BYTCNT		(0x1 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_WAITFE		(0x2 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_WAITFR		(0x3 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_DMAREQ		(0x4 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_DMAACK		(0x5 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_WAITFF		(0x6 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_LDFIFO		(0x7 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_LDDMAR		(0x8 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_RDCMP		(0x9 << 16)
+#define	GPMI_DEBUG2_MAIN_STATE_MSM_DONE			(0xa << 16)
+#define	GPMI_DEBUG2_SYND2GPMI_BE_MASK			(0xf << 12)
+#define	GPMI_DEBUG2_SYND2GPMI_BE_OFFSET			12
+#define	GPMI_DEBUG2_GPMI2SYND_VALID			(1 << 11)
+#define	GPMI_DEBUG2_GPMI2SYND_READY			(1 << 10)
+#define	GPMI_DEBUG2_SYND2GPMI_VALID			(1 << 9)
+#define	GPMI_DEBUG2_SYND2GPMI_READY			(1 << 8)
+#define	GPMI_DEBUG2_VIEW_DELAYED_RDN			(1 << 7)
+#define	GPMI_DEBUG2_UPDATE_WINDOW			(1 << 6)
+#define	GPMI_DEBUG2_RDN_TAP_MASK			0x3f
+#define	GPMI_DEBUG2_RDN_TAP_OFFSET			0
+
+#define	GPMI_DEBUG3_APB_WORD_CNTR_MASK			(0xffff << 16)
+#define	GPMI_DEBUG3_APB_WORD_CNTR_OFFSET		16
+#define	GPMI_DEBUG3_DEV_WORD_CNTR_MASK			0xffff
+#define	GPMI_DEBUG3_DEV_WORD_CNTR_OFFSET		0
+
+#endif	/* __MX28_REGS_GPMI_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-i2c.h b/arch/arm/include/asm/arch-mx28/regs-i2c.h
new file mode 100644
index 0000000..30e0ed7
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-i2c.h
@@ -0,0 +1,207 @@
+/*
+ * Freescale i.MX28 I2C Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_I2C_H__
+#define __MX28_REGS_I2C_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_i2c_regs {
+	mx28_reg(hw_i2c_ctrl0)
+	mx28_reg(hw_i2c_timing0)
+	mx28_reg(hw_i2c_timing1)
+	mx28_reg(hw_i2c_timing2)
+	mx28_reg(hw_i2c_ctrl1)
+	mx28_reg(hw_i2c_stat)
+	mx28_reg(hw_i2c_queuectrl)
+	mx28_reg(hw_i2c_queuestat)
+	mx28_reg(hw_i2c_queuecmd)
+	mx28_reg(hw_i2c_queuedata)
+	mx28_reg(hw_i2c_data)
+	mx28_reg(hw_i2c_debug0)
+	mx28_reg(hw_i2c_debug1)
+	mx28_reg(hw_i2c_version)
+};
+#endif
+
+#define	I2C_CTRL_SFTRST				(1 << 31)
+#define	I2C_CTRL_CLKGATE			(1 << 30)
+#define	I2C_CTRL_RUN				(1 << 29)
+#define	I2C_CTRL_PREACK				(1 << 27)
+#define	I2C_CTRL_ACKNOWLEDGE			(1 << 26)
+#define	I2C_CTRL_SEND_NAK_ON_LAST		(1 << 25)
+#define	I2C_CTRL_MULTI_MASTER			(1 << 23)
+#define	I2C_CTRL_CLOCK_HELD			(1 << 22)
+#define	I2C_CTRL_RETAIN_CLOCK			(1 << 21)
+#define	I2C_CTRL_POST_SEND_STOP			(1 << 20)
+#define	I2C_CTRL_PRE_SEND_START			(1 << 19)
+#define	I2C_CTRL_SLAVE_ADDRESS_ENABLE		(1 << 18)
+#define	I2C_CTRL_MASTER_MODE			(1 << 17)
+#define	I2C_CTRL_DIRECTION			(1 << 16)
+#define	I2C_CTRL_XFER_COUNT_MASK		0xffff
+#define	I2C_CTRL_XFER_COUNT_OFFSET		0
+
+#define	I2C_TIMING0_HIGH_COUNT_MASK		(0x3ff << 16)
+#define	I2C_TIMING0_HIGH_COUNT_OFFSET		16
+#define	I2C_TIMING0_RCV_COUNT_MASK		0x3ff
+#define	I2C_TIMING0_RCV_COUNT_OFFSET		0
+
+#define	I2C_TIMING1_LOW_COUNT_MASK		(0x3ff << 16)
+#define	I2C_TIMING1_LOW_COUNT_OFFSET		16
+#define	I2C_TIMING1_XMIT_COUNT_MASK		0x3ff
+#define	I2C_TIMING1_XMIT_COUNT_OFFSET		0
+
+#define	I2C_TIMING2_BUS_FREE_MASK		(0x3ff << 16)
+#define	I2C_TIMING2_BUS_FREE_OFFSET		16
+#define	I2C_TIMING2_LEADIN_COUNT_MASK		0x3ff
+#define	I2C_TIMING2_LEADIN_COUNT_OFFSET		0
+
+#define	I2C_CTRL1_RD_QUEUE_IRQ			(1 << 30)
+#define	I2C_CTRL1_WR_QUEUE_IRQ			(1 << 29)
+#define	I2C_CTRL1_CLR_GOT_A_NAK			(1 << 28)
+#define	I2C_CTRL1_ACK_MODE			(1 << 27)
+#define	I2C_CTRL1_FORCE_DATA_IDLE		(1 << 26)
+#define	I2C_CTRL1_FORCE_CLK_IDLE		(1 << 25)
+#define	I2C_CTRL1_BCAST_SLAVE_EN		(1 << 24)
+#define	I2C_CTRL1_SLAVE_ADDRESS_BYTE_MASK	(0xff << 16)
+#define	I2C_CTRL1_SLAVE_ADDRESS_BYTE_OFFSET	16
+#define	I2C_CTRL1_BUS_FREE_IRQ_EN		(1 << 15)
+#define	I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ_EN	(1 << 14)
+#define	I2C_CTRL1_NO_SLAVE_ACK_IRQ_EN		(1 << 13)
+#define	I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ_EN	(1 << 12)
+#define	I2C_CTRL1_EARLY_TERM_IRQ_EN		(1 << 11)
+#define	I2C_CTRL1_MASTER_LOSS_IRQ_EN		(1 << 10)
+#define	I2C_CTRL1_SLAVE_STOP_IRQ_EN		(1 << 9)
+#define	I2C_CTRL1_SLAVE_IRQ_EN			(1 << 8)
+#define	I2C_CTRL1_BUS_FREE_IRQ			(1 << 7)
+#define	I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ		(1 << 6)
+#define	I2C_CTRL1_NO_SLAVE_ACK_IRQ		(1 << 5)
+#define	I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ	(1 << 4)
+#define	I2C_CTRL1_EARLY_TERM_IRQ		(1 << 3)
+#define	I2C_CTRL1_MASTER_LOSS_IRQ		(1 << 2)
+#define	I2C_CTRL1_SLAVE_STOP_IRQ		(1 << 1)
+#define	I2C_CTRL1_SLAVE_IRQ			(1 << 0)
+
+#define	I2C_STAT_MASTER_PRESENT			(1 << 31)
+#define	I2C_STAT_SLAVE_PRESENT			(1 << 30)
+#define	I2C_STAT_ANY_ENABLED_IRQ		(1 << 29)
+#define	I2C_STAT_GOT_A_NAK			(1 << 28)
+#define	I2C_STAT_RCVD_SLAVE_ADDR_MASK		(0xff << 16)
+#define	I2C_STAT_RCVD_SLAVE_ADDR_OFFSET		16
+#define	I2C_STAT_SLAVE_ADDR_EQ_ZERO		(1 << 15)
+#define	I2C_STAT_SLAVE_FOUND			(1 << 14)
+#define	I2C_STAT_SLAVE_SEARCHING		(1 << 13)
+#define	I2C_STAT_DATA_ENGING_DMA_WAIT		(1 << 12)
+#define	I2C_STAT_BUS_BUSY			(1 << 11)
+#define	I2C_STAT_CLK_GEN_BUSY			(1 << 10)
+#define	I2C_STAT_DATA_ENGINE_BUSY		(1 << 9)
+#define	I2C_STAT_SLAVE_BUSY			(1 << 8)
+#define	I2C_STAT_BUS_FREE_IRQ_SUMMARY		(1 << 7)
+#define	I2C_STAT_DATA_ENGINE_CMPLT_IRQ_SUMMARY	(1 << 6)
+#define	I2C_STAT_NO_SLAVE_ACK_IRQ_SUMMARY	(1 << 5)
+#define	I2C_STAT_OVERSIZE_XFER_TERM_IRQ_SUMMARY	(1 << 4)
+#define	I2C_STAT_EARLY_TERM_IRQ_SUMMARY		(1 << 3)
+#define	I2C_STAT_MASTER_LOSS_IRQ_SUMMARY	(1 << 2)
+#define	I2C_STAT_SLAVE_STOP_IRQ_SUMMARY		(1 << 1)
+#define	I2C_STAT_SLAVE_IRQ_SUMMARY		(1 << 0)
+
+#define	I2C_QUEUECTRL_RD_THRESH_MASK		(0x1f << 16)
+#define	I2C_QUEUECTRL_RD_THRESH_OFFSET		16
+#define	I2C_QUEUECTRL_WR_THRESH_MASK		(0x1f << 8)
+#define	I2C_QUEUECTRL_WR_THRESH_OFFSET		8
+#define	I2C_QUEUECTRL_QUEUE_RUN			(1 << 5)
+#define	I2C_QUEUECTRL_RD_CLEAR			(1 << 4)
+#define	I2C_QUEUECTRL_WR_CLEAR			(1 << 3)
+#define	I2C_QUEUECTRL_PIO_QUEUE_MODE		(1 << 2)
+#define	I2C_QUEUECTRL_RD_QUEUE_IRQ_EN		(1 << 1)
+#define	I2C_QUEUECTRL_WR_QUEUE_IRQ_EN		(1 << 0)
+
+#define	I2C_QUEUESTAT_RD_QUEUE_FULL		(1 << 14)
+#define	I2C_QUEUESTAT_RD_QUEUE_EMPTY		(1 << 13)
+#define	I2C_QUEUESTAT_RD_QUEUE_CNT_MASK		(0x1f << 8)
+#define	I2C_QUEUESTAT_RD_QUEUE_CNT_OFFSET	8
+#define	I2C_QUEUESTAT_WR_QUEUE_FULL		(1 << 6)
+#define	I2C_QUEUESTAT_WR_QUEUE_EMPTY		(1 << 5)
+#define	I2C_QUEUESTAT_WR_QUEUE_CNT_MASK		0x1f
+#define	I2C_QUEUESTAT_WR_QUEUE_CNT_OFFSET	0
+
+#define	I2C_QUEUECMD_PREACK			(1 << 27)
+#define	I2C_QUEUECMD_ACKNOWLEDGE		(1 << 26)
+#define	I2C_QUEUECMD_SEND_NAK_ON_LAST		(1 << 25)
+#define	I2C_QUEUECMD_MULTI_MASTER		(1 << 23)
+#define	I2C_QUEUECMD_CLOCK_HELD			(1 << 22)
+#define	I2C_QUEUECMD_RETAIN_CLOCK		(1 << 21)
+#define	I2C_QUEUECMD_POST_SEND_STOP		(1 << 20)
+#define	I2C_QUEUECMD_PRE_SEND_START		(1 << 19)
+#define	I2C_QUEUECMD_SLAVE_ADDRESS_ENABLE	(1 << 18)
+#define	I2C_QUEUECMD_MASTER_MODE		(1 << 17)
+#define	I2C_QUEUECMD_DIRECTION			(1 << 16)
+#define	I2C_QUEUECMD_XFER_COUNT_MASK		0xffff
+#define	I2C_QUEUECMD_XFER_COUNT_OFFSET		0
+
+#define	I2C_QUEUEDATA_DATA_MASK			0xffffffff
+#define	I2C_QUEUEDATA_DATA_OFFSET		0
+
+#define	I2C_DATA_DATA_MASK			0xffffffff
+#define	I2C_DATA_DATA_OFFSET			0
+
+#define	I2C_DEBUG0_DMAREQ			(1 << 31)
+#define	I2C_DEBUG0_DMAENDCMD			(1 << 30)
+#define	I2C_DEBUG0_DMAKICK			(1 << 29)
+#define	I2C_DEBUG0_DMATERMINATE			(1 << 28)
+#define	I2C_DEBUG0_STATE_VALUE_MASK		(0x3 << 26)
+#define	I2C_DEBUG0_STATE_VALUE_OFFSET		26
+#define	I2C_DEBUG0_DMA_STATE_MASK		(0x3ff << 16)
+#define	I2C_DEBUG0_DMA_STATE_OFFSET		16
+#define	I2C_DEBUG0_START_TOGGLE			(1 << 15)
+#define	I2C_DEBUG0_STOP_TOGGLE			(1 << 14)
+#define	I2C_DEBUG0_GRAB_TOGGLE			(1 << 13)
+#define	I2C_DEBUG0_CHANGE_TOGGLE		(1 << 12)
+#define	I2C_DEBUG0_STATE_LATCH			(1 << 11)
+#define	I2C_DEBUG0_SLAVE_HOLD_CLK		(1 << 10)
+#define	I2C_DEBUG0_STATE_STATE_MASK		0x3ff
+#define	I2C_DEBUG0_STATE_STATE_OFFSET		0
+
+#define	I2C_DEBUG1_I2C_CLK_IN			(1 << 31)
+#define	I2C_DEBUG1_I2C_DATA_IN			(1 << 30)
+#define	I2C_DEBUG1_DMA_BYTE_ENABLES_MASK	(0xf << 24)
+#define	I2C_DEBUG1_DMA_BYTE_ENABLES_OFFSET	24
+#define	I2C_DEBUG1_CLK_GEN_STATE_MASK		(0xff << 16)
+#define	I2C_DEBUG1_CLK_GEN_STATE_OFFSET		16
+#define	I2C_DEBUG1_LST_MODE_MASK		(0x3 << 9)
+#define	I2C_DEBUG1_LST_MODE_OFFSET		9
+#define	I2C_DEBUG1_LOCAL_SLAVE_TEST		(1 << 8)
+#define	I2C_DEBUG1_FORCE_CLK_ON			(1 << 4)
+#define	I2C_DEBUG1_FORCE_ABR_LOSS		(1 << 3)
+#define	I2C_DEBUG1_FORCE_RCV_ACK		(1 << 2)
+#define	I2C_DEBUG1_FORCE_I2C_DATA_OE		(1 << 1)
+#define	I2C_DEBUG1_FORCE_I2C_CLK_OE		(1 << 0)
+
+#define	I2C_VERSION_MAJOR_MASK			(0xff << 24)
+#define	I2C_VERSION_MAJOR_OFFSET		24
+#define	I2C_VERSION_MINOR_MASK			(0xff << 16)
+#define	I2C_VERSION_MINOR_OFFSET		16
+#define	I2C_VERSION_STEP_MASK			0xffff
+#define	I2C_VERSION_STEP_OFFSET			0
+
+#endif	/* __MX28_REGS_I2C_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-ocotp.h b/arch/arm/include/asm/arch-mx28/regs-ocotp.h
new file mode 100644
index 0000000..ea2fd7b
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-ocotp.h
@@ -0,0 +1,173 @@
+/*
+ * Freescale i.MX28 OCOTP Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_OCOTP_H__
+#define __MX28_REGS_OCOTP_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_ocotp_regs {
+	mx28_reg(hw_ocotp_ctrl)		/* 0x0 */
+	mx28_reg(hw_ocotp_data)		/* 0x10 */
+	mx28_reg(hw_ocotp_cust0)	/* 0x20 */
+	mx28_reg(hw_ocotp_cust1)	/* 0x30 */
+	mx28_reg(hw_ocotp_cust2)	/* 0x40 */
+	mx28_reg(hw_ocotp_cust3)	/* 0x50 */
+	mx28_reg(hw_ocotp_crypto0)	/* 0x60 */
+	mx28_reg(hw_ocotp_crypto1)	/* 0x70 */
+	mx28_reg(hw_ocotp_crypto2)	/* 0x80 */
+	mx28_reg(hw_ocotp_crypto3)	/* 0x90 */
+	mx28_reg(hw_ocotp_hwcap0)	/* 0xa0 */
+	mx28_reg(hw_ocotp_hwcap1)	/* 0xb0 */
+	mx28_reg(hw_ocotp_hwcap2)	/* 0xc0 */
+	mx28_reg(hw_ocotp_hwcap3)	/* 0xd0 */
+	mx28_reg(hw_ocotp_hwcap4)	/* 0xe0 */
+	mx28_reg(hw_ocotp_hwcap5)	/* 0xf0 */
+	mx28_reg(hw_ocotp_swcap)	/* 0x100 */
+	mx28_reg(hw_ocotp_custcap)	/* 0x110 */
+	mx28_reg(hw_ocotp_lock)		/* 0x120 */
+	mx28_reg(hw_ocotp_ops0)		/* 0x130 */
+	mx28_reg(hw_ocotp_ops1)		/* 0x140 */
+	mx28_reg(hw_ocotp_ops2)		/* 0x150 */
+	mx28_reg(hw_ocotp_ops3)		/* 0x160 */
+	mx28_reg(hw_ocotp_un0)		/* 0x170 */
+	mx28_reg(hw_ocotp_un1)		/* 0x180 */
+	mx28_reg(hw_ocotp_un2)		/* 0x190 */
+	mx28_reg(hw_ocotp_rom0)		/* 0x1a0 */
+	mx28_reg(hw_ocotp_rom1)		/* 0x1b0 */
+	mx28_reg(hw_ocotp_rom2)		/* 0x1c0 */
+	mx28_reg(hw_ocotp_rom3)		/* 0x1d0 */
+	mx28_reg(hw_ocotp_rom4)		/* 0x1e0 */
+	mx28_reg(hw_ocotp_rom5)		/* 0x1f0 */
+	mx28_reg(hw_ocotp_rom6)		/* 0x200 */
+	mx28_reg(hw_ocotp_rom7)		/* 0x210 */
+	mx28_reg(hw_ocotp_srk0)		/* 0x220 */
+	mx28_reg(hw_ocotp_srk1)		/* 0x230 */
+	mx28_reg(hw_ocotp_srk2)		/* 0x240 */
+	mx28_reg(hw_ocotp_srk3)		/* 0x250 */
+	mx28_reg(hw_ocotp_srk4)		/* 0x260 */
+	mx28_reg(hw_ocotp_srk5)		/* 0x270 */
+	mx28_reg(hw_ocotp_srk6)		/* 0x280 */
+	mx28_reg(hw_ocotp_srk7)		/* 0x290 */
+	mx28_reg(hw_ocotp_version)	/* 0x2a0 */
+};
+#endif
+
+#define	OCOTP_CTRL_WR_UNLOCK_MASK		(0xffff << 16)
+#define	OCOTP_CTRL_WR_UNLOCK_OFFSET		16
+#define	OCOTP_CTRL_WR_UNLOCK_KEY		(0x3e77 << 16)
+#define	OCOTP_CTRL_RELOAD_SHADOWS		(1 << 13)
+#define	OCOTP_CTRL_RD_BANK_OPEN			(1 << 12)
+#define	OCOTP_CTRL_ERROR			(1 << 9)
+#define	OCOTP_CTRL_BUSY				(1 << 8)
+#define	OCOTP_CTRL_ADDR_MASK			0x3f
+#define	OCOTP_CTRL_ADDR_OFFSET			0
+
+#define	OCOTP_DATA_DATA_MASK			0xffffffff
+#define	OCOTP_DATA_DATA_OFFSET			0
+
+#define	OCOTP_CUST_BITS_MASK			0xffffffff
+#define	OCOTP_CUST_BITS_OFFSET			0
+
+#define	OCOTP_CRYPTO_BITS_MASK			0xffffffff
+#define	OCOTP_CRYPTO_BITS_OFFSET		0
+
+#define	OCOTP_HWCAP_BITS_MASK			0xffffffff
+#define	OCOTP_HWCAP_BITS_OFFSET			0
+
+#define	OCOTP_SWCAP_BITS_MASK			0xffffffff
+#define	OCOTP_SWCAP_BITS_OFFSET			0
+
+#define	OCOTP_CUSTCAP_RTC_XTAL_32768_PRESENT	(1 << 2)
+#define	OCOTP_CUSTCAP_RTC_XTAL_32000_PRESENT	(1 << 1)
+
+#define	OCOTP_LOCK_ROM7				(1 << 31)
+#define	OCOTP_LOCK_ROM6				(1 << 30)
+#define	OCOTP_LOCK_ROM5				(1 << 29)
+#define	OCOTP_LOCK_ROM4				(1 << 28)
+#define	OCOTP_LOCK_ROM3				(1 << 27)
+#define	OCOTP_LOCK_ROM2				(1 << 26)
+#define	OCOTP_LOCK_ROM1				(1 << 25)
+#define	OCOTP_LOCK_ROM0				(1 << 24)
+#define	OCOTP_LOCK_HWSW_SHADOW_ALT		(1 << 23)
+#define	OCOTP_LOCK_CRYPTODCP_ALT		(1 << 22)
+#define	OCOTP_LOCK_CRYPTOKEY_ALT		(1 << 21)
+#define	OCOTP_LOCK_PIN				(1 << 20)
+#define	OCOTP_LOCK_OPS				(1 << 19)
+#define	OCOTP_LOCK_UN2				(1 << 18)
+#define	OCOTP_LOCK_UN1				(1 << 17)
+#define	OCOTP_LOCK_UN0				(1 << 16)
+#define	OCOTP_LOCK_SRK				(1 << 15)
+#define	OCOTP_LOCK_UNALLOCATED_MASK		(0x7 << 12)
+#define	OCOTP_LOCK_UNALLOCATED_OFFSET		12
+#define	OCOTP_LOCK_SRK_SHADOW			(1 << 11)
+#define	OCOTP_LOCK_ROM_SHADOW			(1 << 10)
+#define	OCOTP_LOCK_CUSTCAP			(1 << 9)
+#define	OCOTP_LOCK_HWSW				(1 << 8)
+#define	OCOTP_LOCK_CUSTCAP_SHADOW		(1 << 7)
+#define	OCOTP_LOCK_HWSW_SHADOW			(1 << 6)
+#define	OCOTP_LOCK_CRYPTODCP			(1 << 5)
+#define	OCOTP_LOCK_CRYPTOKEY			(1 << 4)
+#define	OCOTP_LOCK_CUST3			(1 << 3)
+#define	OCOTP_LOCK_CUST2			(1 << 2)
+#define	OCOTP_LOCK_CUST1			(1 << 1)
+#define	OCOTP_LOCK_CUST0			(1 << 0)
+
+#define	OCOTP_OPS_BITS_MASK			0xffffffff
+#define	OCOTP_OPS_BITS_OFFSET			0
+
+#define	OCOTP_UN_BITS_MASK			0xffffffff
+#define	OCOTP_UN_BITS_OFFSET			0
+
+#define	OCOTP_ROM_BOOT_MODE_MASK		(0xff << 24)
+#define	OCOTP_ROM_BOOT_MODE_OFFSET		24
+#define	OCOTP_ROM_SD_MMC_MODE_MASK		(0x3 << 22)
+#define	OCOTP_ROM_SD_MMC_MODE_OFFSET		22
+#define	OCOTP_ROM_SD_POWER_GATE_GPIO_MASK	(0x3 << 20)
+#define	OCOTP_ROM_SD_POWER_GATE_GPIO_OFFSET	20
+#define	OCOTP_ROM_SD_POWER_UP_DELAY_MASK	(0x3f << 14)
+#define	OCOTP_ROM_SD_POWER_UP_DELAY_OFFSET	14
+#define	OCOTP_ROM_SD_BUS_WIDTH_MASK		(0x3 << 12)
+#define	OCOTP_ROM_SD_BUS_WIDTH_OFFSET		12
+#define	OCOTP_ROM_SSP_SCK_INDEX_MASK		(0xf << 8)
+#define	OCOTP_ROM_SSP_SCK_INDEX_OFFSET		8
+#define	OCOTP_ROM_EMMC_USE_DDR			(1 << 7)
+#define	OCOTP_ROM_DISABLE_SPI_NOR_FAST_READ	(1 << 6)
+#define	OCOTP_ROM_ENABLE_USB_BOOT_SERIAL_NUM	(1 << 5)
+#define	OCOTP_ROM_ENABLE_UNENCRYPTED_BOOT	(1 << 4)
+#define	OCOTP_ROM_SD_MBR_BOOT			(1 << 3)
+
+#define	OCOTP_SRK_BITS_MASK			0xffffffff
+#define	OCOTP_SRK_BITS_OFFSET			0
+
+#define	OCOTP_VERSION_MAJOR_MASK		(0xff << 24)
+#define	OCOTP_VERSION_MAJOR_OFFSET		24
+#define	OCOTP_VERSION_MINOR_MASK		(0xff << 16)
+#define	OCOTP_VERSION_MINOR_OFFSET		16
+#define	OCOTP_VERSION_STEP_MASK			0xffff
+#define	OCOTP_VERSION_STEP_OFFSET		0
+
+#endif /* __MX28_REGS_OCOTP_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-pinctrl.h b/arch/arm/include/asm/arch-mx28/regs-pinctrl.h
new file mode 100644
index 0000000..73739ca
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-pinctrl.h
@@ -0,0 +1,1284 @@
+/*
+ * Freescale i.MX28 PINCTRL Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_PINCTRL_H__
+#define __MX28_REGS_PINCTRL_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_pinctrl_regs {
+	mx28_reg(hw_pinctrl_ctrl)		/* 0x0 */
+
+	uint32_t	reserved1[60];
+
+	mx28_reg(hw_pinctrl_muxsel0)		/* 0x100 */
+	mx28_reg(hw_pinctrl_muxsel1)		/* 0x110 */
+	mx28_reg(hw_pinctrl_muxsel2)		/* 0x120 */
+	mx28_reg(hw_pinctrl_muxsel3)		/* 0x130 */
+	mx28_reg(hw_pinctrl_muxsel4)		/* 0x140 */
+	mx28_reg(hw_pinctrl_muxsel5)		/* 0x150 */
+	mx28_reg(hw_pinctrl_muxsel6)		/* 0x160 */
+	mx28_reg(hw_pinctrl_muxsel7)		/* 0x170 */
+	mx28_reg(hw_pinctrl_muxsel8)		/* 0x180 */
+	mx28_reg(hw_pinctrl_muxsel9)		/* 0x190 */
+	mx28_reg(hw_pinctrl_muxsel10)		/* 0x1a0 */
+	mx28_reg(hw_pinctrl_muxsel11)		/* 0x1b0 */
+	mx28_reg(hw_pinctrl_muxsel12)		/* 0x1c0 */
+	mx28_reg(hw_pinctrl_muxsel13)		/* 0x1d0 */
+
+	uint32_t	reserved2[72];
+
+	mx28_reg(hw_pinctrl_drive0)		/* 0x300 */
+	mx28_reg(hw_pinctrl_drive1)		/* 0x310 */
+	mx28_reg(hw_pinctrl_drive2)		/* 0x320 */
+	mx28_reg(hw_pinctrl_drive3)		/* 0x330 */
+	mx28_reg(hw_pinctrl_drive4)		/* 0x340 */
+	mx28_reg(hw_pinctrl_drive5)		/* 0x350 */
+	mx28_reg(hw_pinctrl_drive6)		/* 0x360 */
+	mx28_reg(hw_pinctrl_drive7)		/* 0x370 */
+	mx28_reg(hw_pinctrl_drive8)		/* 0x380 */
+	mx28_reg(hw_pinctrl_drive9)		/* 0x390 */
+	mx28_reg(hw_pinctrl_drive10)		/* 0x3a0 */
+	mx28_reg(hw_pinctrl_drive11)		/* 0x3b0 */
+	mx28_reg(hw_pinctrl_drive12)		/* 0x3c0 */
+	mx28_reg(hw_pinctrl_drive13)		/* 0x3d0 */
+	mx28_reg(hw_pinctrl_drive14)		/* 0x3e0 */
+	mx28_reg(hw_pinctrl_drive15)		/* 0x3f0 */
+	mx28_reg(hw_pinctrl_drive16)		/* 0x400 */
+	mx28_reg(hw_pinctrl_drive17)		/* 0x410 */
+	mx28_reg(hw_pinctrl_drive18)		/* 0x420 */
+	mx28_reg(hw_pinctrl_drive19)		/* 0x430 */
+
+	uint32_t	reserved3[112];
+
+	mx28_reg(hw_pinctrl_pull0)		/* 0x600 */
+	mx28_reg(hw_pinctrl_pull1)		/* 0x610 */
+	mx28_reg(hw_pinctrl_pull2)		/* 0x620 */
+	mx28_reg(hw_pinctrl_pull3)		/* 0x630 */
+	mx28_reg(hw_pinctrl_pull4)		/* 0x640 */
+	mx28_reg(hw_pinctrl_pull5)		/* 0x650 */
+	mx28_reg(hw_pinctrl_pull6)		/* 0x660 */
+
+	uint32_t	reserved4[36];
+
+	mx28_reg(hw_pinctrl_dout0)		/* 0x700 */
+	mx28_reg(hw_pinctrl_dout1)		/* 0x710 */
+	mx28_reg(hw_pinctrl_dout2)		/* 0x720 */
+	mx28_reg(hw_pinctrl_dout3)		/* 0x730 */
+	mx28_reg(hw_pinctrl_dout4)		/* 0x740 */
+
+	uint32_t	reserved5[108];
+
+	mx28_reg(hw_pinctrl_din0)		/* 0x900 */
+	mx28_reg(hw_pinctrl_din1)		/* 0x910 */
+	mx28_reg(hw_pinctrl_din2)		/* 0x920 */
+	mx28_reg(hw_pinctrl_din3)		/* 0x930 */
+	mx28_reg(hw_pinctrl_din4)		/* 0x940 */
+
+	uint32_t	reserved6[108];
+
+	mx28_reg(hw_pinctrl_doe0)		/* 0xb00 */
+	mx28_reg(hw_pinctrl_doe1)		/* 0xb10 */
+	mx28_reg(hw_pinctrl_doe2)		/* 0xb20 */
+	mx28_reg(hw_pinctrl_doe3)		/* 0xb30 */
+	mx28_reg(hw_pinctrl_doe4)		/* 0xb40 */
+
+	uint32_t	reserved7[300];
+
+	mx28_reg(hw_pinctrl_pin2irq0)		/* 0x1000 */
+	mx28_reg(hw_pinctrl_pin2irq1)		/* 0x1010 */
+	mx28_reg(hw_pinctrl_pin2irq2)		/* 0x1020 */
+	mx28_reg(hw_pinctrl_pin2irq3)		/* 0x1030 */
+	mx28_reg(hw_pinctrl_pin2irq4)		/* 0x1040 */
+
+	uint32_t	reserved8[44];
+
+	mx28_reg(hw_pinctrl_irqen0)		/* 0x1100 */
+	mx28_reg(hw_pinctrl_irqen1)		/* 0x1110 */
+	mx28_reg(hw_pinctrl_irqen2)		/* 0x1120 */
+	mx28_reg(hw_pinctrl_irqen3)		/* 0x1130 */
+	mx28_reg(hw_pinctrl_irqen4)		/* 0x1140 */
+
+	uint32_t	reserved9[44];
+
+	mx28_reg(hw_pinctrl_irqlevel0)		/* 0x1200 */
+	mx28_reg(hw_pinctrl_irqlevel1)		/* 0x1210 */
+	mx28_reg(hw_pinctrl_irqlevel2)		/* 0x1220 */
+	mx28_reg(hw_pinctrl_irqlevel3)		/* 0x1230 */
+	mx28_reg(hw_pinctrl_irqlevel4)		/* 0x1240 */
+
+	uint32_t	reserved10[44];
+
+	mx28_reg(hw_pinctrl_irqpol0)		/* 0x1300 */
+	mx28_reg(hw_pinctrl_irqpol1)		/* 0x1310 */
+	mx28_reg(hw_pinctrl_irqpol2)		/* 0x1320 */
+	mx28_reg(hw_pinctrl_irqpol3)		/* 0x1330 */
+	mx28_reg(hw_pinctrl_irqpol4)		/* 0x1340 */
+
+	uint32_t	reserved11[44];
+
+	mx28_reg(hw_pinctrl_irqstat0)		/* 0x1400 */
+	mx28_reg(hw_pinctrl_irqstat1)		/* 0x1410 */
+	mx28_reg(hw_pinctrl_irqstat2)		/* 0x1420 */
+	mx28_reg(hw_pinctrl_irqstat3)		/* 0x1430 */
+	mx28_reg(hw_pinctrl_irqstat4)		/* 0x1440 */
+
+	uint32_t	reserved12[380];
+
+	mx28_reg(hw_pinctrl_emi_odt_ctrl)	/* 0x1a40 */
+
+	uint32_t	reserved13[76];
+
+	mx28_reg(hw_pinctrl_emi_ds_ctrl)	/* 0x1b80 */
+};
+#endif
+
+#define	PINCTRL_CTRL_SFTRST				(1 << 31)
+#define	PINCTRL_CTRL_CLKGATE				(1 << 30)
+#define	PINCTRL_CTRL_PRESENT4				(1 << 24)
+#define	PINCTRL_CTRL_PRESENT3				(1 << 23)
+#define	PINCTRL_CTRL_PRESENT2				(1 << 22)
+#define	PINCTRL_CTRL_PRESENT1				(1 << 21)
+#define	PINCTRL_CTRL_PRESENT0				(1 << 20)
+#define	PINCTRL_CTRL_IRQOUT4				(1 << 4)
+#define	PINCTRL_CTRL_IRQOUT3				(1 << 3)
+#define	PINCTRL_CTRL_IRQOUT2				(1 << 2)
+#define	PINCTRL_CTRL_IRQOUT1				(1 << 1)
+#define	PINCTRL_CTRL_IRQOUT0				(1 << 0)
+
+#define	PINCTRL_MUXSEL0_BANK0_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL0_BANK0_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL0_BANK0_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL0_BANK0_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL0_BANK0_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL0_BANK0_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL0_BANK0_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL0_BANK0_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL0_BANK0_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL0_BANK0_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL0_BANK0_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL0_BANK0_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL0_BANK0_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL0_BANK0_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL0_BANK0_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL0_BANK0_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL1_BANK0_PIN28_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL1_BANK0_PIN28_OFFSET		24
+#define	PINCTRL_MUXSEL1_BANK0_PIN27_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL1_BANK0_PIN27_OFFSET		22
+#define	PINCTRL_MUXSEL1_BANK0_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL1_BANK0_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL1_BANK0_PIN25_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL1_BANK0_PIN25_OFFSET		18
+#define	PINCTRL_MUXSEL1_BANK0_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL1_BANK0_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL1_BANK0_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL1_BANK0_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL1_BANK0_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL1_BANK0_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL1_BANK0_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL1_BANK0_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL1_BANK0_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL1_BANK0_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL1_BANK0_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL1_BANK0_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL1_BANK0_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL1_BANK0_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL1_BANK0_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL1_BANK0_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL1_BANK0_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL1_BANK0_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL2_BANK1_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL2_BANK1_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL2_BANK1_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL2_BANK1_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL2_BANK1_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL2_BANK1_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL2_BANK1_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL2_BANK1_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL2_BANK1_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL2_BANK1_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL2_BANK1_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL2_BANK1_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL2_BANK1_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL2_BANK1_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL2_BANK1_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL2_BANK1_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL2_BANK1_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL2_BANK1_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL2_BANK1_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL2_BANK1_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL2_BANK1_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL2_BANK1_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL2_BANK1_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL2_BANK1_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL2_BANK1_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL2_BANK1_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL2_BANK1_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL2_BANK1_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL2_BANK1_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL2_BANK1_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL2_BANK1_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL2_BANK1_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL3_BANK1_PIN31_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL3_BANK1_PIN31_OFFSET		30
+#define	PINCTRL_MUXSEL3_BANK1_PIN30_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL3_BANK1_PIN30_OFFSET		28
+#define	PINCTRL_MUXSEL3_BANK1_PIN29_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL3_BANK1_PIN29_OFFSET		26
+#define	PINCTRL_MUXSEL3_BANK1_PIN28_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL3_BANK1_PIN28_OFFSET		24
+#define	PINCTRL_MUXSEL3_BANK1_PIN27_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL3_BANK1_PIN27_OFFSET		22
+#define	PINCTRL_MUXSEL3_BANK1_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL3_BANK1_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL3_BANK1_PIN25_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL3_BANK1_PIN25_OFFSET		18
+#define	PINCTRL_MUXSEL3_BANK1_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL3_BANK1_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL3_BANK1_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL3_BANK1_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL3_BANK1_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL3_BANK1_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL3_BANK1_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL3_BANK1_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL3_BANK1_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL3_BANK1_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL3_BANK1_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL3_BANK1_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL3_BANK1_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL3_BANK1_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL3_BANK1_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL3_BANK1_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL3_BANK1_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL3_BANK1_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL4_BANK2_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL4_BANK2_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL4_BANK2_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL4_BANK2_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL4_BANK2_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL4_BANK2_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL4_BANK2_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL4_BANK2_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL4_BANK2_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL4_BANK2_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL4_BANK2_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL4_BANK2_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL4_BANK2_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL4_BANK2_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL4_BANK2_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL4_BANK2_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL4_BANK2_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL4_BANK2_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL4_BANK2_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL4_BANK2_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL4_BANK2_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL4_BANK2_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL4_BANK2_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL4_BANK2_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL4_BANK2_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL4_BANK2_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL4_BANK2_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL4_BANK2_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL4_BANK2_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL4_BANK2_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL5_BANK2_PIN27_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL5_BANK2_PIN27_OFFSET		22
+#define	PINCTRL_MUXSEL5_BANK2_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL5_BANK2_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL5_BANK2_PIN25_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL5_BANK2_PIN25_OFFSET		18
+#define	PINCTRL_MUXSEL5_BANK2_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL5_BANK2_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL5_BANK2_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL5_BANK2_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL5_BANK2_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL5_BANK2_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL5_BANK2_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL5_BANK2_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL5_BANK2_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL5_BANK2_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL5_BANK2_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL5_BANK2_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL5_BANK2_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL5_BANK2_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL6_BANK3_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL6_BANK3_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL6_BANK3_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL6_BANK3_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL6_BANK3_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL6_BANK3_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL6_BANK3_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL6_BANK3_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL6_BANK3_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL6_BANK3_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL6_BANK3_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL6_BANK3_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL6_BANK3_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL6_BANK3_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL6_BANK3_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL6_BANK3_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL6_BANK3_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL6_BANK3_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL6_BANK3_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL6_BANK3_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL6_BANK3_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL6_BANK3_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL6_BANK3_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL6_BANK3_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL6_BANK3_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL6_BANK3_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL6_BANK3_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL6_BANK3_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL6_BANK3_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL6_BANK3_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL6_BANK3_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL6_BANK3_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL7_BANK3_PIN30_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL7_BANK3_PIN30_OFFSET		28
+#define	PINCTRL_MUXSEL7_BANK3_PIN29_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL7_BANK3_PIN29_OFFSET		26
+#define	PINCTRL_MUXSEL7_BANK3_PIN28_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL7_BANK3_PIN28_OFFSET		24
+#define	PINCTRL_MUXSEL7_BANK3_PIN27_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL7_BANK3_PIN27_OFFSET		22
+#define	PINCTRL_MUXSEL7_BANK3_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL7_BANK3_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL7_BANK3_PIN25_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL7_BANK3_PIN25_OFFSET		18
+#define	PINCTRL_MUXSEL7_BANK3_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL7_BANK3_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL7_BANK3_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL7_BANK3_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL7_BANK3_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL7_BANK3_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL7_BANK3_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL7_BANK3_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL7_BANK3_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL7_BANK3_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL7_BANK3_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL7_BANK3_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL7_BANK3_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL7_BANK3_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL7_BANK3_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL7_BANK3_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL8_BANK4_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL8_BANK4_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL8_BANK4_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL8_BANK4_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL8_BANK4_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL8_BANK4_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL8_BANK4_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL8_BANK4_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL8_BANK4_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL8_BANK4_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL8_BANK4_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL8_BANK4_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL8_BANK4_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL8_BANK4_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL8_BANK4_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL8_BANK4_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL8_BANK4_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL8_BANK4_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL8_BANK4_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL8_BANK4_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL8_BANK4_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL8_BANK4_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL8_BANK4_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL8_BANK4_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL8_BANK4_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL8_BANK4_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL8_BANK4_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL8_BANK4_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL8_BANK4_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL8_BANK4_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL8_BANK4_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL8_BANK4_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL9_BANK4_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL9_BANK4_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL9_BANK4_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL9_BANK4_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL10_BANK5_PIN15_MASK		(0x3 << 30)
+#define	PINCTRL_MUXSEL10_BANK5_PIN15_OFFSET		30
+#define	PINCTRL_MUXSEL10_BANK5_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL10_BANK5_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL10_BANK5_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL10_BANK5_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL10_BANK5_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL10_BANK5_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL10_BANK5_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL10_BANK5_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL10_BANK5_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL10_BANK5_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL10_BANK5_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL10_BANK5_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL10_BANK5_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL10_BANK5_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL10_BANK5_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL10_BANK5_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL10_BANK5_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL10_BANK5_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL10_BANK5_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL10_BANK5_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL10_BANK5_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL10_BANK5_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL10_BANK5_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL10_BANK5_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL10_BANK5_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL10_BANK5_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL10_BANK5_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL10_BANK5_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL10_BANK5_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL10_BANK5_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL11_BANK5_PIN26_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL11_BANK5_PIN26_OFFSET		20
+#define	PINCTRL_MUXSEL11_BANK5_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL11_BANK5_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL11_BANK5_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL11_BANK5_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL11_BANK5_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL11_BANK5_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL11_BANK5_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL11_BANK5_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL11_BANK5_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL11_BANK5_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL11_BANK5_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL11_BANK5_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL11_BANK5_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL11_BANK5_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL11_BANK5_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL11_BANK5_PIN16_OFFSET		0
+
+#define	PINCTRL_MUXSEL12_BANK6_PIN14_MASK		(0x3 << 28)
+#define	PINCTRL_MUXSEL12_BANK6_PIN14_OFFSET		28
+#define	PINCTRL_MUXSEL12_BANK6_PIN13_MASK		(0x3 << 26)
+#define	PINCTRL_MUXSEL12_BANK6_PIN13_OFFSET		26
+#define	PINCTRL_MUXSEL12_BANK6_PIN12_MASK		(0x3 << 24)
+#define	PINCTRL_MUXSEL12_BANK6_PIN12_OFFSET		24
+#define	PINCTRL_MUXSEL12_BANK6_PIN11_MASK		(0x3 << 22)
+#define	PINCTRL_MUXSEL12_BANK6_PIN11_OFFSET		22
+#define	PINCTRL_MUXSEL12_BANK6_PIN10_MASK		(0x3 << 20)
+#define	PINCTRL_MUXSEL12_BANK6_PIN10_OFFSET		20
+#define	PINCTRL_MUXSEL12_BANK6_PIN09_MASK		(0x3 << 18)
+#define	PINCTRL_MUXSEL12_BANK6_PIN09_OFFSET		18
+#define	PINCTRL_MUXSEL12_BANK6_PIN08_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL12_BANK6_PIN08_OFFSET		16
+#define	PINCTRL_MUXSEL12_BANK6_PIN07_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL12_BANK6_PIN07_OFFSET		14
+#define	PINCTRL_MUXSEL12_BANK6_PIN06_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL12_BANK6_PIN06_OFFSET		12
+#define	PINCTRL_MUXSEL12_BANK6_PIN05_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL12_BANK6_PIN05_OFFSET		10
+#define	PINCTRL_MUXSEL12_BANK6_PIN04_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL12_BANK6_PIN04_OFFSET		8
+#define	PINCTRL_MUXSEL12_BANK6_PIN03_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL12_BANK6_PIN03_OFFSET		6
+#define	PINCTRL_MUXSEL12_BANK6_PIN02_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL12_BANK6_PIN02_OFFSET		4
+#define	PINCTRL_MUXSEL12_BANK6_PIN01_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL12_BANK6_PIN01_OFFSET		2
+#define	PINCTRL_MUXSEL12_BANK6_PIN00_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL12_BANK6_PIN00_OFFSET		0
+
+#define	PINCTRL_MUXSEL13_BANK6_PIN24_MASK		(0x3 << 16)
+#define	PINCTRL_MUXSEL13_BANK6_PIN24_OFFSET		16
+#define	PINCTRL_MUXSEL13_BANK6_PIN23_MASK		(0x3 << 14)
+#define	PINCTRL_MUXSEL13_BANK6_PIN23_OFFSET		14
+#define	PINCTRL_MUXSEL13_BANK6_PIN22_MASK		(0x3 << 12)
+#define	PINCTRL_MUXSEL13_BANK6_PIN22_OFFSET		12
+#define	PINCTRL_MUXSEL13_BANK6_PIN21_MASK		(0x3 << 10)
+#define	PINCTRL_MUXSEL13_BANK6_PIN21_OFFSET		10
+#define	PINCTRL_MUXSEL13_BANK6_PIN20_MASK		(0x3 << 8)
+#define	PINCTRL_MUXSEL13_BANK6_PIN20_OFFSET		8
+#define	PINCTRL_MUXSEL13_BANK6_PIN19_MASK		(0x3 << 6)
+#define	PINCTRL_MUXSEL13_BANK6_PIN19_OFFSET		6
+#define	PINCTRL_MUXSEL13_BANK6_PIN18_MASK		(0x3 << 4)
+#define	PINCTRL_MUXSEL13_BANK6_PIN18_OFFSET		4
+#define	PINCTRL_MUXSEL13_BANK6_PIN17_MASK		(0x3 << 2)
+#define	PINCTRL_MUXSEL13_BANK6_PIN17_OFFSET		2
+#define	PINCTRL_MUXSEL13_BANK6_PIN16_MASK		(0x3 << 0)
+#define	PINCTRL_MUXSEL13_BANK6_PIN16_OFFSET		0
+
+#define	PINCTRL_DRIVE0_BANK0_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE0_BANK0_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE0_BANK0_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE0_BANK0_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE0_BANK0_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE0_BANK0_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE0_BANK0_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE0_BANK0_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE0_BANK0_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE0_BANK0_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE0_BANK0_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE0_BANK0_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE0_BANK0_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE0_BANK0_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE0_BANK0_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE0_BANK0_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE0_BANK0_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE0_BANK0_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE0_BANK0_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE0_BANK0_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE0_BANK0_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE0_BANK0_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE0_BANK0_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE0_BANK0_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE2_BANK0_PIN23_V			(1 << 30)
+#define	PINCTRL_DRIVE2_BANK0_PIN23_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE2_BANK0_PIN23_MA_OFFSET		28
+#define	PINCTRL_DRIVE2_BANK0_PIN22_V			(1 << 26)
+#define	PINCTRL_DRIVE2_BANK0_PIN22_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE2_BANK0_PIN22_MA_OFFSET		24
+#define	PINCTRL_DRIVE2_BANK0_PIN21_V			(1 << 22)
+#define	PINCTRL_DRIVE2_BANK0_PIN21_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE2_BANK0_PIN21_MA_OFFSET		20
+#define	PINCTRL_DRIVE2_BANK0_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE2_BANK0_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE2_BANK0_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE2_BANK0_PIN19_V			(1 << 14)
+#define	PINCTRL_DRIVE2_BANK0_PIN19_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE2_BANK0_PIN19_MA_OFFSET		12
+#define	PINCTRL_DRIVE2_BANK0_PIN18_V			(1 << 10)
+#define	PINCTRL_DRIVE2_BANK0_PIN18_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE2_BANK0_PIN18_MA_OFFSET		8
+#define	PINCTRL_DRIVE2_BANK0_PIN17_V			(1 << 6)
+#define	PINCTRL_DRIVE2_BANK0_PIN17_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE2_BANK0_PIN17_MA_OFFSET		4
+#define	PINCTRL_DRIVE2_BANK0_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE2_BANK0_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE2_BANK0_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE3_BANK0_PIN28_V			(1 << 18)
+#define	PINCTRL_DRIVE3_BANK0_PIN28_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE3_BANK0_PIN28_MA_OFFSET		16
+#define	PINCTRL_DRIVE3_BANK0_PIN27_V			(1 << 14)
+#define	PINCTRL_DRIVE3_BANK0_PIN27_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE3_BANK0_PIN27_MA_OFFSET		12
+#define	PINCTRL_DRIVE3_BANK0_PIN26_V			(1 << 10)
+#define	PINCTRL_DRIVE3_BANK0_PIN26_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE3_BANK0_PIN26_MA_OFFSET		8
+#define	PINCTRL_DRIVE3_BANK0_PIN25_V			(1 << 6)
+#define	PINCTRL_DRIVE3_BANK0_PIN25_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE3_BANK0_PIN25_MA_OFFSET		4
+#define	PINCTRL_DRIVE3_BANK0_PIN24_V			(1 << 2)
+#define	PINCTRL_DRIVE3_BANK0_PIN24_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE3_BANK0_PIN24_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE4_BANK1_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE4_BANK1_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE4_BANK1_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE4_BANK1_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE4_BANK1_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE4_BANK1_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE4_BANK1_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE4_BANK1_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE4_BANK1_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE4_BANK1_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE4_BANK1_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE4_BANK1_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE4_BANK1_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE4_BANK1_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE4_BANK1_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE4_BANK1_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE4_BANK1_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE4_BANK1_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE4_BANK1_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE4_BANK1_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE4_BANK1_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE4_BANK1_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE4_BANK1_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE4_BANK1_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE5_BANK1_PIN15_V			(1 << 30)
+#define	PINCTRL_DRIVE5_BANK1_PIN15_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE5_BANK1_PIN15_MA_OFFSET		28
+#define	PINCTRL_DRIVE5_BANK1_PIN14_V			(1 << 26)
+#define	PINCTRL_DRIVE5_BANK1_PIN14_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE5_BANK1_PIN14_MA_OFFSET		24
+#define	PINCTRL_DRIVE5_BANK1_PIN13_V			(1 << 22)
+#define	PINCTRL_DRIVE5_BANK1_PIN13_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE5_BANK1_PIN13_MA_OFFSET		20
+#define	PINCTRL_DRIVE5_BANK1_PIN12_V			(1 << 18)
+#define	PINCTRL_DRIVE5_BANK1_PIN12_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE5_BANK1_PIN12_MA_OFFSET		16
+#define	PINCTRL_DRIVE5_BANK1_PIN11_V			(1 << 14)
+#define	PINCTRL_DRIVE5_BANK1_PIN11_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE5_BANK1_PIN11_MA_OFFSET		12
+#define	PINCTRL_DRIVE5_BANK1_PIN10_V			(1 << 10)
+#define	PINCTRL_DRIVE5_BANK1_PIN10_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE5_BANK1_PIN10_MA_OFFSET		8
+#define	PINCTRL_DRIVE5_BANK1_PIN09_V			(1 << 6)
+#define	PINCTRL_DRIVE5_BANK1_PIN09_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE5_BANK1_PIN09_MA_OFFSET		4
+#define	PINCTRL_DRIVE5_BANK1_PIN08_V			(1 << 2)
+#define	PINCTRL_DRIVE5_BANK1_PIN08_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE5_BANK1_PIN08_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE6_BANK1_PIN23_V			(1 << 30)
+#define	PINCTRL_DRIVE6_BANK1_PIN23_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE6_BANK1_PIN23_MA_OFFSET		28
+#define	PINCTRL_DRIVE6_BANK1_PIN22_V			(1 << 26)
+#define	PINCTRL_DRIVE6_BANK1_PIN22_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE6_BANK1_PIN22_MA_OFFSET		24
+#define	PINCTRL_DRIVE6_BANK1_PIN21_V			(1 << 22)
+#define	PINCTRL_DRIVE6_BANK1_PIN21_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE6_BANK1_PIN21_MA_OFFSET		20
+#define	PINCTRL_DRIVE6_BANK1_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE6_BANK1_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE6_BANK1_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE6_BANK1_PIN19_V			(1 << 14)
+#define	PINCTRL_DRIVE6_BANK1_PIN19_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE6_BANK1_PIN19_MA_OFFSET		12
+#define	PINCTRL_DRIVE6_BANK1_PIN18_V			(1 << 10)
+#define	PINCTRL_DRIVE6_BANK1_PIN18_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE6_BANK1_PIN18_MA_OFFSET		8
+#define	PINCTRL_DRIVE6_BANK1_PIN17_V			(1 << 6)
+#define	PINCTRL_DRIVE6_BANK1_PIN17_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE6_BANK1_PIN17_MA_OFFSET		4
+#define	PINCTRL_DRIVE6_BANK1_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE6_BANK1_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE6_BANK1_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE7_BANK1_PIN31_V			(1 << 30)
+#define	PINCTRL_DRIVE7_BANK1_PIN31_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE7_BANK1_PIN31_MA_OFFSET		28
+#define	PINCTRL_DRIVE7_BANK1_PIN30_V			(1 << 26)
+#define	PINCTRL_DRIVE7_BANK1_PIN30_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE7_BANK1_PIN30_MA_OFFSET		24
+#define	PINCTRL_DRIVE7_BANK1_PIN29_V			(1 << 22)
+#define	PINCTRL_DRIVE7_BANK1_PIN29_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE7_BANK1_PIN29_MA_OFFSET		20
+#define	PINCTRL_DRIVE7_BANK1_PIN28_V			(1 << 18)
+#define	PINCTRL_DRIVE7_BANK1_PIN28_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE7_BANK1_PIN28_MA_OFFSET		16
+#define	PINCTRL_DRIVE7_BANK1_PIN27_V			(1 << 14)
+#define	PINCTRL_DRIVE7_BANK1_PIN27_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE7_BANK1_PIN27_MA_OFFSET		12
+#define	PINCTRL_DRIVE7_BANK1_PIN26_V			(1 << 10)
+#define	PINCTRL_DRIVE7_BANK1_PIN26_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE7_BANK1_PIN26_MA_OFFSET		8
+#define	PINCTRL_DRIVE7_BANK1_PIN25_V			(1 << 6)
+#define	PINCTRL_DRIVE7_BANK1_PIN25_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE7_BANK1_PIN25_MA_OFFSET		4
+#define	PINCTRL_DRIVE7_BANK1_PIN24_V			(1 << 2)
+#define	PINCTRL_DRIVE7_BANK1_PIN24_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE7_BANK1_PIN24_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE8_BANK2_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE8_BANK2_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE8_BANK2_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE8_BANK2_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE8_BANK2_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE8_BANK2_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE8_BANK2_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE8_BANK2_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE8_BANK2_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE8_BANK2_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE8_BANK2_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE8_BANK2_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE8_BANK2_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE8_BANK2_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE8_BANK2_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE8_BANK2_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE8_BANK2_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE8_BANK2_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE8_BANK2_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE8_BANK2_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE8_BANK2_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE8_BANK2_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE8_BANK2_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE8_BANK2_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE9_BANK2_PIN15_V			(1 << 30)
+#define	PINCTRL_DRIVE9_BANK2_PIN15_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE9_BANK2_PIN15_MA_OFFSET		28
+#define	PINCTRL_DRIVE9_BANK2_PIN14_V			(1 << 26)
+#define	PINCTRL_DRIVE9_BANK2_PIN14_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE9_BANK2_PIN14_MA_OFFSET		24
+#define	PINCTRL_DRIVE9_BANK2_PIN13_V			(1 << 22)
+#define	PINCTRL_DRIVE9_BANK2_PIN13_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE9_BANK2_PIN13_MA_OFFSET		20
+#define	PINCTRL_DRIVE9_BANK2_PIN12_V			(1 << 18)
+#define	PINCTRL_DRIVE9_BANK2_PIN12_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE9_BANK2_PIN12_MA_OFFSET		16
+#define	PINCTRL_DRIVE9_BANK2_PIN10_V			(1 << 10)
+#define	PINCTRL_DRIVE9_BANK2_PIN10_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE9_BANK2_PIN10_MA_OFFSET		8
+#define	PINCTRL_DRIVE9_BANK2_PIN09_V			(1 << 6)
+#define	PINCTRL_DRIVE9_BANK2_PIN09_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE9_BANK2_PIN09_MA_OFFSET		4
+#define	PINCTRL_DRIVE9_BANK2_PIN08_V			(1 << 2)
+#define	PINCTRL_DRIVE9_BANK2_PIN08_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE9_BANK2_PIN08_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE10_BANK2_PIN21_V			(1 << 22)
+#define	PINCTRL_DRIVE10_BANK2_PIN21_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE10_BANK2_PIN21_MA_OFFSET		20
+#define	PINCTRL_DRIVE10_BANK2_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE10_BANK2_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE10_BANK2_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE10_BANK2_PIN19_V			(1 << 14)
+#define	PINCTRL_DRIVE10_BANK2_PIN19_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE10_BANK2_PIN19_MA_OFFSET		12
+#define	PINCTRL_DRIVE10_BANK2_PIN18_V			(1 << 10)
+#define	PINCTRL_DRIVE10_BANK2_PIN18_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE10_BANK2_PIN18_MA_OFFSET		8
+#define	PINCTRL_DRIVE10_BANK2_PIN17_V			(1 << 6)
+#define	PINCTRL_DRIVE10_BANK2_PIN17_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE10_BANK2_PIN17_MA_OFFSET		4
+#define	PINCTRL_DRIVE10_BANK2_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE10_BANK2_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE10_BANK2_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE11_BANK2_PIN27_V			(1 << 14)
+#define	PINCTRL_DRIVE11_BANK2_PIN27_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE11_BANK2_PIN27_MA_OFFSET		12
+#define	PINCTRL_DRIVE11_BANK2_PIN26_V			(1 << 10)
+#define	PINCTRL_DRIVE11_BANK2_PIN26_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE11_BANK2_PIN26_MA_OFFSET		8
+#define	PINCTRL_DRIVE11_BANK2_PIN25_V			(1 << 6)
+#define	PINCTRL_DRIVE11_BANK2_PIN25_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE11_BANK2_PIN25_MA_OFFSET		4
+#define	PINCTRL_DRIVE11_BANK2_PIN24_V			(1 << 2)
+#define	PINCTRL_DRIVE11_BANK2_PIN24_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE11_BANK2_PIN24_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE12_BANK3_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE12_BANK3_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE12_BANK3_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE12_BANK3_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE12_BANK3_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE12_BANK3_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE12_BANK3_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE12_BANK3_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE12_BANK3_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE12_BANK3_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE12_BANK3_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE12_BANK3_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE12_BANK3_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE12_BANK3_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE12_BANK3_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE12_BANK3_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE12_BANK3_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE12_BANK3_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE12_BANK3_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE12_BANK3_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE12_BANK3_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE12_BANK3_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE12_BANK3_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE12_BANK3_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE13_BANK3_PIN15_V			(1 << 30)
+#define	PINCTRL_DRIVE13_BANK3_PIN15_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE13_BANK3_PIN15_MA_OFFSET		28
+#define	PINCTRL_DRIVE13_BANK3_PIN14_V			(1 << 26)
+#define	PINCTRL_DRIVE13_BANK3_PIN14_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE13_BANK3_PIN14_MA_OFFSET		24
+#define	PINCTRL_DRIVE13_BANK3_PIN13_V			(1 << 22)
+#define	PINCTRL_DRIVE13_BANK3_PIN13_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE13_BANK3_PIN13_MA_OFFSET		20
+#define	PINCTRL_DRIVE13_BANK3_PIN12_V			(1 << 18)
+#define	PINCTRL_DRIVE13_BANK3_PIN12_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE13_BANK3_PIN12_MA_OFFSET		16
+#define	PINCTRL_DRIVE13_BANK3_PIN11_V			(1 << 14)
+#define	PINCTRL_DRIVE13_BANK3_PIN11_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE13_BANK3_PIN11_MA_OFFSET		12
+#define	PINCTRL_DRIVE13_BANK3_PIN10_V			(1 << 10)
+#define	PINCTRL_DRIVE13_BANK3_PIN10_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE13_BANK3_PIN10_MA_OFFSET		8
+#define	PINCTRL_DRIVE13_BANK3_PIN09_V			(1 << 6)
+#define	PINCTRL_DRIVE13_BANK3_PIN09_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE13_BANK3_PIN09_MA_OFFSET		4
+#define	PINCTRL_DRIVE13_BANK3_PIN08_V			(1 << 2)
+#define	PINCTRL_DRIVE13_BANK3_PIN08_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE13_BANK3_PIN08_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE14_BANK3_PIN23_V			(1 << 30)
+#define	PINCTRL_DRIVE14_BANK3_PIN23_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE14_BANK3_PIN23_MA_OFFSET		28
+#define	PINCTRL_DRIVE14_BANK3_PIN22_V			(1 << 26)
+#define	PINCTRL_DRIVE14_BANK3_PIN22_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE14_BANK3_PIN22_MA_OFFSET		24
+#define	PINCTRL_DRIVE14_BANK3_PIN21_V			(1 << 22)
+#define	PINCTRL_DRIVE14_BANK3_PIN21_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE14_BANK3_PIN21_MA_OFFSET		20
+#define	PINCTRL_DRIVE14_BANK3_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE14_BANK3_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE14_BANK3_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE14_BANK3_PIN18_V			(1 << 10)
+#define	PINCTRL_DRIVE14_BANK3_PIN18_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE14_BANK3_PIN18_MA_OFFSET		8
+#define	PINCTRL_DRIVE14_BANK3_PIN17_V			(1 << 6)
+#define	PINCTRL_DRIVE14_BANK3_PIN17_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE14_BANK3_PIN17_MA_OFFSET		4
+#define	PINCTRL_DRIVE14_BANK3_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE14_BANK3_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE14_BANK3_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE15_BANK3_PIN30_V			(1 << 26)
+#define	PINCTRL_DRIVE15_BANK3_PIN30_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE15_BANK3_PIN30_MA_OFFSET		24
+#define	PINCTRL_DRIVE15_BANK3_PIN29_V			(1 << 22)
+#define	PINCTRL_DRIVE15_BANK3_PIN29_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE15_BANK3_PIN29_MA_OFFSET		20
+#define	PINCTRL_DRIVE15_BANK3_PIN28_V			(1 << 18)
+#define	PINCTRL_DRIVE15_BANK3_PIN28_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE15_BANK3_PIN28_MA_OFFSET		16
+#define	PINCTRL_DRIVE15_BANK3_PIN27_V			(1 << 14)
+#define	PINCTRL_DRIVE15_BANK3_PIN27_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE15_BANK3_PIN27_MA_OFFSET		12
+#define	PINCTRL_DRIVE15_BANK3_PIN26_V			(1 << 10)
+#define	PINCTRL_DRIVE15_BANK3_PIN26_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE15_BANK3_PIN26_MA_OFFSET		8
+#define	PINCTRL_DRIVE15_BANK3_PIN25_V			(1 << 6)
+#define	PINCTRL_DRIVE15_BANK3_PIN25_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE15_BANK3_PIN25_MA_OFFSET		4
+#define	PINCTRL_DRIVE15_BANK3_PIN24_V			(1 << 2)
+#define	PINCTRL_DRIVE15_BANK3_PIN24_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE15_BANK3_PIN24_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE16_BANK4_PIN07_V			(1 << 30)
+#define	PINCTRL_DRIVE16_BANK4_PIN07_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE16_BANK4_PIN07_MA_OFFSET		28
+#define	PINCTRL_DRIVE16_BANK4_PIN06_V			(1 << 26)
+#define	PINCTRL_DRIVE16_BANK4_PIN06_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE16_BANK4_PIN06_MA_OFFSET		24
+#define	PINCTRL_DRIVE16_BANK4_PIN05_V			(1 << 22)
+#define	PINCTRL_DRIVE16_BANK4_PIN05_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE16_BANK4_PIN05_MA_OFFSET		20
+#define	PINCTRL_DRIVE16_BANK4_PIN04_V			(1 << 18)
+#define	PINCTRL_DRIVE16_BANK4_PIN04_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE16_BANK4_PIN04_MA_OFFSET		16
+#define	PINCTRL_DRIVE16_BANK4_PIN03_V			(1 << 14)
+#define	PINCTRL_DRIVE16_BANK4_PIN03_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE16_BANK4_PIN03_MA_OFFSET		12
+#define	PINCTRL_DRIVE16_BANK4_PIN02_V			(1 << 10)
+#define	PINCTRL_DRIVE16_BANK4_PIN02_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE16_BANK4_PIN02_MA_OFFSET		8
+#define	PINCTRL_DRIVE16_BANK4_PIN01_V			(1 << 6)
+#define	PINCTRL_DRIVE16_BANK4_PIN01_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE16_BANK4_PIN01_MA_OFFSET		4
+#define	PINCTRL_DRIVE16_BANK4_PIN00_V			(1 << 2)
+#define	PINCTRL_DRIVE16_BANK4_PIN00_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE16_BANK4_PIN00_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE17_BANK4_PIN15_V			(1 << 30)
+#define	PINCTRL_DRIVE17_BANK4_PIN15_MA_MASK		(0x3 << 28)
+#define	PINCTRL_DRIVE17_BANK4_PIN15_MA_OFFSET		28
+#define	PINCTRL_DRIVE17_BANK4_PIN14_V			(1 << 26)
+#define	PINCTRL_DRIVE17_BANK4_PIN14_MA_MASK		(0x3 << 24)
+#define	PINCTRL_DRIVE17_BANK4_PIN14_MA_OFFSET		24
+#define	PINCTRL_DRIVE17_BANK4_PIN13_V			(1 << 22)
+#define	PINCTRL_DRIVE17_BANK4_PIN13_MA_MASK		(0x3 << 20)
+#define	PINCTRL_DRIVE17_BANK4_PIN13_MA_OFFSET		20
+#define	PINCTRL_DRIVE17_BANK4_PIN12_V			(1 << 18)
+#define	PINCTRL_DRIVE17_BANK4_PIN12_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE17_BANK4_PIN12_MA_OFFSET		16
+#define	PINCTRL_DRIVE17_BANK4_PIN11_V			(1 << 14)
+#define	PINCTRL_DRIVE17_BANK4_PIN11_MA_MASK		(0x3 << 12)
+#define	PINCTRL_DRIVE17_BANK4_PIN11_MA_OFFSET		12
+#define	PINCTRL_DRIVE17_BANK4_PIN10_V			(1 << 10)
+#define	PINCTRL_DRIVE17_BANK4_PIN10_MA_MASK		(0x3 << 8)
+#define	PINCTRL_DRIVE17_BANK4_PIN10_MA_OFFSET		8
+#define	PINCTRL_DRIVE17_BANK4_PIN09_V			(1 << 6)
+#define	PINCTRL_DRIVE17_BANK4_PIN09_MA_MASK		(0x3 << 4)
+#define	PINCTRL_DRIVE17_BANK4_PIN09_MA_OFFSET		4
+#define	PINCTRL_DRIVE17_BANK4_PIN08_V			(1 << 2)
+#define	PINCTRL_DRIVE17_BANK4_PIN08_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE17_BANK4_PIN08_MA_OFFSET		0
+
+#define	PINCTRL_DRIVE18_BANK4_PIN20_V			(1 << 18)
+#define	PINCTRL_DRIVE18_BANK4_PIN20_MA_MASK		(0x3 << 16)
+#define	PINCTRL_DRIVE18_BANK4_PIN20_MA_OFFSET		16
+#define	PINCTRL_DRIVE18_BANK4_PIN16_V			(1 << 2)
+#define	PINCTRL_DRIVE18_BANK4_PIN16_MA_MASK		(0x3 << 0)
+#define	PINCTRL_DRIVE18_BANK4_PIN16_MA_OFFSET		0
+
+#define	PINCTRL_PULL0_BANK0_PIN28			(1 << 28)
+#define	PINCTRL_PULL0_BANK0_PIN27			(1 << 27)
+#define	PINCTRL_PULL0_BANK0_PIN26			(1 << 26)
+#define	PINCTRL_PULL0_BANK0_PIN25			(1 << 25)
+#define	PINCTRL_PULL0_BANK0_PIN24			(1 << 24)
+#define	PINCTRL_PULL0_BANK0_PIN23			(1 << 23)
+#define	PINCTRL_PULL0_BANK0_PIN22			(1 << 22)
+#define	PINCTRL_PULL0_BANK0_PIN21			(1 << 21)
+#define	PINCTRL_PULL0_BANK0_PIN20			(1 << 20)
+#define	PINCTRL_PULL0_BANK0_PIN19			(1 << 19)
+#define	PINCTRL_PULL0_BANK0_PIN18			(1 << 18)
+#define	PINCTRL_PULL0_BANK0_PIN17			(1 << 17)
+#define	PINCTRL_PULL0_BANK0_PIN16			(1 << 16)
+#define	PINCTRL_PULL0_BANK0_PIN07			(1 << 7)
+#define	PINCTRL_PULL0_BANK0_PIN06			(1 << 6)
+#define	PINCTRL_PULL0_BANK0_PIN05			(1 << 5)
+#define	PINCTRL_PULL0_BANK0_PIN04			(1 << 4)
+#define	PINCTRL_PULL0_BANK0_PIN03			(1 << 3)
+#define	PINCTRL_PULL0_BANK0_PIN02			(1 << 2)
+#define	PINCTRL_PULL0_BANK0_PIN01			(1 << 1)
+#define	PINCTRL_PULL0_BANK0_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL1_BANK1_PIN31			(1 << 31)
+#define	PINCTRL_PULL1_BANK1_PIN30			(1 << 30)
+#define	PINCTRL_PULL1_BANK1_PIN29			(1 << 29)
+#define	PINCTRL_PULL1_BANK1_PIN28			(1 << 28)
+#define	PINCTRL_PULL1_BANK1_PIN27			(1 << 27)
+#define	PINCTRL_PULL1_BANK1_PIN26			(1 << 26)
+#define	PINCTRL_PULL1_BANK1_PIN25			(1 << 25)
+#define	PINCTRL_PULL1_BANK1_PIN24			(1 << 24)
+#define	PINCTRL_PULL1_BANK1_PIN23			(1 << 23)
+#define	PINCTRL_PULL1_BANK1_PIN22			(1 << 22)
+#define	PINCTRL_PULL1_BANK1_PIN21			(1 << 21)
+#define	PINCTRL_PULL1_BANK1_PIN20			(1 << 20)
+#define	PINCTRL_PULL1_BANK1_PIN19			(1 << 19)
+#define	PINCTRL_PULL1_BANK1_PIN18			(1 << 18)
+#define	PINCTRL_PULL1_BANK1_PIN17			(1 << 17)
+#define	PINCTRL_PULL1_BANK1_PIN16			(1 << 16)
+#define	PINCTRL_PULL1_BANK1_PIN15			(1 << 15)
+#define	PINCTRL_PULL1_BANK1_PIN14			(1 << 14)
+#define	PINCTRL_PULL1_BANK1_PIN13			(1 << 13)
+#define	PINCTRL_PULL1_BANK1_PIN12			(1 << 12)
+#define	PINCTRL_PULL1_BANK1_PIN11			(1 << 11)
+#define	PINCTRL_PULL1_BANK1_PIN10			(1 << 10)
+#define	PINCTRL_PULL1_BANK1_PIN09			(1 << 9)
+#define	PINCTRL_PULL1_BANK1_PIN08			(1 << 8)
+#define	PINCTRL_PULL1_BANK1_PIN07			(1 << 7)
+#define	PINCTRL_PULL1_BANK1_PIN06			(1 << 6)
+#define	PINCTRL_PULL1_BANK1_PIN05			(1 << 5)
+#define	PINCTRL_PULL1_BANK1_PIN04			(1 << 4)
+#define	PINCTRL_PULL1_BANK1_PIN03			(1 << 3)
+#define	PINCTRL_PULL1_BANK1_PIN02			(1 << 2)
+#define	PINCTRL_PULL1_BANK1_PIN01			(1 << 1)
+#define	PINCTRL_PULL1_BANK1_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL2_BANK2_PIN27			(1 << 27)
+#define	PINCTRL_PULL2_BANK2_PIN26			(1 << 26)
+#define	PINCTRL_PULL2_BANK2_PIN25			(1 << 25)
+#define	PINCTRL_PULL2_BANK2_PIN24			(1 << 24)
+#define	PINCTRL_PULL2_BANK2_PIN21			(1 << 21)
+#define	PINCTRL_PULL2_BANK2_PIN20			(1 << 20)
+#define	PINCTRL_PULL2_BANK2_PIN19			(1 << 19)
+#define	PINCTRL_PULL2_BANK2_PIN18			(1 << 18)
+#define	PINCTRL_PULL2_BANK2_PIN17			(1 << 17)
+#define	PINCTRL_PULL2_BANK2_PIN16			(1 << 16)
+#define	PINCTRL_PULL2_BANK2_PIN15			(1 << 15)
+#define	PINCTRL_PULL2_BANK2_PIN14			(1 << 14)
+#define	PINCTRL_PULL2_BANK2_PIN13			(1 << 13)
+#define	PINCTRL_PULL2_BANK2_PIN12			(1 << 12)
+#define	PINCTRL_PULL2_BANK2_PIN10			(1 << 10)
+#define	PINCTRL_PULL2_BANK2_PIN09			(1 << 9)
+#define	PINCTRL_PULL2_BANK2_PIN08			(1 << 8)
+#define	PINCTRL_PULL2_BANK2_PIN07			(1 << 7)
+#define	PINCTRL_PULL2_BANK2_PIN06			(1 << 6)
+#define	PINCTRL_PULL2_BANK2_PIN05			(1 << 5)
+#define	PINCTRL_PULL2_BANK2_PIN04			(1 << 4)
+#define	PINCTRL_PULL2_BANK2_PIN03			(1 << 3)
+#define	PINCTRL_PULL2_BANK2_PIN02			(1 << 2)
+#define	PINCTRL_PULL2_BANK2_PIN01			(1 << 1)
+#define	PINCTRL_PULL2_BANK2_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL3_BANK3_PIN30			(1 << 30)
+#define	PINCTRL_PULL3_BANK3_PIN29			(1 << 29)
+#define	PINCTRL_PULL3_BANK3_PIN28			(1 << 28)
+#define	PINCTRL_PULL3_BANK3_PIN27			(1 << 27)
+#define	PINCTRL_PULL3_BANK3_PIN26			(1 << 26)
+#define	PINCTRL_PULL3_BANK3_PIN25			(1 << 25)
+#define	PINCTRL_PULL3_BANK3_PIN24			(1 << 24)
+#define	PINCTRL_PULL3_BANK3_PIN23			(1 << 23)
+#define	PINCTRL_PULL3_BANK3_PIN22			(1 << 22)
+#define	PINCTRL_PULL3_BANK3_PIN21			(1 << 21)
+#define	PINCTRL_PULL3_BANK3_PIN20			(1 << 20)
+#define	PINCTRL_PULL3_BANK3_PIN18			(1 << 18)
+#define	PINCTRL_PULL3_BANK3_PIN17			(1 << 17)
+#define	PINCTRL_PULL3_BANK3_PIN16			(1 << 16)
+#define	PINCTRL_PULL3_BANK3_PIN15			(1 << 15)
+#define	PINCTRL_PULL3_BANK3_PIN14			(1 << 14)
+#define	PINCTRL_PULL3_BANK3_PIN13			(1 << 13)
+#define	PINCTRL_PULL3_BANK3_PIN12			(1 << 12)
+#define	PINCTRL_PULL3_BANK3_PIN11			(1 << 11)
+#define	PINCTRL_PULL3_BANK3_PIN10			(1 << 10)
+#define	PINCTRL_PULL3_BANK3_PIN09			(1 << 9)
+#define	PINCTRL_PULL3_BANK3_PIN08			(1 << 8)
+#define	PINCTRL_PULL3_BANK3_PIN07			(1 << 7)
+#define	PINCTRL_PULL3_BANK3_PIN06			(1 << 6)
+#define	PINCTRL_PULL3_BANK3_PIN05			(1 << 5)
+#define	PINCTRL_PULL3_BANK3_PIN04			(1 << 4)
+#define	PINCTRL_PULL3_BANK3_PIN03			(1 << 3)
+#define	PINCTRL_PULL3_BANK3_PIN02			(1 << 2)
+#define	PINCTRL_PULL3_BANK3_PIN01			(1 << 1)
+#define	PINCTRL_PULL3_BANK3_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL4_BANK4_PIN20			(1 << 20)
+#define	PINCTRL_PULL4_BANK4_PIN16			(1 << 16)
+#define	PINCTRL_PULL4_BANK4_PIN15			(1 << 15)
+#define	PINCTRL_PULL4_BANK4_PIN14			(1 << 14)
+#define	PINCTRL_PULL4_BANK4_PIN13			(1 << 13)
+#define	PINCTRL_PULL4_BANK4_PIN12			(1 << 12)
+#define	PINCTRL_PULL4_BANK4_PIN11			(1 << 11)
+#define	PINCTRL_PULL4_BANK4_PIN10			(1 << 10)
+#define	PINCTRL_PULL4_BANK4_PIN09			(1 << 9)
+#define	PINCTRL_PULL4_BANK4_PIN08			(1 << 8)
+#define	PINCTRL_PULL4_BANK4_PIN07			(1 << 7)
+#define	PINCTRL_PULL4_BANK4_PIN06			(1 << 6)
+#define	PINCTRL_PULL4_BANK4_PIN05			(1 << 5)
+#define	PINCTRL_PULL4_BANK4_PIN04			(1 << 4)
+#define	PINCTRL_PULL4_BANK4_PIN03			(1 << 3)
+#define	PINCTRL_PULL4_BANK4_PIN02			(1 << 2)
+#define	PINCTRL_PULL4_BANK4_PIN01			(1 << 1)
+#define	PINCTRL_PULL4_BANK4_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL5_BANK5_PIN26			(1 << 26)
+#define	PINCTRL_PULL5_BANK5_PIN23			(1 << 23)
+#define	PINCTRL_PULL5_BANK5_PIN22			(1 << 22)
+#define	PINCTRL_PULL5_BANK5_PIN21			(1 << 21)
+#define	PINCTRL_PULL5_BANK5_PIN20			(1 << 20)
+#define	PINCTRL_PULL5_BANK5_PIN19			(1 << 19)
+#define	PINCTRL_PULL5_BANK5_PIN18			(1 << 18)
+#define	PINCTRL_PULL5_BANK5_PIN17			(1 << 17)
+#define	PINCTRL_PULL5_BANK5_PIN16			(1 << 16)
+#define	PINCTRL_PULL5_BANK5_PIN15			(1 << 15)
+#define	PINCTRL_PULL5_BANK5_PIN14			(1 << 14)
+#define	PINCTRL_PULL5_BANK5_PIN13			(1 << 13)
+#define	PINCTRL_PULL5_BANK5_PIN12			(1 << 12)
+#define	PINCTRL_PULL5_BANK5_PIN11			(1 << 11)
+#define	PINCTRL_PULL5_BANK5_PIN10			(1 << 10)
+#define	PINCTRL_PULL5_BANK5_PIN09			(1 << 9)
+#define	PINCTRL_PULL5_BANK5_PIN08			(1 << 8)
+#define	PINCTRL_PULL5_BANK5_PIN07			(1 << 7)
+#define	PINCTRL_PULL5_BANK5_PIN06			(1 << 6)
+#define	PINCTRL_PULL5_BANK5_PIN05			(1 << 5)
+#define	PINCTRL_PULL5_BANK5_PIN04			(1 << 4)
+#define	PINCTRL_PULL5_BANK5_PIN03			(1 << 3)
+#define	PINCTRL_PULL5_BANK5_PIN02			(1 << 2)
+#define	PINCTRL_PULL5_BANK5_PIN01			(1 << 1)
+#define	PINCTRL_PULL5_BANK5_PIN00			(1 << 0)
+
+#define	PINCTRL_PULL6_BANK6_PIN24			(1 << 24)
+#define	PINCTRL_PULL6_BANK6_PIN23			(1 << 23)
+#define	PINCTRL_PULL6_BANK6_PIN22			(1 << 22)
+#define	PINCTRL_PULL6_BANK6_PIN21			(1 << 21)
+#define	PINCTRL_PULL6_BANK6_PIN20			(1 << 20)
+#define	PINCTRL_PULL6_BANK6_PIN19			(1 << 19)
+#define	PINCTRL_PULL6_BANK6_PIN18			(1 << 18)
+#define	PINCTRL_PULL6_BANK6_PIN17			(1 << 17)
+#define	PINCTRL_PULL6_BANK6_PIN16			(1 << 16)
+#define	PINCTRL_PULL6_BANK6_PIN14			(1 << 14)
+#define	PINCTRL_PULL6_BANK6_PIN13			(1 << 13)
+#define	PINCTRL_PULL6_BANK6_PIN12			(1 << 12)
+#define	PINCTRL_PULL6_BANK6_PIN11			(1 << 11)
+#define	PINCTRL_PULL6_BANK6_PIN10			(1 << 10)
+#define	PINCTRL_PULL6_BANK6_PIN09			(1 << 9)
+#define	PINCTRL_PULL6_BANK6_PIN08			(1 << 8)
+#define	PINCTRL_PULL6_BANK6_PIN07			(1 << 7)
+#define	PINCTRL_PULL6_BANK6_PIN06			(1 << 6)
+#define	PINCTRL_PULL6_BANK6_PIN05			(1 << 5)
+#define	PINCTRL_PULL6_BANK6_PIN04			(1 << 4)
+#define	PINCTRL_PULL6_BANK6_PIN03			(1 << 3)
+#define	PINCTRL_PULL6_BANK6_PIN02			(1 << 2)
+#define	PINCTRL_PULL6_BANK6_PIN01			(1 << 1)
+#define	PINCTRL_PULL6_BANK6_PIN00			(1 << 0)
+
+#define	PINCTRL_DOUT0_DOUT_MASK				0x1fffffff
+#define	PINCTRL_DOUT0_DOUT_OFFSET			0
+
+#define	PINCTRL_DOUT1_DOUT_MASK				0xffffffff
+#define	PINCTRL_DOUT1_DOUT_OFFSET			0
+
+#define	PINCTRL_DOUT2_DOUT_MASK				0xfffffff
+#define	PINCTRL_DOUT2_DOUT_OFFSET			0
+
+#define	PINCTRL_DOUT3_DOUT_MASK				0x7fffffff
+#define	PINCTRL_DOUT3_DOUT_OFFSET			0
+
+#define	PINCTRL_DOUT4_DOUT_MASK				0x1fffff
+#define	PINCTRL_DOUT4_DOUT_OFFSET			0
+
+#define	PINCTRL_DIN0_DIN_MASK				0x1fffffff
+#define	PINCTRL_DIN0_DIN_OFFSET				0
+
+#define	PINCTRL_DIN1_DIN_MASK				0xffffffff
+#define	PINCTRL_DIN1_DIN_OFFSET				0
+
+#define	PINCTRL_DIN2_DIN_MASK				0xfffffff
+#define	PINCTRL_DIN2_DIN_OFFSET				0
+
+#define	PINCTRL_DIN3_DIN_MASK				0x7fffffff
+#define	PINCTRL_DIN3_DIN_OFFSET				0
+
+#define	PINCTRL_DIN4_DIN_MASK				0x1fffff
+#define	PINCTRL_DIN4_DIN_OFFSET				0
+
+#define	PINCTRL_DOE0_DOE_MASK				0x1fffffff
+#define	PINCTRL_DOE0_DOE_OFFSET				0
+
+#define	PINCTRL_DOE1_DOE_MASK				0xffffffff
+#define	PINCTRL_DOE1_DOE_OFFSET				0
+
+#define	PINCTRL_DOE2_DOE_MASK				0xfffffff
+#define	PINCTRL_DOE2_DOE_OFFSET				0
+
+#define	PINCTRL_DOE3_DOE_MASK				0x7fffffff
+#define	PINCTRL_DOE3_DOE_OFFSET				0
+
+#define	PINCTRL_DOE4_DOE_MASK				0x1fffff
+#define	PINCTRL_DOE4_DOE_OFFSET				0
+
+#define	PINCTRL_PIN2IRQ0_PIN2IRQ_MASK			0x1fffffff
+#define	PINCTRL_PIN2IRQ0_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_PIN2IRQ1_PIN2IRQ_MASK			0xffffffff
+#define	PINCTRL_PIN2IRQ1_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_PIN2IRQ2_PIN2IRQ_MASK			0xfffffff
+#define	PINCTRL_PIN2IRQ2_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_PIN2IRQ3_PIN2IRQ_MASK			0x7fffffff
+#define	PINCTRL_PIN2IRQ3_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_PIN2IRQ4_PIN2IRQ_MASK			0x1fffff
+#define	PINCTRL_PIN2IRQ4_PIN2IRQ_OFFSET			0
+
+#define	PINCTRL_IRQEN0_IRQEN_MASK			0x1fffffff
+#define	PINCTRL_IRQEN0_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQEN1_IRQEN_MASK			0xffffffff
+#define	PINCTRL_IRQEN1_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQEN2_IRQEN_MASK			0xfffffff
+#define	PINCTRL_IRQEN2_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQEN3_IRQEN_MASK			0x7fffffff
+#define	PINCTRL_IRQEN3_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQEN4_IRQEN_MASK			0x1fffff
+#define	PINCTRL_IRQEN4_IRQEN_OFFSET			0
+
+#define	PINCTRL_IRQLEVEL0_IRQLEVEL_MASK			0x1fffffff
+#define	PINCTRL_IRQLEVEL0_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQLEVEL1_IRQLEVEL_MASK			0xffffffff
+#define	PINCTRL_IRQLEVEL1_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQLEVEL2_IRQLEVEL_MASK			0xfffffff
+#define	PINCTRL_IRQLEVEL2_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQLEVEL3_IRQLEVEL_MASK			0x7fffffff
+#define	PINCTRL_IRQLEVEL3_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQLEVEL4_IRQLEVEL_MASK			0x1fffff
+#define	PINCTRL_IRQLEVEL4_IRQLEVEL_OFFSET		0
+
+#define	PINCTRL_IRQPOL0_IRQPOL_MASK			0x1fffffff
+#define	PINCTRL_IRQPOL0_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQPOL1_IRQPOL_MASK			0xffffffff
+#define	PINCTRL_IRQPOL1_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQPOL2_IRQPOL_MASK			0xfffffff
+#define	PINCTRL_IRQPOL2_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQPOL3_IRQPOL_MASK			0x7fffffff
+#define	PINCTRL_IRQPOL3_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQPOL4_IRQPOL_MASK			0x1fffff
+#define	PINCTRL_IRQPOL4_IRQPOL_OFFSET			0
+
+#define	PINCTRL_IRQSTAT0_IRQSTAT_MASK			0x1fffffff
+#define	PINCTRL_IRQSTAT0_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_IRQSTAT1_IRQSTAT_MASK			0xffffffff
+#define	PINCTRL_IRQSTAT1_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_IRQSTAT2_IRQSTAT_MASK			0xfffffff
+#define	PINCTRL_IRQSTAT2_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_IRQSTAT3_IRQSTAT_MASK			0x7fffffff
+#define	PINCTRL_IRQSTAT3_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_IRQSTAT4_IRQSTAT_MASK			0x1fffff
+#define	PINCTRL_IRQSTAT4_IRQSTAT_OFFSET			0
+
+#define	PINCTRL_EMI_ODT_CTRL_ADDRESS_CALIB_MASK		(0x3 << 26)
+#define	PINCTRL_EMI_ODT_CTRL_ADDRESS_CALIB_OFFSET	26
+#define	PINCTRL_EMI_ODT_CTRL_ADDRESS_TLOAD_MASK		(0x3 << 24)
+#define	PINCTRL_EMI_ODT_CTRL_ADDRESS_TLOAD_OFFSET	24
+#define	PINCTRL_EMI_ODT_CTRL_CONTROL_CALIB_MASK		(0x3 << 22)
+#define	PINCTRL_EMI_ODT_CTRL_CONTROL_CALIB_OFFSET	22
+#define	PINCTRL_EMI_ODT_CTRL_CONTROL_TLOAD_MASK		(0x3 << 20)
+#define	PINCTRL_EMI_ODT_CTRL_CONTROL_TLOAD_OFFSET	20
+#define	PINCTRL_EMI_ODT_CTRL_DUALPAD_CALIB_MASK		(0x3 << 18)
+#define	PINCTRL_EMI_ODT_CTRL_DUALPAD_CALIB_OFFSET	18
+#define	PINCTRL_EMI_ODT_CTRL_DUALPAD_TLOAD_MASK		(0x3 << 16)
+#define	PINCTRL_EMI_ODT_CTRL_DUALPAD_TLOAD_OFFSET	16
+#define	PINCTRL_EMI_ODT_CTRL_SLICE3_CALIB_MASK		(0x3 << 14)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE3_CALIB_OFFSET	14
+#define	PINCTRL_EMI_ODT_CTRL_SLICE3_TLOAD_MASK		(0x3 << 12)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE3_TLOAD_OFFSET	12
+#define	PINCTRL_EMI_ODT_CTRL_SLICE2_CALIB_MASK		(0x3 << 10)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE2_CALIB_OFFSET	10
+#define	PINCTRL_EMI_ODT_CTRL_SLICE2_TLOAD_MASK		(0x3 << 8)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE2_TLOAD_OFFSET	8
+#define	PINCTRL_EMI_ODT_CTRL_SLICE1_CALIB_MASK		(0x3 << 6)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE1_CALIB_OFFSET	6
+#define	PINCTRL_EMI_ODT_CTRL_SLICE1_TLOAD_MASK		(0x3 << 4)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE1_TLOAD_OFFSET	4
+#define	PINCTRL_EMI_ODT_CTRL_SLICE0_CALIB_MASK		(0x3 << 2)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE0_CALIB_OFFSET	2
+#define	PINCTRL_EMI_ODT_CTRL_SLICE0_TLOAD_MASK		(0x3 << 0)
+#define	PINCTRL_EMI_ODT_CTRL_SLICE0_TLOAD_OFFSET	0
+
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_MASK		(0x3 << 16)
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_OFFSET		16
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_mDDR		(0x0 << 16)
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_GPIO		(0x1 << 16)
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_LVDDR2		(0x2 << 16)
+#define	PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2		(0x3 << 16)
+#define	PINCTRL_EMI_DS_CTRL_ADDRESS_MA_MASK		(0x3 << 12)
+#define	PINCTRL_EMI_DS_CTRL_ADDRESS_MA_OFFSET		12
+#define	PINCTRL_EMI_DS_CTRL_CONTROL_MA_MASK		(0x3 << 10)
+#define	PINCTRL_EMI_DS_CTRL_CONTROL_MA_OFFSET		10
+#define	PINCTRL_EMI_DS_CTRL_DUALPAD_MA_MASK		(0x3 << 8)
+#define	PINCTRL_EMI_DS_CTRL_DUALPAD_MA_OFFSET		8
+#define	PINCTRL_EMI_DS_CTRL_SLICE3_MA_MASK		(0x3 << 6)
+#define	PINCTRL_EMI_DS_CTRL_SLICE3_MA_OFFSET		6
+#define	PINCTRL_EMI_DS_CTRL_SLICE2_MA_MASK		(0x3 << 4)
+#define	PINCTRL_EMI_DS_CTRL_SLICE2_MA_OFFSET		4
+#define	PINCTRL_EMI_DS_CTRL_SLICE1_MA_MASK		(0x3 << 2)
+#define	PINCTRL_EMI_DS_CTRL_SLICE1_MA_OFFSET		2
+#define	PINCTRL_EMI_DS_CTRL_SLICE0_MA_MASK		(0x3 << 0)
+#define	PINCTRL_EMI_DS_CTRL_SLICE0_MA_OFFSET		0
+
+#endif /* __MX28_REGS_PINCTRL_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-power.h b/arch/arm/include/asm/arch-mx28/regs-power.h
new file mode 100644
index 0000000..9da63ad
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-power.h
@@ -0,0 +1,413 @@
+/*
+ * Freescale i.MX28 Power Controller Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_POWER_H__
+#define __MX28_REGS_POWER_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_power_regs {
+	mx28_reg(hw_power_ctrl)
+	mx28_reg(hw_power_5vctrl)
+	mx28_reg(hw_power_minpwr)
+	mx28_reg(hw_power_charge)
+	uint32_t	hw_power_vdddctrl;
+	uint32_t	reserved_vddd[3];
+	uint32_t	hw_power_vddactrl;
+	uint32_t	reserved_vdda[3];
+	uint32_t	hw_power_vddioctrl;
+	uint32_t	reserved_vddio[3];
+	uint32_t	hw_power_vddmemctrl;
+	uint32_t	reserved_vddmem[3];
+	uint32_t	hw_power_dcdc4p2;
+	uint32_t	reserved_dcdc4p2[3];
+	uint32_t	hw_power_misc;
+	uint32_t	reserved_misc[3];
+	uint32_t	hw_power_dclimits;
+	uint32_t	reserved_dclimits[3];
+	mx28_reg(hw_power_loopctrl)
+	uint32_t	hw_power_sts;
+	uint32_t	reserved_sts[3];
+	mx28_reg(hw_power_speed)
+	uint32_t	hw_power_battmonitor;
+	uint32_t	reserved_battmonitor[3];
+
+	uint32_t	reserved[4];
+
+	mx28_reg(hw_power_reset)
+	mx28_reg(hw_power_debug)
+	mx28_reg(hw_power_thermal)
+	mx28_reg(hw_power_usb1ctrl)
+	mx28_reg(hw_power_special)
+	mx28_reg(hw_power_version)
+	mx28_reg(hw_power_anaclkctrl)
+	mx28_reg(hw_power_refctrl)
+};
+#endif
+
+#define	POWER_CTRL_PSWITCH_MID_TRAN			(1 << 27)
+#define	POWER_CTRL_DCDC4P2_BO_IRQ			(1 << 24)
+#define	POWER_CTRL_ENIRQ_DCDC4P2_BO			(1 << 23)
+#define	POWER_CTRL_VDD5V_DROOP_IRQ			(1 << 22)
+#define	POWER_CTRL_ENIRQ_VDD5V_DROOP			(1 << 21)
+#define	POWER_CTRL_PSWITCH_IRQ				(1 << 20)
+#define	POWER_CTRL_PSWITCH_IRQ_SRC			(1 << 19)
+#define	POWER_CTRL_POLARITY_PSWITCH			(1 << 18)
+#define	POWER_CTRL_ENIRQ_PSWITCH			(1 << 17)
+#define	POWER_CTRL_POLARITY_DC_OK			(1 << 16)
+#define	POWER_CTRL_DC_OK_IRQ				(1 << 15)
+#define	POWER_CTRL_ENIRQ_DC_OK				(1 << 14)
+#define	POWER_CTRL_BATT_BO_IRQ				(1 << 13)
+#define	POWER_CTRL_ENIRQ_BATT_BO			(1 << 12)
+#define	POWER_CTRL_VDDIO_BO_IRQ				(1 << 11)
+#define	POWER_CTRL_ENIRQ_VDDIO_BO			(1 << 10)
+#define	POWER_CTRL_VDDA_BO_IRQ				(1 << 9)
+#define	POWER_CTRL_ENIRQ_VDDA_BO			(1 << 8)
+#define	POWER_CTRL_VDDD_BO_IRQ				(1 << 7)
+#define	POWER_CTRL_ENIRQ_VDDD_BO			(1 << 6)
+#define	POWER_CTRL_POLARITY_VBUSVALID			(1 << 5)
+#define	POWER_CTRL_VBUS_VALID_IRQ			(1 << 4)
+#define	POWER_CTRL_ENIRQ_VBUS_VALID			(1 << 3)
+#define	POWER_CTRL_POLARITY_VDD5V_GT_VDDIO		(1 << 2)
+#define	POWER_CTRL_VDD5V_GT_VDDIO_IRQ			(1 << 1)
+#define	POWER_CTRL_ENIRQ_VDD5V_GT_VDDIO			(1 << 0)
+
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_MASK		(0x3 << 30)
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_OFFSET		30
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_4V3			(0x0 << 30)
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_4V4			(0x1 << 30)
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_4V5			(0x2 << 30)
+#define	POWER_5VCTRL_VBUSDROOP_TRSH_4V7			(0x3 << 30)
+#define	POWER_5VCTRL_HEADROOM_ADJ_MASK			(0x7 << 24)
+#define	POWER_5VCTRL_HEADROOM_ADJ_OFFSET		24
+#define	POWER_5VCTRL_PWD_CHARGE_4P2_MASK		(0x3 << 20)
+#define	POWER_5VCTRL_PWD_CHARGE_4P2_OFFSET		20
+#define	POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK		(0x3f << 12)
+#define	POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET		12
+#define	POWER_5VCTRL_VBUSVALID_TRSH_MASK		(0x7 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_OFFSET		8
+#define	POWER_5VCTRL_VBUSVALID_TRSH_2V9			(0x0 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V0			(0x1 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V1			(0x2 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V2			(0x3 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V3			(0x4 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V4			(0x5 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V5			(0x6 << 8)
+#define	POWER_5VCTRL_VBUSVALID_TRSH_4V6			(0x7 << 8)
+#define	POWER_5VCTRL_PWDN_5VBRNOUT			(1 << 7)
+#define	POWER_5VCTRL_ENABLE_LINREG_ILIMIT		(1 << 6)
+#define	POWER_5VCTRL_DCDC_XFER				(1 << 5)
+#define	POWER_5VCTRL_VBUSVALID_5VDETECT			(1 << 4)
+#define	POWER_5VCTRL_VBUSVALID_TO_B			(1 << 3)
+#define	POWER_5VCTRL_ILIMIT_EQ_ZERO			(1 << 2)
+#define	POWER_5VCTRL_PWRUP_VBUS_CMPS			(1 << 1)
+#define	POWER_5VCTRL_ENABLE_DCDC			(1 << 0)
+
+#define	POWER_MINPWR_LOWPWR_4P2				(1 << 14)
+#define	POWER_MINPWR_PWD_BO				(1 << 12)
+#define	POWER_MINPWR_USE_VDDXTAL_VBG			(1 << 11)
+#define	POWER_MINPWR_PWD_ANA_CMPS			(1 << 10)
+#define	POWER_MINPWR_ENABLE_OSC				(1 << 9)
+#define	POWER_MINPWR_SELECT_OSC				(1 << 8)
+#define	POWER_MINPWR_FBG_OFF				(1 << 7)
+#define	POWER_MINPWR_DOUBLE_FETS			(1 << 6)
+#define	POWER_MINPWR_HALFFETS				(1 << 5)
+#define	POWER_MINPWR_LESSANA_I				(1 << 4)
+#define	POWER_MINPWR_PWD_XTAL24				(1 << 3)
+#define	POWER_MINPWR_DC_STOPCLK				(1 << 2)
+#define	POWER_MINPWR_EN_DC_PFM				(1 << 1)
+#define	POWER_MINPWR_DC_HALFCLK				(1 << 0)
+
+#define	POWER_CHARGE_ADJ_VOLT_MASK			(0x7 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_OFFSET			24
+#define	POWER_CHARGE_ADJ_VOLT_M025P			(0x1 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_P050P			(0x2 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_M075P			(0x3 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_P025P			(0x4 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_M050P			(0x5 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_P075P			(0x6 << 24)
+#define	POWER_CHARGE_ADJ_VOLT_M100P			(0x7 << 24)
+#define	POWER_CHARGE_ENABLE_LOAD			(1 << 22)
+#define	POWER_CHARGE_ENABLE_FAULT_DETECT		(1 << 20)
+#define	POWER_CHARGE_CHRG_STS_OFF			(1 << 19)
+#define	POWER_CHARGE_LIION_4P1				(1 << 18)
+#define	POWER_CHARGE_PWD_BATTCHRG			(1 << 16)
+#define	POWER_CHARGE_ENABLE_CHARGER_USB1		(1 << 13)
+#define	POWER_CHARGE_ENABLE_CHARGER_USB0		(1 << 12)
+#define	POWER_CHARGE_STOP_ILIMIT_MASK			(0xf << 8)
+#define	POWER_CHARGE_STOP_ILIMIT_OFFSET			8
+#define	POWER_CHARGE_STOP_ILIMIT_10MA			(0x1 << 8)
+#define	POWER_CHARGE_STOP_ILIMIT_20MA			(0x2 << 8)
+#define	POWER_CHARGE_STOP_ILIMIT_50MA			(0x4 << 8)
+#define	POWER_CHARGE_STOP_ILIMIT_100MA			(0x8 << 8)
+#define	POWER_CHARGE_BATTCHRG_I_MASK			0x3f
+#define	POWER_CHARGE_BATTCHRG_I_OFFSET			0
+#define	POWER_CHARGE_BATTCHRG_I_10MA			0x01
+#define	POWER_CHARGE_BATTCHRG_I_20MA			0x02
+#define	POWER_CHARGE_BATTCHRG_I_50MA			0x04
+#define	POWER_CHARGE_BATTCHRG_I_100MA			0x08
+#define	POWER_CHARGE_BATTCHRG_I_200MA			0x10
+#define	POWER_CHARGE_BATTCHRG_I_400MA			0x20
+
+#define	POWER_VDDDCTRL_ADJTN_MASK			(0xf << 28)
+#define	POWER_VDDDCTRL_ADJTN_OFFSET			28
+#define	POWER_VDDDCTRL_PWDN_BRNOUT			(1 << 23)
+#define	POWER_VDDDCTRL_DISABLE_STEPPING			(1 << 22)
+#define	POWER_VDDDCTRL_ENABLE_LINREG			(1 << 21)
+#define	POWER_VDDDCTRL_DISABLE_FET			(1 << 20)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_MASK		(0x3 << 16)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_OFFSET		16
+#define	POWER_VDDDCTRL_LINREG_OFFSET_0STEPS		(0x0 << 16)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_ABOVE	(0x1 << 16)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW	(0x2 << 16)
+#define	POWER_VDDDCTRL_LINREG_OFFSET_2STEPS_BELOW	(0x3 << 16)
+#define	POWER_VDDDCTRL_BO_OFFSET_MASK			(0x7 << 8)
+#define	POWER_VDDDCTRL_BO_OFFSET_OFFSET			8
+#define	POWER_VDDDCTRL_TRG_MASK				0x1f
+#define	POWER_VDDDCTRL_TRG_OFFSET			0
+
+#define	POWER_VDDACTRL_PWDN_BRNOUT			(1 << 19)
+#define	POWER_VDDACTRL_DISABLE_STEPPING			(1 << 18)
+#define	POWER_VDDACTRL_ENABLE_LINREG			(1 << 17)
+#define	POWER_VDDACTRL_DISABLE_FET			(1 << 16)
+#define	POWER_VDDACTRL_LINREG_OFFSET_MASK		(0x3 << 12)
+#define	POWER_VDDACTRL_LINREG_OFFSET_OFFSET		12
+#define	POWER_VDDACTRL_LINREG_OFFSET_0STEPS		(0x0 << 12)
+#define	POWER_VDDACTRL_LINREG_OFFSET_1STEPS_ABOVE	(0x1 << 12)
+#define	POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW	(0x2 << 12)
+#define	POWER_VDDACTRL_LINREG_OFFSET_2STEPS_BELOW	(0x3 << 12)
+#define	POWER_VDDACTRL_BO_OFFSET_MASK			(0x7 << 8)
+#define	POWER_VDDACTRL_BO_OFFSET_OFFSET			8
+#define	POWER_VDDACTRL_TRG_MASK				0x1f
+#define	POWER_VDDACTRL_TRG_OFFSET			0
+
+#define	POWER_VDDIOCTRL_ADJTN_MASK			(0xf << 20)
+#define	POWER_VDDIOCTRL_ADJTN_OFFSET			20
+#define	POWER_VDDIOCTRL_PWDN_BRNOUT			(1 << 18)
+#define	POWER_VDDIOCTRL_DISABLE_STEPPING		(1 << 17)
+#define	POWER_VDDIOCTRL_DISABLE_FET			(1 << 16)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_MASK		(0x3 << 12)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_OFFSET		12
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_0STEPS		(0x0 << 12)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_ABOVE	(0x1 << 12)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW	(0x2 << 12)
+#define	POWER_VDDIOCTRL_LINREG_OFFSET_2STEPS_BELOW	(0x3 << 12)
+#define	POWER_VDDIOCTRL_BO_OFFSET_MASK			(0x7 << 8)
+#define	POWER_VDDIOCTRL_BO_OFFSET_OFFSET		8
+#define	POWER_VDDIOCTRL_TRG_MASK			0x1f
+#define	POWER_VDDIOCTRL_TRG_OFFSET			0
+
+#define	POWER_VDDMEMCTRL_PULLDOWN_ACTIVE		(1 << 10)
+#define	POWER_VDDMEMCTRL_ENABLE_ILIMIT			(1 << 9)
+#define	POWER_VDDMEMCTRL_ENABLE_LINREG			(1 << 8)
+#define	POWER_VDDMEMCTRL_BO_OFFSET_MASK			(0x7 << 5)
+#define	POWER_VDDMEMCTRL_BO_OFFSET_OFFSET		5
+#define	POWER_VDDMEMCTRL_TRG_MASK			0x1f
+#define	POWER_VDDMEMCTRL_TRG_OFFSET			0
+
+#define	POWER_DCDC4P2_DROPOUT_CTRL_MASK			(0xf << 28)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_OFFSET		28
+#define	POWER_DCDC4P2_DROPOUT_CTRL_200MV		(0x3 << 30)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_100MV		(0x2 << 30)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_50MV			(0x1 << 30)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_25MV			(0x0 << 30)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_SRC_4P2		(0x0 << 28)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_SRC_4P2_LT_BATT	(0x1 << 28)
+#define	POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL		(0x2 << 28)
+#define	POWER_DCDC4P2_ISTEAL_THRESH_MASK		(0x3 << 24)
+#define	POWER_DCDC4P2_ISTEAL_THRESH_OFFSET		24
+#define	POWER_DCDC4P2_ENABLE_4P2			(1 << 23)
+#define	POWER_DCDC4P2_ENABLE_DCDC			(1 << 22)
+#define	POWER_DCDC4P2_HYST_DIR				(1 << 21)
+#define	POWER_DCDC4P2_HYST_THRESH			(1 << 20)
+#define	POWER_DCDC4P2_TRG_MASK				(0x7 << 16)
+#define	POWER_DCDC4P2_TRG_OFFSET			16
+#define	POWER_DCDC4P2_TRG_4V2				(0x0 << 16)
+#define	POWER_DCDC4P2_TRG_4V1				(0x1 << 16)
+#define	POWER_DCDC4P2_TRG_4V0				(0x2 << 16)
+#define	POWER_DCDC4P2_TRG_3V9				(0x3 << 16)
+#define	POWER_DCDC4P2_TRG_BATT				(0x4 << 16)
+#define	POWER_DCDC4P2_BO_MASK				(0x1f << 8)
+#define	POWER_DCDC4P2_BO_OFFSET				8
+#define	POWER_DCDC4P2_CMPTRIP_MASK			0x1f
+#define	POWER_DCDC4P2_CMPTRIP_OFFSET			0
+
+#define	POWER_MISC_FREQSEL_MASK				(0x7 << 4)
+#define	POWER_MISC_FREQSEL_OFFSET			4
+#define	POWER_MISC_FREQSEL_20MHZ			(0x1 << 4)
+#define	POWER_MISC_FREQSEL_24MHZ			(0x2 << 4)
+#define	POWER_MISC_FREQSEL_19MHZ			(0x3 << 4)
+#define	POWER_MISC_FREQSEL_14MHZ			(0x4 << 4)
+#define	POWER_MISC_FREQSEL_18MHZ			(0x5 << 4)
+#define	POWER_MISC_FREQSEL_21MHZ			(0x6 << 4)
+#define	POWER_MISC_FREQSEL_17MHZ			(0x7 << 4)
+#define	POWER_MISC_DISABLE_FET_BO_LOGIC			(1 << 3)
+#define	POWER_MISC_DELAY_TIMING				(1 << 2)
+#define	POWER_MISC_TEST					(1 << 1)
+#define	POWER_MISC_SEL_PLLCLK				(1 << 0)
+
+#define	POWER_DCLIMITS_POSLIMIT_BUCK_MASK		(0x7f << 8)
+#define	POWER_DCLIMITS_POSLIMIT_BUCK_OFFSET		8
+#define	POWER_DCLIMITS_NEGLIMIT_MASK			0x7f
+#define	POWER_DCLIMITS_NETLIMIT_OFFSET			0
+
+#define	POWER_LOOPCTRL_TOGGLE_DIF			(1 << 20)
+#define	POWER_LOOPCTRL_HYST_SIGN			(1 << 19)
+#define	POWER_LOOPCTRL_EN_CM_HYST			(1 << 18)
+#define	POWER_LOOPCTRL_EN_DF_HYST			(1 << 17)
+#define	POWER_LOOPCTRL_CM_HYST_THRESH			(1 << 16)
+#define	POWER_LOOPCTRL_DF_HYST_THRESH			(1 << 15)
+#define	POWER_LOOPCTRL_RCSCALE_THRESH			(1 << 14)
+#define	POWER_LOOPCTRL_EN_RCSCALE_MASK			(0x3 << 12)
+#define	POWER_LOOPCTRL_EN_RCSCALE_OFFSET		12
+#define	POWER_LOOPCTRL_EN_RCSCALE_DIS			(0x0 << 12)
+#define	POWER_LOOPCTRL_EN_RCSCALE_2X			(0x1 << 12)
+#define	POWER_LOOPCTRL_EN_RCSCALE_4X			(0x2 << 12)
+#define	POWER_LOOPCTRL_EN_RCSCALE_8X			(0x3 << 12)
+#define	POWER_LOOPCTRL_DC_FF_MASK			(0x7 << 8)
+#define	POWER_LOOPCTRL_DC_FF_OFFSET			8
+#define	POWER_LOOPCTRL_DC_R_MASK			(0xf << 4)
+#define	POWER_LOOPCTRL_DC_R_OFFSET			4
+#define	POWER_LOOPCTRL_DC_C_MASK			0x3
+#define	POWER_LOOPCTRL_DC_C_OFFSET			0
+#define	POWER_LOOPCTRL_DC_C_MAX				0x0
+#define	POWER_LOOPCTRL_DC_C_2X				0x1
+#define	POWER_LOOPCTRL_DC_C_4X				0x2
+#define	POWER_LOOPCTRL_DC_C_MIN				0x3
+
+#define	POWER_STS_PWRUP_SOURCE_MASK			(0x3f << 24)
+#define	POWER_STS_PWRUP_SOURCE_OFFSET			24
+#define	POWER_STS_PWRUP_SOURCE_5V			(0x20 << 24)
+#define	POWER_STS_PWRUP_SOURCE_RTC			(0x10 << 24)
+#define	POWER_STS_PWRUP_SOURCE_PSWITCH_HIGH		(0x02 << 24)
+#define	POWER_STS_PWRUP_SOURCE_PSWITCH_MID		(0x01 << 24)
+#define	POWER_STS_PSWITCH_MASK				(0x3 << 20)
+#define	POWER_STS_PSWITCH_OFFSET			20
+#define	POWER_STS_THERMAL_WARNING			(1 << 19)
+#define	POWER_STS_VDDMEM_BO				(1 << 18)
+#define	POWER_STS_AVALID0_STATUS			(1 << 17)
+#define	POWER_STS_BVALID0_STATUS			(1 << 16)
+#define	POWER_STS_VBUSVALID0_STATUS			(1 << 15)
+#define	POWER_STS_SESSEND0_STATUS			(1 << 14)
+#define	POWER_STS_BATT_BO				(1 << 13)
+#define	POWER_STS_VDD5V_FAULT				(1 << 12)
+#define	POWER_STS_CHRGSTS				(1 << 11)
+#define	POWER_STS_DCDC_4P2_BO				(1 << 10)
+#define	POWER_STS_DC_OK					(1 << 9)
+#define	POWER_STS_VDDIO_BO				(1 << 8)
+#define	POWER_STS_VDDA_BO				(1 << 7)
+#define	POWER_STS_VDDD_BO				(1 << 6)
+#define	POWER_STS_VDD5V_GT_VDDIO			(1 << 5)
+#define	POWER_STS_VDD5V_DROOP				(1 << 4)
+#define	POWER_STS_AVALID0				(1 << 3)
+#define	POWER_STS_BVALID0				(1 << 2)
+#define	POWER_STS_VBUSVALID0				(1 << 1)
+#define	POWER_STS_SESSEND0				(1 << 0)
+
+#define	POWER_SPEED_STATUS_MASK				(0xffff << 8)
+#define	POWER_SPEED_STATUS_OFFSET			8
+#define	POWER_SPEED_STATUS_SEL_MASK			(0x3 << 6)
+#define	POWER_SPEED_STATUS_SEL_OFFSET			6
+#define	POWER_SPEED_STATUS_SEL_DCDC_STAT		(0x0 << 6)
+#define	POWER_SPEED_STATUS_SEL_CORE_STAT		(0x1 << 6)
+#define	POWER_SPEED_STATUS_SEL_ARM_STAT			(0x2 << 6)
+#define	POWER_SPEED_CTRL_MASK				0x3
+#define	POWER_SPEED_CTRL_OFFSET				0
+#define	POWER_SPEED_CTRL_SS_OFF				0x0
+#define	POWER_SPEED_CTRL_SS_ON				0x1
+#define	POWER_SPEED_CTRL_SS_ENABLE			0x3
+
+#define	POWER_BATTMONITOR_BATT_VAL_MASK			(0x3ff << 16)
+#define	POWER_BATTMONITOR_BATT_VAL_OFFSET		16
+#define	POWER_BATTMONITOR_PWDN_BATTBRNOUT_5VDETECT_EN	(1 << 11)
+#define	POWER_BATTMONITOR_EN_BATADJ			(1 << 10)
+#define	POWER_BATTMONITOR_PWDN_BATTBRNOUT		(1 << 9)
+#define	POWER_BATTMONITOR_BRWNOUT_PWD			(1 << 8)
+#define	POWER_BATTMONITOR_BRWNOUT_LVL_MASK		0x1f
+#define	POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET		0
+
+#define	POWER_RESET_UNLOCK_MASK				(0xffff << 16)
+#define	POWER_RESET_UNLOCK_OFFSET			16
+#define	POWER_RESET_UNLOCK_KEY				(0x3e77 << 16)
+#define	POWER_RESET_FASTFALL_PSWITCH_OFF		(1 << 2)
+#define	POWER_RESET_PWD_OFF				(1 << 1)
+#define	POWER_RESET_PWD					(1 << 0)
+
+#define	POWER_DEBUG_VBUSVALIDPIOLOCK			(1 << 3)
+#define	POWER_DEBUG_AVALIDPIOLOCK			(1 << 2)
+#define	POWER_DEBUG_BVALIDPIOLOCK			(1 << 1)
+#define	POWER_DEBUG_SESSENDPIOLOCK			(1 << 0)
+
+#define	POWER_THERMAL_TEST				(1 << 8)
+#define	POWER_THERMAL_PWD				(1 << 7)
+#define	POWER_THERMAL_LOW_POWER				(1 << 6)
+#define	POWER_THERMAL_OFFSET_ADJ_MASK			(0x3 << 4)
+#define	POWER_THERMAL_OFFSET_ADJ_OFFSET			4
+#define	POWER_THERMAL_OFFSET_ADJ_ENABLE			(1 << 3)
+#define	POWER_THERMAL_TEMP_THRESHOLD_MASK		0x7
+#define	POWER_THERMAL_TEMP_THRESHOLD_OFFSET		0
+
+#define	POWER_USB1CTRL_AVALID1				(1 << 3)
+#define	POWER_USB1CTRL_BVALID1				(1 << 2)
+#define	POWER_USB1CTRL_VBUSVALID1			(1 << 1)
+#define	POWER_USB1CTRL_SESSEND1				(1 << 0)
+
+#define	POWER_SPECIAL_TEST_MASK				0xffffffff
+#define	POWER_SPECIAL_TEST_OFFSET			0
+
+#define	POWER_VERSION_MAJOR_MASK			(0xff << 24)
+#define	POWER_VERSION_MAJOR_OFFSET			24
+#define	POWER_VERSION_MINOR_MASK			(0xff << 16)
+#define	POWER_VERSION_MINOR_OFFSET			16
+#define	POWER_VERSION_STEP_MASK				0xffff
+#define	POWER_VERSION_STEP_OFFSET			0
+
+#define	POWER_ANACLKCTRL_CLKGATE_0			(1 << 31)
+#define	POWER_ANACLKCTRL_OUTDIV_MASK			(0x7 << 28)
+#define	POWER_ANACLKCTRL_OUTDIV_OFFSET			28
+#define	POWER_ANACLKCTRL_INVERT_OUTCLK			(1 << 27)
+#define	POWER_ANACLKCTRL_CLKGATE_I			(1 << 26)
+#define	POWER_ANACLKCTRL_DITHER_OFF			(1 << 10)
+#define	POWER_ANACLKCTRL_SLOW_DITHER			(1 << 9)
+#define	POWER_ANACLKCTRL_INVERT_INCLK			(1 << 8)
+#define	POWER_ANACLKCTRL_INCLK_SHIFT_MASK		(0x3 << 4)
+#define	POWER_ANACLKCTRL_INCLK_SHIFT_OFFSET		4
+#define	POWER_ANACLKCTRL_INDIV_MASK			0x7
+#define	POWER_ANACLKCTRL_INDIV_OFFSET			0
+
+#define	POWER_REFCTRL_FASTSETTLING			(1 << 26)
+#define	POWER_REFCTRL_RAISE_REF				(1 << 25)
+#define	POWER_REFCTRL_XTAL_BGR_BIAS			(1 << 24)
+#define	POWER_REFCTRL_VBG_ADJ_MASK			(0x7 << 20)
+#define	POWER_REFCTRL_VBG_ADJ_OFFSET			20
+#define	POWER_REFCTRL_LOW_PWR				(1 << 19)
+#define	POWER_REFCTRL_BIAS_CTRL_MASK			(0x3 << 16)
+#define	POWER_REFCTRL_BIAS_CTRL_OFFSET			16
+#define	POWER_REFCTRL_VDDXTAL_TO_VDDD			(1 << 14)
+#define	POWER_REFCTRL_ADJ_ANA				(1 << 13)
+#define	POWER_REFCTRL_ADJ_VAG				(1 << 12)
+#define	POWER_REFCTRL_ANA_REFVAL_MASK			(0xf << 8)
+#define	POWER_REFCTRL_ANA_REFVAL_OFFSET			8
+#define	POWER_REFCTRL_VAG_VAL_MASK			(0xf << 4)
+#define	POWER_REFCTRL_VAG_VAL_OFFSET			4
+
+#endif	/* __MX28_REGS_POWER_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-rtc.h b/arch/arm/include/asm/arch-mx28/regs-rtc.h
new file mode 100644
index 0000000..fe2fda9
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-rtc.h
@@ -0,0 +1,147 @@
+/*
+ * Freescale i.MX28 RTC Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_RTC_H__
+#define __MX28_REGS_RTC_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_rtc_regs {
+	mx28_reg(hw_rtc_ctrl)
+	mx28_reg(hw_rtc_stat)
+	mx28_reg(hw_rtc_milliseconds)
+	mx28_reg(hw_rtc_seconds)
+	mx28_reg(hw_rtc_rtc_alarm)
+	mx28_reg(hw_rtc_watchdog)
+	mx28_reg(hw_rtc_persistent0)
+	mx28_reg(hw_rtc_persistent1)
+	mx28_reg(hw_rtc_persistent2)
+	mx28_reg(hw_rtc_persistent3)
+	mx28_reg(hw_rtc_persistent4)
+	mx28_reg(hw_rtc_persistent5)
+	mx28_reg(hw_rtc_debug)
+	mx28_reg(hw_rtc_version)
+};
+#endif
+
+#define	RTC_CTRL_SFTRST				(1 << 31)
+#define	RTC_CTRL_CLKGATE			(1 << 30)
+#define	RTC_CTRL_SUPPRESS_COPY2ANALOG		(1 << 6)
+#define	RTC_CTRL_FORCE_UPDATE			(1 << 5)
+#define	RTC_CTRL_WATCHDOGEN			(1 << 4)
+#define	RTC_CTRL_ONEMSEC_IRQ			(1 << 3)
+#define	RTC_CTRL_ALARM_IRQ			(1 << 2)
+#define	RTC_CTRL_ONEMSEC_IRQ_EN			(1 << 1)
+#define	RTC_CTRL_ALARM_IRQ_EN			(1 << 0)
+
+#define	RTC_STAT_RTC_PRESENT			(1 << 31)
+#define	RTC_STAT_ALARM_PRESENT			(1 << 30)
+#define	RTC_STAT_WATCHDOG_PRESENT		(1 << 29)
+#define	RTC_STAT_XTAL32000_PRESENT		(1 << 28)
+#define	RTC_STAT_XTAL32768_PRESENT		(1 << 27)
+#define	RTC_STAT_STALE_REGS_MASK		(0xff << 16)
+#define	RTC_STAT_STALE_REGS_OFFSET		16
+#define	RTC_STAT_NEW_REGS_MASK			(0xff << 8)
+#define	RTC_STAT_NEW_REGS_OFFSET		8
+
+#define	RTC_MILLISECONDS_COUNT_MASK		0xffffffff
+#define	RTC_MILLISECONDS_COUNT_OFFSET		0
+
+#define	RTC_SECONDS_COUNT_MASK			0xffffffff
+#define	RTC_SECONDS_COUNT_OFFSET		0
+
+#define	RTC_ALARM_VALUE_MASK			0xffffffff
+#define	RTC_ALARM_VALUE_OFFSET			0
+
+#define	RTC_WATCHDOG_COUNT_MASK			0xffffffff
+#define	RTC_WATCHDOG_COUNT_OFFSET		0
+
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_MASK	(0xf << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_OFFSET	28
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V83	(0x0 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V78	(0x1 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V73	(0x2 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V68	(0x3 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V62	(0x4 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V57	(0x5 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V52	(0x6 << 28)
+#define	RTC_PERSISTENT0_ADJ_POSLIMITBUCK_2V48	(0x7 << 28)
+#define	RTC_PERSISTENT0_EXTERNAL_RESET		(1 << 21)
+#define	RTC_PERSISTENT0_THERMAL_RESET		(1 << 20)
+#define	RTC_PERSISTENT0_ENABLE_LRADC_PWRUP	(1 << 18)
+#define	RTC_PERSISTENT0_AUTO_RESTART		(1 << 17)
+#define	RTC_PERSISTENT0_DISABLE_PSWITCH		(1 << 16)
+#define	RTC_PERSISTENT0_LOWERBIAS_MASK		(0xf << 14)
+#define	RTC_PERSISTENT0_LOWERBIAS_OFFSET	14
+#define	RTC_PERSISTENT0_LOWERBIAS_NOMINAL	(0x0 << 14)
+#define	RTC_PERSISTENT0_LOWERBIAS_M25P		(0x1 << 14)
+#define	RTC_PERSISTENT0_LOWERBIAS_M50P		(0x3 << 14)
+#define	RTC_PERSISTENT0_DISABLE_XTALOK		(1 << 13)
+#define	RTC_PERSISTENT0_MSEC_RES_MASK		(0x1f << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_OFFSET		8
+#define	RTC_PERSISTENT0_MSEC_RES_1MS		(0x01 << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_2MS		(0x02 << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_4MS		(0x04 << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_8MS		(0x08 << 8)
+#define	RTC_PERSISTENT0_MSEC_RES_16MS		(0x10 << 8)
+#define	RTC_PERSISTENT0_ALARM_WAKE		(1 << 7)
+#define	RTC_PERSISTENT0_XTAL32_FREQ		(1 << 6)
+#define	RTC_PERSISTENT0_XTAL32KHZ_PWRUP		(1 << 5)
+#define	RTC_PERSISTENT0_XTAL24KHZ_PWRUP		(1 << 4)
+#define	RTC_PERSISTENT0_LCK_SECS		(1 << 3)
+#define	RTC_PERSISTENT0_ALARM_EN		(1 << 2)
+#define	RTC_PERSISTENT0_ALARM_WAKE_EN		(1 << 1)
+#define	RTC_PERSISTENT0_CLOCKSOURCE		(1 << 0)
+
+#define	RTC_PERSISTENT1_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT1_GENERAL_OFFSET		0
+#define	RTC_PERSISTENT1_GENERAL_OTG_ALT_ROLE	0x0080
+#define	RTC_PERSISTENT1_GENERAL_OTG_HNP		0x0100
+#define	RTC_PERSISTENT1_GENERAL_USB_LPM		0x0200
+#define	RTC_PERSISTENT1_GENERAL_SKIP_CHECKDISK	0x0400
+#define	RTC_PERSISTENT1_GENERAL_USB_BOOT_PLAYER	0x0800
+#define	RTC_PERSISTENT1_GENERAL_ENUM_500MA_2X	0x1000
+
+#define	RTC_PERSISTENT2_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT2_GENERAL_OFFSET		0
+
+#define	RTC_PERSISTENT3_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT3_GENERAL_OFFSET		0
+
+#define	RTC_PERSISTENT4_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT4_GENERAL_OFFSET		0
+
+#define	RTC_PERSISTENT5_GENERAL_MASK		0xffffffff
+#define	RTC_PERSISTENT5_GENERAL_OFFSET		0
+
+#define	RTC_DEBUG_WATCHDOG_RESET_MASK		(1 << 1)
+#define	RTC_DEBUG_WATCHDOG_RESET		(1 << 0)
+
+#define	RTC_VERSION_MAJOR_MASK			(0xff << 24)
+#define	RTC_VERSION_MAJOR_OFFSET		24
+#define	RTC_VERSION_MINOR_MASK			(0xff << 16)
+#define	RTC_VERSION_MINOR_OFFSET		16
+#define	RTC_VERSION_STEP_MASK			0xffff
+#define	RTC_VERSION_STEP_OFFSET			0
+
+#endif	/* __MX28_REGS_RTC_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-ssp.h b/arch/arm/include/asm/arch-mx28/regs-ssp.h
new file mode 100644
index 0000000..ab3870c
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-ssp.h
@@ -0,0 +1,349 @@
+/*
+ * Freescale i.MX28 SSP Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_SSP_H__
+#define __MX28_REGS_SSP_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_ssp_regs {
+	mx28_reg(hw_ssp_ctrl0)
+	mx28_reg(hw_ssp_cmd0)
+	mx28_reg(hw_ssp_cmd1)
+	mx28_reg(hw_ssp_xfer_size)
+	mx28_reg(hw_ssp_block_size)
+	mx28_reg(hw_ssp_compref)
+	mx28_reg(hw_ssp_compmask)
+	mx28_reg(hw_ssp_timing)
+	mx28_reg(hw_ssp_ctrl1)
+	mx28_reg(hw_ssp_data)
+	mx28_reg(hw_ssp_sdresp0)
+	mx28_reg(hw_ssp_sdresp1)
+	mx28_reg(hw_ssp_sdresp2)
+	mx28_reg(hw_ssp_sdresp3)
+	mx28_reg(hw_ssp_ddr_ctrl)
+	mx28_reg(hw_ssp_dll_ctrl)
+	mx28_reg(hw_ssp_status)
+	mx28_reg(hw_ssp_dll_sts)
+	mx28_reg(hw_ssp_debug)
+	mx28_reg(hw_ssp_version)
+};
+#endif
+
+#define	SSP_CTRL0_SFTRST			(1 << 31)
+#define	SSP_CTRL0_CLKGATE			(1 << 30)
+#define	SSP_CTRL0_RUN				(1 << 29)
+#define	SSP_CTRL0_SDIO_IRQ_CHECK		(1 << 28)
+#define	SSP_CTRL0_LOCK_CS			(1 << 27)
+#define	SSP_CTRL0_IGNORE_CRC			(1 << 26)
+#define	SSP_CTRL0_READ				(1 << 25)
+#define	SSP_CTRL0_DATA_XFER			(1 << 24)
+#define	SSP_CTRL0_BUS_WIDTH_MASK		(0x3 << 22)
+#define	SSP_CTRL0_BUS_WIDTH_OFFSET		22
+#define	SSP_CTRL0_BUS_WIDTH_ONE_BIT		(0x0 << 22)
+#define	SSP_CTRL0_BUS_WIDTH_FOUR_BIT		(0x1 << 22)
+#define	SSP_CTRL0_BUS_WIDTH_EIGHT_BIT		(0x2 << 22)
+#define	SSP_CTRL0_WAIT_FOR_IRQ			(1 << 21)
+#define	SSP_CTRL0_WAIT_FOR_CMD			(1 << 20)
+#define	SSP_CTRL0_LONG_RESP			(1 << 19)
+#define	SSP_CTRL0_CHECK_RESP			(1 << 18)
+#define	SSP_CTRL0_GET_RESP			(1 << 17)
+#define	SSP_CTRL0_ENABLE			(1 << 16)
+
+#define	SSP_CMD0_SOFT_TERMINATE			(1 << 26)
+#define	SSP_CMD0_DBL_DATA_RATE_EN		(1 << 25)
+#define	SSP_CMD0_PRIM_BOOT_OP_EN		(1 << 24)
+#define	SSP_CMD0_BOOT_ACK_EN			(1 << 23)
+#define	SSP_CMD0_SLOW_CLKING_EN			(1 << 22)
+#define	SSP_CMD0_CONT_CLKING_EN			(1 << 21)
+#define	SSP_CMD0_APPEND_8CYC			(1 << 20)
+#define	SSP_CMD0_CMD_MASK			0xff
+#define	SSP_CMD0_CMD_OFFSET			0
+#define	SSP_CMD0_CMD_MMC_GO_IDLE_STATE		0x00
+#define	SSP_CMD0_CMD_MMC_SEND_OP_COND		0x01
+#define	SSP_CMD0_CMD_MMC_ALL_SEND_CID		0x02
+#define	SSP_CMD0_CMD_MMC_SET_RELATIVE_ADDR	0x03
+#define	SSP_CMD0_CMD_MMC_SET_DSR		0x04
+#define	SSP_CMD0_CMD_MMC_RESERVED_5		0x05
+#define	SSP_CMD0_CMD_MMC_SWITCH			0x06
+#define	SSP_CMD0_CMD_MMC_SELECT_DESELECT_CARD	0x07
+#define	SSP_CMD0_CMD_MMC_SEND_EXT_CSD		0x08
+#define	SSP_CMD0_CMD_MMC_SEND_CSD		0x09
+#define	SSP_CMD0_CMD_MMC_SEND_CID		0x0a
+#define	SSP_CMD0_CMD_MMC_READ_DAT_UNTIL_STOP	0x0b
+#define	SSP_CMD0_CMD_MMC_STOP_TRANSMISSION	0x0c
+#define	SSP_CMD0_CMD_MMC_SEND_STATUS		0x0d
+#define	SSP_CMD0_CMD_MMC_BUSTEST_R		0x0e
+#define	SSP_CMD0_CMD_MMC_GO_INACTIVE_STATE	0x0f
+#define	SSP_CMD0_CMD_MMC_SET_BLOCKLEN		0x10
+#define	SSP_CMD0_CMD_MMC_READ_SINGLE_BLOCK	0x11
+#define	SSP_CMD0_CMD_MMC_READ_MULTIPLE_BLOCK	0x12
+#define	SSP_CMD0_CMD_MMC_BUSTEST_W		0x13
+#define	SSP_CMD0_CMD_MMC_WRITE_DAT_UNTIL_STOP	0x14
+#define	SSP_CMD0_CMD_MMC_SET_BLOCK_COUNT	0x17
+#define	SSP_CMD0_CMD_MMC_WRITE_BLOCK		0x18
+#define	SSP_CMD0_CMD_MMC_WRITE_MULTIPLE_BLOCK	0x19
+#define	SSP_CMD0_CMD_MMC_PROGRAM_CID		0x1a
+#define	SSP_CMD0_CMD_MMC_PROGRAM_CSD		0x1b
+#define	SSP_CMD0_CMD_MMC_SET_WRITE_PROT		0x1c
+#define	SSP_CMD0_CMD_MMC_CLR_WRITE_PROT		0x1d
+#define	SSP_CMD0_CMD_MMC_SEND_WRITE_PROT	0x1e
+#define	SSP_CMD0_CMD_MMC_ERASE_GROUP_START	0x23
+#define	SSP_CMD0_CMD_MMC_ERASE_GROUP_END	0x24
+#define	SSP_CMD0_CMD_MMC_ERASE			0x26
+#define	SSP_CMD0_CMD_MMC_FAST_IO		0x27
+#define	SSP_CMD0_CMD_MMC_GO_IRQ_STATE		0x28
+#define	SSP_CMD0_CMD_MMC_LOCK_UNLOCK		0x2a
+#define	SSP_CMD0_CMD_MMC_APP_CMD		0x37
+#define	SSP_CMD0_CMD_MMC_GEN_CMD		0x38
+#define	SSP_CMD0_CMD_SD_GO_IDLE_STATE		0x00
+#define	SSP_CMD0_CMD_SD_ALL_SEND_CID		0x02
+#define	SSP_CMD0_CMD_SD_SEND_RELATIVE_ADDR	0x03
+#define	SSP_CMD0_CMD_SD_SET_DSR			0x04
+#define	SSP_CMD0_CMD_SD_IO_SEND_OP_COND		0x05
+#define	SSP_CMD0_CMD_SD_SELECT_DESELECT_CARD	0x07
+#define	SSP_CMD0_CMD_SD_SEND_CSD		0x09
+#define	SSP_CMD0_CMD_SD_SEND_CID		0x0a
+#define	SSP_CMD0_CMD_SD_STOP_TRANSMISSION	0x0c
+#define	SSP_CMD0_CMD_SD_SEND_STATUS		0x0d
+#define	SSP_CMD0_CMD_SD_GO_INACTIVE_STATE	0x0f
+#define	SSP_CMD0_CMD_SD_SET_BLOCKLEN		0x10
+#define	SSP_CMD0_CMD_SD_READ_SINGLE_BLOCK	0x11
+#define	SSP_CMD0_CMD_SD_READ_MULTIPLE_BLOCK	0x12
+#define	SSP_CMD0_CMD_SD_WRITE_BLOCK		0x18
+#define	SSP_CMD0_CMD_SD_WRITE_MULTIPLE_BLOCK	0x19
+#define	SSP_CMD0_CMD_SD_PROGRAM_CSD		0x1b
+#define	SSP_CMD0_CMD_SD_SET_WRITE_PROT		0x1c
+#define	SSP_CMD0_CMD_SD_CLR_WRITE_PROT		0x1d
+#define	SSP_CMD0_CMD_SD_SEND_WRITE_PROT		0x1e
+#define	SSP_CMD0_CMD_SD_ERASE_WR_BLK_START	0x20
+#define	SSP_CMD0_CMD_SD_ERASE_WR_BLK_END	0x21
+#define	SSP_CMD0_CMD_SD_ERASE_GROUP_START	0x23
+#define	SSP_CMD0_CMD_SD_ERASE_GROUP_END		0x24
+#define	SSP_CMD0_CMD_SD_ERASE			0x26
+#define	SSP_CMD0_CMD_SD_LOCK_UNLOCK		0x2a
+#define	SSP_CMD0_CMD_SD_IO_RW_DIRECT		0x34
+#define	SSP_CMD0_CMD_SD_IO_RW_EXTENDED		0x35
+#define	SSP_CMD0_CMD_SD_APP_CMD			0x37
+#define	SSP_CMD0_CMD_SD_GEN_CMD			0x38
+
+#define	SSP_CMD1_CMD_ARG_MASK			0xffffffff
+#define	SSP_CMD1_CMD_ARG_OFFSET			0
+
+#define	SSP_XFER_SIZE_XFER_COUNT_MASK		0xffffffff
+#define	SSP_XFER_SIZE_XFER_COUNT_OFFSET		0
+
+#define	SSP_BLOCK_SIZE_BLOCK_COUNT_MASK		(0xffffff << 4)
+#define	SSP_BLOCK_SIZE_BLOCK_COUNT_OFFSET	4
+#define	SSP_BLOCK_SIZE_BLOCK_SIZE_MASK		0xf
+#define	SSP_BLOCK_SIZE_BLOCK_SIZE_OFFSET	0
+
+#define	SSP_COMPREF_REFERENCE_MASK		0xffffffff
+#define	SSP_COMPREF_REFERENCE_OFFSET		0
+
+#define	SSP_COMPMASK_MASK_MASK			0xffffffff
+#define	SSP_COMPMASK_MASK_OFFSET		0
+
+#define	SSP_TIMING_TIMEOUT_MASK			(0xffff << 16)
+#define	SSP_TIMING_TIMEOUT_OFFSET		16
+#define	SSP_TIMING_CLOCK_DIVIDE_MASK		(0xff << 8)
+#define	SSP_TIMING_CLOCK_DIVIDE_OFFSET		8
+#define	SSP_TIMING_CLOCK_RATE_MASK		0xff
+#define	SSP_TIMING_CLOCK_RATE_OFFSET		0
+
+#define	SSP_CTRL1_SDIO_IRQ			(1 << 31)
+#define	SSP_CTRL1_SDIO_IRQ_EN			(1 << 30)
+#define	SSP_CTRL1_RESP_ERR_IRQ			(1 << 29)
+#define	SSP_CTRL1_RESP_ERR_IRQ_EN		(1 << 28)
+#define	SSP_CTRL1_RESP_TIMEOUT_IRQ		(1 << 27)
+#define	SSP_CTRL1_RESP_TIMEOUT_IRQ_EN		(1 << 26)
+#define	SSP_CTRL1_DATA_TIMEOUT_IRQ		(1 << 25)
+#define	SSP_CTRL1_DATA_TIMEOUT_IRQ_EN		(1 << 24)
+#define	SSP_CTRL1_DATA_CRC_IRQ			(1 << 23)
+#define	SSP_CTRL1_DATA_CRC_IRQ_EN		(1 << 22)
+#define	SSP_CTRL1_FIFO_UNDERRUN_IRQ		(1 << 21)
+#define	SSP_CTRL1_FIFO_UNDERRUN_EN		(1 << 20)
+#define	SSP_CTRL1_CEATA_CCS_ERR_IRQ		(1 << 19)
+#define	SSP_CTRL1_CEATA_CCS_ERR_IRQ_EN		(1 << 18)
+#define	SSP_CTRL1_RECV_TIMEOUT_IRQ		(1 << 17)
+#define	SSP_CTRL1_RECV_TIMEOUT_IRQ_EN		(1 << 16)
+#define	SSP_CTRL1_FIFO_OVERRUN_IRQ		(1 << 15)
+#define	SSP_CTRL1_FIFO_OVERRUN_IRQ_EN		(1 << 14)
+#define	SSP_CTRL1_DMA_ENABLE			(1 << 13)
+#define	SSP_CTRL1_CEATA_CCS_ERR_EN		(1 << 12)
+#define	SSP_CTRL1_SLAVE_OUT_DISABLE		(1 << 11)
+#define	SSP_CTRL1_PHASE				(1 << 10)
+#define	SSP_CTRL1_POLARITY			(1 << 9)
+#define	SSP_CTRL1_SLAVE_MODE			(1 << 8)
+#define	SSP_CTRL1_WORD_LENGTH_MASK		(0xf << 4)
+#define	SSP_CTRL1_WORD_LENGTH_OFFSET		4
+#define	SSP_CTRL1_WORD_LENGTH_RESERVED0		(0x0 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_RESERVED1		(0x1 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_RESERVED2		(0x2 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_FOUR_BITS		(0x3 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_EIGHT_BITS	(0x7 << 4)
+#define	SSP_CTRL1_WORD_LENGTH_SIXTEEN_BITS	(0xf << 4)
+#define	SSP_CTRL1_SSP_MODE_MASK			0xf
+#define	SSP_CTRL1_SSP_MODE_OFFSET		0
+#define	SSP_CTRL1_SSP_MODE_SPI			0x0
+#define	SSP_CTRL1_SSP_MODE_SSI			0x1
+#define	SSP_CTRL1_SSP_MODE_SD_MMC		0x3
+#define	SSP_CTRL1_SSP_MODE_MS			0x4
+
+#define	SSP_DATA_DATA_MASK			0xffffffff
+#define	SSP_DATA_DATA_OFFSET			0
+
+#define	SSP_SDRESP0_RESP0_MASK			0xffffffff
+#define	SSP_SDRESP0_RESP0_OFFSET		0
+
+#define	SSP_SDRESP1_RESP1_MASK			0xffffffff
+#define	SSP_SDRESP1_RESP1_OFFSET		0
+
+#define	SSP_SDRESP2_RESP2_MASK			0xffffffff
+#define	SSP_SDRESP2_RESP2_OFFSET		0
+
+#define	SSP_SDRESP3_RESP3_MASK			0xffffffff
+#define	SSP_SDRESP3_RESP3_OFFSET		0
+
+#define	SSP_DDR_CTRL_DMA_BURST_TYPE_MASK	(0x3 << 30)
+#define	SSP_DDR_CTRL_DMA_BURST_TYPE_OFFSET	30
+#define	SSP_DDR_CTRL_NIBBLE_POS			(1 << 1)
+#define	SSP_DDR_CTRL_TXCLK_DELAY_TYPE		(1 << 0)
+
+#define	SSP_DLL_CTRL_REF_UPDATE_INT_MASK	(0xf << 28)
+#define	SSP_DLL_CTRL_REF_UPDATE_INT_OFFSET	28
+#define	SSP_DLL_CTRL_SLV_UPDATE_INT_MASK	(0xff << 20)
+#define	SSP_DLL_CTRL_SLV_UPDATE_INT_OFFSET	20
+#define	SSP_DLL_CTRL_SLV_OVERRIDE_VAL_MASK	(0x3f << 10)
+#define	SSP_DLL_CTRL_SLV_OVERRIDE_VAL_OFFSET	10
+#define	SSP_DLL_CTRL_SLV_OVERRIDE		(1 << 9)
+#define	SSP_DLL_CTRL_GATE_UPDATE		(1 << 7)
+#define	SSP_DLL_CTRL_SLV_DLY_TARGET_MASK	(0xf << 3)
+#define	SSP_DLL_CTRL_SLV_DLY_TARGET_OFFSET	3
+#define	SSP_DLL_CTRL_SLV_FORCE_UPD		(1 << 2)
+#define	SSP_DLL_CTRL_RESET			(1 << 1)
+#define	SSP_DLL_CTRL_ENABLE			(1 << 0)
+
+#define	SSP_STATUS_PRESENT			(1 << 31)
+#define	SSP_STATUS_MS_PRESENT			(1 << 30)
+#define	SSP_STATUS_SD_PRESENT			(1 << 29)
+#define	SSP_STATUS_CARD_DETECT			(1 << 28)
+#define	SSP_STATUS_DMABURST			(1 << 22)
+#define	SSP_STATUS_DMASENSE			(1 << 21)
+#define	SSP_STATUS_DMATERM			(1 << 20)
+#define	SSP_STATUS_DMAREQ			(1 << 19)
+#define	SSP_STATUS_DMAEND			(1 << 18)
+#define	SSP_STATUS_SDIO_IRQ			(1 << 17)
+#define	SSP_STATUS_RESP_CRC_ERR			(1 << 16)
+#define	SSP_STATUS_RESP_ERR			(1 << 15)
+#define	SSP_STATUS_RESP_TIMEOUT			(1 << 14)
+#define	SSP_STATUS_DATA_CRC_ERR			(1 << 13)
+#define	SSP_STATUS_TIMEOUT			(1 << 12)
+#define	SSP_STATUS_RECV_TIMEOUT_STAT		(1 << 11)
+#define	SSP_STATUS_CEATA_CCS_ERR		(1 << 10)
+#define	SSP_STATUS_FIFO_OVRFLW			(1 << 9)
+#define	SSP_STATUS_FIFO_FULL			(1 << 8)
+#define	SSP_STATUS_FIFO_EMPTY			(1 << 5)
+#define	SSP_STATUS_FIFO_UNDRFLW			(1 << 4)
+#define	SSP_STATUS_CMD_BUSY			(1 << 3)
+#define	SSP_STATUS_DATA_BUSY			(1 << 2)
+#define	SSP_STATUS_BUSY				(1 << 0)
+
+#define	SSP_DLL_STS_REF_SEL_MASK		(0x3f << 8)
+#define	SSP_DLL_STS_REF_SEL_OFFSET		8
+#define	SSP_DLL_STS_SLV_SEL_MASK		(0x3f << 2)
+#define	SSP_DLL_STS_SLV_SEL_OFFSET		2
+#define	SSP_DLL_STS_REF_LOCK			(1 << 1)
+#define	SSP_DLL_STS_SLV_LOCK			(1 << 0)
+
+#define	SSP_DEBUG_DATACRC_ERR_MASK		(0xf << 28)
+#define	SSP_DEBUG_DATACRC_ERR_OFFSET		28
+#define	SSP_DEBUG_DATA_STALL			(1 << 27)
+#define	SSP_DEBUG_DAT_SM_MASK			(0x7 << 24)
+#define	SSP_DEBUG_DAT_SM_OFFSET			24
+#define	SSP_DEBUG_DAT_SM_DSM_IDLE		(0x0 << 24)
+#define	SSP_DEBUG_DAT_SM_DSM_WORD		(0x2 << 24)
+#define	SSP_DEBUG_DAT_SM_DSM_CRC1		(0x3 << 24)
+#define	SSP_DEBUG_DAT_SM_DSM_CRC2		(0x4 << 24)
+#define	SSP_DEBUG_DAT_SM_DSM_END		(0x5 << 24)
+#define	SSP_DEBUG_MSTK_SM_MASK			(0xf << 20)
+#define	SSP_DEBUG_MSTK_SM_OFFSET		20
+#define	SSP_DEBUG_MSTK_SM_MSTK_IDLE		(0x0 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_CKON		(0x1 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_BS1		(0x2 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_TPC		(0x3 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_BS2		(0x4 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_HDSHK		(0x5 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_BS3		(0x6 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_RW		(0x7 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_CRC1		(0x8 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_CRC2		(0x9 << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_BS0		(0xa << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_END1		(0xb << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_END2W		(0xc << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_END2R		(0xd << 20)
+#define	SSP_DEBUG_MSTK_SM_MSTK_DONE		(0xe << 20)
+#define	SSP_DEBUG_CMD_OE			(1 << 19)
+#define	SSP_DEBUG_DMA_SM_MASK			(0x7 << 16)
+#define	SSP_DEBUG_DMA_SM_OFFSET			16
+#define	SSP_DEBUG_DMA_SM_DMA_IDLE		(0x0 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_DMAREQ		(0x1 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_DMAACK		(0x2 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_STALL		(0x3 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_BUSY		(0x4 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_DONE		(0x5 << 16)
+#define	SSP_DEBUG_DMA_SM_DMA_COUNT		(0x6 << 16)
+#define	SSP_DEBUG_MMC_SM_MASK			(0xf << 12)
+#define	SSP_DEBUG_MMC_SM_OFFSET			12
+#define	SSP_DEBUG_MMC_SM_MMC_IDLE		(0x0 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_CMD		(0x1 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_TRC		(0x2 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_RESP		(0x3 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_RPRX		(0x4 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_TX			(0x5 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_CTOK		(0x6 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_RX			(0x7 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_CCS		(0x8 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_PUP		(0x9 << 12)
+#define	SSP_DEBUG_MMC_SM_MMC_WAIT		(0xa << 12)
+#define	SSP_DEBUG_CMD_SM_MASK			(0x3 << 10)
+#define	SSP_DEBUG_CMD_SM_OFFSET			10
+#define	SSP_DEBUG_CMD_SM_CSM_IDLE		(0x0 << 10)
+#define	SSP_DEBUG_CMD_SM_CSM_INDEX		(0x1 << 10)
+#define	SSP_DEBUG_CMD_SM_CSM_ARG		(0x2 << 10)
+#define	SSP_DEBUG_CMD_SM_CSM_CRC		(0x3 << 10)
+#define	SSP_DEBUG_SSP_CMD			(1 << 9)
+#define	SSP_DEBUG_SSP_RESP			(1 << 8)
+#define	SSP_DEBUG_SSP_RXD_MASK			0xff
+#define	SSP_DEBUG_SSP_RXD_OFFSET		0
+
+#define	SSP_VERSION_MAJOR_MASK			(0xff << 24)
+#define	SSP_VERSION_MAJOR_OFFSET		24
+#define	SSP_VERSION_MINOR_MASK			(0xff << 16)
+#define	SSP_VERSION_MINOR_OFFSET		16
+#define	SSP_VERSION_STEP_MASK			0xffff
+#define	SSP_VERSION_STEP_OFFSET			0
+
+#endif /* __MX28_REGS_SSP_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/regs-timrot.h b/arch/arm/include/asm/arch-mx28/regs-timrot.h
new file mode 100644
index 0000000..1b941cf
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-timrot.h
@@ -0,0 +1,171 @@
+/*
+ * Freescale i.MX28 TIMROT Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __MX28_REGS_TIMROT_H__
+#define __MX28_REGS_TIMROT_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_timrot_regs {
+	mx28_reg(hw_timrot_rotctrl)
+	mx28_reg(hw_timrot_rotcount)
+	mx28_reg(hw_timrot_timctrl0)
+	mx28_reg(hw_timrot_running_count0)
+	mx28_reg(hw_timrot_fixed_count0)
+	mx28_reg(hw_timrot_match_count0)
+	mx28_reg(hw_timrot_timctrl1)
+	mx28_reg(hw_timrot_running_count1)
+	mx28_reg(hw_timrot_fixed_count1)
+	mx28_reg(hw_timrot_match_count1)
+	mx28_reg(hw_timrot_timctrl2)
+	mx28_reg(hw_timrot_running_count2)
+	mx28_reg(hw_timrot_fixed_count2)
+	mx28_reg(hw_timrot_match_count2)
+	mx28_reg(hw_timrot_timctrl3)
+	mx28_reg(hw_timrot_running_count3)
+	mx28_reg(hw_timrot_fixed_count3)
+	mx28_reg(hw_timrot_match_count3)
+	mx28_reg(hw_timrot_version)
+};
+#endif
+
+#define	TIMROT_ROTCTRL_SFTRST				(1 << 31)
+#define	TIMROT_ROTCTRL_CLKGATE				(1 << 30)
+#define	TIMROT_ROTCTRL_ROTARY_PRESENT			(1 << 29)
+#define	TIMROT_ROTCTRL_TIM3_PRESENT			(1 << 28)
+#define	TIMROT_ROTCTRL_TIM2_PRESENT			(1 << 27)
+#define	TIMROT_ROTCTRL_TIM1_PRESENT			(1 << 26)
+#define	TIMROT_ROTCTRL_TIM0_PRESENT			(1 << 25)
+#define	TIMROT_ROTCTRL_STATE_MASK			(0x7 << 22)
+#define	TIMROT_ROTCTRL_STATE_OFFSET			22
+#define	TIMROT_ROTCTRL_DIVIDER_MASK			(0x3f << 16)
+#define	TIMROT_ROTCTRL_DIVIDER_OFFSET			16
+#define	TIMROT_ROTCTRL_RELATIVE				(1 << 12)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_MASK			(0x3 << 10)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_OFFSET		10
+#define	TIMROT_ROTCTRL_OVERSAMPLE_8X			(0x0 << 10)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_4X			(0x1 << 10)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_2X			(0x2 << 10)
+#define	TIMROT_ROTCTRL_OVERSAMPLE_1X			(0x3 << 10)
+#define	TIMROT_ROTCTRL_POLARITY_B			(1 << 9)
+#define	TIMROT_ROTCTRL_POLARITY_A			(1 << 8)
+#define	TIMROT_ROTCTRL_SELECT_B_MASK			(0xf << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_OFFSET			4
+#define	TIMROT_ROTCTRL_SELECT_B_NEVER_TICK		(0x0 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM0			(0x1 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM1			(0x2 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM2			(0x3 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM3			(0x4 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM4			(0x5 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM5			(0x6 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM6			(0x7 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_PWM7			(0x8 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_ROTARYA			(0x9 << 4)
+#define	TIMROT_ROTCTRL_SELECT_B_ROTARYB			(0xa << 4)
+#define	TIMROT_ROTCTRL_SELECT_A_MASK			0xf
+#define	TIMROT_ROTCTRL_SELECT_A_OFFSET			0
+#define	TIMROT_ROTCTRL_SELECT_A_NEVER_TICK		0x0
+#define	TIMROT_ROTCTRL_SELECT_A_PWM0			0x1
+#define	TIMROT_ROTCTRL_SELECT_A_PWM1			0x2
+#define	TIMROT_ROTCTRL_SELECT_A_PWM2			0x3
+#define	TIMROT_ROTCTRL_SELECT_A_PWM3			0x4
+#define	TIMROT_ROTCTRL_SELECT_A_PWM4			0x5
+#define	TIMROT_ROTCTRL_SELECT_A_PWM5			0x6
+#define	TIMROT_ROTCTRL_SELECT_A_PWM6			0x7
+#define	TIMROT_ROTCTRL_SELECT_A_PWM7			0x8
+#define	TIMROT_ROTCTRL_SELECT_A_ROTARYA			0x9
+#define	TIMROT_ROTCTRL_SELECT_A_ROTARYB			0xa
+
+#define	TIMROT_ROTCOUNT_UPDOWN_MASK			0xffff
+#define	TIMROT_ROTCOUNT_UPDOWN_OFFSET			0
+
+#define	TIMROT_TIMCTRLn_IRQ				(1 << 15)
+#define	TIMROT_TIMCTRLn_IRQ_EN				(1 << 14)
+#define	TIMROT_TIMCTRLn_MATCH_MODE			(1 << 11)
+#define	TIMROT_TIMCTRLn_POLARITY			(1 << 8)
+#define	TIMROT_TIMCTRLn_UPDATE				(1 << 7)
+#define	TIMROT_TIMCTRLn_RELOAD				(1 << 6)
+#define	TIMROT_TIMCTRLn_PRESCALE_MASK			(0x3 << 4)
+#define	TIMROT_TIMCTRLn_PRESCALE_OFFSET			4
+#define	TIMROT_TIMCTRLn_PRESCALE_DIV_BY_1		(0x0 << 4)
+#define	TIMROT_TIMCTRLn_PRESCALE_DIV_BY_2		(0x1 << 4)
+#define	TIMROT_TIMCTRLn_PRESCALE_DIV_BY_4		(0x2 << 4)
+#define	TIMROT_TIMCTRLn_PRESCALE_DIV_BY_8		(0x3 << 4)
+#define	TIMROT_TIMCTRLn_SELECT_MASK			0xf
+#define	TIMROT_TIMCTRLn_SELECT_OFFSET			0
+#define	TIMROT_TIMCTRLn_SELECT_NEVER_TICK		0x0
+#define	TIMROT_TIMCTRLn_SELECT_PWM0			0x1
+#define	TIMROT_TIMCTRLn_SELECT_PWM1			0x2
+#define	TIMROT_TIMCTRLn_SELECT_PWM2			0x3
+#define	TIMROT_TIMCTRLn_SELECT_PWM3			0x4
+#define	TIMROT_TIMCTRLn_SELECT_PWM4			0x5
+#define	TIMROT_TIMCTRLn_SELECT_PWM5			0x6
+#define	TIMROT_TIMCTRLn_SELECT_PWM6			0x7
+#define	TIMROT_TIMCTRLn_SELECT_PWM7			0x8
+#define	TIMROT_TIMCTRLn_SELECT_ROTARYA			0x9
+#define	TIMROT_TIMCTRLn_SELECT_ROTARYB			0xa
+#define	TIMROT_TIMCTRLn_SELECT_32KHZ_XTAL		0xb
+#define	TIMROT_TIMCTRLn_SELECT_8KHZ_XTAL		0xc
+#define	TIMROT_TIMCTRLn_SELECT_4KHZ_XTAL		0xd
+#define	TIMROT_TIMCTRLn_SELECT_1KHZ_XTAL		0xe
+#define	TIMROT_TIMCTRLn_SELECT_TICK_ALWAYS		0xf
+
+#define	TIMROT_RUNNING_COUNTn_RUNNING_COUNT_MASK	0xffffffff
+#define	TIMROT_RUNNING_COUNTn_RUNNING_COUNT_OFFSET	0
+
+#define	TIMROT_FIXED_COUNTn_FIXED_COUNT_MASK		0xffffffff
+#define	TIMROT_FIXED_COUNTn_FIXED_COUNT_OFFSET		0
+
+#define	TIMROT_MATCH_COUNTn_MATCH_COUNT_MASK		0xffffffff
+#define	TIMROT_MATCH_COUNTn_MATCH_COUNT_OFFSET		0
+
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_MASK		(0xf << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_OFFSET		16
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_NEVER_TICK		(0x0 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM0		(0x1 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM1		(0x2 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM2		(0x3 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM3		(0x4 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM4		(0x5 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM5		(0x6 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM6		(0x7 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_PWM7		(0x8 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_ROTARYA		(0x9 << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_ROTARYB		(0xa << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_32KHZ_XTAL		(0xb << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_8KHZ_XTAL		(0xc << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_4KHZ_XTAL		(0xd << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_1KHZ_XTAL		(0xe << 16)
+#define	TIMROT_TIMCTRL3_TEST_SIGNAL_TICK_ALWAYS		(0xf << 16)
+#define	TIMROT_TIMCTRL3_DUTY_CYCLE			(1 << 9)
+
+#define	TIMROT_VERSION_MAJOR_MASK			(0xff << 24)
+#define	TIMROT_VERSION_MAJOR_OFFSET			24
+#define	TIMROT_VERSION_MINOR_MASK			(0xff << 16)
+#define	TIMROT_VERSION_MINOR_OFFSET			16
+#define	TIMROT_VERSION_STEP_MASK			0xffff
+#define	TIMROT_VERSION_STEP_OFFSET			0
+
+#endif /* __MX28_REGS_TIMROT_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/sys_proto.h b/arch/arm/include/asm/arch-mx28/sys_proto.h
new file mode 100644
index 0000000..a262c05
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/sys_proto.h
@@ -0,0 +1,30 @@
+/*
+ * Freescale i.MX28 MX28 specific functions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __MX28_H__
+#define __MX28_H__
+
+int mx28_reset_block(struct mx28_register *reg);
+int mx28_wait_mask_set(struct mx28_register *reg, uint32_t mask, int timeout);
+int mx28_wait_mask_clr(struct mx28_register *reg, uint32_t mask, int timeout);
+
+#endif	/* __MX28_H__ */
-- 
1.7.6.3

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

* [U-Boot] [PATCH 02/17 RESEND] iMX28: Add SSP MMC driver
  2011-10-21 22:44 ` [U-Boot] [PATCH 00/17 V3] Support for the DENX M28 SoM Marek Vasut
  2011-10-21 22:44   ` [U-Boot] [PATCH 01/17 RESEND V5] iMX28: Initial support for iMX28 CPU Marek Vasut
@ 2011-10-21 22:44   ` Marek Vasut
  2011-11-08 20:45     ` Andy Fleming
  2011-10-21 22:44   ` [U-Boot] [PATCH 03/17 RESEND] FEC: Add support for iMX28 quirks Marek Vasut
                     ` (14 subsequent siblings)
  16 siblings, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-10-21 22:44 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Andy Fleming <afleming@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 arch/arm/include/asm/arch-mx28/sys_proto.h |    2 +
 drivers/mmc/Makefile                       |    1 +
 drivers/mmc/mxsmmc.c                       |  351 ++++++++++++++++++++++++++++
 3 files changed, 354 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mmc/mxsmmc.c

diff --git a/arch/arm/include/asm/arch-mx28/sys_proto.h b/arch/arm/include/asm/arch-mx28/sys_proto.h
index a262c05..a226ea4 100644
--- a/arch/arm/include/asm/arch-mx28/sys_proto.h
+++ b/arch/arm/include/asm/arch-mx28/sys_proto.h
@@ -27,4 +27,6 @@ int mx28_reset_block(struct mx28_register *reg);
 int mx28_wait_mask_set(struct mx28_register *reg, uint32_t mask, int timeout);
 int mx28_wait_mask_clr(struct mx28_register *reg, uint32_t mask, int timeout);
 
+int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int));
+
 #endif	/* __MX28_H__ */
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 6e94860..550d289 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -36,6 +36,7 @@ COBJS-$(CONFIG_MMC_SPI) += mmc_spi.o
 COBJS-$(CONFIG_ARM_PL180_MMCI) += arm_pl180_mmci.o
 COBJS-$(CONFIG_MV_SDHCI) += mv_sdhci.o
 COBJS-$(CONFIG_MXC_MMC) += mxcmmc.o
+COBJS-$(CONFIG_MXS_MMC) += mxsmmc.o
 COBJS-$(CONFIG_OMAP_HSMMC) += omap_hsmmc.o
 COBJS-$(CONFIG_PXA_MMC) += pxa_mmc.o
 COBJS-$(CONFIG_S5P_MMC) += s5p_mmc.o
diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c
new file mode 100644
index 0000000..2a9949e
--- /dev/null
+++ b/drivers/mmc/mxsmmc.c
@@ -0,0 +1,351 @@
+/*
+ * Freescale i.MX28 SSP MMC driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * (C) Copyright 2008-2010 Freescale Semiconductor, Inc.
+ * Terry Lv
+ *
+ * Copyright 2007, Freescale Semiconductor, Inc
+ * Andy Fleming
+ *
+ * Based vaguely on the pxa mmc code:
+ * (C) Copyright 2003
+ * Kyle Harris, Nexus Technologies, Inc. kharris at nexus-tech.net
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#include <common.h>
+#include <malloc.h>
+#include <mmc.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+
+struct mxsmmc_priv {
+	int			id;
+	struct mx28_ssp_regs	*regs;
+	uint32_t		clkseq_bypass;
+	uint32_t		*clkctrl_ssp;
+	uint32_t		buswidth;
+	int			(*mmc_is_wp)(int);
+};
+
+#define	MXSMMC_MAX_TIMEOUT	10000
+
+/*
+ * Sends a command out on the bus.  Takes the mmc pointer,
+ * a command pointer, and an optional data pointer.
+ */
+static int
+mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
+{
+	struct mxsmmc_priv *priv = (struct mxsmmc_priv *)mmc->priv;
+	struct mx28_ssp_regs *ssp_regs = priv->regs;
+	uint32_t reg;
+	int timeout;
+	uint32_t data_count;
+	uint32_t *data_ptr;
+	uint32_t ctrl0;
+
+	debug("MMC%d: CMD%d\n", mmc->block_dev.dev, cmd->cmdidx);
+
+	/* Check bus busy */
+	timeout = MXSMMC_MAX_TIMEOUT;
+	while (--timeout) {
+		udelay(1000);
+		reg = readl(&ssp_regs->hw_ssp_status);
+		if (!(reg &
+			(SSP_STATUS_BUSY | SSP_STATUS_DATA_BUSY |
+			SSP_STATUS_CMD_BUSY))) {
+			break;
+		}
+	}
+
+	if (!timeout) {
+		printf("MMC%d: Bus busy timeout!\n", mmc->block_dev.dev);
+		return TIMEOUT;
+	}
+
+	/* See if card is present */
+	if (readl(&ssp_regs->hw_ssp_status) & SSP_STATUS_CARD_DETECT) {
+		printf("MMC%d: No card detected!\n", mmc->block_dev.dev);
+		return NO_CARD_ERR;
+	}
+
+	/* Start building CTRL0 contents */
+	ctrl0 = priv->buswidth;
+
+	/* Set up command */
+	if (!(cmd->resp_type & MMC_RSP_CRC))
+		ctrl0 |= SSP_CTRL0_IGNORE_CRC;
+	if (cmd->resp_type & MMC_RSP_PRESENT)	/* Need to get response */
+		ctrl0 |= SSP_CTRL0_GET_RESP;
+	if (cmd->resp_type & MMC_RSP_136)	/* It's a 136 bits response */
+		ctrl0 |= SSP_CTRL0_LONG_RESP;
+
+	/* Command index */
+	reg = readl(&ssp_regs->hw_ssp_cmd0);
+	reg &= ~(SSP_CMD0_CMD_MASK | SSP_CMD0_APPEND_8CYC);
+	reg |= cmd->cmdidx << SSP_CMD0_CMD_OFFSET;
+	if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
+		reg |= SSP_CMD0_APPEND_8CYC;
+	writel(reg, &ssp_regs->hw_ssp_cmd0);
+
+	/* Command argument */
+	writel(cmd->cmdarg, &ssp_regs->hw_ssp_cmd1);
+
+	/* Set up data */
+	if (data) {
+		/* READ or WRITE */
+		if (data->flags & MMC_DATA_READ) {
+			ctrl0 |= SSP_CTRL0_READ;
+		} else if (priv->mmc_is_wp(mmc->block_dev.dev)) {
+			printf("MMC%d: Can not write a locked card!\n",
+				mmc->block_dev.dev);
+			return UNUSABLE_ERR;
+		}
+
+		ctrl0 |= SSP_CTRL0_DATA_XFER;
+		reg = ((data->blocks - 1) <<
+			SSP_BLOCK_SIZE_BLOCK_COUNT_OFFSET) |
+			((ffs(data->blocksize) - 1) <<
+			SSP_BLOCK_SIZE_BLOCK_SIZE_OFFSET);
+		writel(reg, &ssp_regs->hw_ssp_block_size);
+
+		reg = data->blocksize * data->blocks;
+		writel(reg, &ssp_regs->hw_ssp_xfer_size);
+	}
+
+	/* Kick off the command */
+	ctrl0 |= SSP_CTRL0_WAIT_FOR_IRQ | SSP_CTRL0_ENABLE | SSP_CTRL0_RUN;
+	writel(ctrl0, &ssp_regs->hw_ssp_ctrl0);
+
+	/* Wait for the command to complete */
+	timeout = MXSMMC_MAX_TIMEOUT;
+	while (--timeout) {
+		udelay(1000);
+		reg = readl(&ssp_regs->hw_ssp_status);
+		if (!(reg & SSP_STATUS_CMD_BUSY))
+			break;
+	}
+
+	if (!timeout) {
+		printf("MMC%d: Command %d busy\n",
+			mmc->block_dev.dev, cmd->cmdidx);
+		return TIMEOUT;
+	}
+
+	/* Check command timeout */
+	if (reg & SSP_STATUS_RESP_TIMEOUT) {
+		printf("MMC%d: Command %d timeout (status 0x%08x)\n",
+			mmc->block_dev.dev, cmd->cmdidx, reg);
+		return TIMEOUT;
+	}
+
+	/* Check command errors */
+	if (reg & (SSP_STATUS_RESP_CRC_ERR | SSP_STATUS_RESP_ERR)) {
+		printf("MMC%d: Command %d error (status 0x%08x)!\n",
+			mmc->block_dev.dev, cmd->cmdidx, reg);
+		return COMM_ERR;
+	}
+
+	/* Copy response to response buffer */
+	if (cmd->resp_type & MMC_RSP_136) {
+		cmd->response[3] = readl(&ssp_regs->hw_ssp_sdresp0);
+		cmd->response[2] = readl(&ssp_regs->hw_ssp_sdresp1);
+		cmd->response[1] = readl(&ssp_regs->hw_ssp_sdresp2);
+		cmd->response[0] = readl(&ssp_regs->hw_ssp_sdresp3);
+	} else
+		cmd->response[0] = readl(&ssp_regs->hw_ssp_sdresp0);
+
+	/* Return if no data to process */
+	if (!data)
+		return 0;
+
+	/* Process the data */
+	data_count = data->blocksize * data->blocks;
+	timeout = MXSMMC_MAX_TIMEOUT;
+	if (data->flags & MMC_DATA_READ) {
+		data_ptr = (uint32_t *)data->dest;
+		while (data_count && --timeout) {
+			reg = readl(&ssp_regs->hw_ssp_status);
+			if (!(reg & SSP_STATUS_FIFO_EMPTY)) {
+				*data_ptr++ = readl(&ssp_regs->hw_ssp_data);
+				data_count -= 4;
+				timeout = MXSMMC_MAX_TIMEOUT;
+			} else
+				udelay(1000);
+		}
+	} else {
+		data_ptr = (uint32_t *)data->src;
+		timeout *= 100;
+		while (data_count && --timeout) {
+			reg = readl(&ssp_regs->hw_ssp_status);
+			if (!(reg & SSP_STATUS_FIFO_FULL)) {
+				writel(*data_ptr++, &ssp_regs->hw_ssp_data);
+				data_count -= 4;
+				timeout = MXSMMC_MAX_TIMEOUT;
+			} else
+				udelay(1000);
+		}
+	}
+
+	if (!timeout) {
+		printf("MMC%d: Data timeout with command %d (status 0x%08x)!\n",
+			mmc->block_dev.dev, cmd->cmdidx, reg);
+		return COMM_ERR;
+	}
+
+	/* Check data errors */
+	reg = readl(&ssp_regs->hw_ssp_status);
+	if (reg &
+		(SSP_STATUS_TIMEOUT | SSP_STATUS_DATA_CRC_ERR |
+		SSP_STATUS_FIFO_OVRFLW | SSP_STATUS_FIFO_UNDRFLW)) {
+		printf("MMC%d: Data error with command %d (status 0x%08x)!\n",
+			mmc->block_dev.dev, cmd->cmdidx, reg);
+		return COMM_ERR;
+	}
+
+	return 0;
+}
+
+static void mxsmmc_set_ios(struct mmc *mmc)
+{
+	struct mxsmmc_priv *priv = (struct mxsmmc_priv *)mmc->priv;
+	struct mx28_ssp_regs *ssp_regs = priv->regs;
+
+	/* Set the clock speed */
+	if (mmc->clock)
+		mx28_set_ssp_busclock(priv->id, mmc->clock / 1000);
+
+	switch (mmc->bus_width) {
+	case 1:
+		priv->buswidth = SSP_CTRL0_BUS_WIDTH_ONE_BIT;
+		break;
+	case 4:
+		priv->buswidth = SSP_CTRL0_BUS_WIDTH_FOUR_BIT;
+		break;
+	case 8:
+		priv->buswidth = SSP_CTRL0_BUS_WIDTH_EIGHT_BIT;
+		break;
+	}
+
+	/* Set the bus width */
+	clrsetbits_le32(&ssp_regs->hw_ssp_ctrl0,
+			SSP_CTRL0_BUS_WIDTH_MASK, priv->buswidth);
+
+	debug("MMC%d: Set %d bits bus width\n",
+		mmc->block_dev.dev, mmc->bus_width);
+}
+
+static int mxsmmc_init(struct mmc *mmc)
+{
+	struct mxsmmc_priv *priv = (struct mxsmmc_priv *)mmc->priv;
+	struct mx28_ssp_regs *ssp_regs = priv->regs;
+
+	/* Reset SSP */
+	mx28_reset_block(&ssp_regs->hw_ssp_ctrl0_reg);
+
+	/* 8 bits word length in MMC mode */
+	clrsetbits_le32(&ssp_regs->hw_ssp_ctrl1,
+		SSP_CTRL1_SSP_MODE_MASK | SSP_CTRL1_WORD_LENGTH_MASK,
+		SSP_CTRL1_SSP_MODE_SD_MMC | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS);
+
+	/* Set initial bit clock 400 KHz */
+	mx28_set_ssp_busclock(priv->id, 400);
+
+	/* Send initial 74 clock cycles (185 us @ 400 KHz)*/
+	writel(SSP_CMD0_CONT_CLKING_EN, &ssp_regs->hw_ssp_cmd0_set);
+	udelay(200);
+	writel(SSP_CMD0_CONT_CLKING_EN, &ssp_regs->hw_ssp_cmd0_clr);
+
+	return 0;
+}
+
+int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int))
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	struct mmc *mmc = NULL;
+	struct mxsmmc_priv *priv = NULL;
+
+	mmc = malloc(sizeof(struct mmc));
+	if (!mmc)
+		return -ENOMEM;
+
+	priv = malloc(sizeof(struct mxsmmc_priv));
+	if (!priv) {
+		free(mmc);
+		return -ENOMEM;
+	}
+
+	priv->mmc_is_wp = wp;
+	priv->id = id;
+	switch (id) {
+	case 0:
+		priv->regs = (struct mx28_ssp_regs *)MXS_SSP0_BASE;
+		priv->clkseq_bypass = CLKCTRL_CLKSEQ_BYPASS_SSP0;
+		priv->clkctrl_ssp = &clkctrl_regs->hw_clkctrl_ssp0;
+		break;
+	case 1:
+		priv->regs = (struct mx28_ssp_regs *)MXS_SSP1_BASE;
+		priv->clkseq_bypass = CLKCTRL_CLKSEQ_BYPASS_SSP1;
+		priv->clkctrl_ssp = &clkctrl_regs->hw_clkctrl_ssp1;
+		break;
+	case 2:
+		priv->regs = (struct mx28_ssp_regs *)MXS_SSP2_BASE;
+		priv->clkseq_bypass = CLKCTRL_CLKSEQ_BYPASS_SSP2;
+		priv->clkctrl_ssp = &clkctrl_regs->hw_clkctrl_ssp2;
+		break;
+	case 3:
+		priv->regs = (struct mx28_ssp_regs *)MXS_SSP3_BASE;
+		priv->clkseq_bypass = CLKCTRL_CLKSEQ_BYPASS_SSP3;
+		priv->clkctrl_ssp = &clkctrl_regs->hw_clkctrl_ssp3;
+		break;
+	}
+
+	sprintf(mmc->name, "MXS MMC");
+	mmc->send_cmd = mxsmmc_send_cmd;
+	mmc->set_ios = mxsmmc_set_ios;
+	mmc->init = mxsmmc_init;
+	mmc->priv = priv;
+
+	mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
+
+	mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT |
+			 MMC_MODE_HS_52MHz | MMC_MODE_HS;
+
+	/*
+	 * SSPCLK = 480 * 18 / 29 / 1 = 297.731 MHz
+	 * SSP bit rate = SSPCLK / (CLOCK_DIVIDE * (1 + CLOCK_RATE)),
+	 * CLOCK_DIVIDE has to be an even value from 2 to 254, and
+	 * CLOCK_RATE could be any integer from 0 to 255.
+	 */
+	mmc->f_min = 400000;
+	mmc->f_max = mxc_get_clock(MXC_SSP0_CLK + id) * 1000 / 2;
+	mmc->b_max = 0;
+
+	mmc_register(mmc);
+	return 0;
+}
-- 
1.7.6.3

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

* [U-Boot] [PATCH 03/17 RESEND] FEC: Add support for iMX28 quirks
  2011-10-21 22:44 ` [U-Boot] [PATCH 00/17 V3] Support for the DENX M28 SoM Marek Vasut
  2011-10-21 22:44   ` [U-Boot] [PATCH 01/17 RESEND V5] iMX28: Initial support for iMX28 CPU Marek Vasut
  2011-10-21 22:44   ` [U-Boot] [PATCH 02/17 RESEND] iMX28: Add SSP MMC driver Marek Vasut
@ 2011-10-21 22:44   ` Marek Vasut
  2011-10-21 22:44   ` [U-Boot] [PATCH 04/17 RESEND] iMX28: Add PINMUX control Marek Vasut
                     ` (13 subsequent siblings)
  16 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-10-21 22:44 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Ben Warren <biggerbadderben@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 drivers/net/fec_mxc.c |   44 ++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index cfe2176..f50433dd 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -42,6 +42,14 @@ DECLARE_GLOBAL_DATA_PTR;
 #define	CONFIG_FEC_XCV_TYPE	MII100
 #endif
 
+/*
+ * The i.MX28 operates with packets in big endian. We need to swap them before
+ * sending and after receiving.
+ */
+#ifdef	CONFIG_MX28
+#define	CONFIG_FEC_MXC_SWAP_PACKET
+#endif
+
 #undef DEBUG
 
 struct nbuf {
@@ -51,6 +59,32 @@ struct nbuf {
 	uint8_t head[16];	/**< MAC header(6 + 6 + 2) + 2(aligned) */
 };
 
+#ifdef	CONFIG_FEC_MXC_SWAP_PACKET
+static void swap_packet(uint32_t *packet, int length)
+{
+	int i;
+
+	for (i = 0; i < DIV_ROUND_UP(length, 4); i++)
+		packet[i] = __swab32(packet[i]);
+}
+#endif
+
+/*
+ * The i.MX28 has two ethernet interfaces, but they are not equal.
+ * Only the first one can access the MDIO bus.
+ */
+#ifdef	CONFIG_MX28
+static inline struct ethernet_regs *fec_miiphy_fec_to_eth(struct fec_priv *fec)
+{
+	return (struct ethernet_regs *)MXS_ENET0_BASE;
+}
+#else
+static inline struct ethernet_regs *fec_miiphy_fec_to_eth(struct fec_priv *fec)
+{
+	return fec->eth;
+}
+#endif
+
 /*
  * MII-interface related functions
  */
@@ -59,7 +93,7 @@ static int fec_miiphy_read(const char *dev, uint8_t phyAddr, uint8_t regAddr,
 {
 	struct eth_device *edev = eth_get_dev_by_name(dev);
 	struct fec_priv *fec = (struct fec_priv *)edev->priv;
-	struct ethernet_regs *eth = fec->eth;
+	struct ethernet_regs *eth = fec_miiphy_fec_to_eth(fec);
 
 	uint32_t reg;		/* convenient holder for the PHY register */
 	uint32_t phy;		/* convenient holder for the PHY */
@@ -117,7 +151,7 @@ static int fec_miiphy_write(const char *dev, uint8_t phyAddr, uint8_t regAddr,
 {
 	struct eth_device *edev = eth_get_dev_by_name(dev);
 	struct fec_priv *fec = (struct fec_priv *)edev->priv;
-	struct ethernet_regs *eth = fec->eth;
+	struct ethernet_regs *eth = fec_miiphy_fec_to_eth(fec);
 
 	uint32_t reg;		/* convenient holder for the PHY register */
 	uint32_t phy;		/* convenient holder for the PHY */
@@ -572,6 +606,9 @@ static int fec_send(struct eth_device *dev, volatile void* packet, int length)
 	 * Note: We are always using the first buffer for transmission,
 	 * the second will be empty and only used to stop the DMA engine
 	 */
+#ifdef	CONFIG_FEC_MXC_SWAP_PACKET
+	swap_packet((uint32_t *)packet, length);
+#endif
 	writew(length, &fec->tbd_base[fec->tbd_index].data_length);
 	writel((uint32_t)packet, &fec->tbd_base[fec->tbd_index].data_pointer);
 	/*
@@ -668,6 +705,9 @@ static int fec_recv(struct eth_device *dev)
 			/*
 			 *  Fill the buffer and pass it to upper layers
 			 */
+#ifdef	CONFIG_FEC_MXC_SWAP_PACKET
+			swap_packet((uint32_t *)frame->data, frame_length);
+#endif
 			memcpy(buff, frame->data, frame_length);
 			NetReceive(buff, frame_length);
 			len = frame_length;
-- 
1.7.6.3

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

* [U-Boot] [PATCH 04/17 RESEND] iMX28: Add PINMUX control
  2011-10-21 22:44 ` [U-Boot] [PATCH 00/17 V3] Support for the DENX M28 SoM Marek Vasut
                     ` (2 preceding siblings ...)
  2011-10-21 22:44   ` [U-Boot] [PATCH 03/17 RESEND] FEC: Add support for iMX28 quirks Marek Vasut
@ 2011-10-21 22:44   ` Marek Vasut
  2011-10-21 22:44   ` [U-Boot] [PATCH 05/17 RESEND V2] iMX28: Add I2C bus driver Marek Vasut
                     ` (12 subsequent siblings)
  16 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-10-21 22:44 UTC (permalink / raw)
  To: u-boot

Taken from Linux kernel with minor modifications:

commit bf985969e27b507f734435a99df8bf745a3dbb2b
Author: Shawn Guo <shawn.guo@freescale.com>
Date:   Mon Dec 20 22:57:43 2010 +0800

    ARM: mxs: Add iomux support

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 arch/arm/cpu/arm926ejs/mx28/Makefile        |    2 +-
 arch/arm/cpu/arm926ejs/mx28/iomux.c         |  109 ++++++
 arch/arm/include/asm/arch-mx28/iomux-mx28.h |  537 +++++++++++++++++++++++++++
 arch/arm/include/asm/arch-mx28/iomux.h      |  168 +++++++++
 4 files changed, 815 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/cpu/arm926ejs/mx28/iomux.c
 create mode 100644 arch/arm/include/asm/arch-mx28/iomux-mx28.h
 create mode 100644 arch/arm/include/asm/arch-mx28/iomux.h

diff --git a/arch/arm/cpu/arm926ejs/mx28/Makefile b/arch/arm/cpu/arm926ejs/mx28/Makefile
index 98504f9..7845310 100644
--- a/arch/arm/cpu/arm926ejs/mx28/Makefile
+++ b/arch/arm/cpu/arm926ejs/mx28/Makefile
@@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk
 
 LIB	= $(obj)lib$(SOC).o
 
-COBJS	= clock.o mx28.o timer.o
+COBJS	= clock.o mx28.o iomux.o timer.o
 
 SRCS	:= $(START:.o=.S) $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS))
diff --git a/arch/arm/cpu/arm926ejs/mx28/iomux.c b/arch/arm/cpu/arm926ejs/mx28/iomux.c
new file mode 100644
index 0000000..9ea411f
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/mx28/iomux.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2004-2006,2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
+ * Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH,
+ *                       <armlinux@phytec.de>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <common.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/iomux.h>
+#include <asm/arch/imx-regs.h>
+
+#if	defined(CONFIG_MX23)
+#define	DRIVE_OFFSET	0x200
+#define	PULL_OFFSET	0x400
+#elif	defined(CONFIG_MX28)
+#define	DRIVE_OFFSET	0x300
+#define	PULL_OFFSET	0x600
+#else
+#error "Please select CONFIG_MX23 or CONFIG_MX28"
+#endif
+
+/*
+ * configures a single pad in the iomuxer
+ */
+int mxs_iomux_setup_pad(iomux_cfg_t pad)
+{
+	u32 reg, ofs, bp, bm;
+	void *iomux_base = (void *)MXS_PINCTRL_BASE;
+	struct mx28_register *mxs_reg;
+
+	/* muxsel */
+	ofs = 0x100;
+	ofs += PAD_BANK(pad) * 0x20 + PAD_PIN(pad) / 16 * 0x10;
+	bp = PAD_PIN(pad) % 16 * 2;
+	bm = 0x3 << bp;
+	reg = readl(iomux_base + ofs);
+	reg &= ~bm;
+	reg |= PAD_MUXSEL(pad) << bp;
+	writel(reg, iomux_base + ofs);
+
+	/* drive */
+	ofs = DRIVE_OFFSET;
+	ofs += PAD_BANK(pad) * 0x40 + PAD_PIN(pad) / 8 * 0x10;
+	/* mA */
+	if (PAD_MA_VALID(pad)) {
+		bp = PAD_PIN(pad) % 8 * 4;
+		bm = 0x3 << bp;
+		reg = readl(iomux_base + ofs);
+		reg &= ~bm;
+		reg |= PAD_MA(pad) << bp;
+		writel(reg, iomux_base + ofs);
+	}
+	/* vol */
+	if (PAD_VOL_VALID(pad)) {
+		bp = PAD_PIN(pad) % 8 * 4 + 2;
+		mxs_reg = (struct mx28_register *)(iomux_base + ofs);
+		if (PAD_VOL(pad))
+			writel(1 << bp, &mxs_reg->reg_set);
+		else
+			writel(1 << bp, &mxs_reg->reg_clr);
+	}
+
+	/* pull */
+	if (PAD_PULL_VALID(pad)) {
+		ofs = PULL_OFFSET;
+		ofs += PAD_BANK(pad) * 0x10;
+		bp = PAD_PIN(pad);
+		mxs_reg = (struct mx28_register *)(iomux_base + ofs);
+		if (PAD_PULL(pad))
+			writel(1 << bp, &mxs_reg->reg_set);
+		else
+			writel(1 << bp, &mxs_reg->reg_clr);
+	}
+
+	return 0;
+}
+
+int mxs_iomux_setup_multiple_pads(const iomux_cfg_t *pad_list, unsigned count)
+{
+	const iomux_cfg_t *p = pad_list;
+	int i;
+	int ret;
+
+	for (i = 0; i < count; i++) {
+		ret = mxs_iomux_setup_pad(*p);
+		if (ret)
+			return ret;
+		p++;
+	}
+
+	return 0;
+}
diff --git a/arch/arm/include/asm/arch-mx28/iomux-mx28.h b/arch/arm/include/asm/arch-mx28/iomux-mx28.h
new file mode 100644
index 0000000..b42820d
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/iomux-mx28.h
@@ -0,0 +1,537 @@
+/*
+ * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * 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
+ */
+
+#ifndef __MACH_IOMUX_MX28_H__
+#define __MACH_IOMUX_MX28_H__
+
+#include <asm/arch/iomux.h>
+
+/*
+ * The naming convention for the pad modes is MX28_PAD_<padname>__<padmode>
+ * If <padname> or <padmode> refers to a GPIO, it is named GPIO_<unit>_<num>
+ * See also iomux.h
+ *
+ *									BANK	PIN	MUX
+ */
+/* MUXSEL_0 */
+#define MX28_PAD_GPMI_D00__GPMI_D0			MXS_IOMUX_PAD_NAKED(0,  0, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_D01__GPMI_D1			MXS_IOMUX_PAD_NAKED(0,  1, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_D02__GPMI_D2			MXS_IOMUX_PAD_NAKED(0,  2, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_D03__GPMI_D3			MXS_IOMUX_PAD_NAKED(0,  3, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_D04__GPMI_D4			MXS_IOMUX_PAD_NAKED(0,  4, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_D05__GPMI_D5			MXS_IOMUX_PAD_NAKED(0,  5, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_D06__GPMI_D6			MXS_IOMUX_PAD_NAKED(0,  6, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_D07__GPMI_D7			MXS_IOMUX_PAD_NAKED(0,  7, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_CE0N__GPMI_CE0N			MXS_IOMUX_PAD_NAKED(0, 16, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_CE1N__GPMI_CE1N			MXS_IOMUX_PAD_NAKED(0, 17, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_CE2N__GPMI_CE2N			MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_CE3N__GPMI_CE3N			MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_RDY0__GPMI_READY0			MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_RDY1__GPMI_READY1			MXS_IOMUX_PAD_NAKED(0, 21, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_RDY2__GPMI_READY2			MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_RDY3__GPMI_READY3			MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_RDN__GPMI_RDN			MXS_IOMUX_PAD_NAKED(0, 24, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_WRN__GPMI_WRN			MXS_IOMUX_PAD_NAKED(0, 25, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_ALE__GPMI_ALE			MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_CLE__GPMI_CLE			MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_0)
+#define MX28_PAD_GPMI_RESETN__GPMI_RESETN		MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_0)
+
+#define MX28_PAD_LCD_D00__LCD_D0			MXS_IOMUX_PAD_NAKED(1,  0, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D01__LCD_D1			MXS_IOMUX_PAD_NAKED(1,  1, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D02__LCD_D2			MXS_IOMUX_PAD_NAKED(1,  2, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D03__LCD_D3			MXS_IOMUX_PAD_NAKED(1,  3, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D04__LCD_D4			MXS_IOMUX_PAD_NAKED(1,  4, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D05__LCD_D5			MXS_IOMUX_PAD_NAKED(1,  5, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D06__LCD_D6			MXS_IOMUX_PAD_NAKED(1,  6, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D07__LCD_D7			MXS_IOMUX_PAD_NAKED(1,  7, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D08__LCD_D8			MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D09__LCD_D9			MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D10__LCD_D10			MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D11__LCD_D11			MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D12__LCD_D12			MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D13__LCD_D13			MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D14__LCD_D14			MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D15__LCD_D15			MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D16__LCD_D16			MXS_IOMUX_PAD_NAKED(1, 16, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D17__LCD_D17			MXS_IOMUX_PAD_NAKED(1, 17, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D18__LCD_D18			MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D19__LCD_D19			MXS_IOMUX_PAD_NAKED(1, 19, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D20__LCD_D20			MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D21__LCD_D21			MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D22__LCD_D22			MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_D23__LCD_D23			MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_RD_E__LCD_RD_E			MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_WR_RWN__LCD_WR_RWN			MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_RS__LCD_RS				MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_CS__LCD_CS				MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_VSYNC__LCD_VSYNC			MXS_IOMUX_PAD_NAKED(1, 28, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_HSYNC__LCD_HSYNC			MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_DOTCLK__LCD_DOTCLK			MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_ENABLE__LCD_ENABLE			MXS_IOMUX_PAD_NAKED(1, 31, PAD_MUXSEL_0)
+
+#define MX28_PAD_SSP0_DATA0__SSP0_D0			MXS_IOMUX_PAD_NAKED(2,  0, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_DATA1__SSP0_D1			MXS_IOMUX_PAD_NAKED(2,  1, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_DATA2__SSP0_D2			MXS_IOMUX_PAD_NAKED(2,  2, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_DATA3__SSP0_D3			MXS_IOMUX_PAD_NAKED(2,  3, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_DATA4__SSP0_D4			MXS_IOMUX_PAD_NAKED(2,  4, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_DATA5__SSP0_D5			MXS_IOMUX_PAD_NAKED(2,  5, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_DATA6__SSP0_D6			MXS_IOMUX_PAD_NAKED(2,  6, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_DATA7__SSP0_D7			MXS_IOMUX_PAD_NAKED(2,  7, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_CMD__SSP0_CMD			MXS_IOMUX_PAD_NAKED(2,  8, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT		MXS_IOMUX_PAD_NAKED(2,  9, PAD_MUXSEL_0)
+#define MX28_PAD_SSP0_SCK__SSP0_SCK			MXS_IOMUX_PAD_NAKED(2, 10, PAD_MUXSEL_0)
+#define MX28_PAD_SSP1_SCK__SSP1_SCK			MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_0)
+#define MX28_PAD_SSP1_CMD__SSP1_CMD			MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_0)
+#define MX28_PAD_SSP1_DATA0__SSP1_D0			MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_0)
+#define MX28_PAD_SSP1_DATA3__SSP1_D3			MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_0)
+#define MX28_PAD_SSP2_SCK__SSP2_SCK			MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_0)
+#define MX28_PAD_SSP2_MOSI__SSP2_CMD			MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_0)
+#define MX28_PAD_SSP2_MISO__SSP2_D0			MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_0)
+#define MX28_PAD_SSP2_SS0__SSP2_D3			MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_0)
+#define MX28_PAD_SSP2_SS1__SSP2_D4			MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_0)
+#define MX28_PAD_SSP2_SS2__SSP2_D5			MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_0)
+#define MX28_PAD_SSP3_SCK__SSP3_SCK			MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_0)
+#define MX28_PAD_SSP3_MOSI__SSP3_CMD			MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_0)
+#define MX28_PAD_SSP3_MISO__SSP3_D0			MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_0)
+#define MX28_PAD_SSP3_SS0__SSP3_D3			MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_0)
+
+#define MX28_PAD_AUART0_RX__AUART0_RX			MXS_IOMUX_PAD_NAKED(3,  0, PAD_MUXSEL_0)
+#define MX28_PAD_AUART0_TX__AUART0_TX			MXS_IOMUX_PAD_NAKED(3,  1, PAD_MUXSEL_0)
+#define MX28_PAD_AUART0_CTS__AUART0_CTS			MXS_IOMUX_PAD_NAKED(3,  2, PAD_MUXSEL_0)
+#define MX28_PAD_AUART0_RTS__AUART0_RTS			MXS_IOMUX_PAD_NAKED(3,  3, PAD_MUXSEL_0)
+#define MX28_PAD_AUART1_RX__AUART1_RX			MXS_IOMUX_PAD_NAKED(3,  4, PAD_MUXSEL_0)
+#define MX28_PAD_AUART1_TX__AUART1_TX			MXS_IOMUX_PAD_NAKED(3,  5, PAD_MUXSEL_0)
+#define MX28_PAD_AUART1_CTS__AUART1_CTS			MXS_IOMUX_PAD_NAKED(3,  6, PAD_MUXSEL_0)
+#define MX28_PAD_AUART1_RTS__AUART1_RTS			MXS_IOMUX_PAD_NAKED(3,  7, PAD_MUXSEL_0)
+#define MX28_PAD_AUART2_RX__AUART2_RX			MXS_IOMUX_PAD_NAKED(3,  8, PAD_MUXSEL_0)
+#define MX28_PAD_AUART2_TX__AUART2_TX			MXS_IOMUX_PAD_NAKED(3,  9, PAD_MUXSEL_0)
+#define MX28_PAD_AUART2_CTS__AUART2_CTS			MXS_IOMUX_PAD_NAKED(3, 10, PAD_MUXSEL_0)
+#define MX28_PAD_AUART2_RTS__AUART2_RTS			MXS_IOMUX_PAD_NAKED(3, 11, PAD_MUXSEL_0)
+#define MX28_PAD_AUART3_RX__AUART3_RX			MXS_IOMUX_PAD_NAKED(3, 12, PAD_MUXSEL_0)
+#define MX28_PAD_AUART3_TX__AUART3_TX			MXS_IOMUX_PAD_NAKED(3, 13, PAD_MUXSEL_0)
+#define MX28_PAD_AUART3_CTS__AUART3_CTS			MXS_IOMUX_PAD_NAKED(3, 14, PAD_MUXSEL_0)
+#define MX28_PAD_AUART3_RTS__AUART3_RTS			MXS_IOMUX_PAD_NAKED(3, 15, PAD_MUXSEL_0)
+#define MX28_PAD_PWM0__PWM_0				MXS_IOMUX_PAD_NAKED(3, 16, PAD_MUXSEL_0)
+#define MX28_PAD_PWM1__PWM_1				MXS_IOMUX_PAD_NAKED(3, 17, PAD_MUXSEL_0)
+#define MX28_PAD_PWM2__PWM_2				MXS_IOMUX_PAD_NAKED(3, 18, PAD_MUXSEL_0)
+#define MX28_PAD_SAIF0_MCLK__SAIF0_MCLK			MXS_IOMUX_PAD_NAKED(3, 20, PAD_MUXSEL_0)
+#define MX28_PAD_SAIF0_LRCLK__SAIF0_LRCLK		MXS_IOMUX_PAD_NAKED(3, 21, PAD_MUXSEL_0)
+#define MX28_PAD_SAIF0_BITCLK__SAIF0_BITCLK		MXS_IOMUX_PAD_NAKED(3, 22, PAD_MUXSEL_0)
+#define MX28_PAD_SAIF0_SDATA0__SAIF0_SDATA0		MXS_IOMUX_PAD_NAKED(3, 23, PAD_MUXSEL_0)
+#define MX28_PAD_I2C0_SCL__I2C0_SCL			MXS_IOMUX_PAD_NAKED(3, 24, PAD_MUXSEL_0)
+#define MX28_PAD_I2C0_SDA__I2C0_SDA			MXS_IOMUX_PAD_NAKED(3, 25, PAD_MUXSEL_0)
+#define MX28_PAD_SAIF1_SDATA0__SAIF1_SDATA0		MXS_IOMUX_PAD_NAKED(3, 26, PAD_MUXSEL_0)
+#define MX28_PAD_SPDIF__SPDIF_TX			MXS_IOMUX_PAD_NAKED(3, 27, PAD_MUXSEL_0)
+#define MX28_PAD_PWM3__PWM_3				MXS_IOMUX_PAD_NAKED(3, 28, PAD_MUXSEL_0)
+#define MX28_PAD_PWM4__PWM_4				MXS_IOMUX_PAD_NAKED(3, 29, PAD_MUXSEL_0)
+#define MX28_PAD_LCD_RESET__LCD_RESET			MXS_IOMUX_PAD_NAKED(3, 30, PAD_MUXSEL_0)
+
+#define MX28_PAD_ENET0_MDC__ENET0_MDC			MXS_IOMUX_PAD_NAKED(4,  0, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_MDIO__ENET0_MDIO			MXS_IOMUX_PAD_NAKED(4,  1, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_RX_EN__ENET0_RX_EN		MXS_IOMUX_PAD_NAKED(4,  2, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_RXD0__ENET0_RXD0			MXS_IOMUX_PAD_NAKED(4,  3, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_RXD1__ENET0_RXD1			MXS_IOMUX_PAD_NAKED(4,  4, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_TX_CLK__ENET0_TX_CLK		MXS_IOMUX_PAD_NAKED(4,  5, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_TX_EN__ENET0_TX_EN		MXS_IOMUX_PAD_NAKED(4,  6, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_TXD0__ENET0_TXD0			MXS_IOMUX_PAD_NAKED(4,  7, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_TXD1__ENET0_TXD1			MXS_IOMUX_PAD_NAKED(4,  8, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_RXD2__ENET0_RXD2			MXS_IOMUX_PAD_NAKED(4,  9, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_RXD3__ENET0_RXD3			MXS_IOMUX_PAD_NAKED(4, 10, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_TXD2__ENET0_TXD2			MXS_IOMUX_PAD_NAKED(4, 11, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_TXD3__ENET0_TXD3			MXS_IOMUX_PAD_NAKED(4, 12, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_RX_CLK__ENET0_RX_CLK		MXS_IOMUX_PAD_NAKED(4, 13, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_COL__ENET0_COL			MXS_IOMUX_PAD_NAKED(4, 14, PAD_MUXSEL_0)
+#define MX28_PAD_ENET0_CRS__ENET0_CRS			MXS_IOMUX_PAD_NAKED(4, 15, PAD_MUXSEL_0)
+#define MX28_PAD_ENET_CLK__CLKCTRL_ENET			MXS_IOMUX_PAD_NAKED(4, 16, PAD_MUXSEL_0)
+#define MX28_PAD_JTAG_RTCK__JTAG_RTCK			MXS_IOMUX_PAD_NAKED(4, 20, PAD_MUXSEL_0)
+
+#define MX28_PAD_EMI_D00__EMI_DATA0			MXS_IOMUX_PAD_NAKED(5,  0, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D01__EMI_DATA1			MXS_IOMUX_PAD_NAKED(5,  1, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D02__EMI_DATA2			MXS_IOMUX_PAD_NAKED(5,  2, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D03__EMI_DATA3			MXS_IOMUX_PAD_NAKED(5,  3, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D04__EMI_DATA4			MXS_IOMUX_PAD_NAKED(5,  4, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D05__EMI_DATA5			MXS_IOMUX_PAD_NAKED(5,  5, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D06__EMI_DATA6			MXS_IOMUX_PAD_NAKED(5,  6, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D07__EMI_DATA7			MXS_IOMUX_PAD_NAKED(5,  7, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D08__EMI_DATA8			MXS_IOMUX_PAD_NAKED(5,  8, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D09__EMI_DATA9			MXS_IOMUX_PAD_NAKED(5,  9, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D10__EMI_DATA10			MXS_IOMUX_PAD_NAKED(5, 10, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D11__EMI_DATA11			MXS_IOMUX_PAD_NAKED(5, 11, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D12__EMI_DATA12			MXS_IOMUX_PAD_NAKED(5, 12, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D13__EMI_DATA13			MXS_IOMUX_PAD_NAKED(5, 13, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D14__EMI_DATA14			MXS_IOMUX_PAD_NAKED(5, 14, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_D15__EMI_DATA15			MXS_IOMUX_PAD_NAKED(5, 15, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_ODT0__EMI_ODT0			MXS_IOMUX_PAD_NAKED(5, 16, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_DQM0__EMI_DQM0			MXS_IOMUX_PAD_NAKED(5, 17, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_ODT1__EMI_ODT1			MXS_IOMUX_PAD_NAKED(5, 18, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_DQM1__EMI_DQM1			MXS_IOMUX_PAD_NAKED(5, 19, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_DDR_OPEN_FB__EMI_DDR_OPEN_FEEDBACK	MXS_IOMUX_PAD_NAKED(5, 20, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_CLK__EMI_CLK			MXS_IOMUX_PAD_NAKED(5, 21, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_DQS0__EMI_DQS0			MXS_IOMUX_PAD_NAKED(5, 22, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_DQS1__EMI_DQS1			MXS_IOMUX_PAD_NAKED(5, 23, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_DDR_OPEN__EMI_DDR_OPEN		MXS_IOMUX_PAD_NAKED(5, 26, PAD_MUXSEL_0)
+
+#define MX28_PAD_EMI_A00__EMI_ADDR0			MXS_IOMUX_PAD_NAKED(6,  0, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A01__EMI_ADDR1			MXS_IOMUX_PAD_NAKED(6,  1, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A02__EMI_ADDR2			MXS_IOMUX_PAD_NAKED(6,  2, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A03__EMI_ADDR3			MXS_IOMUX_PAD_NAKED(6,  3, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A04__EMI_ADDR4			MXS_IOMUX_PAD_NAKED(6,  4, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A05__EMI_ADDR5			MXS_IOMUX_PAD_NAKED(6,  5, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A06__EMI_ADDR6			MXS_IOMUX_PAD_NAKED(6,  6, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A07__EMI_ADDR7			MXS_IOMUX_PAD_NAKED(6,  7, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A08__EMI_ADDR8			MXS_IOMUX_PAD_NAKED(6,  8, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A09__EMI_ADDR9			MXS_IOMUX_PAD_NAKED(6,  9, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A10__EMI_ADDR10			MXS_IOMUX_PAD_NAKED(6, 10, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A11__EMI_ADDR11			MXS_IOMUX_PAD_NAKED(6, 11, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A12__EMI_ADDR12			MXS_IOMUX_PAD_NAKED(6, 12, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A13__EMI_ADDR13			MXS_IOMUX_PAD_NAKED(6, 13, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_A14__EMI_ADDR14			MXS_IOMUX_PAD_NAKED(6, 14, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_BA0__EMI_BA0			MXS_IOMUX_PAD_NAKED(6, 16, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_BA1__EMI_BA1			MXS_IOMUX_PAD_NAKED(6, 17, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_BA2__EMI_BA2			MXS_IOMUX_PAD_NAKED(6, 18, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_CASN__EMI_CASN			MXS_IOMUX_PAD_NAKED(6, 19, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_RASN__EMI_RASN			MXS_IOMUX_PAD_NAKED(6, 20, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_WEN__EMI_WEN			MXS_IOMUX_PAD_NAKED(6, 21, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_CE0N__EMI_CE0N			MXS_IOMUX_PAD_NAKED(6, 22, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_CE1N__EMI_CE1N			MXS_IOMUX_PAD_NAKED(6, 23, PAD_MUXSEL_0)
+#define MX28_PAD_EMI_CKE__EMI_CKE			MXS_IOMUX_PAD_NAKED(6, 24, PAD_MUXSEL_0)
+
+/* MUXSEL_1 */
+#define MX28_PAD_GPMI_D00__SSP1_D0			MXS_IOMUX_PAD_NAKED(0,  0, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_D01__SSP1_D1			MXS_IOMUX_PAD_NAKED(0,  1, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_D02__SSP1_D2			MXS_IOMUX_PAD_NAKED(0,  2, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_D03__SSP1_D3			MXS_IOMUX_PAD_NAKED(0,  3, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_D04__SSP1_D4			MXS_IOMUX_PAD_NAKED(0,  4, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_D05__SSP1_D5			MXS_IOMUX_PAD_NAKED(0,  5, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_D06__SSP1_D6			MXS_IOMUX_PAD_NAKED(0,  6, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_D07__SSP1_D7			MXS_IOMUX_PAD_NAKED(0,  7, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_CE0N__SSP3_D0			MXS_IOMUX_PAD_NAKED(0, 16, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_CE1N__SSP3_D3			MXS_IOMUX_PAD_NAKED(0, 17, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_CE2N__CAN1_TX			MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_CE3N__CAN1_RX			MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_RDY0__SSP1_CARD_DETECT		MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_RDY1__SSP1_CMD			MXS_IOMUX_PAD_NAKED(0, 21, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_RDY2__CAN0_TX			MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_RDY3__CAN0_RX			MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_RDN__SSP3_SCK			MXS_IOMUX_PAD_NAKED(0, 24, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_WRN__SSP1_SCK			MXS_IOMUX_PAD_NAKED(0, 25, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_ALE__SSP3_D1			MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_CLE__SSP3_D2			MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_1)
+#define MX28_PAD_GPMI_RESETN__SSP3_CMD			MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_1)
+
+#define MX28_PAD_LCD_D03__ETM_DA8			MXS_IOMUX_PAD_NAKED(1,  3, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_D04__ETM_DA9			MXS_IOMUX_PAD_NAKED(1,  4, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_D08__ETM_DA3			MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_D09__ETM_DA4			MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_D20__ENET1_1588_EVENT2_OUT		MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_D21__ENET1_1588_EVENT2_IN		MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_D22__ENET1_1588_EVENT3_OUT		MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_D23__ENET1_1588_EVENT3_IN		MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_RD_E__LCD_VSYNC			MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_WR_RWN__LCD_HSYNC			MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_RS__LCD_DOTCLK			MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_CS__LCD_ENABLE			MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_VSYNC__SAIF1_SDATA0		MXS_IOMUX_PAD_NAKED(1, 28, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_HSYNC__SAIF1_SDATA1		MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_DOTCLK__SAIF1_MCLK			MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_1)
+
+#define MX28_PAD_SSP0_DATA4__SSP2_D0			MXS_IOMUX_PAD_NAKED(2,  4, PAD_MUXSEL_1)
+#define MX28_PAD_SSP0_DATA5__SSP2_D3			MXS_IOMUX_PAD_NAKED(2,  5, PAD_MUXSEL_1)
+#define MX28_PAD_SSP0_DATA6__SSP2_CMD			MXS_IOMUX_PAD_NAKED(2,  6, PAD_MUXSEL_1)
+#define MX28_PAD_SSP0_DATA7__SSP2_SCK			MXS_IOMUX_PAD_NAKED(2,  7, PAD_MUXSEL_1)
+#define MX28_PAD_SSP1_SCK__SSP2_D1			MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_1)
+#define MX28_PAD_SSP1_CMD__SSP2_D2			MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_1)
+#define MX28_PAD_SSP1_DATA0__SSP2_D6			MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_1)
+#define MX28_PAD_SSP1_DATA3__SSP2_D7			MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_1)
+#define MX28_PAD_SSP2_SCK__AUART2_RX			MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_1)
+#define MX28_PAD_SSP2_MOSI__AUART2_TX			MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_1)
+#define MX28_PAD_SSP2_MISO__AUART3_RX			MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_1)
+#define MX28_PAD_SSP2_SS0__AUART3_TX			MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_1)
+#define MX28_PAD_SSP2_SS1__SSP2_D1			MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_1)
+#define MX28_PAD_SSP2_SS2__SSP2_D2			MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_1)
+#define MX28_PAD_SSP3_SCK__AUART4_TX			MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_1)
+#define MX28_PAD_SSP3_MOSI__AUART4_RX			MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_1)
+#define MX28_PAD_SSP3_MISO__AUART4_RTS			MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_1)
+#define MX28_PAD_SSP3_SS0__AUART4_CTS			MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_1)
+
+#define MX28_PAD_AUART0_RX__I2C0_SCL			MXS_IOMUX_PAD_NAKED(3,  0, PAD_MUXSEL_1)
+#define MX28_PAD_AUART0_TX__I2C0_SDA			MXS_IOMUX_PAD_NAKED(3,  1, PAD_MUXSEL_1)
+#define MX28_PAD_AUART0_CTS__AUART4_RX			MXS_IOMUX_PAD_NAKED(3,  2, PAD_MUXSEL_1)
+#define MX28_PAD_AUART0_RTS__AUART4_TX			MXS_IOMUX_PAD_NAKED(3,  3, PAD_MUXSEL_1)
+#define MX28_PAD_AUART1_RX__SSP2_CARD_DETECT		MXS_IOMUX_PAD_NAKED(3,  4, PAD_MUXSEL_1)
+#define MX28_PAD_AUART1_TX__SSP3_CARD_DETECT		MXS_IOMUX_PAD_NAKED(3,  5, PAD_MUXSEL_1)
+#define MX28_PAD_AUART1_CTS__USB0_OVERCURRENT		MXS_IOMUX_PAD_NAKED(3,  6, PAD_MUXSEL_1)
+#define MX28_PAD_AUART1_RTS__USB0_ID			MXS_IOMUX_PAD_NAKED(3,  7, PAD_MUXSEL_1)
+#define MX28_PAD_AUART2_RX__SSP3_D1			MXS_IOMUX_PAD_NAKED(3,  8, PAD_MUXSEL_1)
+#define MX28_PAD_AUART2_TX__SSP3_D2			MXS_IOMUX_PAD_NAKED(3,  9, PAD_MUXSEL_1)
+#define MX28_PAD_AUART2_CTS__I2C1_SCL			MXS_IOMUX_PAD_NAKED(3, 10, PAD_MUXSEL_1)
+#define MX28_PAD_AUART2_RTS__I2C1_SDA			MXS_IOMUX_PAD_NAKED(3, 11, PAD_MUXSEL_1)
+#define MX28_PAD_AUART3_RX__CAN0_TX			MXS_IOMUX_PAD_NAKED(3, 12, PAD_MUXSEL_1)
+#define MX28_PAD_AUART3_TX__CAN0_RX			MXS_IOMUX_PAD_NAKED(3, 13, PAD_MUXSEL_1)
+#define MX28_PAD_AUART3_CTS__CAN1_TX			MXS_IOMUX_PAD_NAKED(3, 14, PAD_MUXSEL_1)
+#define MX28_PAD_AUART3_RTS__CAN1_RX			MXS_IOMUX_PAD_NAKED(3, 15, PAD_MUXSEL_1)
+#define MX28_PAD_PWM0__I2C1_SCL				MXS_IOMUX_PAD_NAKED(3, 16, PAD_MUXSEL_1)
+#define MX28_PAD_PWM1__I2C1_SDA				MXS_IOMUX_PAD_NAKED(3, 17, PAD_MUXSEL_1)
+#define MX28_PAD_PWM2__USB0_ID				MXS_IOMUX_PAD_NAKED(3, 18, PAD_MUXSEL_1)
+#define MX28_PAD_SAIF0_MCLK__PWM_3			MXS_IOMUX_PAD_NAKED(3, 20, PAD_MUXSEL_1)
+#define MX28_PAD_SAIF0_LRCLK__PWM_4			MXS_IOMUX_PAD_NAKED(3, 21, PAD_MUXSEL_1)
+#define MX28_PAD_SAIF0_BITCLK__PWM_5			MXS_IOMUX_PAD_NAKED(3, 22, PAD_MUXSEL_1)
+#define MX28_PAD_SAIF0_SDATA0__PWM_6			MXS_IOMUX_PAD_NAKED(3, 23, PAD_MUXSEL_1)
+#define MX28_PAD_I2C0_SCL__TIMROT_ROTARYA		MXS_IOMUX_PAD_NAKED(3, 24, PAD_MUXSEL_1)
+#define MX28_PAD_I2C0_SDA__TIMROT_ROTARYB		MXS_IOMUX_PAD_NAKED(3, 25, PAD_MUXSEL_1)
+#define MX28_PAD_SAIF1_SDATA0__PWM_7			MXS_IOMUX_PAD_NAKED(3, 26, PAD_MUXSEL_1)
+#define MX28_PAD_LCD_RESET__LCD_VSYNC			MXS_IOMUX_PAD_NAKED(3, 30, PAD_MUXSEL_1)
+
+#define MX28_PAD_ENET0_MDC__GPMI_CE4N			MXS_IOMUX_PAD_NAKED(4,  0, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_MDIO__GPMI_CE5N			MXS_IOMUX_PAD_NAKED(4,  1, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_RX_EN__GPMI_CE6N			MXS_IOMUX_PAD_NAKED(4,  2, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_RXD0__GPMI_CE7N			MXS_IOMUX_PAD_NAKED(4,  3, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_RXD1__GPMI_READY4		MXS_IOMUX_PAD_NAKED(4,  4, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_TX_CLK__HSADC_TRIGGER		MXS_IOMUX_PAD_NAKED(4,  5, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_TX_EN__GPMI_READY5		MXS_IOMUX_PAD_NAKED(4,  6, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_TXD0__GPMI_READY6		MXS_IOMUX_PAD_NAKED(4,  7, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_TXD1__GPMI_READY7		MXS_IOMUX_PAD_NAKED(4,  8, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_RXD2__ENET1_RXD0			MXS_IOMUX_PAD_NAKED(4,  9, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_RXD3__ENET1_RXD1			MXS_IOMUX_PAD_NAKED(4, 10, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_TXD2__ENET1_TXD0			MXS_IOMUX_PAD_NAKED(4, 11, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_TXD3__ENET1_TXD1			MXS_IOMUX_PAD_NAKED(4, 12, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_RX_CLK__ENET0_RX_ER		MXS_IOMUX_PAD_NAKED(4, 13, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_COL__ENET1_TX_EN			MXS_IOMUX_PAD_NAKED(4, 14, PAD_MUXSEL_1)
+#define MX28_PAD_ENET0_CRS__ENET1_RX_EN			MXS_IOMUX_PAD_NAKED(4, 15, PAD_MUXSEL_1)
+
+/* MUXSEL_2 */
+#define MX28_PAD_GPMI_CE2N__ENET0_RX_ER			MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_2)
+#define MX28_PAD_GPMI_CE3N__SAIF1_MCLK			MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_2)
+#define MX28_PAD_GPMI_RDY0__USB0_ID			MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_2)
+#define MX28_PAD_GPMI_RDY2__ENET0_TX_ER			MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_2)
+#define MX28_PAD_GPMI_RDY3__HSADC_TRIGGER		MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_2)
+#define MX28_PAD_GPMI_ALE__SSP3_D4			MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_2)
+#define MX28_PAD_GPMI_CLE__SSP3_D5			MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_2)
+
+#define MX28_PAD_LCD_D00__ETM_DA0			MXS_IOMUX_PAD_NAKED(1,  0, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D01__ETM_DA1			MXS_IOMUX_PAD_NAKED(1,  1, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D02__ETM_DA2			MXS_IOMUX_PAD_NAKED(1,  2, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D03__ETM_DA3			MXS_IOMUX_PAD_NAKED(1,  3, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D04__ETM_DA4			MXS_IOMUX_PAD_NAKED(1,  4, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D05__ETM_DA5			MXS_IOMUX_PAD_NAKED(1,  5, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D06__ETM_DA6			MXS_IOMUX_PAD_NAKED(1,  6, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D07__ETM_DA7			MXS_IOMUX_PAD_NAKED(1,  7, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D08__ETM_DA8			MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D09__ETM_DA9			MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D10__ETM_DA10			MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D11__ETM_DA11			MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D12__ETM_DA12			MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D13__ETM_DA13			MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D14__ETM_DA14			MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D15__ETM_DA15			MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D16__ETM_DA7			MXS_IOMUX_PAD_NAKED(1, 16, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D17__ETM_DA6			MXS_IOMUX_PAD_NAKED(1, 17, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D18__ETM_DA5			MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D19__ETM_DA4			MXS_IOMUX_PAD_NAKED(1, 19, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D20__ETM_DA3			MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D21__ETM_DA2			MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D22__ETM_DA1			MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_D23__ETM_DA0			MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_RD_E__ETM_TCTL			MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_WR_RWN__ETM_TCLK			MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_HSYNC__ETM_TCTL			MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_2)
+#define MX28_PAD_LCD_DOTCLK__ETM_TCLK			MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_2)
+
+#define MX28_PAD_SSP1_SCK__ENET0_1588_EVENT2_OUT	MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_2)
+#define MX28_PAD_SSP1_CMD__ENET0_1588_EVENT2_IN		MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_2)
+#define MX28_PAD_SSP1_DATA0__ENET0_1588_EVENT3_OUT	MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_2)
+#define MX28_PAD_SSP1_DATA3__ENET0_1588_EVENT3_IN	MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_2)
+#define MX28_PAD_SSP2_SCK__SAIF0_SDATA1			MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_2)
+#define MX28_PAD_SSP2_MOSI__SAIF0_SDATA2		MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_2)
+#define MX28_PAD_SSP2_MISO__SAIF1_SDATA1		MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_2)
+#define MX28_PAD_SSP2_SS0__SAIF1_SDATA2			MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_2)
+#define MX28_PAD_SSP2_SS1__USB1_OVERCURRENT		MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_2)
+#define MX28_PAD_SSP2_SS2__USB0_OVERCURRENT		MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_2)
+#define MX28_PAD_SSP3_SCK__ENET1_1588_EVENT0_OUT	MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_2)
+#define MX28_PAD_SSP3_MOSI__ENET1_1588_EVENT0_IN	MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_2)
+#define MX28_PAD_SSP3_MISO__ENET1_1588_EVENT1_OUT	MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_2)
+#define MX28_PAD_SSP3_SS0__ENET1_1588_EVENT1_IN		MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_2)
+
+#define MX28_PAD_AUART0_RX__DUART_CTS			MXS_IOMUX_PAD_NAKED(3,  0, PAD_MUXSEL_2)
+#define MX28_PAD_AUART0_TX__DUART_RTS			MXS_IOMUX_PAD_NAKED(3,  1, PAD_MUXSEL_2)
+#define MX28_PAD_AUART0_CTS__DUART_RX			MXS_IOMUX_PAD_NAKED(3,  2, PAD_MUXSEL_2)
+#define MX28_PAD_AUART0_RTS__DUART_TX			MXS_IOMUX_PAD_NAKED(3,  3, PAD_MUXSEL_2)
+#define MX28_PAD_AUART1_RX__PWM_0			MXS_IOMUX_PAD_NAKED(3,  4, PAD_MUXSEL_2)
+#define MX28_PAD_AUART1_TX__PWM_1			MXS_IOMUX_PAD_NAKED(3,  5, PAD_MUXSEL_2)
+#define MX28_PAD_AUART1_CTS__TIMROT_ROTARYA		MXS_IOMUX_PAD_NAKED(3,  6, PAD_MUXSEL_2)
+#define MX28_PAD_AUART1_RTS__TIMROT_ROTARYB		MXS_IOMUX_PAD_NAKED(3,  7, PAD_MUXSEL_2)
+#define MX28_PAD_AUART2_RX__SSP3_D4			MXS_IOMUX_PAD_NAKED(3,  8, PAD_MUXSEL_2)
+#define MX28_PAD_AUART2_TX__SSP3_D5			MXS_IOMUX_PAD_NAKED(3,  9, PAD_MUXSEL_2)
+#define MX28_PAD_AUART2_CTS__SAIF1_BITCLK		MXS_IOMUX_PAD_NAKED(3, 10, PAD_MUXSEL_2)
+#define MX28_PAD_AUART2_RTS__SAIF1_LRCLK		MXS_IOMUX_PAD_NAKED(3, 11, PAD_MUXSEL_2)
+#define MX28_PAD_AUART3_RX__ENET0_1588_EVENT0_OUT	MXS_IOMUX_PAD_NAKED(3, 12, PAD_MUXSEL_2)
+#define MX28_PAD_AUART3_TX__ENET0_1588_EVENT0_IN	MXS_IOMUX_PAD_NAKED(3, 13, PAD_MUXSEL_2)
+#define MX28_PAD_AUART3_CTS__ENET0_1588_EVENT1_OUT	MXS_IOMUX_PAD_NAKED(3, 14, PAD_MUXSEL_2)
+#define MX28_PAD_AUART3_RTS__ENET0_1588_EVENT1_IN	MXS_IOMUX_PAD_NAKED(3, 15, PAD_MUXSEL_2)
+#define MX28_PAD_PWM0__DUART_RX				MXS_IOMUX_PAD_NAKED(3, 16, PAD_MUXSEL_2)
+#define MX28_PAD_PWM1__DUART_TX				MXS_IOMUX_PAD_NAKED(3, 17, PAD_MUXSEL_2)
+#define MX28_PAD_PWM2__USB1_OVERCURRENT			MXS_IOMUX_PAD_NAKED(3, 18, PAD_MUXSEL_2)
+#define MX28_PAD_SAIF0_MCLK__AUART4_CTS			MXS_IOMUX_PAD_NAKED(3, 20, PAD_MUXSEL_2)
+#define MX28_PAD_SAIF0_LRCLK__AUART4_RTS		MXS_IOMUX_PAD_NAKED(3, 21, PAD_MUXSEL_2)
+#define MX28_PAD_SAIF0_BITCLK__AUART4_RX		MXS_IOMUX_PAD_NAKED(3, 22, PAD_MUXSEL_2)
+#define MX28_PAD_SAIF0_SDATA0__AUART4_TX		MXS_IOMUX_PAD_NAKED(3, 23, PAD_MUXSEL_2)
+#define MX28_PAD_I2C0_SCL__DUART_RX			MXS_IOMUX_PAD_NAKED(3, 24, PAD_MUXSEL_2)
+#define MX28_PAD_I2C0_SDA__DUART_TX			MXS_IOMUX_PAD_NAKED(3, 25, PAD_MUXSEL_2)
+#define MX28_PAD_SAIF1_SDATA0__SAIF0_SDATA1		MXS_IOMUX_PAD_NAKED(3, 26, PAD_MUXSEL_2)
+#define MX28_PAD_SPDIF__ENET1_RX_ER			MXS_IOMUX_PAD_NAKED(3, 27, PAD_MUXSEL_2)
+
+#define MX28_PAD_ENET0_MDC__SAIF0_SDATA1		MXS_IOMUX_PAD_NAKED(4,  0, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_MDIO__SAIF0_SDATA2		MXS_IOMUX_PAD_NAKED(4,  1, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_RX_EN__SAIF1_SDATA1		MXS_IOMUX_PAD_NAKED(4,  2, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_RXD0__SAIF1_SDATA2		MXS_IOMUX_PAD_NAKED(4,  3, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_TX_CLK__ENET0_1588_EVENT2_OUT	MXS_IOMUX_PAD_NAKED(4,  5, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_RXD2__ENET0_1588_EVENT0_OUT	MXS_IOMUX_PAD_NAKED(4,  9, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_RXD3__ENET0_1588_EVENT0_IN	MXS_IOMUX_PAD_NAKED(4, 10, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_TXD2__ENET0_1588_EVENT1_OUT	MXS_IOMUX_PAD_NAKED(4, 11, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_TXD3__ENET0_1588_EVENT1_IN	MXS_IOMUX_PAD_NAKED(4, 12, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_RX_CLK__ENET0_1588_EVENT2_IN	MXS_IOMUX_PAD_NAKED(4, 13, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_COL__ENET0_1588_EVENT3_OUT	MXS_IOMUX_PAD_NAKED(4, 14, PAD_MUXSEL_2)
+#define MX28_PAD_ENET0_CRS__ENET0_1588_EVENT3_IN	MXS_IOMUX_PAD_NAKED(4, 15, PAD_MUXSEL_2)
+
+/* MUXSEL_GPIO */
+#define MX28_PAD_GPMI_D00__GPIO_0_0			MXS_IOMUX_PAD_NAKED(0,  0, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_D01__GPIO_0_1			MXS_IOMUX_PAD_NAKED(0,  1, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_D02__GPIO_0_2			MXS_IOMUX_PAD_NAKED(0,  2, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_D03__GPIO_0_3			MXS_IOMUX_PAD_NAKED(0,  3, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_D04__GPIO_0_4			MXS_IOMUX_PAD_NAKED(0,  4, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_D05__GPIO_0_5			MXS_IOMUX_PAD_NAKED(0,  5, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_D06__GPIO_0_6			MXS_IOMUX_PAD_NAKED(0,  6, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_D07__GPIO_0_7			MXS_IOMUX_PAD_NAKED(0,  7, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_CE0N__GPIO_0_16			MXS_IOMUX_PAD_NAKED(0, 16, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_CE1N__GPIO_0_17			MXS_IOMUX_PAD_NAKED(0, 17, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_CE2N__GPIO_0_18			MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_CE3N__GPIO_0_19			MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_RDY0__GPIO_0_20			MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_RDY1__GPIO_0_21			MXS_IOMUX_PAD_NAKED(0, 21, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_RDY2__GPIO_0_22			MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_RDY3__GPIO_0_23			MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_RDN__GPIO_0_24			MXS_IOMUX_PAD_NAKED(0, 24, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_WRN__GPIO_0_25			MXS_IOMUX_PAD_NAKED(0, 25, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_ALE__GPIO_0_26			MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_CLE__GPIO_0_27			MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_GPIO)
+#define MX28_PAD_GPMI_RESETN__GPIO_0_28			MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_GPIO)
+
+#define MX28_PAD_LCD_D00__GPIO_1_0			MXS_IOMUX_PAD_NAKED(1,  0, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D01__GPIO_1_1			MXS_IOMUX_PAD_NAKED(1,  1, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D02__GPIO_1_2			MXS_IOMUX_PAD_NAKED(1,  2, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D03__GPIO_1_3			MXS_IOMUX_PAD_NAKED(1,  3, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D04__GPIO_1_4			MXS_IOMUX_PAD_NAKED(1,  4, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D05__GPIO_1_5			MXS_IOMUX_PAD_NAKED(1,  5, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D06__GPIO_1_6			MXS_IOMUX_PAD_NAKED(1,  6, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D07__GPIO_1_7			MXS_IOMUX_PAD_NAKED(1,  7, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D08__GPIO_1_8			MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D09__GPIO_1_9			MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D10__GPIO_1_10			MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D11__GPIO_1_11			MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D12__GPIO_1_12			MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D13__GPIO_1_13			MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D14__GPIO_1_14			MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D15__GPIO_1_15			MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D16__GPIO_1_16			MXS_IOMUX_PAD_NAKED(1, 16, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D17__GPIO_1_17			MXS_IOMUX_PAD_NAKED(1, 17, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D18__GPIO_1_18			MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D19__GPIO_1_19			MXS_IOMUX_PAD_NAKED(1, 19, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D20__GPIO_1_20			MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D21__GPIO_1_21			MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D22__GPIO_1_22			MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_D23__GPIO_1_23			MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_RD_E__GPIO_1_24			MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_WR_RWN__GPIO_1_25			MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_RS__GPIO_1_26			MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_CS__GPIO_1_27			MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_VSYNC__GPIO_1_28			MXS_IOMUX_PAD_NAKED(1, 28, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_HSYNC__GPIO_1_29			MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_DOTCLK__GPIO_1_30			MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_ENABLE__GPIO_1_31			MXS_IOMUX_PAD_NAKED(1, 31, PAD_MUXSEL_GPIO)
+
+#define MX28_PAD_SSP0_DATA0__GPIO_2_0			MXS_IOMUX_PAD_NAKED(2,  0, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_DATA1__GPIO_2_1			MXS_IOMUX_PAD_NAKED(2,  1, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_DATA2__GPIO_2_2			MXS_IOMUX_PAD_NAKED(2,  2, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_DATA3__GPIO_2_3			MXS_IOMUX_PAD_NAKED(2,  3, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_DATA4__GPIO_2_4			MXS_IOMUX_PAD_NAKED(2,  4, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_DATA5__GPIO_2_5			MXS_IOMUX_PAD_NAKED(2,  5, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_DATA6__GPIO_2_6			MXS_IOMUX_PAD_NAKED(2,  6, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_DATA7__GPIO_2_7			MXS_IOMUX_PAD_NAKED(2,  7, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_CMD__GPIO_2_8			MXS_IOMUX_PAD_NAKED(2,  8, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_DETECT__GPIO_2_9			MXS_IOMUX_PAD_NAKED(2,  9, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP0_SCK__GPIO_2_10			MXS_IOMUX_PAD_NAKED(2, 10, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP1_SCK__GPIO_2_12			MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP1_CMD__GPIO_2_13			MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP1_DATA0__GPIO_2_14			MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP1_DATA3__GPIO_2_15			MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP2_SCK__GPIO_2_16			MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP2_MOSI__GPIO_2_17			MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP2_MISO__GPIO_2_18			MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP2_SS0__GPIO_2_19			MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP2_SS1__GPIO_2_20			MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP2_SS2__GPIO_2_21			MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP3_SCK__GPIO_2_24			MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP3_MOSI__GPIO_2_25			MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP3_MISO__GPIO_2_26			MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SSP3_SS0__GPIO_2_27			MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_GPIO)
+
+#define MX28_PAD_AUART0_RX__GPIO_3_0			MXS_IOMUX_PAD_NAKED(3,  0, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART0_TX__GPIO_3_1			MXS_IOMUX_PAD_NAKED(3,  1, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART0_CTS__GPIO_3_2			MXS_IOMUX_PAD_NAKED(3,  2, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART0_RTS__GPIO_3_3			MXS_IOMUX_PAD_NAKED(3,  3, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART1_RX__GPIO_3_4			MXS_IOMUX_PAD_NAKED(3,  4, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART1_TX__GPIO_3_5			MXS_IOMUX_PAD_NAKED(3,  5, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART1_CTS__GPIO_3_6			MXS_IOMUX_PAD_NAKED(3,  6, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART1_RTS__GPIO_3_7			MXS_IOMUX_PAD_NAKED(3,  7, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART2_RX__GPIO_3_8			MXS_IOMUX_PAD_NAKED(3,  8, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART2_TX__GPIO_3_9			MXS_IOMUX_PAD_NAKED(3,  9, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART2_CTS__GPIO_3_10			MXS_IOMUX_PAD_NAKED(3, 10, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART2_RTS__GPIO_3_11			MXS_IOMUX_PAD_NAKED(3, 11, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART3_RX__GPIO_3_12			MXS_IOMUX_PAD_NAKED(3, 12, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART3_TX__GPIO_3_13			MXS_IOMUX_PAD_NAKED(3, 13, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART3_CTS__GPIO_3_14			MXS_IOMUX_PAD_NAKED(3, 14, PAD_MUXSEL_GPIO)
+#define MX28_PAD_AUART3_RTS__GPIO_3_15			MXS_IOMUX_PAD_NAKED(3, 15, PAD_MUXSEL_GPIO)
+#define MX28_PAD_PWM0__GPIO_3_16			MXS_IOMUX_PAD_NAKED(3, 16, PAD_MUXSEL_GPIO)
+#define MX28_PAD_PWM1__GPIO_3_17			MXS_IOMUX_PAD_NAKED(3, 17, PAD_MUXSEL_GPIO)
+#define MX28_PAD_PWM2__GPIO_3_18			MXS_IOMUX_PAD_NAKED(3, 18, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SAIF0_MCLK__GPIO_3_20			MXS_IOMUX_PAD_NAKED(3, 20, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SAIF0_LRCLK__GPIO_3_21			MXS_IOMUX_PAD_NAKED(3, 21, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SAIF0_BITCLK__GPIO_3_22		MXS_IOMUX_PAD_NAKED(3, 22, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SAIF0_SDATA0__GPIO_3_23		MXS_IOMUX_PAD_NAKED(3, 23, PAD_MUXSEL_GPIO)
+#define MX28_PAD_I2C0_SCL__GPIO_3_24			MXS_IOMUX_PAD_NAKED(3, 24, PAD_MUXSEL_GPIO)
+#define MX28_PAD_I2C0_SDA__GPIO_3_25			MXS_IOMUX_PAD_NAKED(3, 25, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SAIF1_SDATA0__GPIO_3_26		MXS_IOMUX_PAD_NAKED(3, 26, PAD_MUXSEL_GPIO)
+#define MX28_PAD_SPDIF__GPIO_3_27			MXS_IOMUX_PAD_NAKED(3, 27, PAD_MUXSEL_GPIO)
+#define MX28_PAD_PWM3__GPIO_3_28			MXS_IOMUX_PAD_NAKED(3, 28, PAD_MUXSEL_GPIO)
+#define MX28_PAD_PWM4__GPIO_3_29			MXS_IOMUX_PAD_NAKED(3, 29, PAD_MUXSEL_GPIO)
+#define MX28_PAD_LCD_RESET__GPIO_3_30			MXS_IOMUX_PAD_NAKED(3, 30, PAD_MUXSEL_GPIO)
+
+#define MX28_PAD_ENET0_MDC__GPIO_4_0			MXS_IOMUX_PAD_NAKED(4,  0, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_MDIO__GPIO_4_1			MXS_IOMUX_PAD_NAKED(4,  1, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_RX_EN__GPIO_4_2			MXS_IOMUX_PAD_NAKED(4,  2, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_RXD0__GPIO_4_3			MXS_IOMUX_PAD_NAKED(4,  3, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_RXD1__GPIO_4_4			MXS_IOMUX_PAD_NAKED(4,  4, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_TX_CLK__GPIO_4_5			MXS_IOMUX_PAD_NAKED(4,  5, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_TX_EN__GPIO_4_6			MXS_IOMUX_PAD_NAKED(4,  6, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_TXD0__GPIO_4_7			MXS_IOMUX_PAD_NAKED(4,  7, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_TXD1__GPIO_4_8			MXS_IOMUX_PAD_NAKED(4,  8, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_RXD2__GPIO_4_9			MXS_IOMUX_PAD_NAKED(4,  9, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_RXD3__GPIO_4_10			MXS_IOMUX_PAD_NAKED(4, 10, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_TXD2__GPIO_4_11			MXS_IOMUX_PAD_NAKED(4, 11, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_TXD3__GPIO_4_12			MXS_IOMUX_PAD_NAKED(4, 12, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_RX_CLK__GPIO_4_13		MXS_IOMUX_PAD_NAKED(4, 13, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_COL__GPIO_4_14			MXS_IOMUX_PAD_NAKED(4, 14, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET0_CRS__GPIO_4_15			MXS_IOMUX_PAD_NAKED(4, 15, PAD_MUXSEL_GPIO)
+#define MX28_PAD_ENET_CLK__GPIO_4_16			MXS_IOMUX_PAD_NAKED(4, 16, PAD_MUXSEL_GPIO)
+#define MX28_PAD_JTAG_RTCK__GPIO_4_20			MXS_IOMUX_PAD_NAKED(4, 20, PAD_MUXSEL_GPIO)
+
+#endif /* __MACH_IOMUX_MX28_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/iomux.h b/arch/arm/include/asm/arch-mx28/iomux.h
new file mode 100644
index 0000000..7abdf58
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/iomux.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH,
+ *			<armlinux@phytec.de>
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifndef __MACH_MXS_IOMUX_H__
+#define __MACH_MXS_IOMUX_H__
+
+/*
+ * IOMUX/PAD Bit field definitions
+ *
+ * PAD_BANK:		 0..2	(3)
+ * PAD_PIN:		 3..7	(5)
+ * PAD_MUXSEL:		 8..9	(2)
+ * PAD_MA:		10..11	(2)
+ * PAD_MA_VALID:	12	(1)
+ * PAD_VOL:		13	(1)
+ * PAD_VOL_VALID:	14	(1)
+ * PAD_PULL:		15	(1)
+ * PAD_PULL_VALID:	16	(1)
+ * RESERVED:		17..31	(15)
+ */
+typedef u32 iomux_cfg_t;
+
+#define MXS_PAD_BANK_SHIFT	0
+#define MXS_PAD_BANK_MASK	((iomux_cfg_t)0x7 << MXS_PAD_BANK_SHIFT)
+#define MXS_PAD_PIN_SHIFT	3
+#define MXS_PAD_PIN_MASK	((iomux_cfg_t)0x1f << MXS_PAD_PIN_SHIFT)
+#define MXS_PAD_MUXSEL_SHIFT	8
+#define MXS_PAD_MUXSEL_MASK	((iomux_cfg_t)0x3 << MXS_PAD_MUXSEL_SHIFT)
+#define MXS_PAD_MA_SHIFT	10
+#define MXS_PAD_MA_MASK		((iomux_cfg_t)0x3 << MXS_PAD_MA_SHIFT)
+#define MXS_PAD_MA_VALID_SHIFT	12
+#define MXS_PAD_MA_VALID_MASK	((iomux_cfg_t)0x1 << MXS_PAD_MA_VALID_SHIFT)
+#define MXS_PAD_VOL_SHIFT	13
+#define MXS_PAD_VOL_MASK	((iomux_cfg_t)0x1 << MXS_PAD_VOL_SHIFT)
+#define MXS_PAD_VOL_VALID_SHIFT	14
+#define MXS_PAD_VOL_VALID_MASK	((iomux_cfg_t)0x1 << MXS_PAD_VOL_VALID_SHIFT)
+#define MXS_PAD_PULL_SHIFT	15
+#define MXS_PAD_PULL_MASK	((iomux_cfg_t)0x1 << MXS_PAD_PULL_SHIFT)
+#define MXS_PAD_PULL_VALID_SHIFT 16
+#define MXS_PAD_PULL_VALID_MASK	((iomux_cfg_t)0x1 << MXS_PAD_PULL_VALID_SHIFT)
+
+#define PAD_MUXSEL_0		0
+#define PAD_MUXSEL_1		1
+#define PAD_MUXSEL_2		2
+#define PAD_MUXSEL_GPIO		3
+
+#define PAD_4MA			0
+#define PAD_8MA			1
+#define PAD_12MA		2
+#define PAD_16MA		3
+
+#define PAD_1V8			0
+#define PAD_3V3			1
+
+#define PAD_NOPULL		0
+#define PAD_PULLUP		1
+
+#define MXS_PAD_4MA	((PAD_4MA << MXS_PAD_MA_SHIFT) | \
+					MXS_PAD_MA_VALID_MASK)
+#define MXS_PAD_8MA	((PAD_8MA << MXS_PAD_MA_SHIFT) | \
+					MXS_PAD_MA_VALID_MASK)
+#define MXS_PAD_12MA	((PAD_12MA << MXS_PAD_MA_SHIFT) | \
+					MXS_PAD_MA_VALID_MASK)
+#define MXS_PAD_16MA	((PAD_16MA << MXS_PAD_MA_SHIFT) | \
+					MXS_PAD_MA_VALID_MASK)
+
+#define MXS_PAD_1V8	((PAD_1V8 << MXS_PAD_VOL_SHIFT) | \
+					MXS_PAD_VOL_VALID_MASK)
+#define MXS_PAD_3V3	((PAD_3V3 << MXS_PAD_VOL_SHIFT) | \
+					MXS_PAD_VOL_VALID_MASK)
+
+#define MXS_PAD_NOPULL	((PAD_NOPULL << MXS_PAD_PULL_SHIFT) | \
+					MXS_PAD_PULL_VALID_MASK)
+#define MXS_PAD_PULLUP	((PAD_PULLUP << MXS_PAD_PULL_SHIFT) | \
+					MXS_PAD_PULL_VALID_MASK)
+
+/* generic pad control used in most cases */
+#define MXS_PAD_CTRL	(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL)
+
+#define MXS_IOMUX_PAD(_bank, _pin, _muxsel, _ma, _vol, _pull)		\
+		(((iomux_cfg_t)(_bank) << MXS_PAD_BANK_SHIFT) |		\
+		((iomux_cfg_t)(_pin) << MXS_PAD_PIN_SHIFT) |		\
+		((iomux_cfg_t)(_muxsel) << MXS_PAD_MUXSEL_SHIFT) |	\
+		((iomux_cfg_t)(_ma) << MXS_PAD_MA_SHIFT) |		\
+		((iomux_cfg_t)(_vol) << MXS_PAD_VOL_SHIFT) |		\
+		((iomux_cfg_t)(_pull) << MXS_PAD_PULL_SHIFT))
+
+/*
+ * A pad becomes naked, when none of mA, vol or pull
+ * validity bits is set.
+ */
+#define MXS_IOMUX_PAD_NAKED(_bank, _pin, _muxsel) \
+		MXS_IOMUX_PAD(_bank, _pin, _muxsel, 0, 0, 0)
+
+static inline unsigned int PAD_BANK(iomux_cfg_t pad)
+{
+	return (pad & MXS_PAD_BANK_MASK) >> MXS_PAD_BANK_SHIFT;
+}
+
+static inline unsigned int PAD_PIN(iomux_cfg_t pad)
+{
+	return (pad & MXS_PAD_PIN_MASK) >> MXS_PAD_PIN_SHIFT;
+}
+
+static inline unsigned int PAD_MUXSEL(iomux_cfg_t pad)
+{
+	return (pad & MXS_PAD_MUXSEL_MASK) >> MXS_PAD_MUXSEL_SHIFT;
+}
+
+static inline unsigned int PAD_MA(iomux_cfg_t pad)
+{
+	return (pad & MXS_PAD_MA_MASK) >> MXS_PAD_MA_SHIFT;
+}
+
+static inline unsigned int PAD_MA_VALID(iomux_cfg_t pad)
+{
+	return (pad & MXS_PAD_MA_VALID_MASK) >> MXS_PAD_MA_VALID_SHIFT;
+}
+
+static inline unsigned int PAD_VOL(iomux_cfg_t pad)
+{
+	return (pad & MXS_PAD_VOL_MASK) >> MXS_PAD_VOL_SHIFT;
+}
+
+static inline unsigned int PAD_VOL_VALID(iomux_cfg_t pad)
+{
+	return (pad & MXS_PAD_VOL_VALID_MASK) >> MXS_PAD_VOL_VALID_SHIFT;
+}
+
+static inline unsigned int PAD_PULL(iomux_cfg_t pad)
+{
+	return (pad & MXS_PAD_PULL_MASK) >> MXS_PAD_PULL_SHIFT;
+}
+
+static inline unsigned int PAD_PULL_VALID(iomux_cfg_t pad)
+{
+	return (pad & MXS_PAD_PULL_VALID_MASK) >> MXS_PAD_PULL_VALID_SHIFT;
+}
+
+/*
+ * configures a single pad in the iomuxer
+ */
+int mxs_iomux_setup_pad(iomux_cfg_t pad);
+
+/*
+ * configures multiple pads
+ * convenient way to call the above function with tables
+ */
+int mxs_iomux_setup_multiple_pads(const iomux_cfg_t *pad_list, unsigned count);
+
+#endif /* __MACH_MXS_IOMUX_H__*/
-- 
1.7.6.3

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

* [U-Boot] [PATCH 05/17 RESEND V2] iMX28: Add I2C bus driver
  2011-10-21 22:44 ` [U-Boot] [PATCH 00/17 V3] Support for the DENX M28 SoM Marek Vasut
                     ` (3 preceding siblings ...)
  2011-10-21 22:44   ` [U-Boot] [PATCH 04/17 RESEND] iMX28: Add PINMUX control Marek Vasut
@ 2011-10-21 22:44   ` Marek Vasut
  2011-10-21 22:44   ` [U-Boot] [PATCH 06/17 RESEND] iMX28: Add GPIO control Marek Vasut
                     ` (11 subsequent siblings)
  16 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-10-21 22:44 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Heiko Schocher <hs@denx.de>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 drivers/i2c/Makefile  |    1 +
 drivers/i2c/mxs_i2c.c |  246 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 247 insertions(+), 0 deletions(-)
 create mode 100644 drivers/i2c/mxs_i2c.c

V2: Add "based on" text.

diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index a48047a..2fb521e 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -31,6 +31,7 @@ COBJS-$(CONFIG_FSL_I2C) += fsl_i2c.o
 COBJS-$(CONFIG_I2C_MVTWSI) += mvtwsi.o
 COBJS-$(CONFIG_I2C_MV) += mv_i2c.o
 COBJS-$(CONFIG_I2C_MXC) += mxc_i2c.o
+COBJS-$(CONFIG_I2C_MXS) += mxs_i2c.o
 COBJS-$(CONFIG_DRIVER_OMAP1510_I2C) += omap1510_i2c.o
 COBJS-$(CONFIG_DRIVER_OMAP24XX_I2C) += omap24xx_i2c.o
 COBJS-$(CONFIG_DRIVER_OMAP34XX_I2C) += omap24xx_i2c.o
diff --git a/drivers/i2c/mxs_i2c.c b/drivers/i2c/mxs_i2c.c
new file mode 100644
index 0000000..c8fea32
--- /dev/null
+++ b/drivers/i2c/mxs_i2c.c
@@ -0,0 +1,246 @@
+/*
+ * Freescale i.MX28 I2C Driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Partly based on Linux kernel i2c-mxs.c driver:
+ * Copyright (C) 2011 Wolfram Sang, Pengutronix e.K.
+ *
+ * Which was based on a (non-working) driver which was:
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+
+#define	MXS_I2C_MAX_TIMEOUT	1000000
+
+void mxs_i2c_reset(void)
+{
+	struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE;
+	int ret;
+
+	ret = mx28_reset_block(&i2c_regs->hw_i2c_ctrl0_reg);
+	if (ret) {
+		debug("MXS I2C: Block reset timeout\n");
+		return;
+	}
+
+	writel(I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ | I2C_CTRL1_NO_SLAVE_ACK_IRQ |
+		I2C_CTRL1_EARLY_TERM_IRQ | I2C_CTRL1_MASTER_LOSS_IRQ |
+		I2C_CTRL1_SLAVE_STOP_IRQ | I2C_CTRL1_SLAVE_IRQ,
+		&i2c_regs->hw_i2c_ctrl1_clr);
+
+	writel(I2C_QUEUECTRL_PIO_QUEUE_MODE, &i2c_regs->hw_i2c_queuectrl_set);
+}
+
+void mxs_i2c_setup_read(uint8_t chip, int len)
+{
+	struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE;
+
+	writel(I2C_QUEUECMD_RETAIN_CLOCK | I2C_QUEUECMD_PRE_SEND_START |
+		I2C_QUEUECMD_MASTER_MODE | I2C_QUEUECMD_DIRECTION |
+		(1 << I2C_QUEUECMD_XFER_COUNT_OFFSET),
+		&i2c_regs->hw_i2c_queuecmd);
+
+	writel((chip << 1) | 1, &i2c_regs->hw_i2c_data);
+
+	writel(I2C_QUEUECMD_SEND_NAK_ON_LAST | I2C_QUEUECMD_MASTER_MODE |
+		(len << I2C_QUEUECMD_XFER_COUNT_OFFSET) |
+		I2C_QUEUECMD_POST_SEND_STOP, &i2c_regs->hw_i2c_queuecmd);
+
+	writel(I2C_QUEUECTRL_QUEUE_RUN, &i2c_regs->hw_i2c_queuectrl_set);
+}
+
+void mxs_i2c_write(uchar chip, uint addr, int alen,
+			uchar *buf, int blen, int stop)
+{
+	struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE;
+	uint32_t data;
+	int i, remain, off;
+
+	if ((alen > 4) || (alen == 0)) {
+		debug("MXS I2C: Invalid address length\n");
+		return;
+	}
+
+	if (stop)
+		stop = I2C_QUEUECMD_POST_SEND_STOP;
+
+	writel(I2C_QUEUECMD_PRE_SEND_START |
+		I2C_QUEUECMD_MASTER_MODE | I2C_QUEUECMD_DIRECTION |
+		((blen + alen + 1) << I2C_QUEUECMD_XFER_COUNT_OFFSET) | stop,
+		&i2c_regs->hw_i2c_queuecmd);
+
+	data = (chip << 1) << 24;
+
+	for (i = 0; i < alen; i++) {
+		data >>= 8;
+		data |= ((char *)&addr)[i] << 24;
+		if ((i & 3) == 2)
+			writel(data, &i2c_regs->hw_i2c_data);
+	}
+
+	off = i;
+	for (; i < off + blen; i++) {
+		data >>= 8;
+		data |= buf[i - off] << 24;
+		if ((i & 3) == 2)
+			writel(data, &i2c_regs->hw_i2c_data);
+	}
+
+	remain = 24 - ((i & 3) * 8);
+	if (remain)
+		writel(data >> remain, &i2c_regs->hw_i2c_data);
+
+	writel(I2C_QUEUECTRL_QUEUE_RUN, &i2c_regs->hw_i2c_queuectrl_set);
+}
+
+int mxs_i2c_wait_for_ack(void)
+{
+	struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE;
+	uint32_t tmp;
+	int timeout = MXS_I2C_MAX_TIMEOUT;
+
+	for (;;) {
+		tmp = readl(&i2c_regs->hw_i2c_ctrl1);
+		if (tmp & I2C_CTRL1_NO_SLAVE_ACK_IRQ) {
+			debug("MXS I2C: No slave ACK\n");
+			goto err;
+		}
+
+		if (tmp & (
+			I2C_CTRL1_EARLY_TERM_IRQ | I2C_CTRL1_MASTER_LOSS_IRQ |
+			I2C_CTRL1_SLAVE_STOP_IRQ | I2C_CTRL1_SLAVE_IRQ)) {
+			debug("MXS I2C: Error (CTRL1 = %08x)\n", tmp);
+			goto err;
+		}
+
+		if (tmp & I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ)
+			break;
+
+		if (!timeout--) {
+			debug("MXS I2C: Operation timed out\n");
+			goto err;
+		}
+
+		udelay(1);
+	}
+
+	return 0;
+
+err:
+	mxs_i2c_reset();
+	return 1;
+}
+
+int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+	struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE;
+	uint32_t tmp = 0;
+	int ret;
+	int i;
+
+	mxs_i2c_write(chip, addr, alen, NULL, 0, 0);
+	ret = mxs_i2c_wait_for_ack();
+	if (ret) {
+		debug("MXS I2C: Failed writing address\n");
+		return ret;
+	}
+
+	mxs_i2c_setup_read(chip, len);
+	ret = mxs_i2c_wait_for_ack();
+	if (ret) {
+		debug("MXS I2C: Failed reading address\n");
+		return ret;
+	}
+
+	for (i = 0; i < len; i++) {
+		if (!(i & 3)) {
+			while (readl(&i2c_regs->hw_i2c_queuestat) &
+				I2C_QUEUESTAT_RD_QUEUE_EMPTY)
+				;
+			tmp = readl(&i2c_regs->hw_i2c_queuedata);
+		}
+		buffer[i] = tmp & 0xff;
+		tmp >>= 8;
+	}
+
+	return 0;
+}
+
+int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+	int ret;
+	mxs_i2c_write(chip, addr, alen, buffer, len, 1);
+	ret = mxs_i2c_wait_for_ack();
+	if (ret)
+		debug("MXS I2C: Failed writing address\n");
+
+	return ret;
+}
+
+int i2c_probe(uchar chip)
+{
+	int ret;
+	mxs_i2c_write(chip, 0, 1, NULL, 0, 1);
+	ret = mxs_i2c_wait_for_ack();
+	mxs_i2c_reset();
+	return ret;
+}
+
+void i2c_init(int speed, int slaveadd)
+{
+	struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE;
+
+	mxs_i2c_reset();
+
+	switch (speed) {
+	case 100000:
+		writel((0x0078 << I2C_TIMING0_HIGH_COUNT_OFFSET) |
+			(0x0030 << I2C_TIMING0_RCV_COUNT_OFFSET),
+			&i2c_regs->hw_i2c_timing0);
+		writel((0x0080 << I2C_TIMING1_LOW_COUNT_OFFSET) |
+			(0x0030 << I2C_TIMING1_XMIT_COUNT_OFFSET),
+			&i2c_regs->hw_i2c_timing1);
+		break;
+	case 400000:
+		writel((0x000f << I2C_TIMING0_HIGH_COUNT_OFFSET) |
+			(0x0007 << I2C_TIMING0_RCV_COUNT_OFFSET),
+			&i2c_regs->hw_i2c_timing0);
+		writel((0x001f << I2C_TIMING1_LOW_COUNT_OFFSET) |
+			(0x000f << I2C_TIMING1_XMIT_COUNT_OFFSET),
+			&i2c_regs->hw_i2c_timing1);
+		break;
+	default:
+		printf("MXS I2C: Invalid speed selected (%d Hz)\n", speed);
+		return;
+	}
+
+	writel((0x0015 << I2C_TIMING2_BUS_FREE_OFFSET) |
+		(0x000d << I2C_TIMING2_LEADIN_COUNT_OFFSET),
+		&i2c_regs->hw_i2c_timing2);
+
+	return;
+}
-- 
1.7.6.3

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

* [U-Boot] [PATCH 06/17 RESEND] iMX28: Add GPIO control
  2011-10-21 22:44 ` [U-Boot] [PATCH 00/17 V3] Support for the DENX M28 SoM Marek Vasut
                     ` (4 preceding siblings ...)
  2011-10-21 22:44   ` [U-Boot] [PATCH 05/17 RESEND V2] iMX28: Add I2C bus driver Marek Vasut
@ 2011-10-21 22:44   ` Marek Vasut
  2011-10-21 22:44   ` [U-Boot] [PATCH 07/17 RESEND V2] iMX28: Add SPI driver Marek Vasut
                     ` (10 subsequent siblings)
  16 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-10-21 22:44 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 arch/arm/cpu/arm926ejs/mx28/mx28.c    |    6 ++
 arch/arm/include/asm/arch-mx28/gpio.h |   32 ++++++++
 drivers/gpio/Makefile                 |    1 +
 drivers/gpio/mxs_gpio.c               |  136 +++++++++++++++++++++++++++++++++
 4 files changed, 175 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-mx28/gpio.h
 create mode 100644 drivers/gpio/mxs_gpio.c

diff --git a/arch/arm/cpu/arm926ejs/mx28/mx28.c b/arch/arm/cpu/arm926ejs/mx28/mx28.c
index 446ea8b..e990f3c 100644
--- a/arch/arm/cpu/arm926ejs/mx28/mx28.c
+++ b/arch/arm/cpu/arm926ejs/mx28/mx28.c
@@ -31,6 +31,7 @@
 #include <asm/io.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/gpio.h>
+#include <asm/arch/iomux.h>
 #include <asm/arch/imx-regs.h>
 #include <asm/arch/sys_proto.h>
 
@@ -134,6 +135,11 @@ int arch_cpu_init(void)
 
 	udelay(1000);
 
+	/*
+	 * Configure GPIO unit
+	 */
+	mxs_gpio_init();
+
 	return 0;
 }
 #endif
diff --git a/arch/arm/include/asm/arch-mx28/gpio.h b/arch/arm/include/asm/arch-mx28/gpio.h
new file mode 100644
index 0000000..be1c944
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/gpio.h
@@ -0,0 +1,32 @@
+/*
+ * Freescale i.MX28 GPIO
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef	__MX28_GPIO_H__
+#define	__MX28_GPIO_H__
+
+#ifdef	CONFIG_MXS_GPIO
+void mxs_gpio_init(void);
+#else
+inline void mxs_gpio_init(void) {}
+#endif
+
+#endif	/* __MX28_GPIO_H__ */
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index beca1da..da79fab 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -30,6 +30,7 @@ COBJS-$(CONFIG_KIRKWOOD_GPIO)	+= kw_gpio.o
 COBJS-$(CONFIG_MARVELL_GPIO)	+= mvgpio.o
 COBJS-$(CONFIG_MARVELL_MFP)	+= mvmfp.o
 COBJS-$(CONFIG_MXC_GPIO)	+= mxc_gpio.o
+COBJS-$(CONFIG_MXS_GPIO)	+= mxs_gpio.o
 COBJS-$(CONFIG_PCA953X)		+= pca953x.o
 COBJS-$(CONFIG_S5P)		+= s5p_gpio.o
 COBJS-$(CONFIG_TEGRA2_GPIO)	+= tegra2_gpio.o
diff --git a/drivers/gpio/mxs_gpio.c b/drivers/gpio/mxs_gpio.c
new file mode 100644
index 0000000..b7e9591
--- /dev/null
+++ b/drivers/gpio/mxs_gpio.c
@@ -0,0 +1,136 @@
+/*
+ * Freescale i.MX28 GPIO control code
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <netdev.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/iomux.h>
+#include <asm/arch/imx-regs.h>
+
+#if	defined(CONFIG_MX23)
+#define	PINCTRL_BANKS		3
+#define	PINCTRL_DOUT(n)		(0x0500 + ((n) * 0x10))
+#define	PINCTRL_DIN(n)		(0x0600 + ((n) * 0x10))
+#define	PINCTRL_DOE(n)		(0x0700 + ((n) * 0x10))
+#define	PINCTRL_PIN2IRQ(n)	(0x0800 + ((n) * 0x10))
+#define	PINCTRL_IRQEN(n)	(0x0900 + ((n) * 0x10))
+#define	PINCTRL_IRQSTAT(n)	(0x0c00 + ((n) * 0x10))
+#elif	defined(CONFIG_MX28)
+#define	PINCTRL_BANKS		5
+#define	PINCTRL_DOUT(n)		(0x0700 + ((n) * 0x10))
+#define	PINCTRL_DIN(n)		(0x0900 + ((n) * 0x10))
+#define	PINCTRL_DOE(n)		(0x0b00 + ((n) * 0x10))
+#define	PINCTRL_PIN2IRQ(n)	(0x1000 + ((n) * 0x10))
+#define	PINCTRL_IRQEN(n)	(0x1100 + ((n) * 0x10))
+#define	PINCTRL_IRQSTAT(n)	(0x1400 + ((n) * 0x10))
+#else
+#error "Please select CONFIG_MX23 or CONFIG_MX28"
+#endif
+
+#define GPIO_INT_FALL_EDGE	0x0
+#define GPIO_INT_LOW_LEV	0x1
+#define GPIO_INT_RISE_EDGE	0x2
+#define GPIO_INT_HIGH_LEV	0x3
+#define GPIO_INT_LEV_MASK	(1 << 0)
+#define GPIO_INT_POL_MASK	(1 << 1)
+
+void mxs_gpio_init(void)
+{
+	int i;
+
+	for (i = 0; i < PINCTRL_BANKS; i++) {
+		writel(0, MXS_PINCTRL_BASE + PINCTRL_PIN2IRQ(i));
+		writel(0, MXS_PINCTRL_BASE + PINCTRL_IRQEN(i));
+		/* Use SCT address here to clear the IRQSTAT bits */
+		writel(0xffffffff, MXS_PINCTRL_BASE + PINCTRL_IRQSTAT(i) + 8);
+	}
+}
+
+int gpio_get_value(int gp)
+{
+	uint32_t bank = PAD_BANK(gp);
+	uint32_t offset = PINCTRL_DIN(bank);
+	struct mx28_register *reg =
+		(struct mx28_register *)(MXS_PINCTRL_BASE + offset);
+
+	return (readl(&reg->reg) >> PAD_PIN(gp)) & 1;
+}
+
+void gpio_set_value(int gp, int value)
+{
+	uint32_t bank = PAD_BANK(gp);
+	uint32_t offset = PINCTRL_DOUT(bank);
+	struct mx28_register *reg =
+		(struct mx28_register *)(MXS_PINCTRL_BASE + offset);
+
+	if (value)
+		writel(1 << PAD_PIN(gp), &reg->reg_set);
+	else
+		writel(1 << PAD_PIN(gp), &reg->reg_clr);
+}
+
+int gpio_direction_input(int gp)
+{
+	uint32_t bank = PAD_BANK(gp);
+	uint32_t offset = PINCTRL_DOE(bank);
+	struct mx28_register *reg =
+		(struct mx28_register *)(MXS_PINCTRL_BASE + offset);
+
+	writel(1 << PAD_PIN(gp), &reg->reg_clr);
+
+	return 0;
+}
+
+int gpio_direction_output(int gp, int value)
+{
+	uint32_t bank = PAD_BANK(gp);
+	uint32_t offset = PINCTRL_DOE(bank);
+	struct mx28_register *reg =
+		(struct mx28_register *)(MXS_PINCTRL_BASE + offset);
+
+	writel(1 << PAD_PIN(gp), &reg->reg_set);
+
+	gpio_set_value(gp, value);
+
+	return 0;
+}
+
+int gpio_request(int gp, const char *label)
+{
+	if (PAD_BANK(gp) > PINCTRL_BANKS)
+		return -EINVAL;
+
+	return 0;
+}
+
+void gpio_free(int gp)
+{
+}
+
+void gpio_toggle_value(int gp)
+{
+	gpio_set_value(gp, !gpio_get_value(gp));
+}
-- 
1.7.6.3

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

* [U-Boot] [PATCH 07/17 RESEND V2] iMX28: Add SPI driver
  2011-10-21 22:44 ` [U-Boot] [PATCH 00/17 V3] Support for the DENX M28 SoM Marek Vasut
                     ` (5 preceding siblings ...)
  2011-10-21 22:44   ` [U-Boot] [PATCH 06/17 RESEND] iMX28: Add GPIO control Marek Vasut
@ 2011-10-21 22:44   ` Marek Vasut
  2011-10-21 22:44   ` [U-Boot] [PATCH 08/17 RESEND] iMX28: Add APBH DMA driver Marek Vasut
                     ` (9 subsequent siblings)
  16 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-10-21 22:44 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 drivers/spi/Makefile  |    1 +
 drivers/spi/mxs_spi.c |  186 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 187 insertions(+), 0 deletions(-)
 create mode 100644 drivers/spi/mxs_spi.c

V2: Use the SPI API properly.

diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 96c9642..9a0c475 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -36,6 +36,7 @@ COBJS-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
 COBJS-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o
 COBJS-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
 COBJS-$(CONFIG_MXC_SPI) += mxc_spi.o
+COBJS-$(CONFIG_MXS_SPI) += mxs_spi.o
 COBJS-$(CONFIG_OC_TINY_SPI) += oc_tiny_spi.o
 COBJS-$(CONFIG_OMAP3_SPI) += omap3_spi.o
 COBJS-$(CONFIG_SOFT_SPI) += soft_spi.o
diff --git a/drivers/spi/mxs_spi.c b/drivers/spi/mxs_spi.c
new file mode 100644
index 0000000..4c27fef
--- /dev/null
+++ b/drivers/spi/mxs_spi.c
@@ -0,0 +1,186 @@
+/*
+ * Freescale i.MX28 SPI driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * NOTE: This driver only supports the SPI-controller chipselects,
+ *       GPIO driven chipselects are not supported.
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+
+#define	MXS_SPI_MAX_TIMEOUT	1000000
+#define	MXS_SPI_PORT_OFFSET	0x2000
+
+struct mxs_spi_slave {
+	struct spi_slave	slave;
+	uint32_t		max_khz;
+	uint32_t		mode;
+	struct mx28_ssp_regs	*regs;
+};
+
+static inline struct mxs_spi_slave *to_mxs_slave(struct spi_slave *slave)
+{
+	return container_of(slave, struct mxs_spi_slave, slave);
+}
+
+void spi_init(void)
+{
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+				  unsigned int max_hz, unsigned int mode)
+{
+	struct mxs_spi_slave *mxs_slave;
+	uint32_t addr;
+
+	if (bus > 3) {
+		printf("MXS SPI: Max bus number is 3\n");
+		return NULL;
+	}
+
+	mxs_slave = malloc(sizeof(struct mxs_spi_slave));
+	if (!mxs_slave)
+		return NULL;
+
+	addr = MXS_SSP0_BASE + (bus * MXS_SPI_PORT_OFFSET);
+
+	mxs_slave->slave.bus = bus;
+	mxs_slave->slave.cs = cs;
+	mxs_slave->max_khz = max_hz / 1000;
+	mxs_slave->mode = mode;
+	mxs_slave->regs = (struct mx28_ssp_regs *)addr;
+
+	return &mxs_slave->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+	struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave);
+	free(mxs_slave);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+	struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave);
+	struct mx28_ssp_regs *ssp_regs = mxs_slave->regs;
+	uint32_t reg = 0;
+
+	mx28_reset_block(&ssp_regs->hw_ssp_ctrl0_reg);
+
+	writel(SSP_CTRL0_BUS_WIDTH_ONE_BIT, &ssp_regs->hw_ssp_ctrl0);
+
+	reg = SSP_CTRL1_SSP_MODE_SPI | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS;
+	reg |= (mxs_slave->mode & SPI_CPOL) ? SSP_CTRL1_POLARITY : 0;
+	reg |= (mxs_slave->mode & SPI_CPHA) ? SSP_CTRL1_PHASE : 0;
+	writel(reg, &ssp_regs->hw_ssp_ctrl1);
+
+	writel(0, &ssp_regs->hw_ssp_cmd0);
+
+	mx28_set_ssp_busclock(slave->bus, mxs_slave->max_khz);
+
+	return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+}
+
+static void mxs_spi_start_xfer(struct mx28_ssp_regs *ssp_regs)
+{
+	writel(SSP_CTRL0_LOCK_CS, &ssp_regs->hw_ssp_ctrl0_set);
+	writel(SSP_CTRL0_IGNORE_CRC, &ssp_regs->hw_ssp_ctrl0_clr);
+}
+
+static void mxs_spi_end_xfer(struct mx28_ssp_regs *ssp_regs)
+{
+	writel(SSP_CTRL0_LOCK_CS, &ssp_regs->hw_ssp_ctrl0_clr);
+	writel(SSP_CTRL0_IGNORE_CRC, &ssp_regs->hw_ssp_ctrl0_set);
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+		const void *dout, void *din, unsigned long flags)
+{
+	struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave);
+	struct mx28_ssp_regs *ssp_regs = mxs_slave->regs;
+	int len = bitlen / 8;
+	const char *tx = dout;
+	char *rx = din;
+
+	if (bitlen == 0)
+		return 0;
+
+	if (!rx && !tx)
+		return 0;
+
+	if (flags & SPI_XFER_BEGIN)
+		mxs_spi_start_xfer(ssp_regs);
+
+	while (len--) {
+		/* We transfer 1 byte */
+		writel(1, &ssp_regs->hw_ssp_xfer_size);
+
+		if ((flags & SPI_XFER_END) && !len)
+			mxs_spi_end_xfer(ssp_regs);
+
+		if (tx)
+			writel(SSP_CTRL0_READ, &ssp_regs->hw_ssp_ctrl0_clr);
+		else
+			writel(SSP_CTRL0_READ, &ssp_regs->hw_ssp_ctrl0_set);
+
+		writel(SSP_CTRL0_RUN, &ssp_regs->hw_ssp_ctrl0_set);
+
+		if (mx28_wait_mask_set(&ssp_regs->hw_ssp_ctrl0_reg,
+			SSP_CTRL0_RUN, MXS_SPI_MAX_TIMEOUT)) {
+			printf("MXS SPI: Timeout waiting for start\n");
+			return -1;
+		}
+
+		if (tx)
+			writel(*tx++, &ssp_regs->hw_ssp_data);
+
+		writel(SSP_CTRL0_DATA_XFER, &ssp_regs->hw_ssp_ctrl0_set);
+
+		if (rx) {
+			if (mx28_wait_mask_clr(&ssp_regs->hw_ssp_status_reg,
+				SSP_STATUS_FIFO_EMPTY, MXS_SPI_MAX_TIMEOUT)) {
+				printf("MXS SPI: Timeout waiting for data\n");
+				return -1;
+			}
+
+			*rx = readl(&ssp_regs->hw_ssp_data);
+			rx++;
+		}
+
+		if (mx28_wait_mask_clr(&ssp_regs->hw_ssp_ctrl0_reg,
+			SSP_CTRL0_RUN, MXS_SPI_MAX_TIMEOUT)) {
+			printf("MXS SPI: Timeout waiting for finish\n");
+			return -1;
+		}
+	}
+
+	return 0;
+}
-- 
1.7.6.3

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

* [U-Boot] [PATCH 08/17 RESEND] iMX28: Add APBH DMA driver
  2011-10-21 22:44 ` [U-Boot] [PATCH 00/17 V3] Support for the DENX M28 SoM Marek Vasut
                     ` (6 preceding siblings ...)
  2011-10-21 22:44   ` [U-Boot] [PATCH 07/17 RESEND V2] iMX28: Add SPI driver Marek Vasut
@ 2011-10-21 22:44   ` Marek Vasut
  2011-10-21 22:44   ` [U-Boot] [PATCH 09/17 RESEND V5] iMX28: Add GPMI NAND driver Marek Vasut
                     ` (8 subsequent siblings)
  16 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-10-21 22:44 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 arch/arm/include/asm/arch-mx28/dma.h       |  170 +++++++
 arch/arm/include/asm/arch-mx28/imx-regs.h  |    1 +
 arch/arm/include/asm/arch-mx28/regs-apbh.h |  466 +++++++++++++++++++
 drivers/dma/Makefile                       |    1 +
 drivers/dma/apbh_dma.c                     |  691 ++++++++++++++++++++++++++++
 5 files changed, 1329 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-mx28/dma.h
 create mode 100644 arch/arm/include/asm/arch-mx28/regs-apbh.h
 create mode 100644 drivers/dma/apbh_dma.c

diff --git a/arch/arm/include/asm/arch-mx28/dma.h b/arch/arm/include/asm/arch-mx28/dma.h
new file mode 100644
index 0000000..7061e7c
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/dma.h
@@ -0,0 +1,170 @@
+/*
+ * Freescale i.MX28 APBH DMA
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __DMA_H__
+#define __DMA_H__
+
+#include <linux/list.h>
+
+#ifndef	CONFIG_ARCH_DMA_PIO_WORDS
+#define	DMA_PIO_WORDS		15
+#else
+#define	DMA_PIO_WORDS		CONFIG_ARCH_DMA_PIO_WORDS
+#endif
+
+#define MXS_DMA_ALIGNMENT	32
+
+/*
+ * MXS DMA channels
+ */
+enum {
+	MXS_DMA_CHANNEL_AHB_APBH_SSP0 = 0,
+	MXS_DMA_CHANNEL_AHB_APBH_SSP1,
+	MXS_DMA_CHANNEL_AHB_APBH_SSP2,
+	MXS_DMA_CHANNEL_AHB_APBH_SSP3,
+	MXS_DMA_CHANNEL_AHB_APBH_GPMI0,
+	MXS_DMA_CHANNEL_AHB_APBH_GPMI1,
+	MXS_DMA_CHANNEL_AHB_APBH_GPMI2,
+	MXS_DMA_CHANNEL_AHB_APBH_GPMI3,
+	MXS_DMA_CHANNEL_AHB_APBH_GPMI4,
+	MXS_DMA_CHANNEL_AHB_APBH_GPMI5,
+	MXS_DMA_CHANNEL_AHB_APBH_GPMI6,
+	MXS_DMA_CHANNEL_AHB_APBH_GPMI7,
+	MXS_DMA_CHANNEL_AHB_APBH_SSP,
+	MXS_MAX_DMA_CHANNELS,
+};
+
+/*
+ * MXS DMA hardware command.
+ *
+ * This structure describes the in-memory layout of an entire DMA command,
+ * including space for the maximum number of PIO accesses. See the appropriate
+ * reference manual for a detailed description of what these fields mean to the
+ * DMA hardware.
+ */
+#define	MXS_DMA_DESC_COMMAND_MASK	0x3
+#define	MXS_DMA_DESC_COMMAND_OFFSET	0
+#define	MXS_DMA_DESC_COMMAND_NO_DMAXFER	0x0
+#define	MXS_DMA_DESC_COMMAND_DMA_WRITE	0x1
+#define	MXS_DMA_DESC_COMMAND_DMA_READ	0x2
+#define	MXS_DMA_DESC_COMMAND_DMA_SENSE	0x3
+#define	MXS_DMA_DESC_CHAIN		(1 << 2)
+#define	MXS_DMA_DESC_IRQ		(1 << 3)
+#define	MXS_DMA_DESC_NAND_LOCK		(1 << 4)
+#define	MXS_DMA_DESC_NAND_WAIT_4_READY	(1 << 5)
+#define	MXS_DMA_DESC_DEC_SEM		(1 << 6)
+#define	MXS_DMA_DESC_WAIT4END		(1 << 7)
+#define	MXS_DMA_DESC_HALT_ON_TERMINATE	(1 << 8)
+#define	MXS_DMA_DESC_TERMINATE_FLUSH	(1 << 9)
+#define	MXS_DMA_DESC_PIO_WORDS_MASK	(0xf << 12)
+#define	MXS_DMA_DESC_PIO_WORDS_OFFSET	12
+#define	MXS_DMA_DESC_BYTES_MASK		(0xffff << 16)
+#define	MXS_DMA_DESC_BYTES_OFFSET	16
+
+struct mxs_dma_cmd {
+	unsigned long		next;
+	unsigned long		data;
+	union {
+		dma_addr_t	address;
+		unsigned long	alternate;
+	};
+	unsigned long		pio_words[DMA_PIO_WORDS];
+};
+
+/*
+ * MXS DMA command descriptor.
+ *
+ * This structure incorporates an MXS DMA hardware command structure, along
+ * with metadata.
+ */
+#define	MXS_DMA_DESC_FIRST	(1 << 0)
+#define	MXS_DMA_DESC_LAST	(1 << 1)
+#define	MXS_DMA_DESC_READY	(1 << 31)
+
+struct mxs_dma_desc {
+	struct mxs_dma_cmd	cmd;
+	unsigned int		flags;
+	dma_addr_t		address;
+	void			*buffer;
+	struct list_head	node;
+};
+
+/**
+ * MXS DMA channel
+ *
+ * This structure represents a single DMA channel. The MXS platform code
+ * maintains an array of these structures to represent every DMA channel in the
+ * system (see mxs_dma_channels).
+ */
+#define	MXS_DMA_FLAGS_IDLE	0
+#define	MXS_DMA_FLAGS_BUSY	(1 << 0)
+#define	MXS_DMA_FLAGS_FREE	0
+#define	MXS_DMA_FLAGS_ALLOCATED	(1 << 16)
+#define	MXS_DMA_FLAGS_VALID	(1 << 31)
+
+struct mxs_dma_chan {
+	const char *name;
+	unsigned long dev;
+	struct mxs_dma_device *dma;
+	unsigned int flags;
+	unsigned int active_num;
+	unsigned int pending_num;
+	struct list_head active;
+	struct list_head done;
+};
+
+/* Hardware management ops */
+int mxs_dma_enable(int channel);
+int mxs_dma_disable(int channel);
+int mxs_dma_reset(int channel);
+int mxs_dma_freeze(int channel);
+int mxs_dma_unfreeze(int channel);
+int mxs_dma_read_semaphore(int channel);
+int mxs_dma_enable_irq(int channel, int enable);
+int mxs_dma_irq_is_pending(int channel);
+int mxs_dma_ack_irq(int channel);
+
+/* Channel management ops */
+int mxs_dma_request(int channel);
+int mxs_dma_release(int channel);
+
+/* Descriptor management ops */
+struct mxs_dma_desc *mxs_dma_desc_alloc(void);
+void mxs_dma_desc_free(struct mxs_dma_desc *);
+
+unsigned int mxs_dma_cmd_address(struct mxs_dma_desc *desc);
+int mxs_dma_desc_pending(struct mxs_dma_desc *pdesc);
+
+int mxs_dma_desc_append(int channel, struct mxs_dma_desc *pdesc);
+
+int mxs_dma_get_finished(int channel, struct list_head *head);
+int mxs_dma_finish(int channel, struct list_head *head);
+
+int mxs_dma_wait_complete(uint32_t timeout, unsigned int chan);
+int mxs_dma_go(int chan);
+
+int mxs_dma_init(void);
+
+#endif	/* __DMA_H__ */
diff --git a/arch/arm/include/asm/arch-mx28/imx-regs.h b/arch/arm/include/asm/arch-mx28/imx-regs.h
index 32bfd7e..9561b5e 100644
--- a/arch/arm/include/asm/arch-mx28/imx-regs.h
+++ b/arch/arm/include/asm/arch-mx28/imx-regs.h
@@ -23,6 +23,7 @@
 #ifndef __IMX_REGS_H__
 #define __IMX_REGS_H__
 
+#include <asm/arch/regs-apbh.h>
 #include <asm/arch/regs-base.h>
 #include <asm/arch/regs-bch.h>
 #include <asm/arch/regs-clkctrl.h>
diff --git a/arch/arm/include/asm/arch-mx28/regs-apbh.h b/arch/arm/include/asm/arch-mx28/regs-apbh.h
new file mode 100644
index 0000000..a7fa1ec
--- /dev/null
+++ b/arch/arm/include/asm/arch-mx28/regs-apbh.h
@@ -0,0 +1,466 @@
+/*
+ * Freescale i.MX28 APBH Register Definitions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __REGS_APBH_H__
+#define __REGS_APBH_H__
+
+#include <asm/arch/regs-common.h>
+
+#ifndef	__ASSEMBLY__
+struct mx28_apbh_regs {
+	mx28_reg(hw_apbh_ctrl0)
+	mx28_reg(hw_apbh_ctrl1)
+	mx28_reg(hw_apbh_ctrl2)
+	mx28_reg(hw_apbh_channel_ctrl)
+	mx28_reg(hw_apbh_devsel)
+	mx28_reg(hw_apbh_dma_burst_size)
+	mx28_reg(hw_apbh_debug)
+
+	uint32_t	reserved[36];
+
+	union {
+	struct {
+		mx28_reg(hw_apbh_ch_curcmdar)
+		mx28_reg(hw_apbh_ch_nxtcmdar)
+		mx28_reg(hw_apbh_ch_cmd)
+		mx28_reg(hw_apbh_ch_bar)
+		mx28_reg(hw_apbh_ch_sema)
+		mx28_reg(hw_apbh_ch_debug1)
+		mx28_reg(hw_apbh_ch_debug2)
+	} ch[16];
+	struct {
+		mx28_reg(hw_apbh_ch0_curcmdar)
+		mx28_reg(hw_apbh_ch0_nxtcmdar)
+		mx28_reg(hw_apbh_ch0_cmd)
+		mx28_reg(hw_apbh_ch0_bar)
+		mx28_reg(hw_apbh_ch0_sema)
+		mx28_reg(hw_apbh_ch0_debug1)
+		mx28_reg(hw_apbh_ch0_debug2)
+		mx28_reg(hw_apbh_ch1_curcmdar)
+		mx28_reg(hw_apbh_ch1_nxtcmdar)
+		mx28_reg(hw_apbh_ch1_cmd)
+		mx28_reg(hw_apbh_ch1_bar)
+		mx28_reg(hw_apbh_ch1_sema)
+		mx28_reg(hw_apbh_ch1_debug1)
+		mx28_reg(hw_apbh_ch1_debug2)
+		mx28_reg(hw_apbh_ch2_curcmdar)
+		mx28_reg(hw_apbh_ch2_nxtcmdar)
+		mx28_reg(hw_apbh_ch2_cmd)
+		mx28_reg(hw_apbh_ch2_bar)
+		mx28_reg(hw_apbh_ch2_sema)
+		mx28_reg(hw_apbh_ch2_debug1)
+		mx28_reg(hw_apbh_ch2_debug2)
+		mx28_reg(hw_apbh_ch3_curcmdar)
+		mx28_reg(hw_apbh_ch3_nxtcmdar)
+		mx28_reg(hw_apbh_ch3_cmd)
+		mx28_reg(hw_apbh_ch3_bar)
+		mx28_reg(hw_apbh_ch3_sema)
+		mx28_reg(hw_apbh_ch3_debug1)
+		mx28_reg(hw_apbh_ch3_debug2)
+		mx28_reg(hw_apbh_ch4_curcmdar)
+		mx28_reg(hw_apbh_ch4_nxtcmdar)
+		mx28_reg(hw_apbh_ch4_cmd)
+		mx28_reg(hw_apbh_ch4_bar)
+		mx28_reg(hw_apbh_ch4_sema)
+		mx28_reg(hw_apbh_ch4_debug1)
+		mx28_reg(hw_apbh_ch4_debug2)
+		mx28_reg(hw_apbh_ch5_curcmdar)
+		mx28_reg(hw_apbh_ch5_nxtcmdar)
+		mx28_reg(hw_apbh_ch5_cmd)
+		mx28_reg(hw_apbh_ch5_bar)
+		mx28_reg(hw_apbh_ch5_sema)
+		mx28_reg(hw_apbh_ch5_debug1)
+		mx28_reg(hw_apbh_ch5_debug2)
+		mx28_reg(hw_apbh_ch6_curcmdar)
+		mx28_reg(hw_apbh_ch6_nxtcmdar)
+		mx28_reg(hw_apbh_ch6_cmd)
+		mx28_reg(hw_apbh_ch6_bar)
+		mx28_reg(hw_apbh_ch6_sema)
+		mx28_reg(hw_apbh_ch6_debug1)
+		mx28_reg(hw_apbh_ch6_debug2)
+		mx28_reg(hw_apbh_ch7_curcmdar)
+		mx28_reg(hw_apbh_ch7_nxtcmdar)
+		mx28_reg(hw_apbh_ch7_cmd)
+		mx28_reg(hw_apbh_ch7_bar)
+		mx28_reg(hw_apbh_ch7_sema)
+		mx28_reg(hw_apbh_ch7_debug1)
+		mx28_reg(hw_apbh_ch7_debug2)
+		mx28_reg(hw_apbh_ch8_curcmdar)
+		mx28_reg(hw_apbh_ch8_nxtcmdar)
+		mx28_reg(hw_apbh_ch8_cmd)
+		mx28_reg(hw_apbh_ch8_bar)
+		mx28_reg(hw_apbh_ch8_sema)
+		mx28_reg(hw_apbh_ch8_debug1)
+		mx28_reg(hw_apbh_ch8_debug2)
+		mx28_reg(hw_apbh_ch9_curcmdar)
+		mx28_reg(hw_apbh_ch9_nxtcmdar)
+		mx28_reg(hw_apbh_ch9_cmd)
+		mx28_reg(hw_apbh_ch9_bar)
+		mx28_reg(hw_apbh_ch9_sema)
+		mx28_reg(hw_apbh_ch9_debug1)
+		mx28_reg(hw_apbh_ch9_debug2)
+		mx28_reg(hw_apbh_ch10_curcmdar)
+		mx28_reg(hw_apbh_ch10_nxtcmdar)
+		mx28_reg(hw_apbh_ch10_cmd)
+		mx28_reg(hw_apbh_ch10_bar)
+		mx28_reg(hw_apbh_ch10_sema)
+		mx28_reg(hw_apbh_ch10_debug1)
+		mx28_reg(hw_apbh_ch10_debug2)
+		mx28_reg(hw_apbh_ch11_curcmdar)
+		mx28_reg(hw_apbh_ch11_nxtcmdar)
+		mx28_reg(hw_apbh_ch11_cmd)
+		mx28_reg(hw_apbh_ch11_bar)
+		mx28_reg(hw_apbh_ch11_sema)
+		mx28_reg(hw_apbh_ch11_debug1)
+		mx28_reg(hw_apbh_ch11_debug2)
+		mx28_reg(hw_apbh_ch12_curcmdar)
+		mx28_reg(hw_apbh_ch12_nxtcmdar)
+		mx28_reg(hw_apbh_ch12_cmd)
+		mx28_reg(hw_apbh_ch12_bar)
+		mx28_reg(hw_apbh_ch12_sema)
+		mx28_reg(hw_apbh_ch12_debug1)
+		mx28_reg(hw_apbh_ch12_debug2)
+		mx28_reg(hw_apbh_ch13_curcmdar)
+		mx28_reg(hw_apbh_ch13_nxtcmdar)
+		mx28_reg(hw_apbh_ch13_cmd)
+		mx28_reg(hw_apbh_ch13_bar)
+		mx28_reg(hw_apbh_ch13_sema)
+		mx28_reg(hw_apbh_ch13_debug1)
+		mx28_reg(hw_apbh_ch13_debug2)
+		mx28_reg(hw_apbh_ch14_curcmdar)
+		mx28_reg(hw_apbh_ch14_nxtcmdar)
+		mx28_reg(hw_apbh_ch14_cmd)
+		mx28_reg(hw_apbh_ch14_bar)
+		mx28_reg(hw_apbh_ch14_sema)
+		mx28_reg(hw_apbh_ch14_debug1)
+		mx28_reg(hw_apbh_ch14_debug2)
+		mx28_reg(hw_apbh_ch15_curcmdar)
+		mx28_reg(hw_apbh_ch15_nxtcmdar)
+		mx28_reg(hw_apbh_ch15_cmd)
+		mx28_reg(hw_apbh_ch15_bar)
+		mx28_reg(hw_apbh_ch15_sema)
+		mx28_reg(hw_apbh_ch15_debug1)
+		mx28_reg(hw_apbh_ch15_debug2)
+	};
+	};
+	mx28_reg(hw_apbh_version)
+};
+#endif
+
+#define	APBH_CTRL0_SFTRST				(1 << 31)
+#define	APBH_CTRL0_CLKGATE				(1 << 30)
+#define	APBH_CTRL0_AHB_BURST8_EN			(1 << 29)
+#define	APBH_CTRL0_APB_BURST_EN				(1 << 28)
+#define	APBH_CTRL0_RSVD0_MASK				(0xfff << 16)
+#define	APBH_CTRL0_RSVD0_OFFSET				16
+#define	APBH_CTRL0_CLKGATE_CHANNEL_MASK			0xffff
+#define	APBH_CTRL0_CLKGATE_CHANNEL_OFFSET		0
+#define	APBH_CTRL0_CLKGATE_CHANNEL_SSP0			0x0001
+#define	APBH_CTRL0_CLKGATE_CHANNEL_SSP1			0x0002
+#define	APBH_CTRL0_CLKGATE_CHANNEL_SSP2			0x0004
+#define	APBH_CTRL0_CLKGATE_CHANNEL_SSP3			0x0008
+#define	APBH_CTRL0_CLKGATE_CHANNEL_NAND0		0x0010
+#define	APBH_CTRL0_CLKGATE_CHANNEL_NAND1		0x0020
+#define	APBH_CTRL0_CLKGATE_CHANNEL_NAND2		0x0040
+#define	APBH_CTRL0_CLKGATE_CHANNEL_NAND3		0x0080
+#define	APBH_CTRL0_CLKGATE_CHANNEL_NAND4		0x0100
+#define	APBH_CTRL0_CLKGATE_CHANNEL_NAND5		0x0200
+#define	APBH_CTRL0_CLKGATE_CHANNEL_NAND6		0x0400
+#define	APBH_CTRL0_CLKGATE_CHANNEL_NAND7		0x0800
+#define	APBH_CTRL0_CLKGATE_CHANNEL_HSADC		0x1000
+#define	APBH_CTRL0_CLKGATE_CHANNEL_LCDIF		0x2000
+
+#define	APBH_CTRL1_CH15_CMDCMPLT_IRQ_EN			(1 << 31)
+#define	APBH_CTRL1_CH14_CMDCMPLT_IRQ_EN			(1 << 30)
+#define	APBH_CTRL1_CH13_CMDCMPLT_IRQ_EN			(1 << 29)
+#define	APBH_CTRL1_CH12_CMDCMPLT_IRQ_EN			(1 << 28)
+#define	APBH_CTRL1_CH11_CMDCMPLT_IRQ_EN			(1 << 27)
+#define	APBH_CTRL1_CH10_CMDCMPLT_IRQ_EN			(1 << 26)
+#define	APBH_CTRL1_CH9_CMDCMPLT_IRQ_EN			(1 << 25)
+#define	APBH_CTRL1_CH8_CMDCMPLT_IRQ_EN			(1 << 24)
+#define	APBH_CTRL1_CH7_CMDCMPLT_IRQ_EN			(1 << 23)
+#define	APBH_CTRL1_CH6_CMDCMPLT_IRQ_EN			(1 << 22)
+#define	APBH_CTRL1_CH5_CMDCMPLT_IRQ_EN			(1 << 21)
+#define	APBH_CTRL1_CH4_CMDCMPLT_IRQ_EN			(1 << 20)
+#define	APBH_CTRL1_CH3_CMDCMPLT_IRQ_EN			(1 << 19)
+#define	APBH_CTRL1_CH2_CMDCMPLT_IRQ_EN			(1 << 18)
+#define	APBH_CTRL1_CH1_CMDCMPLT_IRQ_EN			(1 << 17)
+#define	APBH_CTRL1_CH0_CMDCMPLT_IRQ_EN			(1 << 16)
+#define	APBH_CTRL1_CH_CMDCMPLT_IRQ_EN_OFFSET		16
+#define	APBH_CTRL1_CH_CMDCMPLT_IRQ_EN_MASK		(0xffff << 16)
+#define	APBH_CTRL1_CH15_CMDCMPLT_IRQ			(1 << 15)
+#define	APBH_CTRL1_CH14_CMDCMPLT_IRQ			(1 << 14)
+#define	APBH_CTRL1_CH13_CMDCMPLT_IRQ			(1 << 13)
+#define	APBH_CTRL1_CH12_CMDCMPLT_IRQ			(1 << 12)
+#define	APBH_CTRL1_CH11_CMDCMPLT_IRQ			(1 << 11)
+#define	APBH_CTRL1_CH10_CMDCMPLT_IRQ			(1 << 10)
+#define	APBH_CTRL1_CH9_CMDCMPLT_IRQ			(1 << 9)
+#define	APBH_CTRL1_CH8_CMDCMPLT_IRQ			(1 << 8)
+#define	APBH_CTRL1_CH7_CMDCMPLT_IRQ			(1 << 7)
+#define	APBH_CTRL1_CH6_CMDCMPLT_IRQ			(1 << 6)
+#define	APBH_CTRL1_CH5_CMDCMPLT_IRQ			(1 << 5)
+#define	APBH_CTRL1_CH4_CMDCMPLT_IRQ			(1 << 4)
+#define	APBH_CTRL1_CH3_CMDCMPLT_IRQ			(1 << 3)
+#define	APBH_CTRL1_CH2_CMDCMPLT_IRQ			(1 << 2)
+#define	APBH_CTRL1_CH1_CMDCMPLT_IRQ			(1 << 1)
+#define	APBH_CTRL1_CH0_CMDCMPLT_IRQ			(1 << 0)
+
+#define	APBH_CTRL2_CH15_ERROR_STATUS			(1 << 31)
+#define	APBH_CTRL2_CH14_ERROR_STATUS			(1 << 30)
+#define	APBH_CTRL2_CH13_ERROR_STATUS			(1 << 29)
+#define	APBH_CTRL2_CH12_ERROR_STATUS			(1 << 28)
+#define	APBH_CTRL2_CH11_ERROR_STATUS			(1 << 27)
+#define	APBH_CTRL2_CH10_ERROR_STATUS			(1 << 26)
+#define	APBH_CTRL2_CH9_ERROR_STATUS			(1 << 25)
+#define	APBH_CTRL2_CH8_ERROR_STATUS			(1 << 24)
+#define	APBH_CTRL2_CH7_ERROR_STATUS			(1 << 23)
+#define	APBH_CTRL2_CH6_ERROR_STATUS			(1 << 22)
+#define	APBH_CTRL2_CH5_ERROR_STATUS			(1 << 21)
+#define	APBH_CTRL2_CH4_ERROR_STATUS			(1 << 20)
+#define	APBH_CTRL2_CH3_ERROR_STATUS			(1 << 19)
+#define	APBH_CTRL2_CH2_ERROR_STATUS			(1 << 18)
+#define	APBH_CTRL2_CH1_ERROR_STATUS			(1 << 17)
+#define	APBH_CTRL2_CH0_ERROR_STATUS			(1 << 16)
+#define	APBH_CTRL2_CH15_ERROR_IRQ			(1 << 15)
+#define	APBH_CTRL2_CH14_ERROR_IRQ			(1 << 14)
+#define	APBH_CTRL2_CH13_ERROR_IRQ			(1 << 13)
+#define	APBH_CTRL2_CH12_ERROR_IRQ			(1 << 12)
+#define	APBH_CTRL2_CH11_ERROR_IRQ			(1 << 11)
+#define	APBH_CTRL2_CH10_ERROR_IRQ			(1 << 10)
+#define	APBH_CTRL2_CH9_ERROR_IRQ			(1 << 9)
+#define	APBH_CTRL2_CH8_ERROR_IRQ			(1 << 8)
+#define	APBH_CTRL2_CH7_ERROR_IRQ			(1 << 7)
+#define	APBH_CTRL2_CH6_ERROR_IRQ			(1 << 6)
+#define	APBH_CTRL2_CH5_ERROR_IRQ			(1 << 5)
+#define	APBH_CTRL2_CH4_ERROR_IRQ			(1 << 4)
+#define	APBH_CTRL2_CH3_ERROR_IRQ			(1 << 3)
+#define	APBH_CTRL2_CH2_ERROR_IRQ			(1 << 2)
+#define	APBH_CTRL2_CH1_ERROR_IRQ			(1 << 1)
+#define	APBH_CTRL2_CH0_ERROR_IRQ			(1 << 0)
+
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_MASK		(0xffff << 16)
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_OFFSET		16
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_SSP0		(0x0001 << 16)
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_SSP1		(0x0002 << 16)
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_SSP2		(0x0004 << 16)
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_SSP3		(0x0008 << 16)
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_NAND0		(0x0010 << 16)
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_NAND1		(0x0020 << 16)
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_NAND2		(0x0040 << 16)
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_NAND3		(0x0080 << 16)
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_NAND4		(0x0100 << 16)
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_NAND5		(0x0200 << 16)
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_NAND6		(0x0400 << 16)
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_NAND7		(0x0800 << 16)
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_HSADC		(0x1000 << 16)
+#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_LCDIF		(0x2000 << 16)
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_MASK		0xffff
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_OFFSET		0
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_SSP0		0x0001
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_SSP1		0x0002
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_SSP2		0x0004
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_SSP3		0x0008
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_NAND0		0x0010
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_NAND1		0x0020
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_NAND2		0x0040
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_NAND3		0x0080
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_NAND4		0x0100
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_NAND5		0x0200
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_NAND6		0x0400
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_NAND7		0x0800
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_HSADC		0x1000
+#define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_LCDIF		0x2000
+
+#define	APBH_DEVSEL_CH15_MASK				(0x3 << 30)
+#define	APBH_DEVSEL_CH15_OFFSET				30
+#define	APBH_DEVSEL_CH14_MASK				(0x3 << 28)
+#define	APBH_DEVSEL_CH14_OFFSET				28
+#define	APBH_DEVSEL_CH13_MASK				(0x3 << 26)
+#define	APBH_DEVSEL_CH13_OFFSET				26
+#define	APBH_DEVSEL_CH12_MASK				(0x3 << 24)
+#define	APBH_DEVSEL_CH12_OFFSET				24
+#define	APBH_DEVSEL_CH11_MASK				(0x3 << 22)
+#define	APBH_DEVSEL_CH11_OFFSET				22
+#define	APBH_DEVSEL_CH10_MASK				(0x3 << 20)
+#define	APBH_DEVSEL_CH10_OFFSET				20
+#define	APBH_DEVSEL_CH9_MASK				(0x3 << 18)
+#define	APBH_DEVSEL_CH9_OFFSET				18
+#define	APBH_DEVSEL_CH8_MASK				(0x3 << 16)
+#define	APBH_DEVSEL_CH8_OFFSET				16
+#define	APBH_DEVSEL_CH7_MASK				(0x3 << 14)
+#define	APBH_DEVSEL_CH7_OFFSET				14
+#define	APBH_DEVSEL_CH6_MASK				(0x3 << 12)
+#define	APBH_DEVSEL_CH6_OFFSET				12
+#define	APBH_DEVSEL_CH5_MASK				(0x3 << 10)
+#define	APBH_DEVSEL_CH5_OFFSET				10
+#define	APBH_DEVSEL_CH4_MASK				(0x3 << 8)
+#define	APBH_DEVSEL_CH4_OFFSET				8
+#define	APBH_DEVSEL_CH3_MASK				(0x3 << 6)
+#define	APBH_DEVSEL_CH3_OFFSET				6
+#define	APBH_DEVSEL_CH2_MASK				(0x3 << 4)
+#define	APBH_DEVSEL_CH2_OFFSET				4
+#define	APBH_DEVSEL_CH1_MASK				(0x3 << 2)
+#define	APBH_DEVSEL_CH1_OFFSET				2
+#define	APBH_DEVSEL_CH0_MASK				(0x3 << 0)
+#define	APBH_DEVSEL_CH0_OFFSET				0
+
+#define	APBH_DMA_BURST_SIZE_CH15_MASK			(0x3 << 30)
+#define	APBH_DMA_BURST_SIZE_CH15_OFFSET			30
+#define	APBH_DMA_BURST_SIZE_CH14_MASK			(0x3 << 28)
+#define	APBH_DMA_BURST_SIZE_CH14_OFFSET			28
+#define	APBH_DMA_BURST_SIZE_CH13_MASK			(0x3 << 26)
+#define	APBH_DMA_BURST_SIZE_CH13_OFFSET			26
+#define	APBH_DMA_BURST_SIZE_CH12_MASK			(0x3 << 24)
+#define	APBH_DMA_BURST_SIZE_CH12_OFFSET			24
+#define	APBH_DMA_BURST_SIZE_CH11_MASK			(0x3 << 22)
+#define	APBH_DMA_BURST_SIZE_CH11_OFFSET			22
+#define	APBH_DMA_BURST_SIZE_CH10_MASK			(0x3 << 20)
+#define	APBH_DMA_BURST_SIZE_CH10_OFFSET			20
+#define	APBH_DMA_BURST_SIZE_CH9_MASK			(0x3 << 18)
+#define	APBH_DMA_BURST_SIZE_CH9_OFFSET			18
+#define	APBH_DMA_BURST_SIZE_CH8_MASK			(0x3 << 16)
+#define	APBH_DMA_BURST_SIZE_CH8_OFFSET			16
+#define	APBH_DMA_BURST_SIZE_CH8_BURST0			(0x0 << 16)
+#define	APBH_DMA_BURST_SIZE_CH8_BURST4			(0x1 << 16)
+#define	APBH_DMA_BURST_SIZE_CH8_BURST8			(0x2 << 16)
+#define	APBH_DMA_BURST_SIZE_CH7_MASK			(0x3 << 14)
+#define	APBH_DMA_BURST_SIZE_CH7_OFFSET			14
+#define	APBH_DMA_BURST_SIZE_CH6_MASK			(0x3 << 12)
+#define	APBH_DMA_BURST_SIZE_CH6_OFFSET			12
+#define	APBH_DMA_BURST_SIZE_CH5_MASK			(0x3 << 10)
+#define	APBH_DMA_BURST_SIZE_CH5_OFFSET			10
+#define	APBH_DMA_BURST_SIZE_CH4_MASK			(0x3 << 8)
+#define	APBH_DMA_BURST_SIZE_CH4_OFFSET			8
+#define	APBH_DMA_BURST_SIZE_CH3_MASK			(0x3 << 6)
+#define	APBH_DMA_BURST_SIZE_CH3_OFFSET			6
+#define	APBH_DMA_BURST_SIZE_CH3_BURST0			(0x0 << 6)
+#define	APBH_DMA_BURST_SIZE_CH3_BURST4			(0x1 << 6)
+#define	APBH_DMA_BURST_SIZE_CH3_BURST8			(0x2 << 6)
+
+#define	APBH_DMA_BURST_SIZE_CH2_MASK			(0x3 << 4)
+#define	APBH_DMA_BURST_SIZE_CH2_OFFSET			4
+#define	APBH_DMA_BURST_SIZE_CH2_BURST0			(0x0 << 4)
+#define	APBH_DMA_BURST_SIZE_CH2_BURST4			(0x1 << 4)
+#define	APBH_DMA_BURST_SIZE_CH2_BURST8			(0x2 << 4)
+#define	APBH_DMA_BURST_SIZE_CH1_MASK			(0x3 << 2)
+#define	APBH_DMA_BURST_SIZE_CH1_OFFSET			2
+#define	APBH_DMA_BURST_SIZE_CH1_BURST0			(0x0 << 2)
+#define	APBH_DMA_BURST_SIZE_CH1_BURST4			(0x1 << 2)
+#define	APBH_DMA_BURST_SIZE_CH1_BURST8			(0x2 << 2)
+
+#define	APBH_DMA_BURST_SIZE_CH0_MASK			0x3
+#define	APBH_DMA_BURST_SIZE_CH0_OFFSET			0
+#define	APBH_DMA_BURST_SIZE_CH0_BURST0			0x0
+#define	APBH_DMA_BURST_SIZE_CH0_BURST4			0x1
+#define	APBH_DMA_BURST_SIZE_CH0_BURST8			0x2
+
+#define	APBH_DEBUG_GPMI_ONE_FIFO			(1 << 0)
+
+#define	APBH_CHn_CURCMDAR_CMD_ADDR_MASK			0xffffffff
+#define	APBH_CHn_CURCMDAR_CMD_ADDR_OFFSET		0
+
+#define	APBH_CHn_NXTCMDAR_CMD_ADDR_MASK			0xffffffff
+#define	APBH_CHn_NXTCMDAR_CMD_ADDR_OFFSET		0
+
+#define	APBH_CHn_CMD_XFER_COUNT_MASK			(0xffff << 16)
+#define	APBH_CHn_CMD_XFER_COUNT_OFFSET			16
+#define	APBH_CHn_CMD_CMDWORDS_MASK			(0xf << 12)
+#define	APBH_CHn_CMD_CMDWORDS_OFFSET			12
+#define	APBH_CHn_CMD_HALTONTERMINATE			(1 << 8)
+#define	APBH_CHn_CMD_WAIT4ENDCMD			(1 << 7)
+#define	APBH_CHn_CMD_SEMAPHORE				(1 << 6)
+#define	APBH_CHn_CMD_NANDWAIT4READY			(1 << 5)
+#define	APBH_CHn_CMD_NANDLOCK				(1 << 4)
+#define	APBH_CHn_CMD_IRQONCMPLT				(1 << 3)
+#define	APBH_CHn_CMD_CHAIN				(1 << 2)
+#define	APBH_CHn_CMD_COMMAND_MASK			0x3
+#define	APBH_CHn_CMD_COMMAND_OFFSET			0
+#define	APBH_CHn_CMD_COMMAND_NO_DMA_XFER		0x0
+#define	APBH_CHn_CMD_COMMAND_DMA_WRITE			0x1
+#define	APBH_CHn_CMD_COMMAND_DMA_READ			0x2
+#define	APBH_CHn_CMD_COMMAND_DMA_SENSE			0x3
+
+#define	APBH_CHn_BAR_ADDRESS_MASK			0xffffffff
+#define	APBH_CHn_BAR_ADDRESS_OFFSET			0
+
+#define	APBH_CHn_SEMA_RSVD2_MASK			(0xff << 24)
+#define	APBH_CHn_SEMA_RSVD2_OFFSET			24
+#define	APBH_CHn_SEMA_PHORE_MASK			(0xff << 16)
+#define	APBH_CHn_SEMA_PHORE_OFFSET			16
+#define	APBH_CHn_SEMA_RSVD1_MASK			(0xff << 8)
+#define	APBH_CHn_SEMA_RSVD1_OFFSET			8
+#define	APBH_CHn_SEMA_INCREMENT_SEMA_MASK		(0xff << 0)
+#define	APBH_CHn_SEMA_INCREMENT_SEMA_OFFSET		0
+
+#define	APBH_CHn_DEBUG1_REQ				(1 << 31)
+#define	APBH_CHn_DEBUG1_BURST				(1 << 30)
+#define	APBH_CHn_DEBUG1_KICK				(1 << 29)
+#define	APBH_CHn_DEBUG1_END				(1 << 28)
+#define	APBH_CHn_DEBUG1_SENSE				(1 << 27)
+#define	APBH_CHn_DEBUG1_READY				(1 << 26)
+#define	APBH_CHn_DEBUG1_LOCK				(1 << 25)
+#define	APBH_CHn_DEBUG1_NEXTCMDADDRVALID		(1 << 24)
+#define	APBH_CHn_DEBUG1_RD_FIFO_EMPTY			(1 << 23)
+#define	APBH_CHn_DEBUG1_RD_FIFO_FULL			(1 << 22)
+#define	APBH_CHn_DEBUG1_WR_FIFO_EMPTY			(1 << 21)
+#define	APBH_CHn_DEBUG1_WR_FIFO_FULL			(1 << 20)
+#define	APBH_CHn_DEBUG1_RSVD1_MASK			(0x7fff << 5)
+#define	APBH_CHn_DEBUG1_RSVD1_OFFSET			5
+#define	APBH_CHn_DEBUG1_STATEMACHINE_MASK		0x1f
+#define	APBH_CHn_DEBUG1_STATEMACHINE_OFFSET		0
+#define	APBH_CHn_DEBUG1_STATEMACHINE_IDLE		0x00
+#define	APBH_CHn_DEBUG1_STATEMACHINE_REQ_CMD1		0x01
+#define	APBH_CHn_DEBUG1_STATEMACHINE_REQ_CMD3		0x02
+#define	APBH_CHn_DEBUG1_STATEMACHINE_REQ_CMD2		0x03
+#define	APBH_CHn_DEBUG1_STATEMACHINE_XFER_DECODE	0x04
+#define	APBH_CHn_DEBUG1_STATEMACHINE_REQ_WAIT		0x05
+#define	APBH_CHn_DEBUG1_STATEMACHINE_REQ_CMD4		0x06
+#define	APBH_CHn_DEBUG1_STATEMACHINE_PIO_REQ		0x07
+#define	APBH_CHn_DEBUG1_STATEMACHINE_READ_FLUSH		0x08
+#define	APBH_CHn_DEBUG1_STATEMACHINE_READ_WAIT		0x09
+#define	APBH_CHn_DEBUG1_STATEMACHINE_WRITE		0x0c
+#define	APBH_CHn_DEBUG1_STATEMACHINE_READ_REQ		0x0d
+#define	APBH_CHn_DEBUG1_STATEMACHINE_CHECK_CHAIN	0x0e
+#define	APBH_CHn_DEBUG1_STATEMACHINE_XFER_COMPLETE	0x0f
+#define	APBH_CHn_DEBUG1_STATEMACHINE_TERMINATE		0x14
+#define	APBH_CHn_DEBUG1_STATEMACHINE_WAIT_END		0x15
+#define	APBH_CHn_DEBUG1_STATEMACHINE_WRITE_WAIT		0x1c
+#define	APBH_CHn_DEBUG1_STATEMACHINE_HALT_AFTER_TERM	0x1d
+#define	APBH_CHn_DEBUG1_STATEMACHINE_CHECK_WAIT		0x1e
+#define	APBH_CHn_DEBUG1_STATEMACHINE_WAIT_READY		0x1f
+
+#define	APBH_CHn_DEBUG2_APB_BYTES_MASK			(0xffff << 16)
+#define	APBH_CHn_DEBUG2_APB_BYTES_OFFSET		16
+#define	APBH_CHn_DEBUG2_AHB_BYTES_MASK			0xffff
+#define	APBH_CHn_DEBUG2_AHB_BYTES_OFFSET		0
+
+#define	APBH_VERSION_MAJOR_MASK				(0xff << 24)
+#define	APBH_VERSION_MAJOR_OFFSET			24
+#define	APBH_VERSION_MINOR_MASK				(0xff << 16)
+#define	APBH_VERSION_MINOR_OFFSET			16
+#define	APBH_VERSION_STEP_MASK				0xffff
+#define	APBH_VERSION_STEP_OFFSET			0
+
+#endif	/* __REGS_APBH_H__ */
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 9d945a0..514828b 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -26,6 +26,7 @@ include $(TOPDIR)/config.mk
 LIB	:= $(obj)libdma.o
 
 COBJS-$(CONFIG_FSLDMAFEC) += MCD_tasksInit.o MCD_dmaApi.o MCD_tasks.o
+COBJS-$(CONFIG_APBH_DMA) += apbh_dma.o
 COBJS-$(CONFIG_FSL_DMA) += fsl_dma.o
 
 COBJS	:= $(COBJS-y)
diff --git a/drivers/dma/apbh_dma.c b/drivers/dma/apbh_dma.c
new file mode 100644
index 0000000..69a1042
--- /dev/null
+++ b/drivers/dma/apbh_dma.c
@@ -0,0 +1,691 @@
+/*
+ * Freescale i.MX28 APBH DMA driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/list.h>
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/dma.h>
+
+static struct mxs_dma_chan mxs_dma_channels[MXS_MAX_DMA_CHANNELS];
+
+/*
+ * Test is the DMA channel is valid channel
+ */
+int mxs_dma_validate_chan(int channel)
+{
+	struct mxs_dma_chan *pchan;
+
+	if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS))
+		return -EINVAL;
+
+	pchan = mxs_dma_channels + channel;
+	if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+		return -EINVAL;
+
+	return 0;
+}
+
+/*
+ * Enable a DMA channel.
+ *
+ * If the given channel has any DMA descriptors on its active list, this
+ * function causes the DMA hardware to begin processing them.
+ *
+ * This function marks the DMA channel as "busy," whether or not there are any
+ * descriptors to process.
+ */
+int mxs_dma_enable(int channel)
+{
+	struct mx28_apbh_regs *apbh_regs =
+		(struct mx28_apbh_regs *)MXS_APBH_BASE;
+	unsigned int sem;
+	struct mxs_dma_chan *pchan;
+	struct mxs_dma_desc *pdesc;
+	int ret;
+
+	ret = mxs_dma_validate_chan(channel);
+	if (ret)
+		return ret;
+
+	pchan = mxs_dma_channels + channel;
+
+	if (pchan->pending_num == 0) {
+		pchan->flags |= MXS_DMA_FLAGS_BUSY;
+		return 0;
+	}
+
+	pdesc = list_first_entry(&pchan->active, struct mxs_dma_desc, node);
+	if (pdesc == NULL)
+		return -EFAULT;
+
+	if (pchan->flags & MXS_DMA_FLAGS_BUSY) {
+		if (!(pdesc->cmd.data & MXS_DMA_DESC_CHAIN))
+			return 0;
+
+		sem = mxs_dma_read_semaphore(channel);
+		if (sem == 0)
+			return 0;
+
+		if (sem == 1) {
+			pdesc = list_entry(pdesc->node.next,
+					   struct mxs_dma_desc, node);
+			writel(mxs_dma_cmd_address(pdesc),
+				&apbh_regs->ch[channel].hw_apbh_ch_nxtcmdar);
+		}
+		writel(pchan->pending_num,
+			&apbh_regs->ch[channel].hw_apbh_ch_sema);
+		pchan->active_num += pchan->pending_num;
+		pchan->pending_num = 0;
+	} else {
+		pchan->active_num += pchan->pending_num;
+		pchan->pending_num = 0;
+		writel(mxs_dma_cmd_address(pdesc),
+			&apbh_regs->ch[channel].hw_apbh_ch_nxtcmdar);
+		writel(pchan->active_num,
+			&apbh_regs->ch[channel].hw_apbh_ch_sema);
+		writel(1 << (channel + APBH_CTRL0_CLKGATE_CHANNEL_OFFSET),
+			&apbh_regs->hw_apbh_ctrl0_clr);
+	}
+
+	pchan->flags |= MXS_DMA_FLAGS_BUSY;
+	return 0;
+}
+
+/*
+ * Disable a DMA channel.
+ *
+ * This function shuts down a DMA channel and marks it as "not busy." Any
+ * descriptors on the active list are immediately moved to the head of the
+ * "done" list, whether or not they have actually been processed by the
+ * hardware. The "ready" flags of these descriptors are NOT cleared, so they
+ * still appear to be active.
+ *
+ * This function immediately shuts down a DMA channel's hardware, aborting any
+ * I/O that may be in progress, potentially leaving I/O hardware in an undefined
+ * state. It is unwise to call this function if there is ANY chance the hardware
+ * is still processing a command.
+ */
+int mxs_dma_disable(int channel)
+{
+	struct mxs_dma_chan *pchan;
+	struct mx28_apbh_regs *apbh_regs =
+		(struct mx28_apbh_regs *)MXS_APBH_BASE;
+	int ret;
+
+	ret = mxs_dma_validate_chan(channel);
+	if (ret)
+		return ret;
+
+	pchan = mxs_dma_channels + channel;
+
+	if (!(pchan->flags & MXS_DMA_FLAGS_BUSY))
+		return -EINVAL;
+
+	writel(1 << (channel + APBH_CTRL0_CLKGATE_CHANNEL_OFFSET),
+		&apbh_regs->hw_apbh_ctrl0_set);
+
+	pchan->flags &= ~MXS_DMA_FLAGS_BUSY;
+	pchan->active_num = 0;
+	pchan->pending_num = 0;
+	list_splice_init(&pchan->active, &pchan->done);
+
+	return 0;
+}
+
+/*
+ * Resets the DMA channel hardware.
+ */
+int mxs_dma_reset(int channel)
+{
+	struct mx28_apbh_regs *apbh_regs =
+		(struct mx28_apbh_regs *)MXS_APBH_BASE;
+	int ret;
+
+	ret = mxs_dma_validate_chan(channel);
+	if (ret)
+		return ret;
+
+	writel(1 << (channel + APBH_CHANNEL_CTRL_RESET_CHANNEL_OFFSET),
+		&apbh_regs->hw_apbh_channel_ctrl_set);
+
+	return 0;
+}
+
+/*
+ * Freeze a DMA channel.
+ *
+ * This function causes the channel to continuously fail arbitration for bus
+ * access, which halts all forward progress without losing any state. A call to
+ * mxs_dma_unfreeze() will cause the channel to continue its current operation
+ * with no ill effect.
+ */
+int mxs_dma_freeze(int channel)
+{
+	struct mx28_apbh_regs *apbh_regs =
+		(struct mx28_apbh_regs *)MXS_APBH_BASE;
+	int ret;
+
+	ret = mxs_dma_validate_chan(channel);
+	if (ret)
+		return ret;
+
+	writel(1 << (channel + APBH_CHANNEL_CTRL_FREEZE_CHANNEL_OFFSET),
+		&apbh_regs->hw_apbh_channel_ctrl_set);
+
+	return 0;
+}
+
+/*
+ * Unfreeze a DMA channel.
+ *
+ * This function reverses the effect of mxs_dma_freeze(), enabling the DMA
+ * channel to continue from where it was frozen.
+ */
+int mxs_dma_unfreeze(int channel)
+{
+	struct mx28_apbh_regs *apbh_regs =
+		(struct mx28_apbh_regs *)MXS_APBH_BASE;
+	int ret;
+
+	ret = mxs_dma_validate_chan(channel);
+	if (ret)
+		return ret;
+
+	writel(1 << (channel + APBH_CHANNEL_CTRL_FREEZE_CHANNEL_OFFSET),
+		&apbh_regs->hw_apbh_channel_ctrl_clr);
+
+	return 0;
+}
+
+/*
+ * Read a DMA channel's hardware semaphore.
+ *
+ * As used by the MXS platform's DMA software, the DMA channel's hardware
+ * semaphore reflects the number of DMA commands the hardware will process, but
+ * has not yet finished. This is a volatile value read directly from hardware,
+ * so it must be be viewed as immediately stale.
+ *
+ * If the channel is not marked busy, or has finished processing all its
+ * commands, this value should be zero.
+ *
+ * See mxs_dma_append() for details on how DMA command blocks must be configured
+ * to maintain the expected behavior of the semaphore's value.
+ */
+int mxs_dma_read_semaphore(int channel)
+{
+	struct mx28_apbh_regs *apbh_regs =
+		(struct mx28_apbh_regs *)MXS_APBH_BASE;
+	uint32_t tmp;
+	int ret;
+
+	ret = mxs_dma_validate_chan(channel);
+	if (ret)
+		return ret;
+
+	tmp = readl(&apbh_regs->ch[channel].hw_apbh_ch_sema);
+
+	tmp &= APBH_CHn_SEMA_PHORE_MASK;
+	tmp >>= APBH_CHn_SEMA_PHORE_OFFSET;
+
+	return tmp;
+}
+
+/*
+ * Enable or disable DMA interrupt.
+ *
+ * This function enables the given DMA channel to interrupt the CPU.
+ */
+int mxs_dma_enable_irq(int channel, int enable)
+{
+	struct mx28_apbh_regs *apbh_regs =
+		(struct mx28_apbh_regs *)MXS_APBH_BASE;
+	int ret;
+
+	ret = mxs_dma_validate_chan(channel);
+	if (ret)
+		return ret;
+
+	if (enable)
+		writel(1 << (channel + APBH_CTRL1_CH_CMDCMPLT_IRQ_EN_OFFSET),
+			&apbh_regs->hw_apbh_ctrl1_set);
+	else
+		writel(1 << (channel + APBH_CTRL1_CH_CMDCMPLT_IRQ_EN_OFFSET),
+			&apbh_regs->hw_apbh_ctrl1_clr);
+
+	return 0;
+}
+
+/*
+ * Check if a DMA interrupt is pending.
+ */
+int mxs_dma_irq_is_pending(int channel)
+{
+	struct mx28_apbh_regs *apbh_regs =
+		(struct mx28_apbh_regs *)MXS_APBH_BASE;
+	uint32_t tmp;
+	int ret;
+
+	ret = mxs_dma_validate_chan(channel);
+	if (ret)
+		return ret;
+
+	tmp = readl(&apbh_regs->hw_apbh_ctrl1);
+	tmp |= readl(&apbh_regs->hw_apbh_ctrl2);
+
+	return (tmp >> channel) & 1;
+}
+
+/*
+ * Clear DMA interrupt.
+ *
+ * The software that is using the DMA channel must register to receive its
+ * interrupts and, when they arrive, must call this function to clear them.
+ */
+int mxs_dma_ack_irq(int channel)
+{
+	struct mx28_apbh_regs *apbh_regs =
+		(struct mx28_apbh_regs *)MXS_APBH_BASE;
+	int ret;
+
+	ret = mxs_dma_validate_chan(channel);
+	if (ret)
+		return ret;
+
+	writel(1 << channel, &apbh_regs->hw_apbh_ctrl1_clr);
+	writel(1 << channel, &apbh_regs->hw_apbh_ctrl2_clr);
+
+	return 0;
+}
+
+/*
+ * Request to reserve a DMA channel
+ */
+int mxs_dma_request(int channel)
+{
+	struct mxs_dma_chan *pchan;
+
+	if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS))
+		return -EINVAL;
+
+	pchan = mxs_dma_channels + channel;
+	if ((pchan->flags & MXS_DMA_FLAGS_VALID) != MXS_DMA_FLAGS_VALID)
+		return -ENODEV;
+
+	if (pchan->flags & MXS_DMA_FLAGS_ALLOCATED)
+		return -EBUSY;
+
+	pchan->flags |= MXS_DMA_FLAGS_ALLOCATED;
+	pchan->active_num = 0;
+	pchan->pending_num = 0;
+
+	INIT_LIST_HEAD(&pchan->active);
+	INIT_LIST_HEAD(&pchan->done);
+
+	return 0;
+}
+
+/*
+ * Release a DMA channel.
+ *
+ * This function releases a DMA channel from its current owner.
+ *
+ * The channel will NOT be released if it's marked "busy" (see
+ * mxs_dma_enable()).
+ */
+int mxs_dma_release(int channel)
+{
+	struct mxs_dma_chan *pchan;
+	int ret;
+
+	ret = mxs_dma_validate_chan(channel);
+	if (ret)
+		return ret;
+
+	pchan = mxs_dma_channels + channel;
+
+	if (pchan->flags & MXS_DMA_FLAGS_BUSY)
+		return -EBUSY;
+
+	pchan->dev = 0;
+	pchan->active_num = 0;
+	pchan->pending_num = 0;
+	pchan->flags &= ~MXS_DMA_FLAGS_ALLOCATED;
+
+	return 0;
+}
+
+/*
+ * Allocate DMA descriptor
+ */
+struct mxs_dma_desc *mxs_dma_desc_alloc(void)
+{
+	struct mxs_dma_desc *pdesc;
+
+	pdesc = memalign(MXS_DMA_ALIGNMENT, sizeof(struct mxs_dma_desc));
+
+	if (pdesc == NULL)
+		return NULL;
+
+	memset(pdesc, 0, sizeof(*pdesc));
+	pdesc->address = (dma_addr_t)pdesc;
+
+	return pdesc;
+};
+
+/*
+ * Free DMA descriptor
+ */
+void mxs_dma_desc_free(struct mxs_dma_desc *pdesc)
+{
+	if (pdesc == NULL)
+		return;
+
+	free(pdesc);
+}
+
+/*
+ * Return the address of the command within a descriptor.
+ */
+unsigned int mxs_dma_cmd_address(struct mxs_dma_desc *desc)
+{
+	return desc->address + offsetof(struct mxs_dma_desc, cmd);
+}
+
+/*
+ * Check if descriptor is on a channel's active list.
+ *
+ * This function returns the state of a descriptor's "ready" flag. This flag is
+ * usually set only if the descriptor appears on a channel's active list. The
+ * descriptor may or may not have already been processed by the hardware.
+ *
+ * The "ready" flag is set when the descriptor is submitted to a channel by a
+ * call to mxs_dma_append() or mxs_dma_append_list(). The "ready" flag is
+ * cleared when a processed descriptor is moved off the active list by a call
+ * to mxs_dma_finish(). The "ready" flag is NOT cleared if the descriptor is
+ * aborted by a call to mxs_dma_disable().
+ */
+int mxs_dma_desc_pending(struct mxs_dma_desc *pdesc)
+{
+	return pdesc->flags & MXS_DMA_DESC_READY;
+}
+
+/*
+ * Add a DMA descriptor to a channel.
+ *
+ * If the descriptor list for this channel is not empty, this function sets the
+ * CHAIN bit and the NEXTCMD_ADDR fields in the last descriptor's DMA command so
+ * it will chain to the new descriptor's command.
+ *
+ * Then, this function marks the new descriptor as "ready," adds it to the end
+ * of the active descriptor list, and increments the count of pending
+ * descriptors.
+ *
+ * The MXS platform DMA software imposes some rules on DMA commands to maintain
+ * important invariants. These rules are NOT checked, but they must be carefully
+ * applied by software that uses MXS DMA channels.
+ *
+ * Invariant:
+ *     The DMA channel's hardware semaphore must reflect the number of DMA
+ *     commands the hardware will process, but has not yet finished.
+ *
+ * Explanation:
+ *     A DMA channel begins processing commands when its hardware semaphore is
+ *     written with a value greater than zero, and it stops processing commands
+ *     when the semaphore returns to zero.
+ *
+ *     When a channel finishes a DMA command, it will decrement its semaphore if
+ *     the DECREMENT_SEMAPHORE bit is set in that command's flags bits.
+ *
+ *     In principle, it's not necessary for the DECREMENT_SEMAPHORE to be set,
+ *     unless it suits the purposes of the software. For example, one could
+ *     construct a series of five DMA commands, with the DECREMENT_SEMAPHORE
+ *     bit set only in the last one. Then, setting the DMA channel's hardware
+ *     semaphore to one would cause the entire series of five commands to be
+ *     processed. However, this example would violate the invariant given above.
+ *
+ * Rule:
+ *    ALL DMA commands MUST have the DECREMENT_SEMAPHORE bit set so that the DMA
+ *    channel's hardware semaphore will be decremented EVERY time a command is
+ *    processed.
+ */
+int mxs_dma_desc_append(int channel, struct mxs_dma_desc *pdesc)
+{
+	struct mxs_dma_chan *pchan;
+	struct mxs_dma_desc *last;
+	int ret;
+
+	ret = mxs_dma_validate_chan(channel);
+	if (ret)
+		return ret;
+
+	pchan = mxs_dma_channels + channel;
+
+	pdesc->cmd.next = mxs_dma_cmd_address(pdesc);
+	pdesc->flags |= MXS_DMA_DESC_FIRST | MXS_DMA_DESC_LAST;
+
+	if (!list_empty(&pchan->active)) {
+		last = list_entry(pchan->active.prev, struct mxs_dma_desc,
+					node);
+
+		pdesc->flags &= ~MXS_DMA_DESC_FIRST;
+		last->flags &= ~MXS_DMA_DESC_LAST;
+
+		last->cmd.next = mxs_dma_cmd_address(pdesc);
+		last->cmd.data |= MXS_DMA_DESC_CHAIN;
+	}
+	pdesc->flags |= MXS_DMA_DESC_READY;
+	if (pdesc->flags & MXS_DMA_DESC_FIRST)
+		pchan->pending_num++;
+	list_add_tail(&pdesc->node, &pchan->active);
+
+	return ret;
+}
+
+/*
+ * Retrieve processed DMA descriptors.
+ *
+ * This function moves all the descriptors from the DMA channel's "done" list to
+ * the head of the given list.
+ */
+int mxs_dma_get_finished(int channel, struct list_head *head)
+{
+	struct mxs_dma_chan *pchan;
+	int ret;
+
+	ret = mxs_dma_validate_chan(channel);
+	if (ret)
+		return ret;
+
+	if (head == NULL)
+		return 0;
+
+	pchan = mxs_dma_channels + channel;
+
+	list_splice(&pchan->done, head);
+
+	return 0;
+}
+
+/*
+ * Clean up processed DMA descriptors.
+ *
+ * This function removes processed DMA descriptors from the "active" list. Pass
+ * in a non-NULL list head to get the descriptors moved to your list. Pass NULL
+ * to get the descriptors moved to the channel's "done" list. Descriptors on
+ * the "done" list can be retrieved with mxs_dma_get_finished().
+ *
+ * This function marks the DMA channel as "not busy" if no unprocessed
+ * descriptors remain on the "active" list.
+ */
+int mxs_dma_finish(int channel, struct list_head *head)
+{
+	int sem;
+	struct mxs_dma_chan *pchan;
+	struct list_head *p, *q;
+	struct mxs_dma_desc *pdesc;
+	int ret;
+
+	ret = mxs_dma_validate_chan(channel);
+	if (ret)
+		return ret;
+
+	pchan = mxs_dma_channels + channel;
+
+	sem = mxs_dma_read_semaphore(channel);
+	if (sem < 0)
+		return sem;
+
+	if (sem == pchan->active_num)
+		return 0;
+
+	list_for_each_safe(p, q, &pchan->active) {
+		if ((pchan->active_num) <= sem)
+			break;
+
+		pdesc = list_entry(p, struct mxs_dma_desc, node);
+		pdesc->flags &= ~MXS_DMA_DESC_READY;
+
+		if (head)
+			list_move_tail(p, head);
+		else
+			list_move_tail(p, &pchan->done);
+
+		if (pdesc->flags & MXS_DMA_DESC_LAST)
+			pchan->active_num--;
+	}
+
+	if (sem == 0)
+		pchan->flags &= ~MXS_DMA_FLAGS_BUSY;
+
+	return 0;
+}
+
+/*
+ * Wait for DMA channel to complete
+ */
+int mxs_dma_wait_complete(uint32_t timeout, unsigned int chan)
+{
+	struct mx28_apbh_regs *apbh_regs =
+		(struct mx28_apbh_regs *)MXS_APBH_BASE;
+	int ret;
+
+	ret = mxs_dma_validate_chan(chan);
+	if (ret)
+		return ret;
+
+	if (mx28_wait_mask_set(&apbh_regs->hw_apbh_ctrl1_reg,
+				1 << chan, timeout)) {
+		ret = -ETIMEDOUT;
+		mxs_dma_reset(chan);
+	}
+
+	return 0;
+}
+
+/*
+ * Execute the DMA channel
+ */
+int mxs_dma_go(int chan)
+{
+	uint32_t timeout = 10000;
+	int ret;
+
+	LIST_HEAD(tmp_desc_list);
+
+	mxs_dma_enable_irq(chan, 1);
+	mxs_dma_enable(chan);
+
+	/* Wait for DMA to finish. */
+	ret = mxs_dma_wait_complete(timeout, chan);
+
+	/* Clear out the descriptors we just ran. */
+	mxs_dma_finish(chan, &tmp_desc_list);
+
+	/* Shut the DMA channel down. */
+	mxs_dma_ack_irq(chan);
+	mxs_dma_reset(chan);
+	mxs_dma_enable_irq(chan, 0);
+	mxs_dma_disable(chan);
+
+	return ret;
+}
+
+/*
+ * Initialize the DMA hardware
+ */
+int mxs_dma_init(void)
+{
+	struct mx28_apbh_regs *apbh_regs =
+		(struct mx28_apbh_regs *)MXS_APBH_BASE;
+	struct mxs_dma_chan *pchan;
+	int ret, channel;
+
+	mx28_reset_block(&apbh_regs->hw_apbh_ctrl0_reg);
+
+#ifdef CONFIG_APBH_DMA_BURST8
+	writel(APBH_CTRL0_AHB_BURST8_EN,
+		&apbh_regs->hw_apbh_ctrl0_set);
+#else
+	writel(APBH_CTRL0_AHB_BURST8_EN,
+		&apbh_regs->hw_apbh_ctrl0_clr);
+#endif
+
+#ifdef CONFIG_APBH_DMA_BURST
+	writel(APBH_CTRL0_APB_BURST_EN,
+		&apbh_regs->hw_apbh_ctrl0_set);
+#else
+	writel(APBH_CTRL0_APB_BURST_EN,
+		&apbh_regs->hw_apbh_ctrl0_clr);
+#endif
+
+	for (channel = 0; channel < MXS_MAX_DMA_CHANNELS; channel++) {
+		pchan = mxs_dma_channels + channel;
+		pchan->flags = MXS_DMA_FLAGS_VALID;
+
+		ret = mxs_dma_request(channel);
+
+		if (ret) {
+			printf("MXS DMA: Can't acquire DMA channel %i\n",
+				channel);
+
+			goto err;
+		}
+
+		mxs_dma_reset(channel);
+		mxs_dma_ack_irq(channel);
+	}
+
+	return 0;
+
+err:
+	while (--channel >= 0)
+		mxs_dma_release(channel);
+	return ret;
+}
-- 
1.7.6.3

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

* [U-Boot] [PATCH 09/17 RESEND V5] iMX28: Add GPMI NAND driver
  2011-10-21 22:44 ` [U-Boot] [PATCH 00/17 V3] Support for the DENX M28 SoM Marek Vasut
                     ` (7 preceding siblings ...)
  2011-10-21 22:44   ` [U-Boot] [PATCH 08/17 RESEND] iMX28: Add APBH DMA driver Marek Vasut
@ 2011-10-21 22:44   ` Marek Vasut
  2011-11-04 13:13     ` Veli-Pekka Peltola
  2011-10-21 22:44   ` [U-Boot] [PATCH 10/17 RESEND] iMX28: Add driver for internal RTC Marek Vasut
                     ` (7 subsequent siblings)
  16 siblings, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-10-21 22:44 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Scott Wood <scottwood@freescale.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
Acked-By: Scott Wood <scottwood@freescale.com>
---
 drivers/mtd/nand/Makefile   |    1 +
 drivers/mtd/nand/mxs_nand.c | 1118 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1119 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/nand/mxs_nand.c

V2: Update comments, drop inlines
V3: Fix descriptor reclamation loop
V4: Trim bogus comments
V5: Remove redundant mxs_nand_aux_size() function (gcc 4.6 finding)

diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 1eeba5c..a6c746b 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -51,6 +51,7 @@ COBJS-$(CONFIG_NAND_KIRKWOOD) += kirkwood_nand.o
 COBJS-$(CONFIG_NAND_KMETER1) += kmeter1_nand.o
 COBJS-$(CONFIG_NAND_MPC5121_NFC) += mpc5121_nfc.o
 COBJS-$(CONFIG_NAND_MXC) += mxc_nand.o
+COBJS-$(CONFIG_NAND_MXS) += mxs_nand.o
 COBJS-$(CONFIG_NAND_NDFC) += ndfc.o
 COBJS-$(CONFIG_NAND_NOMADIK) += nomadik.o
 COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o
diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c
new file mode 100644
index 0000000..ce2a326
--- /dev/null
+++ b/drivers/mtd/nand/mxs_nand.c
@@ -0,0 +1,1118 @@
+/*
+ * Freescale i.MX28 NAND flash driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Freescale GPMI NFC NAND Flash Driver
+ *
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ * Copyright (C) 2008 Embedded Alley Solutions, Inc.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/types.h>
+#include <common.h>
+#include <malloc.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/dma.h>
+
+#define	MXS_NAND_DMA_DESCRIPTOR_COUNT		4
+
+#define	MXS_NAND_CHUNK_DATA_CHUNK_SIZE		512
+#define	MXS_NAND_METADATA_SIZE			10
+
+#define	MXS_NAND_COMMAND_BUFFER_SIZE		32
+
+#define	MXS_NAND_BCH_TIMEOUT			10000
+
+struct mxs_nand_info {
+	int		cur_chip;
+
+	uint32_t	cmd_queue_len;
+
+	uint8_t		*cmd_buf;
+	uint8_t		*data_buf;
+	uint8_t		*oob_buf;
+
+	uint8_t		marking_block_bad;
+	uint8_t		raw_oob_mode;
+
+	/* Functions with altered behaviour */
+	int		(*hooked_read_oob)(struct mtd_info *mtd,
+				loff_t from, struct mtd_oob_ops *ops);
+	int		(*hooked_write_oob)(struct mtd_info *mtd,
+				loff_t to, struct mtd_oob_ops *ops);
+	int		(*hooked_block_markbad)(struct mtd_info *mtd,
+				loff_t ofs);
+
+	/* DMA descriptors */
+	struct mxs_dma_desc	**desc;
+	uint32_t		desc_index;
+};
+
+struct nand_ecclayout fake_ecc_layout;
+
+static struct mxs_dma_desc *mxs_nand_get_dma_desc(struct mxs_nand_info *info)
+{
+	struct mxs_dma_desc *desc;
+
+	if (info->desc_index >= MXS_NAND_DMA_DESCRIPTOR_COUNT) {
+		printf("MXS NAND: Too many DMA descriptors requested\n");
+		return NULL;
+	}
+
+	desc = info->desc[info->desc_index];
+	info->desc_index++;
+
+	return desc;
+}
+
+static void mxs_nand_return_dma_descs(struct mxs_nand_info *info)
+{
+	int i;
+	struct mxs_dma_desc *desc;
+
+	for (i = 0; i < info->desc_index; i++) {
+		desc = info->desc[i];
+		memset(desc, 0, sizeof(struct mxs_dma_desc));
+		desc->address = (dma_addr_t)desc;
+	}
+
+	info->desc_index = 0;
+}
+
+static uint32_t mxs_nand_ecc_chunk_cnt(uint32_t page_data_size)
+{
+	return page_data_size / MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
+}
+
+static uint32_t mxs_nand_ecc_size_in_bits(uint32_t ecc_strength)
+{
+	return ecc_strength * 13;
+}
+
+static uint32_t mxs_nand_aux_status_offset(void)
+{
+	return (MXS_NAND_METADATA_SIZE + 0x3) & ~0x3;
+}
+
+static inline uint32_t mxs_nand_get_ecc_strength(uint32_t page_data_size,
+						uint32_t page_oob_size)
+{
+	if (page_data_size == 2048)
+		return 8;
+
+	if (page_data_size == 4096) {
+		if (page_oob_size == 128)
+			return 8;
+
+		if (page_oob_size == 218)
+			return 16;
+	}
+
+	return 0;
+}
+
+static inline uint32_t mxs_nand_get_mark_offset(uint32_t page_data_size,
+						uint32_t ecc_strength)
+{
+	uint32_t chunk_data_size_in_bits;
+	uint32_t chunk_ecc_size_in_bits;
+	uint32_t chunk_total_size_in_bits;
+	uint32_t block_mark_chunk_number;
+	uint32_t block_mark_chunk_bit_offset;
+	uint32_t block_mark_bit_offset;
+
+	chunk_data_size_in_bits = MXS_NAND_CHUNK_DATA_CHUNK_SIZE * 8;
+	chunk_ecc_size_in_bits  = mxs_nand_ecc_size_in_bits(ecc_strength);
+
+	chunk_total_size_in_bits =
+			chunk_data_size_in_bits + chunk_ecc_size_in_bits;
+
+	/* Compute the bit offset of the block mark within the physical page. */
+	block_mark_bit_offset = page_data_size * 8;
+
+	/* Subtract the metadata bits. */
+	block_mark_bit_offset -= MXS_NAND_METADATA_SIZE * 8;
+
+	/*
+	 * Compute the chunk number (starting at zero) in which the block mark
+	 * appears.
+	 */
+	block_mark_chunk_number =
+			block_mark_bit_offset / chunk_total_size_in_bits;
+
+	/*
+	 * Compute the bit offset of the block mark within its chunk, and
+	 * validate it.
+	 */
+	block_mark_chunk_bit_offset = block_mark_bit_offset -
+			(block_mark_chunk_number * chunk_total_size_in_bits);
+
+	if (block_mark_chunk_bit_offset > chunk_data_size_in_bits)
+		return 1;
+
+	/*
+	 * Now that we know the chunk number in which the block mark appears,
+	 * we can subtract all the ECC bits that appear before it.
+	 */
+	block_mark_bit_offset -=
+		block_mark_chunk_number * chunk_ecc_size_in_bits;
+
+	return block_mark_bit_offset;
+}
+
+static uint32_t mxs_nand_mark_byte_offset(struct mtd_info *mtd)
+{
+	uint32_t ecc_strength;
+	ecc_strength = mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize);
+	return mxs_nand_get_mark_offset(mtd->writesize, ecc_strength) >> 3;
+}
+
+static uint32_t mxs_nand_mark_bit_offset(struct mtd_info *mtd)
+{
+	uint32_t ecc_strength;
+	ecc_strength = mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize);
+	return mxs_nand_get_mark_offset(mtd->writesize, ecc_strength) & 0x7;
+}
+
+/*
+ * Wait for BCH complete IRQ and clear the IRQ
+ */
+static int mxs_nand_wait_for_bch_complete(void)
+{
+	struct mx28_bch_regs *bch_regs = (struct mx28_bch_regs *)MXS_BCH_BASE;
+	int timeout = MXS_NAND_BCH_TIMEOUT;
+	int ret;
+
+	ret = mx28_wait_mask_set(&bch_regs->hw_bch_ctrl_reg,
+		BCH_CTRL_COMPLETE_IRQ, timeout);
+
+	writel(BCH_CTRL_COMPLETE_IRQ, &bch_regs->hw_bch_ctrl_clr);
+
+	return ret;
+}
+
+/*
+ * This is the function that we install in the cmd_ctrl function pointer of the
+ * owning struct nand_chip. The only functions in the reference implementation
+ * that use these functions pointers are cmdfunc and select_chip.
+ *
+ * In this driver, we implement our own select_chip, so this function will only
+ * be called by the reference implementation's cmdfunc. For this reason, we can
+ * ignore the chip enable bit and concentrate only on sending bytes to the NAND
+ * Flash.
+ */
+static void mxs_nand_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	int ret;
+
+	/*
+	 * If this condition is true, something is _VERY_ wrong in MTD
+	 * subsystem!
+	 */
+	if (nand_info->cmd_queue_len == MXS_NAND_COMMAND_BUFFER_SIZE) {
+		printf("MXS NAND: Command queue too long\n");
+		return;
+	}
+
+	/*
+	 * Every operation begins with a command byte and a series of zero or
+	 * more address bytes. These are distinguished by either the Address
+	 * Latch Enable (ALE) or Command Latch Enable (CLE) signals being
+	 * asserted. When MTD is ready to execute the command, it will
+	 * deasert both latch enables.
+	 *
+	 * Rather than run a separate DMA operation for every single byte, we
+	 * queue them up and run a single DMA operation for the entire series
+	 * of command and data bytes.
+	 */
+	if (ctrl & (NAND_ALE | NAND_CLE)) {
+		if (data != NAND_CMD_NONE)
+			nand_info->cmd_buf[nand_info->cmd_queue_len++] = data;
+		return;
+	}
+
+	/*
+	 * If control arrives here, MTD has deasserted both the ALE and CLE,
+	 * which means it's ready to run an operation. Check if we have any
+	 * bytes to send.
+	 */
+	if (nand_info->cmd_queue_len == 0)
+		return;
+
+	/* Compile the DMA descriptor -- a descriptor that sends command. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_DMA_READ | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_CHAIN | MXS_DMA_DESC_DEC_SEM |
+		MXS_DMA_DESC_WAIT4END | (3 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
+		(nand_info->cmd_queue_len << MXS_DMA_DESC_BYTES_OFFSET);
+
+	d->cmd.address = (dma_addr_t)nand_info->cmd_buf;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_CLE |
+		GPMI_CTRL0_ADDRESS_INCREMENT |
+		nand_info->cmd_queue_len;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret)
+		printf("MXS NAND: Error sending command\n");
+
+	mxs_nand_return_dma_descs(nand_info);
+
+	/* Reset the command queue. */
+	nand_info->cmd_queue_len = 0;
+}
+
+/*
+ * Test if the NAND flash is ready.
+ */
+static int mxs_nand_device_ready(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mxs_nand_info *nand_info = chip->priv;
+	struct mx28_gpmi_regs *gpmi_regs =
+		(struct mx28_gpmi_regs *)MXS_GPMI_BASE;
+	uint32_t tmp;
+
+	tmp = readl(&gpmi_regs->hw_gpmi_stat);
+	tmp >>= (GPMI_STAT_READY_BUSY_OFFSET + nand_info->cur_chip);
+
+	return tmp & 1;
+}
+
+/*
+ * Select the NAND chip.
+ */
+static void mxs_nand_select_chip(struct mtd_info *mtd, int chip)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+
+	nand_info->cur_chip = chip;
+}
+
+/*
+ * Handle block mark swapping.
+ *
+ * Note that, when this function is called, it doesn't know whether it's
+ * swapping the block mark, or swapping it *back* -- but it doesn't matter
+ * because the the operation is the same.
+ */
+static void mxs_nand_swap_block_mark(struct mtd_info *mtd,
+					uint8_t *data_buf, uint8_t *oob_buf)
+{
+	uint32_t bit_offset;
+	uint32_t buf_offset;
+
+	uint32_t src;
+	uint32_t dst;
+
+	bit_offset = mxs_nand_mark_bit_offset(mtd);
+	buf_offset = mxs_nand_mark_byte_offset(mtd);
+
+	/*
+	 * Get the byte from the data area that overlays the block mark. Since
+	 * the ECC engine applies its own view to the bits in the page, the
+	 * physical block mark won't (in general) appear on a byte boundary in
+	 * the data.
+	 */
+	src = data_buf[buf_offset] >> bit_offset;
+	src |= data_buf[buf_offset + 1] << (8 - bit_offset);
+
+	dst = oob_buf[0];
+
+	oob_buf[0] = src;
+
+	data_buf[buf_offset] &= ~(0xff << bit_offset);
+	data_buf[buf_offset + 1] &= 0xff << bit_offset;
+
+	data_buf[buf_offset] |= dst << bit_offset;
+	data_buf[buf_offset + 1] |= dst >> (8 - bit_offset);
+}
+
+/*
+ * Read data from NAND.
+ */
+static void mxs_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int length)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	int ret;
+
+	if (length > NAND_MAX_PAGESIZE) {
+		printf("MXS NAND: DMA buffer too big\n");
+		return;
+	}
+
+	if (!buf) {
+		printf("MXS NAND: DMA buffer is NULL\n");
+		return;
+	}
+
+	/* Compile the DMA descriptor - a descriptor that reads data. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_DMA_WRITE | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
+		(1 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
+		(length << MXS_DMA_DESC_BYTES_OFFSET);
+
+	d->cmd.address = (dma_addr_t)nand_info->data_buf;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_READ |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		length;
+
+	mxs_dma_desc_append(channel, d);
+
+	/*
+	 * A DMA descriptor that waits for the command to end and the chip to
+	 * become ready.
+	 *
+	 * I think we actually should *not* be waiting for the chip to become
+	 * ready because, after all, we don't care. I think the original code
+	 * did that and no one has re-thought it yet.
+	 */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_DEC_SEM |
+		MXS_DMA_DESC_WAIT4END | (4 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret) {
+		printf("MXS NAND: DMA read error\n");
+		goto rtn;
+	}
+
+	memcpy(buf, nand_info->data_buf, length);
+
+rtn:
+	mxs_nand_return_dma_descs(nand_info);
+}
+
+/*
+ * Write data to NAND.
+ */
+static void mxs_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf,
+				int length)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	int ret;
+
+	if (length > NAND_MAX_PAGESIZE) {
+		printf("MXS NAND: DMA buffer too big\n");
+		return;
+	}
+
+	if (!buf) {
+		printf("MXS NAND: DMA buffer is NULL\n");
+		return;
+	}
+
+	memcpy(nand_info->data_buf, buf, length);
+
+	/* Compile the DMA descriptor - a descriptor that writes data. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_DMA_READ | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
+		(4 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
+		(length << MXS_DMA_DESC_BYTES_OFFSET);
+
+	d->cmd.address = (dma_addr_t)nand_info->data_buf;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		length;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret)
+		printf("MXS NAND: DMA write error\n");
+
+	mxs_nand_return_dma_descs(nand_info);
+}
+
+/*
+ * Read a single byte from NAND.
+ */
+static uint8_t mxs_nand_read_byte(struct mtd_info *mtd)
+{
+	uint8_t buf;
+	mxs_nand_read_buf(mtd, &buf, 1);
+	return buf;
+}
+
+/*
+ * Read a page from NAND.
+ */
+static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
+					uint8_t *buf, int page)
+{
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	uint32_t corrected = 0, failed = 0;
+	uint8_t	*status;
+	int i, ret;
+
+	/* Compile the DMA descriptor - wait for ready. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
+		MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_WAIT4END |
+		(1 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Compile the DMA descriptor - enable the BCH block and read. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
+		MXS_DMA_DESC_WAIT4END |	(6 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_READ |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		(mtd->writesize + mtd->oobsize);
+	d->cmd.pio_words[1] = 0;
+	d->cmd.pio_words[2] =
+		GPMI_ECCCTRL_ENABLE_ECC |
+		GPMI_ECCCTRL_ECC_CMD_DECODE |
+		GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE;
+	d->cmd.pio_words[3] = mtd->writesize + mtd->oobsize;
+	d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf;
+	d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Compile the DMA descriptor - disable the BCH block. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
+		MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_WAIT4END |
+		(3 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		(mtd->writesize + mtd->oobsize);
+	d->cmd.pio_words[1] = 0;
+	d->cmd.pio_words[2] = 0;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Compile the DMA descriptor - deassert the NAND lock and interrupt. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_DEC_SEM;
+
+	d->cmd.address = 0;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret) {
+		printf("MXS NAND: DMA read error\n");
+		goto rtn;
+	}
+
+	ret = mxs_nand_wait_for_bch_complete();
+	if (ret) {
+		printf("MXS NAND: BCH read timeout\n");
+		goto rtn;
+	}
+
+	/* Read DMA completed, now do the mark swapping. */
+	mxs_nand_swap_block_mark(mtd, nand_info->data_buf, nand_info->oob_buf);
+
+	/* Loop over status bytes, accumulating ECC status. */
+	status = nand_info->oob_buf + mxs_nand_aux_status_offset();
+	for (i = 0; i < mxs_nand_ecc_chunk_cnt(mtd->writesize); i++) {
+		if (status[i] == 0x00)
+			continue;
+
+		if (status[i] == 0xff)
+			continue;
+
+		if (status[i] == 0xfe) {
+			failed++;
+			continue;
+		}
+
+		corrected += status[i];
+	}
+
+	/* Propagate ECC status to the owning MTD. */
+	mtd->ecc_stats.failed += failed;
+	mtd->ecc_stats.corrected += corrected;
+
+	/*
+	 * It's time to deliver the OOB bytes. See mxs_nand_ecc_read_oob() for
+	 * details about our policy for delivering the OOB.
+	 *
+	 * We fill the caller's buffer with set bits, and then copy the block
+	 * mark to the caller's buffer. Note that, if block mark swapping was
+	 * necessary, it has already been done, so we can rely on the first
+	 * byte of the auxiliary buffer to contain the block mark.
+	 */
+	memset(nand->oob_poi, 0xff, mtd->oobsize);
+
+	nand->oob_poi[0] = nand_info->oob_buf[0];
+
+	memcpy(buf, nand_info->data_buf, mtd->writesize);
+
+rtn:
+	mxs_nand_return_dma_descs(nand_info);
+
+	return ret;
+}
+
+/*
+ * Write a page to NAND.
+ */
+static void mxs_nand_ecc_write_page(struct mtd_info *mtd,
+				struct nand_chip *nand, const uint8_t *buf)
+{
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_dma_desc *d;
+	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
+	int ret;
+
+	memcpy(nand_info->data_buf, buf, mtd->writesize);
+	memcpy(nand_info->oob_buf, nand->oob_poi, mtd->oobsize);
+
+	/* Handle block mark swapping. */
+	mxs_nand_swap_block_mark(mtd, nand_info->data_buf, nand_info->oob_buf);
+
+	/* Compile the DMA descriptor - write data. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data =
+		MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
+		MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
+		(6 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] =
+		GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		(nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA;
+	d->cmd.pio_words[1] = 0;
+	d->cmd.pio_words[2] =
+		GPMI_ECCCTRL_ENABLE_ECC |
+		GPMI_ECCCTRL_ECC_CMD_ENCODE |
+		GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE;
+	d->cmd.pio_words[3] = (mtd->writesize + mtd->oobsize);
+	d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf;
+	d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret) {
+		printf("MXS NAND: DMA write error\n");
+		goto rtn;
+	}
+
+	ret = mxs_nand_wait_for_bch_complete();
+	if (ret) {
+		printf("MXS NAND: BCH write timeout\n");
+		goto rtn;
+	}
+
+rtn:
+	mxs_nand_return_dma_descs(nand_info);
+}
+
+/*
+ * Read OOB from NAND.
+ *
+ * This function is a veneer that replaces the function originally installed by
+ * the NAND Flash MTD code.
+ */
+static int mxs_nand_hook_read_oob(struct mtd_info *mtd, loff_t from,
+					struct mtd_oob_ops *ops)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mxs_nand_info *nand_info = chip->priv;
+	int ret;
+
+	if (ops->mode == MTD_OOB_RAW)
+		nand_info->raw_oob_mode = 1;
+	else
+		nand_info->raw_oob_mode = 0;
+
+	ret = nand_info->hooked_read_oob(mtd, from, ops);
+
+	nand_info->raw_oob_mode = 0;
+
+	return ret;
+}
+
+/*
+ * Write OOB to NAND.
+ *
+ * This function is a veneer that replaces the function originally installed by
+ * the NAND Flash MTD code.
+ */
+static int mxs_nand_hook_write_oob(struct mtd_info *mtd, loff_t to,
+					struct mtd_oob_ops *ops)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mxs_nand_info *nand_info = chip->priv;
+	int ret;
+
+	if (ops->mode == MTD_OOB_RAW)
+		nand_info->raw_oob_mode = 1;
+	else
+		nand_info->raw_oob_mode = 0;
+
+	ret = nand_info->hooked_write_oob(mtd, to, ops);
+
+	nand_info->raw_oob_mode = 0;
+
+	return ret;
+}
+
+/*
+ * Mark a block bad in NAND.
+ *
+ * This function is a veneer that replaces the function originally installed by
+ * the NAND Flash MTD code.
+ */
+static int mxs_nand_hook_block_markbad(struct mtd_info *mtd, loff_t ofs)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mxs_nand_info *nand_info = chip->priv;
+	int ret;
+
+	nand_info->marking_block_bad = 1;
+
+	ret = nand_info->hooked_block_markbad(mtd, ofs);
+
+	nand_info->marking_block_bad = 0;
+
+	return ret;
+}
+
+/*
+ * There are several places in this driver where we have to handle the OOB and
+ * block marks. This is the function where things are the most complicated, so
+ * this is where we try to explain it all. All the other places refer back to
+ * here.
+ *
+ * These are the rules, in order of decreasing importance:
+ *
+ * 1) Nothing the caller does can be allowed to imperil the block mark, so all
+ *    write operations take measures to protect it.
+ *
+ * 2) In read operations, the first byte of the OOB we return must reflect the
+ *    true state of the block mark, no matter where that block mark appears in
+ *    the physical page.
+ *
+ * 3) ECC-based read operations return an OOB full of set bits (since we never
+ *    allow ECC-based writes to the OOB, it doesn't matter what ECC-based reads
+ *    return).
+ *
+ * 4) "Raw" read operations return a direct view of the physical bytes in the
+ *    page, using the conventional definition of which bytes are data and which
+ *    are OOB. This gives the caller a way to see the actual, physical bytes
+ *    in the page, without the distortions applied by our ECC engine.
+ *
+ * What we do for this specific read operation depends on whether we're doing
+ * "raw" read, or an ECC-based read.
+ *
+ * It turns out that knowing whether we want an "ECC-based" or "raw" read is not
+ * easy. When reading a page, for example, the NAND Flash MTD code calls our
+ * ecc.read_page or ecc.read_page_raw function. Thus, the fact that MTD wants an
+ * ECC-based or raw view of the page is implicit in which function it calls
+ * (there is a similar pair of ECC-based/raw functions for writing).
+ *
+ * Since MTD assumes the OOB is not covered by ECC, there is no pair of
+ * ECC-based/raw functions for reading or or writing the OOB. The fact that the
+ * caller wants an ECC-based or raw view of the page is not propagated down to
+ * this driver.
+ *
+ * Since our OOB *is* covered by ECC, we need this information. So, we hook the
+ * ecc.read_oob and ecc.write_oob function pointers in the owning
+ * struct mtd_info with our own functions. These hook functions set the
+ * raw_oob_mode field so that, when control finally arrives here, we'll know
+ * what to do.
+ */
+static int mxs_nand_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *nand,
+				int page, int cmd)
+{
+	struct mxs_nand_info *nand_info = nand->priv;
+
+	/*
+	 * First, fill in the OOB buffer. If we're doing a raw read, we need to
+	 * get the bytes from the physical page. If we're not doing a raw read,
+	 * we need to fill the buffer with set bits.
+	 */
+	if (nand_info->raw_oob_mode) {
+		/*
+		 * If control arrives here, we're doing a "raw" read. Send the
+		 * command to read the conventional OOB and read it.
+		 */
+		nand->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page);
+		nand->read_buf(mtd, nand->oob_poi, mtd->oobsize);
+	} else {
+		/*
+		 * If control arrives here, we're not doing a "raw" read. Fill
+		 * the OOB buffer with set bits and correct the block mark.
+		 */
+		memset(nand->oob_poi, 0xff, mtd->oobsize);
+
+		nand->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page);
+		mxs_nand_read_buf(mtd, nand->oob_poi, 1);
+	}
+
+	return 0;
+
+}
+
+/*
+ * Write OOB data to NAND.
+ */
+static int mxs_nand_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *nand,
+					int page)
+{
+	struct mxs_nand_info *nand_info = nand->priv;
+	uint8_t block_mark = 0;
+
+	/*
+	 * There are fundamental incompatibilities between the i.MX GPMI NFC and
+	 * the NAND Flash MTD model that make it essentially impossible to write
+	 * the out-of-band bytes.
+	 *
+	 * We permit *ONE* exception. If the *intent* of writing the OOB is to
+	 * mark a block bad, we can do that.
+	 */
+
+	if (!nand_info->marking_block_bad) {
+		printf("NXS NAND: Writing OOB isn't supported\n");
+		return -EIO;
+	}
+
+	/* Write the block mark. */
+	nand->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
+	nand->write_buf(mtd, &block_mark, 1);
+	nand->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+
+	/* Check if it worked. */
+	if (nand->waitfunc(mtd, nand) & NAND_STATUS_FAIL)
+		return -EIO;
+
+	return 0;
+}
+
+/*
+ * Claims all blocks are good.
+ *
+ * In principle, this function is *only* called when the NAND Flash MTD system
+ * isn't allowed to keep an in-memory bad block table, so it is forced to ask
+ * the driver for bad block information.
+ *
+ * In fact, we permit the NAND Flash MTD system to have an in-memory BBT, so
+ * this function is *only* called when we take it away.
+ *
+ * Thus, this function is only called when we want *all* blocks to look good,
+ * so it *always* return success.
+ */
+static int mxs_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
+{
+	return 0;
+}
+
+/*
+ * Nominally, the purpose of this function is to look for or create the bad
+ * block table. In fact, since the we call this function at the very end of
+ * the initialization process started by nand_scan(), and we doesn't have a
+ * more formal mechanism, we "hook" this function to continue init process.
+ *
+ * At this point, the physical NAND Flash chips have been identified and
+ * counted, so we know the physical geometry. This enables us to make some
+ * important configuration decisions.
+ *
+ * The return value of this function propogates directly back to this driver's
+ * call to nand_scan(). Anything other than zero will cause this driver to
+ * tear everything down and declare failure.
+ */
+static int mxs_nand_scan_bbt(struct mtd_info *mtd)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mxs_nand_info *nand_info = nand->priv;
+	struct mx28_bch_regs *bch_regs = (struct mx28_bch_regs *)MXS_BCH_BASE;
+	uint32_t tmp;
+
+	/* Configure BCH and set NFC geometry */
+	mx28_reset_block(&bch_regs->hw_bch_ctrl_reg);
+
+	/* Configure layout 0 */
+	tmp = (mxs_nand_ecc_chunk_cnt(mtd->writesize) - 1)
+		<< BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
+	tmp |= MXS_NAND_METADATA_SIZE << BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
+	tmp |= (mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1)
+		<< BCH_FLASHLAYOUT0_ECC0_OFFSET;
+	tmp |= MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
+	writel(tmp, &bch_regs->hw_bch_flash0layout0);
+
+	tmp = (mtd->writesize + mtd->oobsize)
+		<< BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
+	tmp |= (mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1)
+		<< BCH_FLASHLAYOUT1_ECCN_OFFSET;
+	tmp |= MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
+	writel(tmp, &bch_regs->hw_bch_flash0layout1);
+
+	/* Set *all* chip selects to use layout 0 */
+	writel(0, &bch_regs->hw_bch_layoutselect);
+
+	/* Enable BCH complete interrupt */
+	writel(BCH_CTRL_COMPLETE_IRQ_EN, &bch_regs->hw_bch_ctrl_set);
+
+	/* Hook some operations at the MTD level. */
+	if (mtd->read_oob != mxs_nand_hook_read_oob) {
+		nand_info->hooked_read_oob = mtd->read_oob;
+		mtd->read_oob = mxs_nand_hook_read_oob;
+	}
+
+	if (mtd->write_oob != mxs_nand_hook_write_oob) {
+		nand_info->hooked_write_oob = mtd->write_oob;
+		mtd->write_oob = mxs_nand_hook_write_oob;
+	}
+
+	if (mtd->block_markbad != mxs_nand_hook_block_markbad) {
+		nand_info->hooked_block_markbad = mtd->block_markbad;
+		mtd->block_markbad = mxs_nand_hook_block_markbad;
+	}
+
+	/* We use the reference implementation for bad block management. */
+	return nand_default_bbt(mtd);
+}
+
+/*
+ * Allocate DMA buffers
+ */
+int mxs_nand_alloc_buffers(struct mxs_nand_info *nand_info)
+{
+	uint8_t *buf;
+	const int size = NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE;
+
+	/* DMA buffers */
+	buf = memalign(MXS_DMA_ALIGNMENT, size);
+	if (!buf) {
+		printf("MXS NAND: Error allocating DMA buffers\n");
+		return -ENOMEM;
+	}
+
+	memset(buf, 0, size);
+
+	nand_info->data_buf = buf;
+	nand_info->oob_buf = buf + NAND_MAX_PAGESIZE;
+
+	/* Command buffers */
+	nand_info->cmd_buf = memalign(MXS_DMA_ALIGNMENT,
+				MXS_NAND_COMMAND_BUFFER_SIZE);
+	if (!nand_info->cmd_buf) {
+		free(buf);
+		printf("MXS NAND: Error allocating command buffers\n");
+		return -ENOMEM;
+	}
+	memset(nand_info->cmd_buf, 0, MXS_NAND_COMMAND_BUFFER_SIZE);
+	nand_info->cmd_queue_len = 0;
+
+	return 0;
+}
+
+/*
+ * Initializes the NFC hardware.
+ */
+int mxs_nand_init(struct mxs_nand_info *info)
+{
+	struct mx28_gpmi_regs *gpmi_regs =
+		(struct mx28_gpmi_regs *)MXS_GPMI_BASE;
+	int i = 0;
+
+	info->desc = malloc(sizeof(struct mxs_dma_desc *) *
+				MXS_NAND_DMA_DESCRIPTOR_COUNT);
+	if (!info->desc)
+		goto err1;
+
+	/* Allocate the DMA descriptors. */
+	for (i = 0; i < MXS_NAND_DMA_DESCRIPTOR_COUNT; i++) {
+		info->desc[i] = mxs_dma_desc_alloc();
+		if (!info->desc[i])
+			goto err2;
+	}
+
+	/* Init the DMA controller. */
+	mxs_dma_init();
+
+	/* Reset the GPMI block. */
+	mx28_reset_block(&gpmi_regs->hw_gpmi_ctrl0_reg);
+
+	/*
+	 * Choose NAND mode, set IRQ polarity, disable write protection and
+	 * select BCH ECC.
+	 */
+	clrsetbits_le32(&gpmi_regs->hw_gpmi_ctrl1,
+			GPMI_CTRL1_GPMI_MODE,
+			GPMI_CTRL1_ATA_IRQRDY_POLARITY | GPMI_CTRL1_DEV_RESET |
+			GPMI_CTRL1_BCH_MODE);
+
+	return 0;
+
+err2:
+	free(info->desc);
+err1:
+	for (--i; i >= 0; i--)
+		mxs_dma_desc_free(info->desc[i]);
+	printf("MXS NAND: Unable to allocate DMA descriptors\n");
+	return -ENOMEM;
+}
+
+/*!
+ * This function is called during the driver binding process.
+ *
+ * @param   pdev  the device structure used to store device specific
+ *                information that is used by the suspend, resume and
+ *                remove functions
+ *
+ * @return  The function always returns 0.
+ */
+int board_nand_init(struct nand_chip *nand)
+{
+	struct mxs_nand_info *nand_info;
+	int err;
+
+	nand_info = malloc(sizeof(struct mxs_nand_info));
+	if (!nand_info) {
+		printf("MXS NAND: Failed to allocate private data\n");
+		return -ENOMEM;
+	}
+	memset(nand_info, 0, sizeof(struct mxs_nand_info));
+
+	err = mxs_nand_alloc_buffers(nand_info);
+	if (err)
+		goto err1;
+
+	err = mxs_nand_init(nand_info);
+	if (err)
+		goto err2;
+
+	memset(&fake_ecc_layout, 0, sizeof(fake_ecc_layout));
+
+	nand->priv = nand_info;
+	nand->options |= NAND_NO_SUBPAGE_WRITE;
+
+	nand->cmd_ctrl		= mxs_nand_cmd_ctrl;
+
+	nand->dev_ready		= mxs_nand_device_ready;
+	nand->select_chip	= mxs_nand_select_chip;
+	nand->block_bad		= mxs_nand_block_bad;
+	nand->scan_bbt		= mxs_nand_scan_bbt;
+
+	nand->read_byte		= mxs_nand_read_byte;
+
+	nand->read_buf		= mxs_nand_read_buf;
+	nand->write_buf		= mxs_nand_write_buf;
+
+	nand->ecc.read_page	= mxs_nand_ecc_read_page;
+	nand->ecc.write_page	= mxs_nand_ecc_write_page;
+	nand->ecc.read_oob	= mxs_nand_ecc_read_oob;
+	nand->ecc.write_oob	= mxs_nand_ecc_write_oob;
+
+	nand->ecc.layout	= &fake_ecc_layout;
+	nand->ecc.mode		= NAND_ECC_HW;
+	nand->ecc.bytes		= 9;
+	nand->ecc.size		= 512;
+
+	return 0;
+
+err2:
+	free(nand_info->data_buf);
+	free(nand_info->cmd_buf);
+err1:
+	free(nand_info);
+	return err;
+}
-- 
1.7.6.3

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

* [U-Boot] [PATCH 10/17 RESEND] iMX28: Add driver for internal RTC
  2011-10-21 22:44 ` [U-Boot] [PATCH 00/17 V3] Support for the DENX M28 SoM Marek Vasut
                     ` (8 preceding siblings ...)
  2011-10-21 22:44   ` [U-Boot] [PATCH 09/17 RESEND V5] iMX28: Add GPMI NAND driver Marek Vasut
@ 2011-10-21 22:44   ` Marek Vasut
  2011-10-21 22:44   ` [U-Boot] [PATCH 11/17 RESEND V2] iMX28: Add image header generator tool Marek Vasut
                     ` (6 subsequent siblings)
  16 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-10-21 22:44 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 drivers/rtc/Makefile |    1 +
 drivers/rtc/mxsrtc.c |   86 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 87 insertions(+), 0 deletions(-)
 create mode 100644 drivers/rtc/mxsrtc.c

diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index df440c6..391071e 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -57,6 +57,7 @@ COBJS-$(CONFIG_RTC_MK48T59) += mk48t59.o
 COBJS-$(CONFIG_RTC_MPC5200) += mpc5xxx.o
 COBJS-$(CONFIG_RTC_MPC8xx) += mpc8xx.o
 COBJS-$(CONFIG_RTC_MV) += mvrtc.o
+COBJS-$(CONFIG_RTC_MXS) += mxsrtc.o
 COBJS-$(CONFIG_RTC_PCF8563) += pcf8563.o
 COBJS-$(CONFIG_RTC_PL031) += pl031.o
 COBJS-$(CONFIG_RTC_PT7C4338) += pt7c4338.o
diff --git a/drivers/rtc/mxsrtc.c b/drivers/rtc/mxsrtc.c
new file mode 100644
index 0000000..5beb1a0
--- /dev/null
+++ b/drivers/rtc/mxsrtc.c
@@ -0,0 +1,86 @@
+/*
+ * Freescale i.MX28 RTC Driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <rtc.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+
+#define	MXS_RTC_MAX_TIMEOUT	1000000
+
+/* Set time in seconds since 1970-01-01 */
+int mxs_rtc_set_time(uint32_t secs)
+{
+	struct mx28_rtc_regs *rtc_regs = (struct mx28_rtc_regs *)MXS_RTC_BASE;
+	int ret;
+
+	writel(secs, &rtc_regs->hw_rtc_seconds);
+
+	/*
+	 * The 0x80 here means seconds were copied to analog. This information
+	 * is taken from the linux kernel driver for the STMP37xx RTC since
+	 * documentation doesn't mention it.
+	 */
+	ret = mx28_wait_mask_clr(&rtc_regs->hw_rtc_stat_reg,
+		0x80 << RTC_STAT_STALE_REGS_OFFSET, MXS_RTC_MAX_TIMEOUT);
+
+	if (ret)
+		printf("MXS RTC: Timeout waiting for update\n");
+
+	return ret;
+}
+
+int rtc_get(struct rtc_time *time)
+{
+	struct mx28_rtc_regs *rtc_regs = (struct mx28_rtc_regs *)MXS_RTC_BASE;
+	uint32_t secs;
+
+	secs = readl(&rtc_regs->hw_rtc_seconds);
+	to_tm(secs, time);
+
+	return 0;
+}
+
+int rtc_set(struct rtc_time *time)
+{
+	uint32_t secs;
+
+	secs = mktime(time->tm_year, time->tm_mon, time->tm_mday,
+		time->tm_hour, time->tm_min, time->tm_sec);
+
+	return mxs_rtc_set_time(secs);
+}
+
+void rtc_reset(void)
+{
+	struct mx28_rtc_regs *rtc_regs = (struct mx28_rtc_regs *)MXS_RTC_BASE;
+	int ret;
+
+	/* Set time to 1970-01-01 */
+	mxs_rtc_set_time(0);
+
+	/* Reset the RTC block */
+	ret = mx28_reset_block(&rtc_regs->hw_rtc_ctrl_reg);
+	if (ret)
+		printf("MXS RTC: Block reset timeout\n");
+}
-- 
1.7.6.3

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

* [U-Boot] [PATCH 11/17 RESEND V2] iMX28: Add image header generator tool
  2011-10-21 22:44 ` [U-Boot] [PATCH 00/17 V3] Support for the DENX M28 SoM Marek Vasut
                     ` (9 preceding siblings ...)
  2011-10-21 22:44   ` [U-Boot] [PATCH 10/17 RESEND] iMX28: Add driver for internal RTC Marek Vasut
@ 2011-10-21 22:44   ` Marek Vasut
  2011-10-21 22:44   ` [U-Boot] [PATCH 12/17 V3] iMX28: Add u-boot.sb target to Makefile Marek Vasut
                     ` (5 subsequent siblings)
  16 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-10-21 22:44 UTC (permalink / raw)
  To: u-boot

This tool can now generate proper image for "BootStream" files.

NOTE: This tool now works only for NAND.

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 tools/.gitignore |    1 +
 tools/Makefile   |    6 +
 tools/mxsboot.c  |  684 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 691 insertions(+), 0 deletions(-)
 create mode 100644 tools/mxsboot.c

V2: Add missing .gitignore entry

diff --git a/tools/.gitignore b/tools/.gitignore
index 07f21a3..98a5c78 100644
--- a/tools/.gitignore
+++ b/tools/.gitignore
@@ -4,6 +4,7 @@
 /img2srec
 /mkimage
 /mpc86x_clk
+/mxsboot
 /ncb
 /ncp
 /ubsha1
diff --git a/tools/Makefile b/tools/Makefile
index fc741d3..2caac78 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -67,6 +67,7 @@ BIN_FILES-$(CONFIG_CMD_NET) += gen_eth_addr$(SFX)
 BIN_FILES-$(CONFIG_CMD_LOADS) += img2srec$(SFX)
 BIN_FILES-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes$(SFX)
 BIN_FILES-y += mkimage$(SFX)
+BIN_FILES-$(CONFIG_MX28) += mxsboot$(SFX)
 BIN_FILES-$(CONFIG_NETCONSOLE) += ncb$(SFX)
 BIN_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1$(SFX)
 
@@ -90,6 +91,7 @@ NOPED_OBJ_FILES-y += kwbimage.o
 NOPED_OBJ_FILES-y += imximage.o
 NOPED_OBJ_FILES-y += omapimage.o
 NOPED_OBJ_FILES-y += mkimage.o
+OBJ_FILES-$(CONFIG_MX28) += mxsboot.o
 OBJ_FILES-$(CONFIG_NETCONSOLE) += ncb.o
 NOPED_OBJ_FILES-y += os_support.o
 OBJ_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1.o
@@ -204,6 +206,10 @@ $(obj)mpc86x_clk$(SFX):	$(obj)mpc86x_clk.o
 	$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
 	$(HOSTSTRIP) $@
 
+$(obj)mxsboot$(SFX):	$(obj)mxsboot.o
+	$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
+	$(HOSTSTRIP) $@
+
 $(obj)ncb$(SFX):	$(obj)ncb.o
 	$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
 	$(HOSTSTRIP) $@
diff --git a/tools/mxsboot.c b/tools/mxsboot.c
new file mode 100644
index 0000000..176753d
--- /dev/null
+++ b/tools/mxsboot.c
@@ -0,0 +1,684 @@
+/*
+ * Freescale i.MX28 image generator
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "compiler.h"
+
+/*
+ * Default BCB layout.
+ *
+ * TWEAK this if you have blown any OCOTP fuses.
+ */
+#define	STRIDE_PAGES		64
+#define	STRIDE_COUNT		4
+
+/*
+ * Layout for 256Mb big NAND with 2048b page size, 64b OOB size and
+ * 128kb erase size.
+ *
+ * TWEAK this if you have different kind of NAND chip.
+ */
+uint32_t nand_writesize = 2048;
+uint32_t nand_oobsize = 64;
+uint32_t nand_erasesize = 128 * 1024;
+
+/*
+ * Sector on which the SigmaTel boot partition (0x53) starts.
+ */
+uint32_t sd_sector = 2048;
+
+/*
+ * Each of the U-Boot bootstreams is at maximum 1MB big.
+ *
+ * TWEAK this if, for some wild reason, you need to boot bigger image.
+ */
+#define	MAX_BOOTSTREAM_SIZE	(1 * 1024 * 1024)
+
+/* i.MX28 NAND controller-specific constants. DO NOT TWEAK! */
+#define	MXS_NAND_DMA_DESCRIPTOR_COUNT		4
+#define	MXS_NAND_CHUNK_DATA_CHUNK_SIZE		512
+#define	MXS_NAND_METADATA_SIZE			10
+#define	MXS_NAND_COMMAND_BUFFER_SIZE		32
+
+struct mx28_nand_fcb {
+	uint32_t		checksum;
+	uint32_t		fingerprint;
+	uint32_t		version;
+	struct {
+		uint8_t			data_setup;
+		uint8_t			data_hold;
+		uint8_t			address_setup;
+		uint8_t			dsample_time;
+		uint8_t			nand_timing_state;
+		uint8_t			rea;
+		uint8_t			rloh;
+		uint8_t			rhoh;
+	}			timing;
+	uint32_t		page_data_size;
+	uint32_t		total_page_size;
+	uint32_t		sectors_per_block;
+	uint32_t		number_of_nands;		/* Ignored */
+	uint32_t		total_internal_die;		/* Ignored */
+	uint32_t		cell_type;			/* Ignored */
+	uint32_t		ecc_block_n_ecc_type;
+	uint32_t		ecc_block_0_size;
+	uint32_t		ecc_block_n_size;
+	uint32_t		ecc_block_0_ecc_type;
+	uint32_t		metadata_bytes;
+	uint32_t		num_ecc_blocks_per_page;
+	uint32_t		ecc_block_n_ecc_level_sdk;	/* Ignored */
+	uint32_t		ecc_block_0_size_sdk;		/* Ignored */
+	uint32_t		ecc_block_n_size_sdk;		/* Ignored */
+	uint32_t		ecc_block_0_ecc_level_sdk;	/* Ignored */
+	uint32_t		num_ecc_blocks_per_page_sdk;	/* Ignored */
+	uint32_t		metadata_bytes_sdk;		/* Ignored */
+	uint32_t		erase_threshold;
+	uint32_t		boot_patch;
+	uint32_t		patch_sectors;
+	uint32_t		firmware1_starting_sector;
+	uint32_t		firmware2_starting_sector;
+	uint32_t		sectors_in_firmware1;
+	uint32_t		sectors_in_firmware2;
+	uint32_t		dbbt_search_area_start_address;
+	uint32_t		badblock_marker_byte;
+	uint32_t		badblock_marker_start_bit;
+	uint32_t		bb_marker_physical_offset;
+};
+
+struct mx28_nand_dbbt {
+	uint32_t		checksum;
+	uint32_t		fingerprint;
+	uint32_t		version;
+	uint32_t		number_bb;
+	uint32_t		number_2k_pages_bb;
+};
+
+struct mx28_nand_bbt {
+	uint32_t		nand;
+	uint32_t		number_bb;
+	uint32_t		badblock[510];
+};
+
+struct mx28_sd_drive_info {
+	uint32_t		chip_num;
+	uint32_t		drive_type;
+	uint32_t		tag;
+	uint32_t		first_sector_number;
+	uint32_t		sector_count;
+};
+
+struct mx28_sd_config_block {
+	uint32_t			signature;
+	uint32_t			primary_boot_tag;
+	uint32_t			secondary_boot_tag;
+	uint32_t			num_copies;
+	struct mx28_sd_drive_info	drv_info[1];
+};
+
+static inline uint32_t mx28_nand_ecc_size_in_bits(uint32_t ecc_strength)
+{
+	return ecc_strength * 13;
+}
+
+static inline uint32_t mx28_nand_get_ecc_strength(uint32_t page_data_size,
+						uint32_t page_oob_size)
+{
+	if (page_data_size == 2048)
+		return 8;
+
+	if (page_data_size == 4096) {
+		if (page_oob_size == 128)
+			return 8;
+
+		if (page_oob_size == 218)
+			return 16;
+	}
+
+	return 0;
+}
+
+static inline uint32_t mx28_nand_get_mark_offset(uint32_t page_data_size,
+						uint32_t ecc_strength)
+{
+	uint32_t chunk_data_size_in_bits;
+	uint32_t chunk_ecc_size_in_bits;
+	uint32_t chunk_total_size_in_bits;
+	uint32_t block_mark_chunk_number;
+	uint32_t block_mark_chunk_bit_offset;
+	uint32_t block_mark_bit_offset;
+
+	chunk_data_size_in_bits = MXS_NAND_CHUNK_DATA_CHUNK_SIZE * 8;
+	chunk_ecc_size_in_bits  = mx28_nand_ecc_size_in_bits(ecc_strength);
+
+	chunk_total_size_in_bits =
+			chunk_data_size_in_bits + chunk_ecc_size_in_bits;
+
+	/* Compute the bit offset of the block mark within the physical page. */
+	block_mark_bit_offset = page_data_size * 8;
+
+	/* Subtract the metadata bits. */
+	block_mark_bit_offset -= MXS_NAND_METADATA_SIZE * 8;
+
+	/*
+	 * Compute the chunk number (starting at zero) in which the block mark
+	 * appears.
+	 */
+	block_mark_chunk_number =
+			block_mark_bit_offset / chunk_total_size_in_bits;
+
+	/*
+	 * Compute the bit offset of the block mark within its chunk, and
+	 * validate it.
+	 */
+	block_mark_chunk_bit_offset = block_mark_bit_offset -
+			(block_mark_chunk_number * chunk_total_size_in_bits);
+
+	if (block_mark_chunk_bit_offset > chunk_data_size_in_bits)
+		return 1;
+
+	/*
+	 * Now that we know the chunk number in which the block mark appears,
+	 * we can subtract all the ECC bits that appear before it.
+	 */
+	block_mark_bit_offset -=
+		block_mark_chunk_number * chunk_ecc_size_in_bits;
+
+	return block_mark_bit_offset;
+}
+
+static inline uint32_t mx28_nand_mark_byte_offset(void)
+{
+	uint32_t ecc_strength;
+	ecc_strength = mx28_nand_get_ecc_strength(nand_writesize, nand_oobsize);
+	return mx28_nand_get_mark_offset(nand_writesize, ecc_strength) >> 3;
+}
+
+static inline uint32_t mx28_nand_mark_bit_offset(void)
+{
+	uint32_t ecc_strength;
+	ecc_strength = mx28_nand_get_ecc_strength(nand_writesize, nand_oobsize);
+	return mx28_nand_get_mark_offset(nand_writesize, ecc_strength) & 0x7;
+}
+
+static uint32_t mx28_nand_block_csum(uint8_t *block, uint32_t size)
+{
+	uint32_t csum = 0;
+	int i;
+
+	for (i = 0; i < size; i++)
+		csum += block[i];
+
+	return csum ^ 0xffffffff;
+}
+
+static struct mx28_nand_fcb *mx28_nand_get_fcb(uint32_t size)
+{
+	struct mx28_nand_fcb *fcb;
+	uint32_t bcb_size_bytes;
+	uint32_t stride_size_bytes;
+	uint32_t bootstream_size_pages;
+	uint32_t fw1_start_page;
+	uint32_t fw2_start_page;
+
+	fcb = malloc(nand_writesize);
+	if (!fcb) {
+		printf("MX28 NAND: Unable to allocate FCB\n");
+		return NULL;
+	}
+
+	memset(fcb, 0, nand_writesize);
+
+	fcb->fingerprint =			0x20424346;
+	fcb->version =				0x01000000;
+
+	/*
+	 * FIXME: These here are default values as found in kobs-ng. We should
+	 * probably retrieve the data from NAND or something.
+	 */
+	fcb->timing.data_setup =		80;
+	fcb->timing.data_hold =			60;
+	fcb->timing.address_setup =		25;
+	fcb->timing.dsample_time =		6;
+
+	fcb->page_data_size =		nand_writesize;
+	fcb->total_page_size =		nand_writesize + nand_oobsize;
+	fcb->sectors_per_block =	nand_erasesize / nand_writesize;
+
+	fcb->num_ecc_blocks_per_page =	(nand_writesize / 512) - 1;
+	fcb->ecc_block_0_size =		512;
+	fcb->ecc_block_n_size =		512;
+	fcb->metadata_bytes =		10;
+
+	if (nand_writesize == 2048) {
+		fcb->ecc_block_n_ecc_type =		4;
+		fcb->ecc_block_0_ecc_type =		4;
+	} else if (nand_writesize == 4096) {
+		if (nand_oobsize == 128) {
+			fcb->ecc_block_n_ecc_type =	4;
+			fcb->ecc_block_0_ecc_type =	4;
+		} else if (nand_oobsize == 218) {
+			fcb->ecc_block_n_ecc_type =	8;
+			fcb->ecc_block_0_ecc_type =	8;
+		}
+	}
+
+	if (fcb->ecc_block_n_ecc_type == 0) {
+		printf("MX28 NAND: Unsupported NAND geometry\n");
+		goto err;
+	}
+
+	fcb->boot_patch =			0;
+	fcb->patch_sectors =			0;
+
+	fcb->badblock_marker_byte =	mx28_nand_mark_byte_offset();
+	fcb->badblock_marker_start_bit = mx28_nand_mark_bit_offset();
+	fcb->bb_marker_physical_offset = nand_writesize;
+
+	stride_size_bytes = STRIDE_PAGES * nand_writesize;
+	bcb_size_bytes = stride_size_bytes * STRIDE_COUNT;
+
+	bootstream_size_pages = (size + (nand_writesize - 1)) /
+					nand_writesize;
+
+	fw1_start_page = 2 * bcb_size_bytes / nand_writesize;
+	fw2_start_page = (2 * bcb_size_bytes + MAX_BOOTSTREAM_SIZE) /
+				nand_writesize;
+
+	fcb->firmware1_starting_sector =	fw1_start_page;
+	fcb->firmware2_starting_sector =	fw2_start_page;
+	fcb->sectors_in_firmware1 =		bootstream_size_pages;
+	fcb->sectors_in_firmware2 =		bootstream_size_pages;
+
+	fcb->dbbt_search_area_start_address =	STRIDE_PAGES * STRIDE_COUNT;
+
+	return fcb;
+
+err:
+	free(fcb);
+	return NULL;
+}
+
+static struct mx28_nand_dbbt *mx28_nand_get_dbbt(void)
+{
+	struct mx28_nand_dbbt *dbbt;
+
+	dbbt = malloc(nand_writesize);
+	if (!dbbt) {
+		printf("MX28 NAND: Unable to allocate DBBT\n");
+		return NULL;
+	}
+
+	memset(dbbt, 0, nand_writesize);
+
+	dbbt->fingerprint	= 0x54424244;
+	dbbt->version		= 0x1;
+
+	return dbbt;
+}
+
+static inline uint8_t mx28_nand_parity_13_8(const uint8_t b)
+{
+	uint32_t parity = 0, tmp;
+
+	tmp = ((b >> 6) ^ (b >> 5) ^ (b >> 3) ^ (b >> 2)) & 1;
+	parity |= tmp << 0;
+
+	tmp = ((b >> 7) ^ (b >> 5) ^ (b >> 4) ^ (b >> 2) ^ (b >> 1)) & 1;
+	parity |= tmp << 1;
+
+	tmp = ((b >> 7) ^ (b >> 6) ^ (b >> 5) ^ (b >> 1) ^ (b >> 0)) & 1;
+	parity |= tmp << 2;
+
+	tmp = ((b >> 7) ^ (b >> 4) ^ (b >> 3) ^ (b >> 0)) & 1;
+	parity |= tmp << 3;
+
+	tmp = ((b >> 6) ^ (b >> 4) ^ (b >> 3) ^
+		(b >> 2) ^ (b >> 1) ^ (b >> 0)) & 1;
+	parity |= tmp << 4;
+
+	return parity;
+}
+
+static uint8_t *mx28_nand_fcb_block(struct mx28_nand_fcb *fcb)
+{
+	uint8_t *block;
+	uint8_t *ecc;
+	int i;
+
+	block = malloc(nand_writesize + nand_oobsize);
+	if (!block) {
+		printf("MX28 NAND: Unable to allocate FCB block\n");
+		return NULL;
+	}
+
+	memset(block, 0, nand_writesize + nand_oobsize);
+
+	/* Update the FCB checksum */
+	fcb->checksum = mx28_nand_block_csum(((uint8_t *)fcb) + 4, 508);
+
+	/* Figure 12-11. in iMX28RM, rev. 1, says FCB is at offset 12 */
+	memcpy(block + 12, fcb, sizeof(struct mx28_nand_fcb));
+
+	/* ECC is at offset 12 + 512 */
+	ecc = block + 12 + 512;
+
+	/* Compute the ECC parity */
+	for (i = 0; i < sizeof(struct mx28_nand_fcb); i++)
+		ecc[i] = mx28_nand_parity_13_8(block[i + 12]);
+
+	return block;
+}
+
+static int mx28_nand_write_fcb(struct mx28_nand_fcb *fcb, char *buf)
+{
+	uint32_t offset;
+	uint8_t *fcbblock;
+	int ret = 0;
+	int i;
+
+	fcbblock = mx28_nand_fcb_block(fcb);
+	if (!fcbblock)
+		return -1;
+
+	for (i = 0; i < STRIDE_PAGES * STRIDE_COUNT; i += STRIDE_PAGES) {
+		offset = i * nand_writesize;
+		memcpy(buf + offset, fcbblock, nand_writesize + nand_oobsize);
+	}
+
+	free(fcbblock);
+	return ret;
+}
+
+static int mx28_nand_write_dbbt(struct mx28_nand_dbbt *dbbt, char *buf)
+{
+	uint32_t offset;
+	int i = STRIDE_PAGES * STRIDE_COUNT;
+
+	for (; i < 2 * STRIDE_PAGES * STRIDE_COUNT; i += STRIDE_PAGES) {
+		offset = i * nand_writesize;
+		memcpy(buf + offset, dbbt, sizeof(struct mx28_nand_dbbt));
+	}
+
+	return 0;
+}
+
+static int mx28_nand_write_firmware(struct mx28_nand_fcb *fcb, int infd,
+					char *buf)
+{
+	int ret;
+	off_t size;
+	uint32_t offset1, offset2;
+
+	size = lseek(infd, 0, SEEK_END);
+	lseek(infd, 0, SEEK_SET);
+
+	offset1 = fcb->firmware1_starting_sector * nand_writesize;
+	offset2 = fcb->firmware2_starting_sector * nand_writesize;
+
+	ret = read(infd, buf + offset1, size);
+	if (ret != size)
+		return -1;
+
+	memcpy(buf + offset2, buf + offset1, size);
+
+	return 0;
+}
+
+void usage(void)
+{
+	printf(
+		"Usage: mx28image [ops] <type> <infile> <outfile>\n"
+		"Augment BootStream file with a proper header for i.MX28 boot\n"
+		"\n"
+		"  <type>	type of image:\n"
+		"                 \"nand\" for NAND image\n"
+		"                 \"sd\" for SD image\n"
+		"  <infile>     input file, the u-boot.sb bootstream\n"
+		"  <outfile>    output file, the bootable image\n"
+		"\n");
+	printf(
+		"For NAND boot, these options are accepted:\n"
+		"  -w <size>    NAND page size\n"
+		"  -o <size>    NAND OOB size\n"
+		"  -e <size>    NAND erase size\n"
+		"\n"
+		"For SD boot, these options are accepted:\n"
+		"  -p <sector>  Sector where the SGTL partition starts\n"
+	);
+}
+
+static int mx28_create_nand_image(int infd, int outfd)
+{
+	struct mx28_nand_fcb *fcb;
+	struct mx28_nand_dbbt *dbbt;
+	int ret = -1;
+	char *buf;
+	int size;
+	ssize_t wr_size;
+
+	size = nand_writesize * 512 + 2 * MAX_BOOTSTREAM_SIZE;
+
+	buf = malloc(size);
+	if (!buf) {
+		printf("Can not allocate output buffer of %d bytes\n", size);
+		goto err0;
+	}
+
+	memset(buf, 0, size);
+
+	fcb = mx28_nand_get_fcb(MAX_BOOTSTREAM_SIZE);
+	if (!fcb) {
+		printf("Unable to compile FCB\n");
+		goto err1;
+	}
+
+	dbbt = mx28_nand_get_dbbt();
+	if (!dbbt) {
+		printf("Unable to compile DBBT\n");
+		goto err2;
+	}
+
+	ret = mx28_nand_write_fcb(fcb, buf);
+	if (ret) {
+		printf("Unable to write FCB to buffer\n");
+		goto err3;
+	}
+
+	ret = mx28_nand_write_dbbt(dbbt, buf);
+	if (ret) {
+		printf("Unable to write DBBT to buffer\n");
+		goto err3;
+	}
+
+	ret = mx28_nand_write_firmware(fcb, infd, buf);
+	if (ret) {
+		printf("Unable to write firmware to buffer\n");
+		goto err3;
+	}
+
+	wr_size = write(outfd, buf, size);
+	if (wr_size != size) {
+		ret = -1;
+		goto err3;
+	}
+
+	ret = 0;
+
+err3:
+	free(dbbt);
+err2:
+	free(fcb);
+err1:
+	free(buf);
+err0:
+	return ret;
+}
+
+static int mx28_create_sd_image(int infd, int outfd)
+{
+	int ret = -1;
+	uint32_t *buf;
+	int size;
+	off_t fsize;
+	ssize_t wr_size;
+	struct mx28_sd_config_block *cb;
+
+	fsize = lseek(infd, 0, SEEK_END);
+	lseek(infd, 0, SEEK_SET);
+	size = fsize + 512;
+
+	buf = malloc(size);
+	if (!buf) {
+		printf("Can not allocate output buffer of %d bytes\n", size);
+		goto err0;
+	}
+
+	ret = read(infd, (uint8_t *)buf + 512, fsize);
+	if (ret != fsize) {
+		ret = -1;
+		goto err1;
+	}
+
+	cb = (struct mx28_sd_config_block *)buf;
+
+	cb->signature = 0x00112233;
+	cb->primary_boot_tag = 0x1;
+	cb->secondary_boot_tag = 0x1;
+	cb->num_copies = 1;
+	cb->drv_info[0].chip_num = 0x0;
+	cb->drv_info[0].drive_type = 0x0;
+	cb->drv_info[0].tag = 0x1;
+	cb->drv_info[0].first_sector_number = sd_sector + 1;
+	cb->drv_info[0].sector_count = (size - 1) / 512;
+
+	wr_size = write(outfd, buf, size);
+	if (wr_size != size) {
+		ret = -1;
+		goto err1;
+	}
+
+	ret = 0;
+
+err1:
+	free(buf);
+err0:
+	return ret;
+}
+
+int parse_ops(int argc, char **argv)
+{
+	int i;
+	int tmp;
+	char *end;
+	enum param {
+		PARAM_WRITE,
+		PARAM_OOB,
+		PARAM_ERASE,
+		PARAM_PART,
+		PARAM_SD,
+		PARAM_NAND
+	};
+	int type;
+
+	for (i = 1; i < argc; i++) {
+		if (!strncmp(argv[i], "-w", 2))
+			type = PARAM_WRITE;
+		else if (!strncmp(argv[i], "-o", 2))
+			type = PARAM_OOB;
+		else if (!strncmp(argv[i], "-e", 2))
+			type = PARAM_ERASE;
+		else if (!strncmp(argv[i], "-p", 2))
+			type = PARAM_PART;
+		else	/* SD/MMC */
+			break;
+
+		tmp = strtol(argv[++i], &end, 10);
+		if (tmp % 2)
+			return -1;
+		if (tmp <= 0)
+			return -1;
+
+		if (type == PARAM_WRITE)
+			nand_writesize = tmp;
+		if (type == PARAM_OOB)
+			nand_oobsize = tmp;
+		if (type == PARAM_ERASE)
+			nand_erasesize = tmp;
+		if (type == PARAM_PART)
+			sd_sector = tmp;
+	}
+
+	if (strcmp(argv[i], "sd") && strcmp(argv[i], "nand"))
+		return -1;
+
+	if (i + 3 != argc)
+		return -1;
+
+	return i;
+}
+
+int main(int argc, char **argv)
+{
+	int infd, outfd;
+	int ret = 0;
+	int offset;
+
+	offset = parse_ops(argc, argv);
+	if (offset < 0) {
+		usage();
+		ret = 1;
+		goto err1;
+	}
+
+	infd = open(argv[offset + 1], O_RDONLY);
+	if (infd < 0) {
+		printf("Input BootStream file can not be opened\n");
+		ret = 2;
+		goto err1;
+	}
+
+	outfd = open(argv[offset + 2], O_CREAT | O_TRUNC | O_WRONLY,
+					S_IRUSR | S_IWUSR);
+	if (outfd < 0) {
+		printf("Output file can not be created\n");
+		ret = 3;
+		goto err2;
+	}
+
+	if (!strcmp(argv[offset], "sd"))
+		ret = mx28_create_sd_image(infd, outfd);
+	else if (!strcmp(argv[offset], "nand"))
+		ret = mx28_create_nand_image(infd, outfd);
+
+	close(outfd);
+err2:
+	close(infd);
+err1:
+	return ret;
+}
-- 
1.7.6.3

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

* [U-Boot] [PATCH 12/17 V3] iMX28: Add u-boot.sb target to Makefile
  2011-10-21 22:44 ` [U-Boot] [PATCH 00/17 V3] Support for the DENX M28 SoM Marek Vasut
                     ` (10 preceding siblings ...)
  2011-10-21 22:44   ` [U-Boot] [PATCH 11/17 RESEND V2] iMX28: Add image header generator tool Marek Vasut
@ 2011-10-21 22:44   ` Marek Vasut
  2011-10-21 22:44   ` [U-Boot] [PATCH 13/17 V4] iMX28: Add support for DENX M28EVK board Marek Vasut
                     ` (4 subsequent siblings)
  16 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-10-21 22:44 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 .gitignore |    1 +
 Makefile   |    5 +++++
 2 files changed, 6 insertions(+), 0 deletions(-)

V2: Add missing .gitignore entry
V3: Use $(TOPDIR)/board/$(BOARDDIR)/u-boot.bd instead of
    board/denx/m28evk/u-boot.bd path in Makefile

diff --git a/.gitignore b/.gitignore
index 320d21e..00fd360 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,6 +35,7 @@
 /u-boot.dis
 /u-boot.lds
 /u-boot.ubl
+/u-boot.sb
 
 #
 # Generated files
diff --git a/Makefile b/Makefile
index e9a153c..c1b1265 100644
--- a/Makefile
+++ b/Makefile
@@ -403,6 +403,10 @@ $(obj)u-boot.ubl:       $(obj)u-boot-nand.bin
 		$(obj)tools/mkimage -n $(UBL_CONFIG) -T ublimage \
 		-e $(CONFIG_SYS_TEXT_BASE) -d $< $@
 
+$(obj)u-boot.sb:       $(obj)u-boot.bin $(obj)spl/u-boot-spl.bin
+		elftosb -zdf imx28 -c $(TOPDIR)/board/$(BOARDDIR)/u-boot.bd \
+			-o $(obj)u-boot.sb
+
 ifeq ($(CONFIG_SANDBOX),y)
 GEN_UBOOT = \
 		cd $(LNDIR) && $(CC) $(SYMS) -T $(obj)u-boot.lds \
@@ -973,6 +977,7 @@ clobber:	clean
 	@rm -f $(obj)u-boot.kwb
 	@rm -f $(obj)u-boot.imx
 	@rm -f $(obj)u-boot.ubl
+	@rm -f $(obj)u-boot.sb
 	@rm -f $(obj)tools/{env/crc32.c,inca-swap-bytes}
 	@rm -f $(obj)arch/powerpc/cpu/mpc824x/bedbug_603e.c
 	@rm -fr $(obj)include/asm/proc $(obj)include/asm/arch $(obj)include/asm
-- 
1.7.6.3

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

* [U-Boot] [PATCH 13/17 V4] iMX28: Add support for DENX M28EVK board
  2011-10-21 22:44 ` [U-Boot] [PATCH 00/17 V3] Support for the DENX M28 SoM Marek Vasut
                     ` (11 preceding siblings ...)
  2011-10-21 22:44   ` [U-Boot] [PATCH 12/17 V3] iMX28: Add u-boot.sb target to Makefile Marek Vasut
@ 2011-10-21 22:44   ` Marek Vasut
  2011-10-31  9:12     ` Igor Grinberg
  2011-10-31 11:42     ` [U-Boot] [PATCH 13/17 V5] " Marek Vasut
  2011-10-21 22:44   ` [U-Boot] [PATCH 14/17 V4] M28: Add MMC SPL Marek Vasut
                     ` (3 subsequent siblings)
  16 siblings, 2 replies; 116+ messages in thread
From: Marek Vasut @ 2011-10-21 22:44 UTC (permalink / raw)
  To: u-boot

This contains support for the following components:
- DUART
- MMC
- Both FEC interfaces
- NAND
- I2C (RTC, EEPROM)
- SPI (FLASH)

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 MAINTAINERS                |    1 +
 board/denx/m28evk/Makefile |   49 ++++++++
 board/denx/m28evk/m28evk.c |  195 ++++++++++++++++++++++++++++++
 boards.cfg                 |    1 +
 include/configs/m28evk.h   |  282 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 528 insertions(+), 0 deletions(-)
 create mode 100644 board/denx/m28evk/Makefile
 create mode 100644 board/denx/m28evk/m28evk.c
 create mode 100644 include/configs/m28evk.h

V2: Use scrub -y instead of scrub.quiet in the scripts.
V3: Use CONFIG_ENV_RANGE
V4: Configure the RAM size to 128MB for V1.1 module

diff --git a/MAINTAINERS b/MAINTAINERS
index bb95e6d..12c9e96 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -841,6 +841,7 @@ Marek Vasut <marek.vasut@gmail.com>
 	palmtc		xscale/pxa
 	vpac270		xscale/pxa
 	zipitz2		xscale/pxa
+	m28evk		i.MX28
  	efikamx		i.MX51
 	efikasb		i.MX51
 
diff --git a/board/denx/m28evk/Makefile b/board/denx/m28evk/Makefile
new file mode 100644
index 0000000..4037199
--- /dev/null
+++ b/board/denx/m28evk/Makefile
@@ -0,0 +1,49 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(BOARD).o
+
+COBJS	:= m28evk.o
+
+SRCS	:= $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+clean:
+	rm -f $(OBJS)
+
+distclean:	clean
+	rm -f $(LIB) core *.bak .depend
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/denx/m28evk/m28evk.c b/board/denx/m28evk/m28evk.c
new file mode 100644
index 0000000..118e222
--- /dev/null
+++ b/board/denx/m28evk/m28evk.c
@@ -0,0 +1,195 @@
+/*
+ * DENX M28 module
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/iomux-mx28.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sys_proto.h>
+#include <linux/mii.h>
+#include <miiphy.h>
+#include <netdev.h>
+#include <errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Functions
+ */
+int board_early_init_f(void)
+{
+	/* IO0 clock at 480MHz */
+	mx28_set_ioclk(MXC_IOCLK0, 480000);
+	/* IO1 clock at 480MHz */
+	mx28_set_ioclk(MXC_IOCLK1, 480000);
+
+	/* SSP0 clock at 96MHz */
+	mx28_set_sspclk(MXC_SSPCLK0, 96000, 0);
+	/* SSP2 clock at 96MHz */
+	mx28_set_sspclk(MXC_SSPCLK2, 96000, 0);
+
+	return 0;
+}
+
+int board_init(void)
+{
+	/* Adress of boot parameters */
+	gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
+
+	return 0;
+}
+
+int dram_init(void)
+{
+	/* dram_init must store complete ramsize in gd->ram_size */
+	gd->ram_size = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE);
+	return 0;
+}
+
+#ifdef	CONFIG_CMD_MMC
+static int m28_mmc_wp(int id)
+{
+	if (id != 0) {
+		printf("MXS MMC: Invalid card selected (card id = %d)\n", id);
+		return 1;
+	}
+
+	return gpio_get_value(MX28_PAD_AUART2_CTS__GPIO_3_10);
+}
+
+int board_mmc_init(bd_t *bis)
+{
+	/* Configure WP as output */
+	gpio_direction_input(MX28_PAD_AUART2_CTS__GPIO_3_10);
+
+	return mxsmmc_initialize(bis, 0, m28_mmc_wp);
+}
+#endif
+
+#ifdef	CONFIG_CMD_NET
+
+#define	MII_OPMODE_STRAP_OVERRIDE	0x16
+#define	MII_PHY_CTRL1			0x1e
+#define	MII_PHY_CTRL2			0x1f
+
+int fecmxc_mii_postcall(int phy)
+{
+	miiphy_write("FEC1", phy, MII_BMCR, 0x9000);
+	miiphy_write("FEC1", phy, MII_OPMODE_STRAP_OVERRIDE, 0x0202);
+	if (phy == 3)
+		miiphy_write("FEC1", 3, MII_PHY_CTRL2, 0x8180);
+	return 0;
+}
+
+int board_eth_init(bd_t *bis)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	struct eth_device *dev;
+	int ret;
+
+	ret = cpu_eth_init(bis);
+
+	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_enet,
+		CLKCTRL_ENET_TIME_SEL_MASK | CLKCTRL_ENET_CLK_OUT_EN,
+		CLKCTRL_ENET_TIME_SEL_RMII_CLK);
+
+	ret = fecmxc_initialize_multi(bis, 0, 0, MXS_ENET0_BASE);
+	if (ret) {
+		printf("FEC MXS: Unable to init FEC0\n");
+		return ret;
+	}
+
+	ret = fecmxc_initialize_multi(bis, 1, 3, MXS_ENET1_BASE);
+	if (ret) {
+		printf("FEC MXS: Unable to init FEC1\n");
+		return ret;
+	}
+
+	dev = eth_get_dev_by_name("FEC0");
+	if (!dev) {
+		printf("FEC MXS: Unable to get FEC0 device entry\n");
+		return -EINVAL;
+	}
+
+	ret = fecmxc_register_mii_postcall(dev, fecmxc_mii_postcall);
+	if (ret) {
+		printf("FEC MXS: Unable to register FEC0 mii postcall\n");
+		return ret;
+	}
+
+	dev = eth_get_dev_by_name("FEC1");
+	if (!dev) {
+		printf("FEC MXS: Unable to get FEC1 device entry\n");
+		return -EINVAL;
+	}
+
+	ret = fecmxc_register_mii_postcall(dev, fecmxc_mii_postcall);
+	if (ret) {
+		printf("FEC MXS: Unable to register FEC1 mii postcall\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+#ifdef	CONFIG_M28_FEC_MAC_IN_OCOTP
+
+#define	MXS_OCOTP_MAX_TIMEOUT	1000000
+void imx_get_mac_from_fuse(char *mac)
+{
+	struct mx28_ocotp_regs *ocotp_regs =
+		(struct mx28_ocotp_regs *)MXS_OCOTP_BASE;
+	uint32_t data;
+
+	memset(mac, 0, 6);
+
+	writel(OCOTP_CTRL_RD_BANK_OPEN, &ocotp_regs->hw_ocotp_ctrl_set);
+
+	if (mx28_wait_mask_clr(&ocotp_regs->hw_ocotp_ctrl_reg, OCOTP_CTRL_BUSY,
+				MXS_OCOTP_MAX_TIMEOUT)) {
+		printf("MXS FEC: Can't get MAC from OCOTP\n");
+		return;
+	}
+
+	data = readl(&ocotp_regs->hw_ocotp_cust0);
+
+	mac[0] = 0x00;
+	mac[1] = 0x04;
+	mac[2] = (data >> 24) & 0xff;
+	mac[3] = (data >> 16) & 0xff;
+	mac[4] = (data >> 8) & 0xff;
+	mac[5] = data & 0xff;
+}
+#else
+void imx_get_mac_from_fuse(char *mac)
+{
+	memset(mac, 0, 6);
+}
+#endif
+
+#endif
diff --git a/boards.cfg b/boards.cfg
index 1776a73..c863c82 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -152,6 +152,7 @@ tx25                         arm         arm926ejs   tx25                karo
 zmx25                        arm         arm926ejs   zmx25               syteco         mx25
 imx27lite                    arm         arm926ejs   imx27lite           logicpd        mx27
 magnesium                    arm         arm926ejs   imx27lite           logicpd        mx27
+m28evk                       arm         arm926ejs   -                   denx           mx28
 nhk8815                      arm         arm926ejs   nhk8815             st             nomadik
 nhk8815_onenand              arm         arm926ejs   nhk8815             st             nomadik       nhk8815:BOOT_ONENAND
 omap5912osk                  arm         arm926ejs   -                   ti             omap
diff --git a/include/configs/m28evk.h b/include/configs/m28evk.h
new file mode 100644
index 0000000..d88e09e
--- /dev/null
+++ b/include/configs/m28evk.h
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef __M28_H__
+#define __M28_H__
+
+#include <asm/arch/regs-base.h>
+
+/*
+ * SoC configurations
+ */
+#define	CONFIG_MX28				/* i.MX28 SoC */
+#define	CONFIG_MXS_GPIO				/* GPIO control */
+#define	CONFIG_SYS_HZ		1000		/* Ticks per second */
+
+/*
+ * Define M28EVK machine type by hand until it lands in mach-types
+ */
+#define	MACH_TYPE_M28EVK	3613
+
+#define	CONFIG_MACH_TYPE	MACH_TYPE_M28EVK
+
+#define	CONFIG_SYS_NO_FLASH
+#define	CONFIG_SYS_ICACHE_OFF
+#define	CONFIG_SYS_DCACHE_OFF
+#define	CONFIG_BOARD_EARLY_INIT_F
+#define	CONFIG_ARCH_CPU_INIT
+
+/*
+ * U-Boot Commands
+ */
+#include <config_cmd_default.h>
+#define	CONFIG_DISPLAY_CPUINFO
+#define	CONFIG_DOS_PARTITION
+
+#define	CONFIG_CMD_CACHE
+#define	CONFIG_CMD_DATE
+#define	CONFIG_CMD_DHCP
+#define	CONFIG_CMD_EEPROM
+#define	CONFIG_CMD_EXT2
+#define	CONFIG_CMD_FAT
+#define	CONFIG_CMD_GPIO
+#define	CONFIG_CMD_I2C
+#define	CONFIG_CMD_MII
+#define	CONFIG_CMD_MMC
+#define	CONFIG_CMD_NAND
+#define	CONFIG_CMD_NET
+#define	CONFIG_CMD_NFS
+#define	CONFIG_CMD_PING
+#define	CONFIG_CMD_SETEXPR
+#define	CONFIG_CMD_SF
+#define	CONFIG_CMD_SPI
+
+/*
+ * Memory configurations
+ */
+#define	CONFIG_NR_DRAM_BANKS		1		/* 2 banks of DRAM */
+#define	PHYS_SDRAM_1			0x40000000	/* Base address */
+#define	PHYS_SDRAM_1_SIZE		0x08000000	/* 128 MB */
+#define	CONFIG_STACKSIZE		0x00010000	/* 128 KB stack */
+#define	CONFIG_SYS_MALLOC_LEN		0x00400000	/* 4 MB for malloc */
+#define	CONFIG_SYS_GBL_DATA_SIZE	128		/* Initial data */
+#define	CONFIG_SYS_MEMTEST_START	0x40000000	/* Memtest start adr */
+#define	CONFIG_SYS_MEMTEST_END		0x40400000	/* 4 MB RAM test */
+#define	CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM_1
+/* Point initial SP in SRAM so SPL can use it too. */
+#define	CONFIG_SYS_INIT_SP_ADDR		0x00002000
+/*
+ * We need to sacrifice first 4 bytes of RAM here to avoid triggering some
+ * strange BUG in ROM corrupting first 4 bytes of RAM when loading U-Boot
+ * binary. In case there was more of this mess, 0x100 bytes are skipped.
+ */
+#define	CONFIG_SYS_TEXT_BASE		0x40000100
+
+/*
+ * U-Boot general configurations
+ */
+#define	CONFIG_SYS_LONGHELP
+#define	CONFIG_SYS_PROMPT	"=> "
+#define	CONFIG_SYS_CBSIZE	1024		/* Console I/O buffer size */
+#define	CONFIG_SYS_PBSIZE	\
+	(CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+						/* Print buffer size */
+#define	CONFIG_SYS_MAXARGS	32		/* Max number of command args */
+#define	CONFIG_SYS_BARGSIZE	CONFIG_SYS_CBSIZE
+						/* Boot argument buffer size */
+#define	CONFIG_VERSION_VARIABLE			/* U-BOOT version */
+#define	CONFIG_AUTO_COMPLETE			/* Command auto complete */
+#define	CONFIG_CMDLINE_EDITING			/* Command history etc */
+#define	CONFIG_SYS_HUSH_PARSER
+#define	CONFIG_SYS_PROMPT_HUSH_PS2	"> "
+
+/*
+ * Serial Driver
+ */
+#define	CONFIG_PL011_SERIAL
+#define	CONFIG_PL011_CLOCK		24000000
+#define	CONFIG_PL01x_PORTS		{ (void *)MXS_UARTDBG_BASE }
+#define	CONFIG_CONS_INDEX		0
+#define	CONFIG_BAUDRATE			115200	/* Default baud rate */
+#define	CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 }
+
+/*
+ * MMC Driver
+ */
+#ifdef	CONFIG_CMD_MMC
+#define	CONFIG_MMC
+#define	CONFIG_GENERIC_MMC
+#define	CONFIG_MXS_MMC
+#endif
+
+/*
+ * NAND
+ */
+#ifdef	CONFIG_CMD_NAND
+#define	CONFIG_NAND_MXS
+#define CONFIG_APBH_DMA
+#define	CONFIG_SYS_MAX_NAND_DEVICE	1
+#define	CONFIG_SYS_NAND_BASE		0x60000000
+#define	CONFIG_SYS_NAND_5_ADDR_CYCLE
+#define	NAND_MAX_CHIPS			8
+
+/* Environment is in NAND */
+#define	CONFIG_ENV_IS_IN_NAND
+#define	CONFIG_ENV_SIZE			(16 * 1024)
+#define	CONFIG_ENV_SIZE_REDUND		CONFIG_ENV_SIZE
+#define	CONFIG_ENV_SECT_SIZE		(128 * 1024)
+#define	CONFIG_ENV_RANGE		(512 * 1024)
+#define	CONFIG_ENV_OFFSET		0x300000
+#define	CONFIG_ENV_OFFSET_REDUND	\
+		(CONFIG_ENV_OFFSET + CONFIG_ENV_RANGE)
+
+#define	CONFIG_CMD_UBI
+#define	CONFIG_CMD_UBIFS
+#define	CONFIG_CMD_MTDPARTS
+#define	CONFIG_RBTREE
+#define	CONFIG_LZO
+#define	CONFIG_MTD_DEVICE
+#define	CONFIG_MTD_PARTITIONS
+#define	MTDIDS_DEFAULT			"nand0=gpmi-nand.0"
+#define	MTDPARTS_DEFAULT			\
+	"mtdparts=gpmi-nand.0:"			\
+		"3m(bootloader)ro,"		\
+		"512k(environment),"		\
+		"512k(redundant-environment),"	\
+		"4m(kernel),"			\
+		"-(filesystem)"
+#endif
+
+/*
+ * Ethernet on SOC (FEC)
+ */
+#ifdef	CONFIG_CMD_NET
+#define	CONFIG_NET_MULTI
+#define	CONFIG_ETHPRIME			"FEC0"
+#define	CONFIG_FEC_MXC
+#define	CONFIG_FEC_MXC_MULTI
+#define	CONFIG_MII
+#define	CONFIG_DISCOVER_PHY
+#define	CONFIG_FEC_XCV_TYPE		RMII
+#endif
+
+/*
+ * I2C
+ */
+#ifdef	CONFIG_CMD_I2C
+#define	CONFIG_I2C_MXS
+#define	CONFIG_HARD_I2C
+#define	CONFIG_SYS_I2C_SPEED		400000
+#endif
+
+/*
+ * EEPROM
+ */
+#ifdef	CONFIG_CMD_EEPROM
+#define	CONFIG_SYS_I2C_MULTI_EEPROMS
+#define	CONFIG_SYS_I2C_EEPROM_ADDR_LEN	2
+#endif
+
+/*
+ * RTC
+ */
+#ifdef	CONFIG_CMD_DATE
+/* Use the internal RTC in the MXS chip */
+#define	CONFIG_RTC_INTERNAL
+#ifdef	CONFIG_RTC_INTERNAL
+#define	CONFIG_RTC_MXS
+#else
+#define	CONFIG_RTC_M41T62
+#define	CONFIG_SYS_I2C_RTC_ADDR		0x68
+#define	CONFIG_SYS_M41T11_BASE_YEAR	2000
+#endif
+#endif
+
+/*
+ * SPI
+ */
+#ifdef	CONFIG_CMD_SPI
+#define	CONFIG_HARD_SPI
+#define	CONFIG_MXS_SPI
+#define	CONFIG_SPI_HALF_DUPLEX
+#define	CONFIG_DEFAULT_SPI_BUS		2
+#define	CONFIG_DEFAULT_SPI_MODE		SPI_MODE_0
+
+/* SPI FLASH */
+#ifdef	CONFIG_CMD_SF
+#define	CONFIG_SPI_FLASH
+#define	CONFIG_SPI_FLASH_STMICRO
+#define	CONFIG_SPI_FLASH_CS		2
+#define	CONFIG_SF_DEFAULT_MODE		SPI_MODE_0
+#define	CONFIG_SF_DEFAULT_SPEED		24000000
+
+#define	CONFIG_ENV_SPI_CS		0
+#define	CONFIG_ENV_SPI_BUS		2
+#define	CONFIG_ENV_SPI_MAX_HZ		24000000
+#define	CONFIG_ENV_SPI_MODE		SPI_MODE_0
+#endif
+#endif
+
+/*
+ * Boot Linux
+ */
+#define	CONFIG_CMDLINE_TAG
+#define	CONFIG_SETUP_MEMORY_TAGS
+#define	CONFIG_BOOTDELAY	3
+#define	CONFIG_BOOTFILE		"uImage"
+#define	CONFIG_BOOTARGS		"console=ttyAM0,115200n8 "
+#define	CONFIG_BOOTCOMMAND	"run bootcmd_net"
+#define	CONFIG_LOADADDR		0x42000000
+#define	CONFIG_SYS_LOAD_ADDR	CONFIG_LOADADDR
+
+/*
+ * Extra Environments
+ */
+#define	CONFIG_EXTRA_ENV_SETTINGS					\
+	"update_nand_full_filename=u-boot.nand\0"			\
+	"update_nand_firmware_filename=u-boot.sb\0"			\
+	"update_nand_firmware_maxsz=0x100000\0"				\
+	"update_nand_stride=0x40\0"	/* MX28 datasheet ch. 12.12 */	\
+	"update_nand_count=0x4\0"	/* MX28 datasheet ch. 12.12 */	\
+	"update_nand_get_fcb_size="	/* Get size of FCB blocks */	\
+		"nand device 0 ; "					\
+		"nand info ; "						\
+		"setexpr fcb_sz ${update_nand_stride} * ${update_nand_count};" \
+		"setexpr update_nand_fcb ${fcb_sz} * ${nand_writesize}\0" \
+	"update_nand_full="		/* Update FCB, DBBT and FW */	\
+		"if tftp ${update_nand_full_filename} ; then "		\
+		"run update_nand_get_fcb_size ; "			\
+		"nand scrub -y 0x0 ${filesize} ; "			\
+		"nand write.raw ${loadaddr} 0x0 ${update_nand_fcb} ; "	\
+		"setexpr update_off ${loadaddr} + ${update_nand_fcb} ; " \
+		"setexpr update_sz ${filesize} - ${update_nand_fcb} ; " \
+		"nand write ${update_off} ${update_nand_fcb} ${update_sz} ; " \
+		"fi\0"							\
+	"update_nand_firmware="		/* Update only firmware */	\
+		"if tftp ${update_nand_firmware_filename} ; then "	\
+		"run update_nand_get_fcb_size ; "			\
+		"setexpr fcb_sz ${update_nand_fcb} * 2 ; " /* FCB + DBBT */ \
+		"setexpr fw_sz ${update_nand_firmware_maxsz} * 2 ; "	\
+		"setexpr fw_off ${fcb_sz} + ${update_nand_firmware_maxsz};" \
+		"nand erase ${fcb_sz} ${fw_sz} ; "			\
+		"nand write ${loadaddr} ${fcb_sz} ${filesize} ; "	\
+		"nand write ${loadaddr} ${fw_off} ${filesize} ; "	\
+		"fi\0"
+
+#endif /* __M28_H__ */
-- 
1.7.6.3

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

* [U-Boot] [PATCH 14/17 V4] M28: Add MMC SPL
  2011-10-21 22:44 ` [U-Boot] [PATCH 00/17 V3] Support for the DENX M28 SoM Marek Vasut
                     ` (12 preceding siblings ...)
  2011-10-21 22:44   ` [U-Boot] [PATCH 13/17 V4] iMX28: Add support for DENX M28EVK board Marek Vasut
@ 2011-10-21 22:44   ` Marek Vasut
  2011-10-23 21:42     ` Robert Schwebel
  2011-10-31 11:44     ` [U-Boot] [PATCH 14/17 V5] " Marek Vasut
  2011-10-21 22:44   ` [U-Boot] [PATCH 15/17 RESEND] M28: Add doc/README.m28 documentation Marek Vasut
                     ` (2 subsequent siblings)
  16 siblings, 2 replies; 116+ messages in thread
From: Marek Vasut @ 2011-10-21 22:44 UTC (permalink / raw)
  To: u-boot

This patch adds SPL code for the M28 board.

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Andy Fleming <afleming@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 board/denx/m28evk/Makefile       |    8 +
 board/denx/m28evk/m28_init.h     |   41 ++
 board/denx/m28evk/mem_init.c     |  213 +++++++++
 board/denx/m28evk/mmc_boot.c     |  273 ++++++++++++
 board/denx/m28evk/power_init.c   |  913 ++++++++++++++++++++++++++++++++++++++
 board/denx/m28evk/start.S        |  396 +++++++++++++++++
 board/denx/m28evk/u-boot-spl.lds |   87 ++++
 board/denx/m28evk/u-boot.bd      |   14 +
 include/configs/m28evk.h         |    8 +
 9 files changed, 1953 insertions(+), 0 deletions(-)
 create mode 100644 board/denx/m28evk/m28_init.h
 create mode 100644 board/denx/m28evk/mem_init.c
 create mode 100644 board/denx/m28evk/mmc_boot.c
 create mode 100644 board/denx/m28evk/power_init.c
 create mode 100644 board/denx/m28evk/start.S
 create mode 100644 board/denx/m28evk/u-boot-spl.lds
 create mode 100644 board/denx/m28evk/u-boot.bd

V2: Make waiting for powerswitch to be pressed configurable
V3: Squash checkpatch warning
V4: Configure DUART on PWM pins for V1.1 module

diff --git a/board/denx/m28evk/Makefile b/board/denx/m28evk/Makefile
index 4037199..953143a 100644
--- a/board/denx/m28evk/Makefile
+++ b/board/denx/m28evk/Makefile
@@ -25,7 +25,13 @@ include $(TOPDIR)/config.mk
 
 LIB	= $(obj)lib$(BOARD).o
 
+ifndef	CONFIG_SPL_BUILD
 COBJS	:= m28evk.o
+endif
+
+ifdef	CONFIG_SPL_BUILD
+COBJS	:= mem_init.o mmc_boot.o power_init.o
+endif
 
 SRCS	:= $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS))
@@ -33,6 +39,8 @@ OBJS	:= $(addprefix $(obj),$(COBJS))
 $(LIB):	$(obj).depend $(OBJS)
 	$(call cmd_link_o_target, $(OBJS))
 
+all:	$(ALL)
+
 clean:
 	rm -f $(OBJS)
 
diff --git a/board/denx/m28evk/m28_init.h b/board/denx/m28evk/m28_init.h
new file mode 100644
index 0000000..98d3631
--- /dev/null
+++ b/board/denx/m28evk/m28_init.h
@@ -0,0 +1,41 @@
+/*
+ * Freescale i.MX28 SPL functions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef	__M28_INIT_H__
+#define	__M28_INIT_H__
+
+void early_delay(int delay);
+
+void mx28_power_init(void);
+
+#ifdef	CONFIG_SPL_MX28_PSWITCH_WAIT
+void mx28_power_wait_pswitch(void);
+#else
+static inline void mx28_power_wait_pswitch(void) { }
+#endif
+
+void mx28_mem_init(void);
+
+#endif	/* __M28_INIT_H__ */
diff --git a/board/denx/m28evk/mem_init.c b/board/denx/m28evk/mem_init.c
new file mode 100644
index 0000000..066fe0d
--- /dev/null
+++ b/board/denx/m28evk/mem_init.c
@@ -0,0 +1,213 @@
+/*
+ * Freescale i.MX28 RAM init
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/io.h>
+#include <asm/arch/iomux-mx28.h>
+#include <asm/arch/imx-regs.h>
+
+#include "m28_init.h"
+
+uint32_t dram_vals[] = {
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000100, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00010101, 0x01010101, 0x000f0f01, 0x0f02020a,
+	0x00000000, 0x00010101, 0x00000100, 0x00000100, 0x00000000,
+	0x00000002, 0x01010000, 0x05060302, 0x06005003, 0x0a0000c8,
+	0x02009c40, 0x0000030c, 0x0036a609, 0x031a0612, 0x02030202,
+	0x00c8001c, 0x00000000, 0x00000000, 0x00012100, 0xffff0303,
+	0x00012100, 0xffff0303, 0x00012100, 0xffff0303, 0x00012100,
+	0xffff0303, 0x00000003, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000612, 0x01000F02, 0x06120612, 0x00000200,
+	0x00020007, 0xf5014b27, 0xf5014b27, 0xf5014b27, 0xf5014b27,
+	0x07000300, 0x07000300, 0x07000300, 0x07000300, 0x00000006,
+	0x00000000, 0x00000000, 0x01000000, 0x01020408, 0x08040201,
+	0x000f1133, 0x00000000, 0x00001f04, 0x00001f04, 0x00001f04,
+	0x00001f04, 0x00001f04, 0x00001f04, 0x00001f04, 0x00001f04,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00010000, 0x00020304, 0x00000004,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x01010000, 0x01000000, 0x03030000, 0x00010303,
+	0x01020202, 0x00000000, 0x02040303, 0x21002103, 0x00061200,
+	0x06120612, 0x04320432, 0x04320432, 0x00040004, 0x00040004,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00010001
+};
+
+void init_m28_200mhz_ddr2(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dram_vals); i++)
+		writel(dram_vals[i], MXS_DRAM_BASE + (4 * i));
+}
+
+void mx28_mem_init_clock(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/* Gate EMI clock */
+	writel(CLKCTRL_FRAC0_CLKGATEEMI,
+		&clkctrl_regs->hw_clkctrl_frac0_set);
+
+	/* EMI = 205MHz */
+	writel(CLKCTRL_FRAC0_EMIFRAC_MASK,
+		&clkctrl_regs->hw_clkctrl_frac0_set);
+	writel((0x2a << CLKCTRL_FRAC0_EMIFRAC_OFFSET) &
+		CLKCTRL_FRAC0_EMIFRAC_MASK,
+		&clkctrl_regs->hw_clkctrl_frac0_clr);
+
+	/* Ungate EMI clock */
+	writel(CLKCTRL_FRAC0_CLKGATEEMI,
+		&clkctrl_regs->hw_clkctrl_frac0_clr);
+
+	early_delay(11000);
+
+	writel((2 << CLKCTRL_EMI_DIV_EMI_OFFSET) |
+		(1 << CLKCTRL_EMI_DIV_XTAL_OFFSET),
+		&clkctrl_regs->hw_clkctrl_emi);
+
+	/* Unbypass EMI */
+	writel(CLKCTRL_CLKSEQ_BYPASS_EMI,
+		&clkctrl_regs->hw_clkctrl_clkseq_clr);
+
+	early_delay(10000);
+}
+
+void mx28_mem_setup_cpu_and_hbus(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/* CPU = 454MHz and ungate CPU clock */
+	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_frac0,
+		CLKCTRL_FRAC0_CPUFRAC_MASK | CLKCTRL_FRAC0_CLKGATECPU,
+		19 << CLKCTRL_FRAC0_CPUFRAC_OFFSET);
+
+	/* Set CPU bypass */
+	writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
+		&clkctrl_regs->hw_clkctrl_clkseq_set);
+
+	/* HBUS = 151MHz */
+	writel(CLKCTRL_HBUS_DIV_MASK, &clkctrl_regs->hw_clkctrl_hbus_set);
+	writel(((~3) << CLKCTRL_HBUS_DIV_OFFSET) & CLKCTRL_HBUS_DIV_MASK,
+		&clkctrl_regs->hw_clkctrl_hbus_clr);
+
+	early_delay(10000);
+
+	/* CPU clock divider = 1 */
+	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_cpu,
+			CLKCTRL_CPU_DIV_CPU_MASK, 1);
+
+	/* Disable CPU bypass */
+	writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
+		&clkctrl_regs->hw_clkctrl_clkseq_clr);
+}
+
+void mx28_mem_setup_vdda(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	writel((0xc << POWER_VDDACTRL_TRG_OFFSET) |
+		(0x7 << POWER_VDDACTRL_BO_OFFSET_OFFSET) |
+		POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW,
+		&power_regs->hw_power_vddactrl);
+}
+
+void mx28_mem_setup_vddd(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	writel((0x1c << POWER_VDDDCTRL_TRG_OFFSET) |
+		(0x7 << POWER_VDDDCTRL_BO_OFFSET_OFFSET) |
+		POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW,
+		&power_regs->hw_power_vdddctrl);
+}
+
+void mx28_mem_init(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	struct mx28_pinctrl_regs *pinctrl_regs =
+		(struct mx28_pinctrl_regs *)MXS_PINCTRL_BASE;
+
+	/* Set DDR2 mode */
+	writel(PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2,
+		&pinctrl_regs->hw_pinctrl_emi_ds_ctrl_set);
+
+	/* Power up PLL0 */
+	writel(CLKCTRL_PLL0CTRL0_POWER,
+		&clkctrl_regs->hw_clkctrl_pll0ctrl0_set);
+
+	early_delay(11000);
+
+	mx28_mem_init_clock();
+
+	mx28_mem_setup_vdda();
+
+	/*
+	 * Configure the DRAM registers
+	 */
+
+	/* Clear START bit from DRAM_CTL16 */
+	clrbits_le32(MXS_DRAM_BASE + 0x40, 1);
+
+	init_m28_200mhz_ddr2();
+
+	/* Clear SREFRESH bit from DRAM_CTL17 */
+	clrbits_le32(MXS_DRAM_BASE + 0x44, 1);
+
+	/* Set START bit in DRAM_CTL16 */
+	setbits_le32(MXS_DRAM_BASE + 0x40, 1);
+
+	/* Wait for bit 20 (DRAM init complete) in DRAM_CTL58 */
+	while (!(readl(MXS_DRAM_BASE + 0xe8) & (1 << 20)))
+		;
+
+	mx28_mem_setup_vddd();
+
+	early_delay(10000);
+
+	mx28_mem_setup_cpu_and_hbus();
+}
diff --git a/board/denx/m28evk/mmc_boot.c b/board/denx/m28evk/mmc_boot.c
new file mode 100644
index 0000000..86d3ab5
--- /dev/null
+++ b/board/denx/m28evk/mmc_boot.c
@@ -0,0 +1,273 @@
+/*
+ * Freescale i.MX28 Boot setup
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/io.h>
+#include <asm/arch/iomux-mx28.h>
+
+#include "m28_init.h"
+
+/*
+ * This delay function is intended to be used only in early stage of boot, where
+ * clock are not set up yet. The timer used here is reset on every boot and
+ * takes a few seconds to roll. The boot doesn't take that long, so to keep the
+ * code simple, it doesn't take rolling into consideration.
+ */
+#define	HW_DIGCTRL_MICROSECONDS	0x8001c0c0
+void early_delay(int delay)
+{
+	uint32_t st = readl(HW_DIGCTRL_MICROSECONDS);
+	st += delay;
+	while (st > readl(HW_DIGCTRL_MICROSECONDS))
+		;
+}
+
+#define	MUX_CONFIG_LED	(MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL)
+#define	MUX_CONFIG_LCD	(MXS_PAD_3V3 | MXS_PAD_4MA)
+#define	MUX_CONFIG_TSC	(MXS_PAD_3V3 | MXS_PAD_8MA | MXS_PAD_PULLUP)
+#define	MUX_CONFIG_SSP0	(MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_PULLUP)
+#define	MUX_CONFIG_SSP2	(MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_PULLUP)
+#define	MUX_CONFIG_GPMI	(MXS_PAD_1V8 | MXS_PAD_4MA | MXS_PAD_NOPULL)
+#define	MUX_CONFIG_ENET	(MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_PULLUP)
+#define	MUX_CONFIG_EMI	(MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_NOPULL)
+
+const iomux_cfg_t iomux_setup[] = {
+	/* LED */
+	MX28_PAD_ENET0_RXD3__GPIO_4_10 | MUX_CONFIG_LED,
+
+	/* framebuffer */
+	MX28_PAD_LCD_D00__LCD_D0 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D01__LCD_D1 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D02__LCD_D2 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D03__LCD_D3 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D04__LCD_D4 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D05__LCD_D5 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D06__LCD_D6 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D07__LCD_D7 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D08__LCD_D8 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D09__LCD_D9 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D10__LCD_D10 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D11__LCD_D11 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D12__LCD_D12 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D13__LCD_D13 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D14__LCD_D14 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D15__LCD_D15 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D16__LCD_D16 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D17__LCD_D17 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D18__LCD_D18 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D19__LCD_D19 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D20__LCD_D20 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D21__LCD_D21 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D22__LCD_D22 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D23__LCD_D23 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_RD_E__LCD_VSYNC | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_WR_RWN__LCD_HSYNC | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_RS__LCD_DOTCLK | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_CS__LCD_CS | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_VSYNC__LCD_VSYNC | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_HSYNC__LCD_HSYNC | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_DOTCLK__LCD_DOTCLK | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_ENABLE__GPIO_1_31 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_RESET__GPIO_3_30 | MUX_CONFIG_LCD,
+
+	/* UART1 */
+	MX28_PAD_PWM0__DUART_RX,
+	MX28_PAD_PWM1__DUART_TX,
+	MX28_PAD_AUART0_TX__DUART_RTS,
+	MX28_PAD_AUART0_RX__DUART_CTS,
+
+	/* UART2 */
+	MX28_PAD_AUART1_RX__AUART1_RX,
+	MX28_PAD_AUART1_TX__AUART1_TX,
+	MX28_PAD_AUART1_RTS__AUART1_RTS,
+	MX28_PAD_AUART1_CTS__AUART1_CTS,
+
+	/* CAN */
+	MX28_PAD_GPMI_RDY2__CAN0_TX,
+	MX28_PAD_GPMI_RDY3__CAN0_RX,
+
+	/* I2C */
+	MX28_PAD_I2C0_SCL__I2C0_SCL,
+	MX28_PAD_I2C0_SDA__I2C0_SDA,
+
+	/* TSC2007 */
+	MX28_PAD_SAIF0_MCLK__GPIO_3_20 | MUX_CONFIG_TSC,
+
+	/* MMC0 */
+	MX28_PAD_SSP0_DATA0__SSP0_D0 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA1__SSP0_D1 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA2__SSP0_D2 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA3__SSP0_D3 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA4__SSP0_D4 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA5__SSP0_D5 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA6__SSP0_D6 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA7__SSP0_D7 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_CMD__SSP0_CMD | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT |
+		(MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_NOPULL),
+	MX28_PAD_SSP0_SCK__SSP0_SCK |
+		(MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_NOPULL),
+	MX28_PAD_PWM3__GPIO_3_28 | MUX_CONFIG_SSP0,	/* Power .. FIXME */
+	MX28_PAD_AUART2_CTS__GPIO_3_10,	/* WP ... FIXME */
+
+	/* GPMI NAND */
+	MX28_PAD_GPMI_D00__GPMI_D0 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D01__GPMI_D1 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D02__GPMI_D2 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D03__GPMI_D3 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D04__GPMI_D4 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D05__GPMI_D5 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D06__GPMI_D6 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D07__GPMI_D7 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_CE0N__GPMI_CE0N | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_RDY0__GPMI_READY0 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_RDN__GPMI_RDN |
+		(MXS_PAD_1V8 | MXS_PAD_8MA | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_WRN__GPMI_WRN | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_ALE__GPMI_ALE | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_CLE__GPMI_CLE | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_RESETN__GPMI_RESETN | MUX_CONFIG_GPMI,
+
+	/* FEC Ethernet */
+	MX28_PAD_ENET0_MDC__ENET0_MDC | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_MDIO__ENET0_MDIO | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_RX_EN__ENET0_RX_EN | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_TX_EN__ENET0_TX_EN | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_RXD0__ENET0_RXD0 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_RXD1__ENET0_RXD1 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_TXD0__ENET0_TXD0 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_TXD1__ENET0_TXD1 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET_CLK__CLKCTRL_ENET | MUX_CONFIG_ENET,
+
+	MX28_PAD_ENET0_COL__ENET1_TX_EN | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_CRS__ENET1_RX_EN | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_RXD2__ENET1_RXD0 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_RXD3__ENET1_RXD1 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_TXD2__ENET1_TXD0 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_TXD3__ENET1_TXD1 | MUX_CONFIG_ENET,
+
+	/* I2C */
+	MX28_PAD_I2C0_SCL__I2C0_SCL,
+	MX28_PAD_I2C0_SDA__I2C0_SDA,
+
+	/* EMI */
+	MX28_PAD_EMI_D00__EMI_DATA0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D01__EMI_DATA1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D02__EMI_DATA2 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D03__EMI_DATA3 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D04__EMI_DATA4 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D05__EMI_DATA5 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D06__EMI_DATA6 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D07__EMI_DATA7 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D08__EMI_DATA8 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D09__EMI_DATA9 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D10__EMI_DATA10 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D11__EMI_DATA11 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D12__EMI_DATA12 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D13__EMI_DATA13 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D14__EMI_DATA14 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D15__EMI_DATA15 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_ODT0__EMI_ODT0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DQM0__EMI_DQM0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_ODT1__EMI_ODT1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DQM1__EMI_DQM1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DDR_OPEN_FB__EMI_DDR_OPEN_FEEDBACK | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_CLK__EMI_CLK | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DQS0__EMI_DQS0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DQS1__EMI_DQS1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DDR_OPEN__EMI_DDR_OPEN | MUX_CONFIG_EMI,
+
+	MX28_PAD_EMI_A00__EMI_ADDR0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A01__EMI_ADDR1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A02__EMI_ADDR2 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A03__EMI_ADDR3 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A04__EMI_ADDR4 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A05__EMI_ADDR5 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A06__EMI_ADDR6 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A07__EMI_ADDR7 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A08__EMI_ADDR8 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A09__EMI_ADDR9 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A10__EMI_ADDR10 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A11__EMI_ADDR11 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A12__EMI_ADDR12 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A13__EMI_ADDR13 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A14__EMI_ADDR14 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_BA0__EMI_BA0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_BA1__EMI_BA1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_BA2__EMI_BA2 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_CASN__EMI_CASN | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_RASN__EMI_RASN | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_WEN__EMI_WEN | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_CE0N__EMI_CE0N | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_CE1N__EMI_CE1N | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_CKE__EMI_CKE | MUX_CONFIG_EMI,
+
+	/* SPI2 (for flash) */
+	MX28_PAD_SSP2_SCK__SSP2_SCK | MUX_CONFIG_SSP2,
+	MX28_PAD_SSP2_MOSI__SSP2_CMD | MUX_CONFIG_SSP2,
+	MX28_PAD_SSP2_MISO__SSP2_D0 | MUX_CONFIG_SSP2,
+	MX28_PAD_SSP2_SS0__SSP2_D3 |
+		(MXS_PAD_3V3 | MXS_PAD_8MA | MXS_PAD_PULLUP),
+};
+
+void board_init_ll(void)
+{
+	mxs_iomux_setup_multiple_pads(iomux_setup, ARRAY_SIZE(iomux_setup));
+	mx28_power_init();
+	mx28_mem_init();
+	mx28_power_wait_pswitch();
+}
+
+/* Support aparatus */
+inline void board_init_f(unsigned long bootflag)
+{
+	for (;;)
+		;
+}
+
+inline void board_init_r(gd_t *id, ulong dest_addr)
+{
+	for (;;)
+		;
+}
+
+inline int printf(const char *fmt, ...)
+{
+	return 0;
+}
+
+inline void __coloured_LED_init(void) {}
+inline void __red_LED_on(void) {}
+void coloured_LED_init(void)
+	__attribute__((weak, alias("__coloured_LED_init")));
+void red_LED_on(void)
+	__attribute__((weak, alias("__red_LED_on")));
+void hang(void) __attribute__ ((noreturn));
+void hang(void)
+{
+	for (;;)
+		;
+}
diff --git a/board/denx/m28evk/power_init.c b/board/denx/m28evk/power_init.c
new file mode 100644
index 0000000..27322b4
--- /dev/null
+++ b/board/denx/m28evk/power_init.c
@@ -0,0 +1,913 @@
+/*
+ * Freescale i.MX28 Boot PMIC init
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+
+#include "m28_init.h"
+
+void mx28_power_clock2xtal(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/* Set XTAL as CPU reference clock */
+	writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
+		&clkctrl_regs->hw_clkctrl_clkseq_set);
+}
+
+void mx28_power_clock2pll(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	writel(CLKCTRL_PLL0CTRL0_POWER,
+		&clkctrl_regs->hw_clkctrl_pll0ctrl0_set);
+	early_delay(100);
+	writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
+		&clkctrl_regs->hw_clkctrl_clkseq_clr);
+}
+
+void mx28_power_clear_auto_restart(void)
+{
+	struct mx28_rtc_regs *rtc_regs =
+		(struct mx28_rtc_regs *)MXS_RTC_BASE;
+
+	writel(RTC_CTRL_SFTRST, &rtc_regs->hw_rtc_ctrl_clr);
+	while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_SFTRST)
+		;
+
+	writel(RTC_CTRL_CLKGATE, &rtc_regs->hw_rtc_ctrl_clr);
+	while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_CLKGATE)
+		;
+
+	/*
+	 * Due to the hardware design bug of mx28 EVK-A
+	 * we need to set the AUTO_RESTART bit.
+	 */
+	if (readl(&rtc_regs->hw_rtc_persistent0) & RTC_PERSISTENT0_AUTO_RESTART)
+		return;
+
+	while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK)
+		;
+
+	setbits_le32(&rtc_regs->hw_rtc_persistent0,
+			RTC_PERSISTENT0_AUTO_RESTART);
+	writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_set);
+	writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_clr);
+	while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK)
+		;
+	while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_STALE_REGS_MASK)
+		;
+}
+
+void mx28_power_set_linreg(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/* Set linear regulator 25mV below switching converter */
+	clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+			POWER_VDDDCTRL_LINREG_OFFSET_MASK,
+			POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
+
+	clrsetbits_le32(&power_regs->hw_power_vddactrl,
+			POWER_VDDACTRL_LINREG_OFFSET_MASK,
+			POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW);
+
+	clrsetbits_le32(&power_regs->hw_power_vddioctrl,
+			POWER_VDDIOCTRL_LINREG_OFFSET_MASK,
+			POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW);
+}
+
+void mx28_power_setup_5v_detect(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/* Start 5V detection */
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+			POWER_5VCTRL_VBUSVALID_TRSH_MASK,
+			POWER_5VCTRL_VBUSVALID_TRSH_4V4 |
+			POWER_5VCTRL_PWRUP_VBUS_CMPS);
+}
+
+void mx28_src_power_init(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/* Improve efficieny and reduce transient ripple */
+	writel(POWER_LOOPCTRL_TOGGLE_DIF | POWER_LOOPCTRL_EN_CM_HYST |
+		POWER_LOOPCTRL_EN_DF_HYST, &power_regs->hw_power_loopctrl_set);
+
+	clrsetbits_le32(&power_regs->hw_power_dclimits,
+			POWER_DCLIMITS_POSLIMIT_BUCK_MASK,
+			0x30 << POWER_DCLIMITS_POSLIMIT_BUCK_OFFSET);
+
+	setbits_le32(&power_regs->hw_power_battmonitor,
+			POWER_BATTMONITOR_EN_BATADJ);
+
+	/* Increase the RCSCALE level for quick DCDC response to dynamic load */
+	clrsetbits_le32(&power_regs->hw_power_loopctrl,
+			POWER_LOOPCTRL_EN_RCSCALE_MASK,
+			POWER_LOOPCTRL_RCSCALE_THRESH |
+			POWER_LOOPCTRL_EN_RCSCALE_8X);
+
+	clrsetbits_le32(&power_regs->hw_power_minpwr,
+			POWER_MINPWR_HALFFETS, POWER_MINPWR_DOUBLE_FETS);
+
+	/* 5V to battery handoff ... FIXME */
+	setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
+	early_delay(30);
+	clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
+}
+
+void mx28_power_init_4p2_params(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/* Setup 4P2 parameters */
+	clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
+		POWER_DCDC4P2_CMPTRIP_MASK | POWER_DCDC4P2_TRG_MASK,
+		POWER_DCDC4P2_TRG_4V2 | (31 << POWER_DCDC4P2_CMPTRIP_OFFSET));
+
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+		POWER_5VCTRL_HEADROOM_ADJ_MASK,
+		0x4 << POWER_5VCTRL_HEADROOM_ADJ_OFFSET);
+
+	clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
+		POWER_DCDC4P2_DROPOUT_CTRL_MASK,
+		POWER_DCDC4P2_DROPOUT_CTRL_100MV |
+		POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL);
+
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+		POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
+		0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
+}
+
+void mx28_enable_4p2_dcdc_input(int xfer)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp, vbus_thresh, vbus_5vdetect, pwd_bo;
+	uint32_t prev_5v_brnout, prev_5v_droop;
+
+	prev_5v_brnout = readl(&power_regs->hw_power_5vctrl) &
+				POWER_5VCTRL_PWDN_5VBRNOUT;
+	prev_5v_droop = readl(&power_regs->hw_power_ctrl) &
+				POWER_CTRL_ENIRQ_VDD5V_DROOP;
+
+	clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_PWDN_5VBRNOUT);
+	writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
+		&power_regs->hw_power_reset);
+
+	clrbits_le32(&power_regs->hw_power_ctrl, POWER_CTRL_ENIRQ_VDD5V_DROOP);
+
+	if (xfer && (readl(&power_regs->hw_power_5vctrl) &
+			POWER_5VCTRL_ENABLE_DCDC)) {
+		return;
+	}
+
+	/*
+	 * Recording orignal values that will be modified temporarlily
+	 * to handle a chip bug. See chip errata for CQ ENGR00115837
+	 */
+	tmp = readl(&power_regs->hw_power_5vctrl);
+	vbus_thresh = tmp & POWER_5VCTRL_VBUSVALID_TRSH_MASK;
+	vbus_5vdetect = tmp & POWER_5VCTRL_VBUSVALID_5VDETECT;
+
+	pwd_bo = readl(&power_regs->hw_power_minpwr) & POWER_MINPWR_PWD_BO;
+
+	/*
+	 * Disable mechanisms that get erroneously tripped by when setting
+	 * the DCDC4P2 EN_DCDC
+	 */
+	clrbits_le32(&power_regs->hw_power_5vctrl,
+		POWER_5VCTRL_VBUSVALID_5VDETECT |
+		POWER_5VCTRL_VBUSVALID_TRSH_MASK);
+
+	writel(POWER_MINPWR_PWD_BO, &power_regs->hw_power_minpwr_set);
+
+	if (xfer) {
+		setbits_le32(&power_regs->hw_power_5vctrl,
+				POWER_5VCTRL_DCDC_XFER);
+		early_delay(20);
+		clrbits_le32(&power_regs->hw_power_5vctrl,
+				POWER_5VCTRL_DCDC_XFER);
+
+		setbits_le32(&power_regs->hw_power_5vctrl,
+				POWER_5VCTRL_ENABLE_DCDC);
+	} else {
+		setbits_le32(&power_regs->hw_power_dcdc4p2,
+				POWER_DCDC4P2_ENABLE_DCDC);
+	}
+
+	early_delay(25);
+
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+			POWER_5VCTRL_VBUSVALID_TRSH_MASK, vbus_thresh);
+
+	if (vbus_5vdetect)
+		writel(vbus_5vdetect, &power_regs->hw_power_5vctrl_set);
+
+	if (!pwd_bo)
+		clrbits_le32(&power_regs->hw_power_minpwr, POWER_MINPWR_PWD_BO);
+
+	while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ)
+		clrbits_le32(&power_regs->hw_power_ctrl,
+				POWER_CTRL_VBUS_VALID_IRQ);
+
+	if (prev_5v_brnout) {
+		writel(POWER_5VCTRL_PWDN_5VBRNOUT,
+			&power_regs->hw_power_5vctrl_set);
+		writel(POWER_RESET_UNLOCK_KEY,
+			&power_regs->hw_power_reset);
+	} else {
+		writel(POWER_5VCTRL_PWDN_5VBRNOUT,
+			&power_regs->hw_power_5vctrl_clr);
+		writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
+			&power_regs->hw_power_reset);
+	}
+
+	while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VDD5V_DROOP_IRQ)
+		clrbits_le32(&power_regs->hw_power_ctrl,
+				POWER_CTRL_VDD5V_DROOP_IRQ);
+
+	if (prev_5v_droop)
+		clrbits_le32(&power_regs->hw_power_ctrl,
+				POWER_CTRL_ENIRQ_VDD5V_DROOP);
+	else
+		setbits_le32(&power_regs->hw_power_ctrl,
+				POWER_CTRL_ENIRQ_VDD5V_DROOP);
+}
+
+void mx28_power_init_4p2_regulator(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp, tmp2;
+
+	setbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_ENABLE_4P2);
+
+	writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_set);
+
+	writel(POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
+		&power_regs->hw_power_5vctrl_clr);
+	clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_TRG_MASK);
+
+	/* Power up the 4p2 rail and logic/control */
+	writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+		&power_regs->hw_power_5vctrl_clr);
+
+	/*
+	 * Start charging up the 4p2 capacitor. We ramp of this charge
+	 * gradually to avoid large inrush current from the 5V cable which can
+	 * cause transients/problems
+	 */
+	mx28_enable_4p2_dcdc_input(0);
+
+	if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) {
+		/*
+		 * If we arrived here, we were unable to recover from mx23 chip
+		 * errata 5837. 4P2 is disabled and sufficient battery power is
+		 * not present. Exiting to not enable DCDC power during 5V
+		 * connected state.
+		 */
+		clrbits_le32(&power_regs->hw_power_dcdc4p2,
+			POWER_DCDC4P2_ENABLE_DCDC);
+		writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+			&power_regs->hw_power_5vctrl_set);
+		hang();
+	}
+
+	/*
+	 * Here we set the 4p2 brownout level to something very close to 4.2V.
+	 * We then check the brownout status. If the brownout status is false,
+	 * the voltage is already close to the target voltage of 4.2V so we
+	 * can go ahead and set the 4P2 current limit to our max target limit.
+	 * If the brownout status is true, we need to ramp us the current limit
+	 * so that we don't cause large inrush current issues. We step up the
+	 * current limit until the brownout status is false or until we've
+	 * reached our maximum defined 4p2 current limit.
+	 */
+	clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
+			POWER_DCDC4P2_BO_MASK,
+			22 << POWER_DCDC4P2_BO_OFFSET);	/* 4.15V */
+
+	if (!(readl(&power_regs->hw_power_sts) & POWER_STS_DCDC_4P2_BO)) {
+		setbits_le32(&power_regs->hw_power_5vctrl,
+			0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
+	} else {
+		tmp = (readl(&power_regs->hw_power_5vctrl) &
+			POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK) >>
+			POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET;
+		while (tmp < 0x3f) {
+			if (!(readl(&power_regs->hw_power_sts) &
+					POWER_STS_DCDC_4P2_BO)) {
+				tmp = readl(&power_regs->hw_power_5vctrl);
+				tmp |= POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK;
+				early_delay(100);
+				writel(tmp, &power_regs->hw_power_5vctrl);
+				break;
+			} else {
+				tmp++;
+				tmp2 = readl(&power_regs->hw_power_5vctrl);
+				tmp2 &= ~POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK;
+				tmp2 |= tmp <<
+					POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET;
+				writel(tmp2, &power_regs->hw_power_5vctrl);
+				early_delay(100);
+			}
+		}
+	}
+
+	clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_BO_MASK);
+	writel(POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+}
+
+void mx28_power_init_dcdc_4p2_source(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	if (!(readl(&power_regs->hw_power_dcdc4p2) &
+		POWER_DCDC4P2_ENABLE_DCDC)) {
+		hang();
+	}
+
+	mx28_enable_4p2_dcdc_input(1);
+
+	if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) {
+		clrbits_le32(&power_regs->hw_power_dcdc4p2,
+			POWER_DCDC4P2_ENABLE_DCDC);
+		writel(POWER_5VCTRL_ENABLE_DCDC,
+			&power_regs->hw_power_5vctrl_clr);
+		writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+			&power_regs->hw_power_5vctrl_set);
+	}
+}
+
+void mx28_power_enable_4p2(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t vdddctrl, vddactrl, vddioctrl;
+	uint32_t tmp;
+
+	vdddctrl = readl(&power_regs->hw_power_vdddctrl);
+	vddactrl = readl(&power_regs->hw_power_vddactrl);
+	vddioctrl = readl(&power_regs->hw_power_vddioctrl);
+
+	setbits_le32(&power_regs->hw_power_vdddctrl,
+		POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG |
+		POWER_VDDDCTRL_PWDN_BRNOUT);
+
+	setbits_le32(&power_regs->hw_power_vddactrl,
+		POWER_VDDACTRL_DISABLE_FET | POWER_VDDACTRL_ENABLE_LINREG |
+		POWER_VDDACTRL_PWDN_BRNOUT);
+
+	setbits_le32(&power_regs->hw_power_vddioctrl,
+		POWER_VDDIOCTRL_DISABLE_FET | POWER_VDDIOCTRL_PWDN_BRNOUT);
+
+	mx28_power_init_4p2_params();
+	mx28_power_init_4p2_regulator();
+
+	/* Shutdown battery (none present) */
+	clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_BO_MASK);
+	writel(POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+	writel(POWER_CTRL_ENIRQ_DCDC4P2_BO, &power_regs->hw_power_ctrl_clr);
+
+	mx28_power_init_dcdc_4p2_source();
+
+	writel(vdddctrl, &power_regs->hw_power_vdddctrl);
+	early_delay(20);
+	writel(vddactrl, &power_regs->hw_power_vddactrl);
+	early_delay(20);
+	writel(vddioctrl, &power_regs->hw_power_vddioctrl);
+
+	/*
+	 * Check if FET is enabled on either powerout and if so,
+	 * disable load.
+	 */
+	tmp = 0;
+	tmp |= !(readl(&power_regs->hw_power_vdddctrl) &
+			POWER_VDDDCTRL_DISABLE_FET);
+	tmp |= !(readl(&power_regs->hw_power_vddactrl) &
+			POWER_VDDACTRL_DISABLE_FET);
+	tmp |= !(readl(&power_regs->hw_power_vddioctrl) &
+			POWER_VDDIOCTRL_DISABLE_FET);
+	if (tmp)
+		writel(POWER_CHARGE_ENABLE_LOAD,
+			&power_regs->hw_power_charge_clr);
+}
+
+void mx28_boot_valid_5v(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/*
+	 * Use VBUSVALID level instead of VDD5V_GT_VDDIO level to trigger a 5V
+	 * disconnect event. FIXME
+	 */
+	writel(POWER_5VCTRL_VBUSVALID_5VDETECT,
+		&power_regs->hw_power_5vctrl_set);
+
+	/* Configure polarity to check for 5V disconnection. */
+	writel(POWER_CTRL_POLARITY_VBUSVALID |
+		POWER_CTRL_POLARITY_VDD5V_GT_VDDIO,
+		&power_regs->hw_power_ctrl_clr);
+
+	writel(POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_VDD5V_GT_VDDIO_IRQ,
+		&power_regs->hw_power_ctrl_clr);
+
+	mx28_power_enable_4p2();
+}
+
+void mx28_powerdown(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	writel(POWER_RESET_UNLOCK_KEY, &power_regs->hw_power_reset);
+	writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
+		&power_regs->hw_power_reset);
+}
+
+void mx28_handle_5v_conflict(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp;
+
+	setbits_le32(&power_regs->hw_power_vddioctrl,
+			POWER_VDDIOCTRL_BO_OFFSET_MASK);
+
+	for (;;) {
+		tmp = readl(&power_regs->hw_power_sts);
+
+		if (tmp & POWER_STS_VDDIO_BO) {
+			mx28_powerdown();
+			break;
+		}
+
+		if (tmp & POWER_STS_VDD5V_GT_VDDIO) {
+			mx28_boot_valid_5v();
+			break;
+		} else {
+			mx28_powerdown();
+			break;
+		}
+	}
+}
+
+int mx28_get_batt_volt(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t volt = readl(&power_regs->hw_power_battmonitor);
+	volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
+	volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
+	volt *= 8;
+	return volt;
+}
+
+int mx28_is_batt_ready(void)
+{
+	return (mx28_get_batt_volt() >= 3600);
+}
+
+void mx28_5v_boot(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/*
+	 * NOTE: In original IMX-Bootlets, this also checks for VBUSVALID,
+	 * but their implementation always returns 1 so we omit it here.
+	 */
+	if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+		mx28_boot_valid_5v();
+		return;
+	}
+
+	early_delay(1000);
+	if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+		mx28_boot_valid_5v();
+		return;
+	}
+
+	mx28_handle_5v_conflict();
+}
+
+void mx28_init_batt_bo(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/* Brownout at 3V */
+	clrsetbits_le32(&power_regs->hw_power_battmonitor,
+		POWER_BATTMONITOR_BRWNOUT_LVL_MASK,
+		15 << POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET);
+
+	writel(POWER_CTRL_BATT_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+	writel(POWER_CTRL_ENIRQ_BATT_BO, &power_regs->hw_power_ctrl_clr);
+}
+
+void mx28_switch_vddd_to_dcdc_source(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+		POWER_VDDDCTRL_LINREG_OFFSET_MASK,
+		POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
+
+	clrbits_le32(&power_regs->hw_power_vdddctrl,
+		POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG |
+		POWER_VDDDCTRL_DISABLE_STEPPING);
+}
+
+int mx28_is_batt_good(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t volt;
+
+	volt = readl(&power_regs->hw_power_battmonitor);
+	volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
+	volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
+	volt *= 8;
+
+	if ((volt >= 2400) && (volt <= 4300))
+		return 1;
+
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+		POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
+		0x3 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
+	writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+		&power_regs->hw_power_5vctrl_clr);
+
+	clrsetbits_le32(&power_regs->hw_power_charge,
+		POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
+		POWER_CHARGE_STOP_ILIMIT_10MA | 0x3);
+
+	writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_clr);
+	writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+		&power_regs->hw_power_5vctrl_clr);
+
+	early_delay(500000);
+
+	volt = readl(&power_regs->hw_power_battmonitor);
+	volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
+	volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
+	volt *= 8;
+
+	if (volt >= 3500)
+		return 0;
+
+	if (volt >= 2400)
+		return 1;
+
+	writel(POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
+		&power_regs->hw_power_charge_clr);
+	writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_set);
+
+	return 0;
+}
+
+void mx28_power_configure_power_source(void)
+{
+	mx28_src_power_init();
+
+	mx28_5v_boot();
+	mx28_power_clock2pll();
+
+	mx28_init_batt_bo();
+	mx28_switch_vddd_to_dcdc_source();
+}
+
+void mx28_enable_output_rail_protection(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
+		POWER_CTRL_VDDIO_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+
+	setbits_le32(&power_regs->hw_power_vdddctrl,
+			POWER_VDDDCTRL_PWDN_BRNOUT);
+
+	setbits_le32(&power_regs->hw_power_vddactrl,
+			POWER_VDDACTRL_PWDN_BRNOUT);
+
+	setbits_le32(&power_regs->hw_power_vddioctrl,
+			POWER_VDDIOCTRL_PWDN_BRNOUT);
+}
+
+int mx28_get_vddio_power_source_off(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp;
+
+	if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+		tmp = readl(&power_regs->hw_power_vddioctrl);
+		if (tmp & POWER_VDDIOCTRL_DISABLE_FET) {
+			if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
+				POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
+				return 1;
+			}
+		}
+
+		if (!(readl(&power_regs->hw_power_5vctrl) &
+			POWER_5VCTRL_ENABLE_DCDC)) {
+			if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
+				POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
+				return 1;
+			}
+		}
+	}
+
+	return 0;
+
+}
+
+int mx28_get_vddd_power_source_off(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp;
+
+	tmp = readl(&power_regs->hw_power_vdddctrl);
+	if (tmp & POWER_VDDDCTRL_DISABLE_FET) {
+		if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
+			POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
+			return 1;
+		}
+	}
+
+	if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+		if (!(readl(&power_regs->hw_power_5vctrl) &
+			POWER_5VCTRL_ENABLE_DCDC)) {
+			return 1;
+		}
+	}
+
+	if (!(tmp & POWER_VDDDCTRL_ENABLE_LINREG)) {
+		if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
+			POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW) {
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+void mx28_power_set_vddio(uint32_t new_target, uint32_t new_brownout)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t cur_target, diff, bo_int = 0;
+	uint32_t powered_by_linreg = 0;
+
+	new_brownout = new_target - new_brownout;
+
+	cur_target = readl(&power_regs->hw_power_vddioctrl);
+	cur_target &= POWER_VDDIOCTRL_TRG_MASK;
+	cur_target *= 50;	/* 50 mV step*/
+	cur_target += 2800;	/* 2800 mV lowest */
+
+	powered_by_linreg = mx28_get_vddio_power_source_off();
+	if (new_target > cur_target) {
+
+		if (powered_by_linreg) {
+			bo_int = readl(&power_regs->hw_power_vddioctrl);
+			clrbits_le32(&power_regs->hw_power_vddioctrl,
+					POWER_CTRL_ENIRQ_VDDIO_BO);
+		}
+
+		setbits_le32(&power_regs->hw_power_vddioctrl,
+				POWER_VDDIOCTRL_BO_OFFSET_MASK);
+		do {
+			if (new_target - cur_target > 100)
+				diff = cur_target + 100;
+			else
+				diff = new_target;
+
+			diff -= 2800;
+			diff /= 50;
+
+			clrsetbits_le32(&power_regs->hw_power_vddioctrl,
+				POWER_VDDIOCTRL_TRG_MASK, diff);
+
+			if (powered_by_linreg)
+				early_delay(1500);
+			else {
+				while (!(readl(&power_regs->hw_power_sts) &
+					POWER_STS_DC_OK))
+					;
+
+			}
+
+			cur_target = readl(&power_regs->hw_power_vddioctrl);
+			cur_target &= POWER_VDDIOCTRL_TRG_MASK;
+			cur_target *= 50;	/* 50 mV step*/
+			cur_target += 2800;	/* 2800 mV lowest */
+		} while (new_target > cur_target);
+
+		if (powered_by_linreg) {
+			writel(POWER_CTRL_VDDIO_BO_IRQ,
+				&power_regs->hw_power_ctrl_clr);
+			if (bo_int & POWER_CTRL_ENIRQ_VDDIO_BO)
+				setbits_le32(&power_regs->hw_power_vddioctrl,
+						POWER_CTRL_ENIRQ_VDDIO_BO);
+		}
+	} else {
+		do {
+			if (cur_target - new_target > 100)
+				diff = cur_target - 100;
+			else
+				diff = new_target;
+
+			diff -= 2800;
+			diff /= 50;
+
+			clrsetbits_le32(&power_regs->hw_power_vddioctrl,
+				POWER_VDDIOCTRL_TRG_MASK, diff);
+
+			if (powered_by_linreg)
+				early_delay(1500);
+			else {
+				while (!(readl(&power_regs->hw_power_sts) &
+					POWER_STS_DC_OK))
+					;
+
+			}
+
+			cur_target = readl(&power_regs->hw_power_vddioctrl);
+			cur_target &= POWER_VDDIOCTRL_TRG_MASK;
+			cur_target *= 50;	/* 50 mV step*/
+			cur_target += 2800;	/* 2800 mV lowest */
+		} while (new_target < cur_target);
+	}
+
+	clrsetbits_le32(&power_regs->hw_power_vddioctrl,
+			POWER_VDDDCTRL_BO_OFFSET_MASK,
+			new_brownout << POWER_VDDDCTRL_BO_OFFSET_OFFSET);
+}
+
+void mx28_power_set_vddd(uint32_t new_target, uint32_t new_brownout)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t cur_target, diff, bo_int = 0;
+	uint32_t powered_by_linreg = 0;
+
+	new_brownout = new_target - new_brownout;
+
+	cur_target = readl(&power_regs->hw_power_vdddctrl);
+	cur_target &= POWER_VDDDCTRL_TRG_MASK;
+	cur_target *= 25;	/* 25 mV step*/
+	cur_target += 800;	/* 800 mV lowest */
+
+	powered_by_linreg = mx28_get_vddd_power_source_off();
+	if (new_target > cur_target) {
+		if (powered_by_linreg) {
+			bo_int = readl(&power_regs->hw_power_vdddctrl);
+			clrbits_le32(&power_regs->hw_power_vdddctrl,
+					POWER_CTRL_ENIRQ_VDDD_BO);
+		}
+
+		setbits_le32(&power_regs->hw_power_vdddctrl,
+				POWER_VDDDCTRL_BO_OFFSET_MASK);
+
+		do {
+			if (new_target - cur_target > 100)
+				diff = cur_target + 100;
+			else
+				diff = new_target;
+
+			diff -= 800;
+			diff /= 25;
+
+			clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+				POWER_VDDDCTRL_TRG_MASK, diff);
+
+			if (powered_by_linreg)
+				early_delay(1500);
+			else {
+				while (!(readl(&power_regs->hw_power_sts) &
+					POWER_STS_DC_OK))
+					;
+
+			}
+
+			cur_target = readl(&power_regs->hw_power_vdddctrl);
+			cur_target &= POWER_VDDDCTRL_TRG_MASK;
+			cur_target *= 25;	/* 25 mV step*/
+			cur_target += 800;	/* 800 mV lowest */
+		} while (new_target > cur_target);
+
+		if (powered_by_linreg) {
+			writel(POWER_CTRL_VDDD_BO_IRQ,
+				&power_regs->hw_power_ctrl_clr);
+			if (bo_int & POWER_CTRL_ENIRQ_VDDD_BO)
+				setbits_le32(&power_regs->hw_power_vdddctrl,
+						POWER_CTRL_ENIRQ_VDDD_BO);
+		}
+	} else {
+		do {
+			if (cur_target - new_target > 100)
+				diff = cur_target - 100;
+			else
+				diff = new_target;
+
+			diff -= 800;
+			diff /= 25;
+
+			clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+					POWER_VDDDCTRL_TRG_MASK, diff);
+
+			if (powered_by_linreg)
+				early_delay(1500);
+			else {
+				while (!(readl(&power_regs->hw_power_sts) &
+					POWER_STS_DC_OK))
+					;
+
+			}
+
+			cur_target = readl(&power_regs->hw_power_vdddctrl);
+			cur_target &= POWER_VDDDCTRL_TRG_MASK;
+			cur_target *= 25;	/* 25 mV step*/
+			cur_target += 800;	/* 800 mV lowest */
+		} while (new_target < cur_target);
+	}
+
+	clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+			POWER_VDDDCTRL_BO_OFFSET_MASK,
+			new_brownout << POWER_VDDDCTRL_BO_OFFSET_OFFSET);
+}
+
+void mx28_power_init(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	mx28_power_clock2xtal();
+	mx28_power_clear_auto_restart();
+	mx28_power_set_linreg();
+	mx28_power_setup_5v_detect();
+	mx28_power_configure_power_source();
+	mx28_enable_output_rail_protection();
+
+	mx28_power_set_vddio(3300, 3150);
+
+	mx28_power_set_vddd(1350, 1200);
+
+	writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
+		POWER_CTRL_VDDIO_BO_IRQ | POWER_CTRL_VDD5V_DROOP_IRQ |
+		POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_BATT_BO_IRQ |
+		POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+
+	writel(POWER_5VCTRL_PWDN_5VBRNOUT, &power_regs->hw_power_5vctrl_set);
+
+	early_delay(1000);
+}
+
+#ifdef	CONFIG_SPL_MX28_PSWITCH_WAIT
+void mx28_power_wait_pswitch(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	while (!(readl(&power_regs->hw_power_sts) & POWER_STS_PSWITCH_MASK))
+		;
+}
+#endif
diff --git a/board/denx/m28evk/start.S b/board/denx/m28evk/start.S
new file mode 100644
index 0000000..cf67599
--- /dev/null
+++ b/board/denx/m28evk/start.S
@@ -0,0 +1,396 @@
+/*
+ *  armboot - Startup Code for ARM926EJS CPU-core
+ *
+ *  Copyright (c) 2003  Texas Instruments
+ *
+ *  ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------
+ *
+ *  Copyright (c) 2001	Marius Groger <mag@sysgo.de>
+ *  Copyright (c) 2002	Alex Zupke <azu@sysgo.de>
+ *  Copyright (c) 2002	Gary Jennejohn <garyj@denx.de>
+ *  Copyright (c) 2003	Richard Woodruff <r-woodruff2@ti.com>
+ *  Copyright (c) 2003	Kshitij <kshitij@ti.com>
+ *  Copyright (c) 2010	Albert Aribaud <albert.u.boot@aribaud.net>
+ *
+ * Change to support call back into iMX28 bootrom
+ * Copyright (c) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <common.h>
+#include <version.h>
+
+#if defined(CONFIG_OMAP1610)
+#include <./configs/omap1510.h>
+#elif defined(CONFIG_OMAP730)
+#include <./configs/omap730.h>
+#endif
+
+/*
+ *************************************************************************
+ *
+ * Jump vector table as in table 3.1 in [1]
+ *
+ *************************************************************************
+ */
+
+
+.globl _start
+_start:
+	b	reset
+#ifdef CONFIG_SPL_BUILD
+/* No exception handlers in preloader */
+	ldr	pc, _hang
+	ldr	pc, _hang
+	ldr	pc, _hang
+	ldr	pc, _hang
+	b	reset
+	ldr	pc, _hang
+	ldr	pc, _hang
+
+_hang:
+	.word	do_hang
+/* pad to 64 byte boundary */
+	.word	0x12345678
+	.word	0x12345678
+	.word	0x12345678
+	.word	0x12345678
+	.word	0x12345678
+	.word	0x12345678
+	.word	0x12345678
+#else
+	ldr	pc, _undefined_instruction
+	ldr	pc, _software_interrupt
+	ldr	pc, _prefetch_abort
+	ldr	pc, _data_abort
+	ldr	pc, _not_used
+	ldr	pc, _irq
+	ldr	pc, _fiq
+
+_undefined_instruction:
+	.word undefined_instruction
+_software_interrupt:
+	.word software_interrupt
+_prefetch_abort:
+	.word prefetch_abort
+_data_abort:
+	.word data_abort
+_not_used:
+	.word not_used
+_irq:
+	.word irq
+_fiq:
+	.word fiq
+
+#endif	/* CONFIG_SPL_BUILD */
+	.balignl 16,0xdeadbeef
+
+
+/*
+ *************************************************************************
+ *
+ * Startup Code (reset vector)
+ *
+ * do important init only if we don't start from memory!
+ * setup Memory and board specific bits prior to relocation.
+ * relocate armboot to ram
+ * setup stack
+ *
+ *************************************************************************
+ */
+
+.globl _TEXT_BASE
+_TEXT_BASE:
+	.word	CONFIG_SYS_TEXT_BASE
+
+/*
+ * These are defined in the board-specific linker script.
+ * Subtracting _start from them lets the linker put their
+ * relative position in the executable instead of leaving
+ * them null.
+ */
+.globl _bss_start_ofs
+_bss_start_ofs:
+	.word __bss_start - _start
+
+.globl _bss_end_ofs
+_bss_end_ofs:
+	.word __bss_end__ - _start
+
+.globl _end_ofs
+_end_ofs:
+	.word _end - _start
+
+#ifdef CONFIG_USE_IRQ
+/* IRQ stack memory (calculated at run-time) */
+.globl IRQ_STACK_START
+IRQ_STACK_START:
+	.word	0x0badc0de
+
+/* IRQ stack memory (calculated at run-time) */
+.globl FIQ_STACK_START
+FIQ_STACK_START:
+	.word 0x0badc0de
+#endif
+
+/* IRQ stack memory (calculated at run-time) + 8 bytes */
+.globl IRQ_STACK_START_IN
+IRQ_STACK_START_IN:
+	.word	0x0badc0de
+
+/*
+ * the actual reset code
+ */
+
+reset:
+	/*
+	 * Store all registers on old stack pointer, this will allow us later to
+	 * return to the BootROM and let the BootROM load U-Boot into RAM.
+	 */
+	push	{r0-r12,r14}
+
+	/*
+	 * set the cpu to SVC32 mode
+	 */
+	mrs	r0,cpsr
+	bic	r0,r0,#0x1f
+	orr	r0,r0,#0xd3
+	msr	cpsr,r0
+
+	/*
+	 * we do sys-critical inits only at reboot,
+	 * not when booting from ram!
+	 */
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+	bl	cpu_init_crit
+#endif
+
+	bl	board_init_ll
+
+	pop	{r0-r12,r14}
+	bx	lr
+
+/*
+ *************************************************************************
+ *
+ * CPU_init_critical registers
+ *
+ * setup important registers
+ * setup memory timing
+ *
+ *************************************************************************
+ */
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+cpu_init_crit:
+	/*
+	 * flush v4 I/D caches
+	 */
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c7, 0	/* flush v3/v4 cache */
+	mcr	p15, 0, r0, c8, c7, 0	/* flush v4 TLB */
+
+	/*
+	 * disable MMU stuff and caches
+	 */
+	mrc	p15, 0, r0, c1, c0, 0
+	bic	r0, r0, #0x00002300	/* clear bits 13, 9:8 (--V- --RS) */
+	bic	r0, r0, #0x00000087	/* clear bits 7, 2:0 (B--- -CAM) */
+	orr	r0, r0, #0x00000002	/* set bit 2 (A) Align */
+	orr	r0, r0, #0x00001000	/* set bit 12 (I) I-Cache */
+	mcr	p15, 0, r0, c1, c0, 0
+
+	mov	pc, lr		/* back to my caller */
+#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
+
+#ifndef CONFIG_SPL_BUILD
+/*
+ *************************************************************************
+ *
+ * Interrupt handling
+ *
+ *************************************************************************
+ */
+
+@
+@ IRQ stack frame.
+@
+#define S_FRAME_SIZE	72
+
+#define S_OLD_R0	68
+#define S_PSR		64
+#define S_PC		60
+#define S_LR		56
+#define S_SP		52
+
+#define S_IP		48
+#define S_FP		44
+#define S_R10		40
+#define S_R9		36
+#define S_R8		32
+#define S_R7		28
+#define S_R6		24
+#define S_R5		20
+#define S_R4		16
+#define S_R3		12
+#define S_R2		8
+#define S_R1		4
+#define S_R0		0
+
+#define MODE_SVC 0x13
+#define I_BIT	 0x80
+
+/*
+ * use bad_save_user_regs for abort/prefetch/undef/swi ...
+ * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
+ */
+
+	.macro	bad_save_user_regs
+	@ carve out a frame on current user stack
+	sub	sp, sp, #S_FRAME_SIZE
+	stmia	sp, {r0 - r12}	@ Save user registers (now in svc mode) r0-r12
+	ldr	r2, IRQ_STACK_START_IN
+	@ get values for "aborted" pc and cpsr (into parm regs)
+	ldmia	r2, {r2 - r3}
+	add	r0, sp, #S_FRAME_SIZE		@ grab pointer to old stack
+	add	r5, sp, #S_SP
+	mov	r1, lr
+	stmia	r5, {r0 - r3}	@ save sp_SVC, lr_SVC, pc, cpsr
+	mov	r0, sp		@ save current stack into r0 (param register)
+	.endm
+
+	.macro	irq_save_user_regs
+	sub	sp, sp, #S_FRAME_SIZE
+	stmia	sp, {r0 - r12}			@ Calling r0-r12
+	@ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
+	add	r8, sp, #S_PC
+	stmdb	r8, {sp, lr}^		@ Calling SP, LR
+	str	lr, [r8, #0]		@ Save calling PC
+	mrs	r6, spsr
+	str	r6, [r8, #4]		@ Save CPSR
+	str	r0, [r8, #8]		@ Save OLD_R0
+	mov	r0, sp
+	.endm
+
+	.macro	irq_restore_user_regs
+	ldmia	sp, {r0 - lr}^			@ Calling r0 - lr
+	mov	r0, r0
+	ldr	lr, [sp, #S_PC]			@ Get PC
+	add	sp, sp, #S_FRAME_SIZE
+	subs	pc, lr, #4		@ return & move spsr_svc into cpsr
+	.endm
+
+	.macro get_bad_stack
+	ldr	r13, IRQ_STACK_START_IN		@ setup our mode stack
+
+	str	lr, [r13]	@ save caller lr in position 0 of saved stack
+	mrs	lr, spsr	@ get the spsr
+	str	lr, [r13, #4]	@ save spsr in position 1 of saved stack
+	mov	r13, #MODE_SVC	@ prepare SVC-Mode
+	@ msr	spsr_c, r13
+	msr	spsr, r13	@ switch modes, make sure moves will execute
+	mov	lr, pc		@ capture return pc
+	movs	pc, lr		@ jump to next instruction & switch modes.
+	.endm
+
+	.macro get_irq_stack			@ setup IRQ stack
+	ldr	sp, IRQ_STACK_START
+	.endm
+
+	.macro get_fiq_stack			@ setup FIQ stack
+	ldr	sp, FIQ_STACK_START
+	.endm
+#endif	/* CONFIG_SPL_BUILD */
+
+/*
+ * exception handlers
+ */
+#ifdef CONFIG_SPL_BUILD
+	.align	5
+do_hang:
+	ldr	sp, _TEXT_BASE			/* switch to abort stack */
+1:
+	bl	1b				/* hang and never return */
+#else	/* !CONFIG_SPL_BUILD */
+	.align  5
+undefined_instruction:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_undefined_instruction
+
+	.align	5
+software_interrupt:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_software_interrupt
+
+	.align	5
+prefetch_abort:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_prefetch_abort
+
+	.align	5
+data_abort:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_data_abort
+
+	.align	5
+not_used:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_not_used
+
+#ifdef CONFIG_USE_IRQ
+
+	.align	5
+irq:
+	get_irq_stack
+	irq_save_user_regs
+	bl	do_irq
+	irq_restore_user_regs
+
+	.align	5
+fiq:
+	get_fiq_stack
+	/* someone ought to write a more effiction fiq_save_user_regs */
+	irq_save_user_regs
+	bl	do_fiq
+	irq_restore_user_regs
+
+#else
+
+	.align	5
+irq:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_irq
+
+	.align	5
+fiq:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_fiq
+
+#endif
+#endif	/* CONFIG_SPL_BUILD */
diff --git a/board/denx/m28evk/u-boot-spl.lds b/board/denx/m28evk/u-boot-spl.lds
new file mode 100644
index 0000000..e296a92
--- /dev/null
+++ b/board/denx/m28evk/u-boot-spl.lds
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * January 2004 - Changed to support H4 device
+ * Copyright (c) 2004-2008 Texas Instruments
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+	. = 0x00000000;
+
+	. = ALIGN(4);
+	.text	:
+	{
+		board/denx/m28evk/start.o	(.text)
+		*(.text)
+	}
+
+	. = ALIGN(4);
+	.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
+
+	. = ALIGN(4);
+	.data : {
+		*(.data)
+	}
+
+	. = ALIGN(4);
+	__u_boot_cmd_start = .;
+	.u_boot_cmd : { *(.u_boot_cmd) }
+	__u_boot_cmd_end = .;
+
+	. = ALIGN(4);
+
+	.rel.dyn : {
+		__rel_dyn_start = .;
+		*(.rel*)
+		__rel_dyn_end = .;
+	}
+
+	.dynsym : {
+		__dynsym_start = .;
+		*(.dynsym)
+	}
+
+	_end = .;
+
+	.bss __rel_dyn_start (OVERLAY) : {
+		__bss_start = .;
+		*(.bss)
+		 . = ALIGN(4);
+		__bss_end__ = .;
+	}
+
+	/DISCARD/ : { *(.bss*) }
+	/DISCARD/ : { *(.dynstr*) }
+	/DISCARD/ : { *(.dynsym*) }
+	/DISCARD/ : { *(.dynamic*) }
+	/DISCARD/ : { *(.hash*) }
+	/DISCARD/ : { *(.plt*) }
+	/DISCARD/ : { *(.interp*) }
+	/DISCARD/ : { *(.gnu*) }
+}
diff --git a/board/denx/m28evk/u-boot.bd b/board/denx/m28evk/u-boot.bd
new file mode 100644
index 0000000..3ce7f92
--- /dev/null
+++ b/board/denx/m28evk/u-boot.bd
@@ -0,0 +1,14 @@
+sources {
+	u_boot_spl="spl/u-boot-spl.bin";
+	u_boot="u-boot.bin";
+}
+
+section (0) {
+        load u_boot_spl > 0x0000;
+        load ivt (entry = 0x0014) > 0x8000;
+	hab call 0x8000;
+
+        load u_boot > 0x40000100;
+        load ivt (entry = 0x40000100) > 0x8000;
+	hab call 0x8000;
+}
diff --git a/include/configs/m28evk.h b/include/configs/m28evk.h
index d88e09e..59e3e05 100644
--- a/include/configs/m28evk.h
+++ b/include/configs/m28evk.h
@@ -43,6 +43,14 @@
 #define	CONFIG_ARCH_CPU_INIT
 
 /*
+ * SPL
+ */
+#define	CONFIG_SPL
+#define	CONFIG_SPL_NO_CPU_SUPPORT_CODE
+#define	CONFIG_SPL_START_S_PATH		"board/denx/m28evk"
+#define	CONFIG_SPL_LDSCRIPT		"board/denx/m28evk/u-boot-spl.lds"
+
+/*
  * U-Boot Commands
  */
 #include <config_cmd_default.h>
-- 
1.7.6.3

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

* [U-Boot] [PATCH 15/17 RESEND] M28: Add doc/README.m28 documentation
  2011-10-21 22:44 ` [U-Boot] [PATCH 00/17 V3] Support for the DENX M28 SoM Marek Vasut
                     ` (13 preceding siblings ...)
  2011-10-21 22:44   ` [U-Boot] [PATCH 14/17 V4] M28: Add MMC SPL Marek Vasut
@ 2011-10-21 22:44   ` Marek Vasut
  2011-10-21 22:44   ` [U-Boot] [PATCH 16/17] iMX28: Fix ARM vector handling Marek Vasut
  2011-10-21 22:44   ` [U-Boot] [PATCH 17/17] M28: Add memory detection into SPL Marek Vasut
  16 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-10-21 22:44 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 doc/README.m28 |  223 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 223 insertions(+), 0 deletions(-)
 create mode 100644 doc/README.m28

diff --git a/doc/README.m28 b/doc/README.m28
new file mode 100644
index 0000000..b749ce0
--- /dev/null
+++ b/doc/README.m28
@@ -0,0 +1,223 @@
+DENX M28EVK
+===========
+
+This document describes the DENX M28/M28EVK U-Boot port. This document mostly
+covers topics related to making the module/board bootable.
+
+Terminology
+-----------
+
+The dollar symbol ($) introduces a snipped of shell code. This shall be typed
+into the unix command prompt in U-Boot source code root directory.
+
+The (=>) introduces a snipped of code that should by typed into U-Boot command
+prompt.
+
+Contents
+--------
+
+0) Files of the M28/M28EVK port
+1) Prerequisites
+2) Compiling U-Boot for M28
+3) Installation of U-Boot for M28EVK to SD card
+4) Installation of U-Boot for M28 to NAND flash
+
+0) Files of the M28/M28EVK port
+-------------------------------
+
+arch/arm/cpu/arm926ejs/mx28/	- The CPU support code for the Freescale i.MX28
+arch/arm/include/asm/arch-mx28/	- Header files for the Freescale i.MX28
+board/denx/m28evk/		- M28EVK board specific files
+include/configs/m28evk.h	- M28EVK configuration file
+
+1) Prerequisites
+----------------
+
+To make the M28 module or the M28 module or M28EVK board bootable, some tools
+are necessary. The first one is the "elftosb" tool distributed by Freescale
+Semiconductor. The other tool is the "mxsboot" tool found in U-Boot source tree.
+
+Firstly, obtain the elftosb archive from the following location:
+
+	http://foss.doredevelopment.dk/mirrors/imx/elftosb-10.12.01.tar.gz
+
+We use a $VER variable here to denote the current version. At the time of
+writing of this document, that is "10.12.01". To obtain the file from command
+line, use:
+
+	$ VER="10.12.01"
+	$ wget http://foss.doredevelopment.dk/mirrors/imx/elftosb-${VER}.tar.gz
+
+Extract the file:
+
+	$ tar xzf elftosb-${VER}.tar.gz
+
+Compile the file. We need to manually tell the linker to use also libm:
+
+	$ cd elftosb-${VER}/
+	$ make LIBS="-lstdc++ -lm" elftosb
+
+Optionally, remove debugging symbols from elftosb:
+
+	$ strip bld/linux/elftosb
+
+Finally, install the "elftosb" binary. The "install" target is missing, so just
+copy the binary by hand:
+
+	$ sudo cp bld/linux/elftosb /usr/local/bin/
+
+Make sure the "elftosb" binary can be found in your $PATH, in this case this
+means "/usr/local/bin/" has to be in your $PATH.
+
+2) Compiling U-Boot for M28
+---------------------------
+
+Compiling the U-Boot for M28 is straightforward and done as compiling U-Boot
+for any other ARM device. For cross-compiler setup, please refer to ELDK5.0
+documentation. First, clean up the source code:
+
+	$ make mrproper
+
+Next, configure U-Boot for M28EVK:
+
+	$ make m28evk_config
+
+Lastly, compile U-Boot and prepare a "BootStream". The "BootStream" is a special
+type of file, which the i.MX28 CPU can boot. This is handled by the following
+command:
+
+	$ make u-boot.sb
+
+HINT: To speed-up the build process, you can add -j<N>, where N is number of
+      compiler instances that'll run in parallel.
+
+The code produces "u-boot.sb" file. This file needs to be augmented with a
+proper header to allow successful boot from SD or NAND. Adding the header is
+discussed in the following chapters.
+
+3) Installation of U-Boot for M28EVK to SD card
+-----------------------------------------------
+
+To boot an M28 from SD, set the boot mode DIP switches according to i.MX28
+manual chapter 12.2.1 (Table 12-2), PORT=SSP0, SD/MMC master on SSP0, 3.3V.
+
+An SD card the i.MX28 CPU can use to boot U-Boot must contain a DOS partition
+table, which in turn carries a partition of special type and which contains a
+special header. The rest of partitions in the DOS partition table can be used
+by the user.
+
+To prepare such partition, use your favourite partitioning tool. The partition
+must have the following parameters:
+
+	* Start sector .......... sector 2048
+	* Partition size ........ at least 1024 kb
+	* Partition type ........ 0x53 (sometimes "OnTrack DM6 Aux3")
+
+For example in Linux fdisk, the sequence for a clear card is the following:
+
+	* o ..................... create a clear partition table
+	* n ..................... create new partition
+		* p ............. primary partition
+		* 1 ............. first partition
+		* 2048 .......... first sector is 2048
+		* +1M ........... make the partition 1Mb big
+	* t 1 ................... change first partition ID
+		* 53 ............ change the ID to 0x53 (OnTrack DM6 Aux3)
+	* <create other partitions>
+	* w ..................... write partition table to disk
+
+The partition layout is ready, next the special partition must be filled with
+proper contents. The contents is generated by running the following command (see
+chapter 2)):
+
+	$ ./tools/mxsboot sd u-boot.sb u-boot.sd
+
+The resulting file, "u-boot.sd", shall then be written to the partition. In this
+case, we assume the first partition of the SD card is /dev/mmcblk0p1:
+
+	$ dd if=u-boot.sd of=/dev/mmcblk0p1
+
+Last step is to insert the card into M28EVK and boot.
+
+NOTE: If the user needs to adjust the start sector, the "mxsboot" tool contains
+      a "-p" switch for that purpose. The "-p" switch takes the sector number as
+      an argument.
+
+4) Installation of U-Boot for M28 to NAND flash
+-----------------------------------------------
+
+To boot an M28 from NAND, set the boot mode DIP switches according to i.MX28
+manual chapter 12.2.1 (Table 12-2), PORT=GPMI, NAND 1.8 V.
+
+There are two possibilities when preparing an image writable to NAND flash.
+
+	I) The NAND wasn't written at all yet or the BCB is broken
+	----------------------------------------------------------
+	   In this case, both BCB (FCB and DBBT) and firmware needs to be
+	   written to NAND. To generate NAND image containing all these,
+	   there is a tool called "mxsboot" in the "tools/" directory. The tool
+	   is invoked on "u-boot.sb" file from chapter 2):
+
+		 $ ./tools/mxsboot nand u-boot.sb u-boot.nand
+
+	   NOTE: The above invokation works for NAND flash with geometry of
+		 2048b per page, 64b OOB data, 128kb erase size. If your chip
+		 has a different geometry, please use:
+
+		 -w <size>	change page size (default 2048 b)
+		 -o <size>	change oob size (default 64 b)
+		 -e <size>	change erase size (default 131072 b)
+
+		 The geometry information can be obtained from running U-Boot
+		 on M28 by issuing the "nand info" command.
+
+	   The resulting file, "u-boot.nand" can be written directly to NAND
+	   from the U-Boot prompt. To simplify the process, the U-Boot default
+	   environment contains script "update_nand_full" to update the system.
+
+	   This script expects a working TFTP server containing the file
+	   "u-boot.nand" in it's root directory. This can be changed by
+	   adjusting the "update_nand_full_filename" varible.
+
+	   To update the system, run the following in U-Boot prompt:
+
+		 => run update_nand_full
+
+	   In case you would only need to update the bootloader in future,
+	   see II) below.
+
+	II) The NAND was already written with a good BCB
+	------------------------------------------------
+	   This part applies after the part I) above was done at least once.
+
+	   If part I) above was done correctly already, there is no need to
+	   write the FCB and DBBT parts of NAND again. It's possible to upgrade
+	   only the bootloader image.
+
+	   To simplify the process of firmware update, the U-Boot default
+	   environment contains script "update_nand_firmware" to update only
+	   the firmware, without rewriting FCB and DBBT.
+
+	   This script expects a working TFTP server containing the file
+	   "u-boot.sb" in it's root directory. This can be changed by
+	   adjusting the "update_nand_firmware_filename" varible.
+
+	   To update the system, run the following in U-Boot prompt:
+
+		 => run update_nand_firmware
+
+	III) Special settings for the update scripts
+	--------------------------------------------
+	   There is a slight possibility of the user wanting to adjust the
+	   STRIDE and COUNT options of the NAND boot. For description of these,
+	   see i.MX28 manual section 12.12.1.2 and 12.12.1.3.
+
+	   The update scripts take this possibility into account. In case the
+	   user changes STRIDE by blowing fuses, the user also has to change
+	   "update_nand_stride" variable. In case the user changes COUNT by
+	   blowing fuses, the user also has to change "update_nand_count"
+	   variable for the update scripts to work correctly.
+
+	   In case the user needs to boot a firmware image bigger than 1Mb, the
+	   user has to adjust the "update_nand_firmware_maxsz" variable for the
+	   update scripts to work properly.
-- 
1.7.6.3

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

* [U-Boot] [PATCH 16/17] iMX28: Fix ARM vector handling
  2011-10-21 22:44 ` [U-Boot] [PATCH 00/17 V3] Support for the DENX M28 SoM Marek Vasut
                     ` (14 preceding siblings ...)
  2011-10-21 22:44   ` [U-Boot] [PATCH 15/17 RESEND] M28: Add doc/README.m28 documentation Marek Vasut
@ 2011-10-21 22:44   ` Marek Vasut
  2011-10-21 22:44   ` [U-Boot] [PATCH 17/17] M28: Add memory detection into SPL Marek Vasut
  16 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-10-21 22:44 UTC (permalink / raw)
  To: u-boot

This patch introduces proper ARM vector handling for i.MX28 CPU. This issue
wasn't addressed because the interrupts weren't enabled on any ARMv5 core,
therefore the issue wasn't noticed earlier.

In previous implementation, the vectoring code used by i.MX28 CPU when an
exception happened was that of the SPL. With this change, the branch target when
an exception happens can be reconfigured by U-Boot.

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
---
 arch/arm/cpu/arm926ejs/mx28/mx28.c |   22 +++
 board/denx/m28evk/start.S          |  264 +++++++-----------------------------
 include/configs/m28evk.h           |    1 +
 3 files changed, 74 insertions(+), 213 deletions(-)

diff --git a/arch/arm/cpu/arm926ejs/mx28/mx28.c b/arch/arm/cpu/arm926ejs/mx28/mx28.c
index e990f3c..088c019 100644
--- a/arch/arm/cpu/arm926ejs/mx28/mx28.c
+++ b/arch/arm/cpu/arm926ejs/mx28/mx28.c
@@ -35,6 +35,8 @@
 #include <asm/arch/imx-regs.h>
 #include <asm/arch/sys_proto.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 /* 1 second delay should be plenty of time for block reset. */
 #define	RESET_MAX_TIMEOUT	1000000
 
@@ -116,11 +118,31 @@ int mx28_reset_block(struct mx28_register *reg)
 	return 0;
 }
 
+void mx28_fixup_vt(uint32_t start_addr)
+{
+	uint32_t *vt = (uint32_t *)0x20;
+	int i;
+
+	for (i = 0; i < 8; i++)
+		vt[i] = start_addr + (4 * i);
+}
+
+#ifdef	CONFIG_ARCH_MISC_INIT
+int arch_misc_init(void)
+{
+	mx28_fixup_vt(gd->relocaddr);
+	return 0;
+}
+#endif
+
 #ifdef	CONFIG_ARCH_CPU_INIT
 int arch_cpu_init(void)
 {
 	struct mx28_clkctrl_regs *clkctrl_regs =
 		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	extern uint32_t _start;
+
+	mx28_fixup_vt((uint32_t)&_start);
 
 	/*
 	 * Enable NAND clock
diff --git a/board/denx/m28evk/start.S b/board/denx/m28evk/start.S
index cf67599..94696d6 100644
--- a/board/denx/m28evk/start.S
+++ b/board/denx/m28evk/start.S
@@ -58,54 +58,58 @@
 .globl _start
 _start:
 	b	reset
-#ifdef CONFIG_SPL_BUILD
-/* No exception handlers in preloader */
-	ldr	pc, _hang
-	ldr	pc, _hang
-	ldr	pc, _hang
-	ldr	pc, _hang
-	b	reset
-	ldr	pc, _hang
-	ldr	pc, _hang
+	b	undefined_instruction
+	b	software_interrupt
+	b	prefetch_abort
+	b	data_abort
+	b	not_used
+	b	irq
+	b	fiq
 
-_hang:
-	.word	do_hang
-/* pad to 64 byte boundary */
-	.word	0x12345678
-	.word	0x12345678
-	.word	0x12345678
-	.word	0x12345678
-	.word	0x12345678
-	.word	0x12345678
-	.word	0x12345678
-#else
-	ldr	pc, _undefined_instruction
-	ldr	pc, _software_interrupt
-	ldr	pc, _prefetch_abort
-	ldr	pc, _data_abort
-	ldr	pc, _not_used
-	ldr	pc, _irq
-	ldr	pc, _fiq
+/*
+ * Vector table, located at address 0x20.
+ * This table allows the code running AFTER SPL, the U-Boot, to install it's
+ * interrupt handlers here. The problem is that the U-Boot is loaded into RAM,
+ * including it's interrupt vectoring table and the table at 0x0 is still the
+ * SPLs. So if interrupt happens in U-Boot, the SPLs interrupt vectoring table
+ * is still used.
+ */
+_vt_reset:
+	.word	_reset
+_vt_undefined_instruction:
+	.word	_hang
+_vt_software_interrupt:
+	.word	_hang
+_vt_prefetch_abort:
+	.word	_hang
+_vt_data_abort:
+	.word	_hang
+_vt_not_used:
+	.word	_reset
+_vt_irq:
+	.word	_hang
+_vt_fiq:
+	.word	_hang
 
-_undefined_instruction:
-	.word undefined_instruction
-_software_interrupt:
-	.word software_interrupt
-_prefetch_abort:
-	.word prefetch_abort
-_data_abort:
-	.word data_abort
-_not_used:
-	.word not_used
-_irq:
-	.word irq
-_fiq:
-	.word fiq
+reset:
+	ldr	pc, _vt_reset
+undefined_instruction:
+	ldr	pc, _vt_undefined_instruction
+software_interrupt:
+	ldr	pc, _vt_software_interrupt
+prefetch_abort:
+	ldr	pc, _vt_prefetch_abort
+data_abort:
+	ldr	pc, _vt_data_abort
+not_used:
+	ldr	pc, _vt_not_used
+irq:
+	ldr	pc, _vt_irq
+fiq:
+	ldr	pc, _vt_fiq
 
-#endif	/* CONFIG_SPL_BUILD */
 	.balignl 16,0xdeadbeef
 
-
 /*
  *************************************************************************
  *
@@ -162,7 +166,7 @@ IRQ_STACK_START_IN:
  * the actual reset code
  */
 
-reset:
+_reset:
 	/*
 	 * Store all registers on old stack pointer, this will allow us later to
 	 * return to the BootROM and let the BootROM load U-Boot into RAM.
@@ -220,177 +224,11 @@ cpu_init_crit:
 	mcr	p15, 0, r0, c1, c0, 0
 
 	mov	pc, lr		/* back to my caller */
-#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
-
-#ifndef CONFIG_SPL_BUILD
-/*
- *************************************************************************
- *
- * Interrupt handling
- *
- *************************************************************************
- */
-
-@
-@ IRQ stack frame.
-@
-#define S_FRAME_SIZE	72
-
-#define S_OLD_R0	68
-#define S_PSR		64
-#define S_PC		60
-#define S_LR		56
-#define S_SP		52
-
-#define S_IP		48
-#define S_FP		44
-#define S_R10		40
-#define S_R9		36
-#define S_R8		32
-#define S_R7		28
-#define S_R6		24
-#define S_R5		20
-#define S_R4		16
-#define S_R3		12
-#define S_R2		8
-#define S_R1		4
-#define S_R0		0
-
-#define MODE_SVC 0x13
-#define I_BIT	 0x80
-
-/*
- * use bad_save_user_regs for abort/prefetch/undef/swi ...
- * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
- */
-
-	.macro	bad_save_user_regs
-	@ carve out a frame on current user stack
-	sub	sp, sp, #S_FRAME_SIZE
-	stmia	sp, {r0 - r12}	@ Save user registers (now in svc mode) r0-r12
-	ldr	r2, IRQ_STACK_START_IN
-	@ get values for "aborted" pc and cpsr (into parm regs)
-	ldmia	r2, {r2 - r3}
-	add	r0, sp, #S_FRAME_SIZE		@ grab pointer to old stack
-	add	r5, sp, #S_SP
-	mov	r1, lr
-	stmia	r5, {r0 - r3}	@ save sp_SVC, lr_SVC, pc, cpsr
-	mov	r0, sp		@ save current stack into r0 (param register)
-	.endm
-
-	.macro	irq_save_user_regs
-	sub	sp, sp, #S_FRAME_SIZE
-	stmia	sp, {r0 - r12}			@ Calling r0-r12
-	@ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
-	add	r8, sp, #S_PC
-	stmdb	r8, {sp, lr}^		@ Calling SP, LR
-	str	lr, [r8, #0]		@ Save calling PC
-	mrs	r6, spsr
-	str	r6, [r8, #4]		@ Save CPSR
-	str	r0, [r8, #8]		@ Save OLD_R0
-	mov	r0, sp
-	.endm
-
-	.macro	irq_restore_user_regs
-	ldmia	sp, {r0 - lr}^			@ Calling r0 - lr
-	mov	r0, r0
-	ldr	lr, [sp, #S_PC]			@ Get PC
-	add	sp, sp, #S_FRAME_SIZE
-	subs	pc, lr, #4		@ return & move spsr_svc into cpsr
-	.endm
-
-	.macro get_bad_stack
-	ldr	r13, IRQ_STACK_START_IN		@ setup our mode stack
-
-	str	lr, [r13]	@ save caller lr in position 0 of saved stack
-	mrs	lr, spsr	@ get the spsr
-	str	lr, [r13, #4]	@ save spsr in position 1 of saved stack
-	mov	r13, #MODE_SVC	@ prepare SVC-Mode
-	@ msr	spsr_c, r13
-	msr	spsr, r13	@ switch modes, make sure moves will execute
-	mov	lr, pc		@ capture return pc
-	movs	pc, lr		@ jump to next instruction & switch modes.
-	.endm
-
-	.macro get_irq_stack			@ setup IRQ stack
-	ldr	sp, IRQ_STACK_START
-	.endm
-
-	.macro get_fiq_stack			@ setup FIQ stack
-	ldr	sp, FIQ_STACK_START
-	.endm
-#endif	/* CONFIG_SPL_BUILD */
 
-/*
- * exception handlers
- */
-#ifdef CONFIG_SPL_BUILD
 	.align	5
-do_hang:
+#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
+
+_hang:
 	ldr	sp, _TEXT_BASE			/* switch to abort stack */
 1:
 	bl	1b				/* hang and never return */
-#else	/* !CONFIG_SPL_BUILD */
-	.align  5
-undefined_instruction:
-	get_bad_stack
-	bad_save_user_regs
-	bl	do_undefined_instruction
-
-	.align	5
-software_interrupt:
-	get_bad_stack
-	bad_save_user_regs
-	bl	do_software_interrupt
-
-	.align	5
-prefetch_abort:
-	get_bad_stack
-	bad_save_user_regs
-	bl	do_prefetch_abort
-
-	.align	5
-data_abort:
-	get_bad_stack
-	bad_save_user_regs
-	bl	do_data_abort
-
-	.align	5
-not_used:
-	get_bad_stack
-	bad_save_user_regs
-	bl	do_not_used
-
-#ifdef CONFIG_USE_IRQ
-
-	.align	5
-irq:
-	get_irq_stack
-	irq_save_user_regs
-	bl	do_irq
-	irq_restore_user_regs
-
-	.align	5
-fiq:
-	get_fiq_stack
-	/* someone ought to write a more effiction fiq_save_user_regs */
-	irq_save_user_regs
-	bl	do_fiq
-	irq_restore_user_regs
-
-#else
-
-	.align	5
-irq:
-	get_bad_stack
-	bad_save_user_regs
-	bl	do_irq
-
-	.align	5
-fiq:
-	get_bad_stack
-	bad_save_user_regs
-	bl	do_fiq
-
-#endif
-#endif	/* CONFIG_SPL_BUILD */
diff --git a/include/configs/m28evk.h b/include/configs/m28evk.h
index 59e3e05..381b01e 100644
--- a/include/configs/m28evk.h
+++ b/include/configs/m28evk.h
@@ -41,6 +41,7 @@
 #define	CONFIG_SYS_DCACHE_OFF
 #define	CONFIG_BOARD_EARLY_INIT_F
 #define	CONFIG_ARCH_CPU_INIT
+#define	CONFIG_ARCH_MISC_INIT
 
 /*
  * SPL
-- 
1.7.6.3

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

* [U-Boot] [PATCH 17/17] M28: Add memory detection into SPL
  2011-10-21 22:44 ` [U-Boot] [PATCH 00/17 V3] Support for the DENX M28 SoM Marek Vasut
                     ` (15 preceding siblings ...)
  2011-10-21 22:44   ` [U-Boot] [PATCH 16/17] iMX28: Fix ARM vector handling Marek Vasut
@ 2011-10-21 22:44   ` Marek Vasut
  2011-10-31 11:45     ` [U-Boot] [PATCH 17/17 V2] " Marek Vasut
  16 siblings, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-10-21 22:44 UTC (permalink / raw)
  To: u-boot

This code allows the DDR DRAM size to be detected at runtime. The RAM size is
stored into two scratch registers, from which it is then fetched in U-Boot.

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
---
 board/denx/m28evk/Makefile   |    7 ++++++-
 board/denx/m28evk/m28evk.c   |   18 ++++++++++++++++--
 board/denx/m28evk/mem_init.c |   27 +++++++++++++++++++++++++++
 include/configs/m28evk.h     |    2 +-
 4 files changed, 50 insertions(+), 4 deletions(-)

diff --git a/board/denx/m28evk/Makefile b/board/denx/m28evk/Makefile
index 953143a..7bafff5 100644
--- a/board/denx/m28evk/Makefile
+++ b/board/denx/m28evk/Makefile
@@ -30,7 +30,7 @@ COBJS	:= m28evk.o
 endif
 
 ifdef	CONFIG_SPL_BUILD
-COBJS	:= mem_init.o mmc_boot.o power_init.o
+COBJS	:= mem_init.o mmc_boot.o power_init.o memsize.o
 endif
 
 SRCS	:= $(COBJS:.o=.c)
@@ -47,6 +47,11 @@ clean:
 distclean:	clean
 	rm -f $(LIB) core *.bak .depend
 
+ifdef	CONFIG_SPL_BUILD
+memsize.c:
+	ln -sf $(TOPDIR)/common/memsize.c $@
+endif
+
 #########################################################################
 
 # defines $(obj).depend target
diff --git a/board/denx/m28evk/m28evk.c b/board/denx/m28evk/m28evk.c
index 118e222..168ceeb 100644
--- a/board/denx/m28evk/m28evk.c
+++ b/board/denx/m28evk/m28evk.c
@@ -63,10 +63,24 @@ int board_init(void)
 	return 0;
 }
 
+#define	HW_DIGCTRL_SCRATCH0	0x8001c280
+#define	HW_DIGCTRL_SCRATCH1	0x8001c290
 int dram_init(void)
 {
-	/* dram_init must store complete ramsize in gd->ram_size */
-	gd->ram_size = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE);
+	uint32_t sz[2];
+
+	sz[0] = readl(HW_DIGCTRL_SCRATCH0);
+	sz[1] = readl(HW_DIGCTRL_SCRATCH1);
+
+	if (sz[0] != sz[1]) {
+		printf("MX28:\n"
+			"Error, the RAM size in HW_DIGCTRL_SCRATCH0 and\n"
+			"HW_DIGCTRL_SCRATCH1 is not the same. Please\n"
+			"verify these two registers contain valid RAM size!\n");
+		hang();
+	}
+
+	gd->ram_size = sz[0];
 	return 0;
 }
 
diff --git a/board/denx/m28evk/mem_init.c b/board/denx/m28evk/mem_init.c
index 066fe0d..17d1f9b 100644
--- a/board/denx/m28evk/mem_init.c
+++ b/board/denx/m28evk/mem_init.c
@@ -165,6 +165,31 @@ void mx28_mem_setup_vddd(void)
 		&power_regs->hw_power_vdddctrl);
 }
 
+#define	HW_DIGCTRL_SCRATCH0	0x8001c280
+#define	HW_DIGCTRL_SCRATCH1	0x8001c290
+void data_abort_memdetect_handler(void) __attribute__((naked));
+void data_abort_memdetect_handler(void)
+{
+	asm volatile("subs pc, r14, #4");
+}
+
+void mx28_mem_get_size(void)
+{
+	uint32_t sz, da;
+	uint32_t *vt = (uint32_t *)0x20;
+
+	/* Replace the DABT handler. */
+	da = vt[4];
+	vt[4] = (uint32_t)&data_abort_memdetect_handler;
+
+	sz = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE);
+	writel(sz, HW_DIGCTRL_SCRATCH0);
+	writel(sz, HW_DIGCTRL_SCRATCH1);
+
+	/* Restore the old DABT handler. */
+	vt[4] = da;
+}
+
 void mx28_mem_init(void)
 {
 	struct mx28_clkctrl_regs *clkctrl_regs =
@@ -210,4 +235,6 @@ void mx28_mem_init(void)
 	early_delay(10000);
 
 	mx28_mem_setup_cpu_and_hbus();
+
+	mx28_mem_get_size();
 }
diff --git a/include/configs/m28evk.h b/include/configs/m28evk.h
index 381b01e..c8b0cf5 100644
--- a/include/configs/m28evk.h
+++ b/include/configs/m28evk.h
@@ -81,7 +81,7 @@
  */
 #define	CONFIG_NR_DRAM_BANKS		1		/* 2 banks of DRAM */
 #define	PHYS_SDRAM_1			0x40000000	/* Base address */
-#define	PHYS_SDRAM_1_SIZE		0x08000000	/* 128 MB */
+#define	PHYS_SDRAM_1_SIZE		0x40000000	/* Max 1 GB RAM */
 #define	CONFIG_STACKSIZE		0x00010000	/* 128 KB stack */
 #define	CONFIG_SYS_MALLOC_LEN		0x00400000	/* 4 MB for malloc */
 #define	CONFIG_SYS_GBL_DATA_SIZE	128		/* Initial data */
-- 
1.7.6.3

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

* [U-Boot] [PATCH 14/17 V4] M28: Add MMC SPL
  2011-10-21 22:44   ` [U-Boot] [PATCH 14/17 V4] M28: Add MMC SPL Marek Vasut
@ 2011-10-23 21:42     ` Robert Schwebel
  2011-10-31 11:44     ` [U-Boot] [PATCH 14/17 V5] " Marek Vasut
  1 sibling, 0 replies; 116+ messages in thread
From: Robert Schwebel @ 2011-10-23 21:42 UTC (permalink / raw)
  To: u-boot

Hi Marek,

On Sat, Oct 22, 2011 at 12:44:23AM +0200, Marek Vasut wrote:
>  board/denx/m28evk/power_init.c   |  913 ++++++++++++++++++++++++++++++++++++++

Shouldn't the power library functions go into
arch/arm/cpu/arm926ejs/mx28/? They are not m28evk specific and should be
re-usable by other MX28 boards.

rsc
-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

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

* [U-Boot] [PATCH 13/17 V4] iMX28: Add support for DENX M28EVK board
  2011-10-21 22:44   ` [U-Boot] [PATCH 13/17 V4] iMX28: Add support for DENX M28EVK board Marek Vasut
@ 2011-10-31  9:12     ` Igor Grinberg
  2011-10-31 11:42     ` [U-Boot] [PATCH 13/17 V5] " Marek Vasut
  1 sibling, 0 replies; 116+ messages in thread
From: Igor Grinberg @ 2011-10-31  9:12 UTC (permalink / raw)
  To: u-boot

Hi Marek,

On 10/22/11 00:44, Marek Vasut wrote:
> This contains support for the following components:
> - DUART
> - MMC
> - Both FEC interfaces
> - NAND
> - I2C (RTC, EEPROM)
> - SPI (FLASH)
> 
> Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
> Cc: Stefano Babic <sbabic@denx.de>
> Cc: Wolfgang Denk <wd@denx.de>
> Cc: Detlev Zundel <dzu@denx.de>
> ---
>  MAINTAINERS                |    1 +
>  board/denx/m28evk/Makefile |   49 ++++++++
>  board/denx/m28evk/m28evk.c |  195 ++++++++++++++++++++++++++++++
>  boards.cfg                 |    1 +
>  include/configs/m28evk.h   |  282 ++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 528 insertions(+), 0 deletions(-)
>  create mode 100644 board/denx/m28evk/Makefile
>  create mode 100644 board/denx/m28evk/m28evk.c
>  create mode 100644 include/configs/m28evk.h
> 
> V2: Use scrub -y instead of scrub.quiet in the scripts.
> V3: Use CONFIG_ENV_RANGE
> V4: Configure the RAM size to 128MB for V1.1 module

[...]

> diff --git a/board/denx/m28evk/Makefile b/board/denx/m28evk/Makefile
> new file mode 100644
> index 0000000..4037199
> --- /dev/null
> +++ b/board/denx/m28evk/Makefile

[...]

> +
> +clean:
> +	rm -f $(OBJS)
> +
> +distclean:	clean
> +	rm -f $(LIB) core *.bak .depend

These, should not be here anymore, right?

[...]


-- 
Regards,
Igor.

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

* [U-Boot] [PATCH 13/17 V5] iMX28: Add support for DENX M28EVK board
  2011-10-21 22:44   ` [U-Boot] [PATCH 13/17 V4] iMX28: Add support for DENX M28EVK board Marek Vasut
  2011-10-31  9:12     ` Igor Grinberg
@ 2011-10-31 11:42     ` Marek Vasut
  1 sibling, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-10-31 11:42 UTC (permalink / raw)
  To: u-boot

This contains support for the following components:
- DUART
- MMC
- Both FEC interfaces
- NAND
- I2C (RTC, EEPROM)
- SPI (FLASH)

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 MAINTAINERS                |    1 +
 board/denx/m28evk/Makefile |   43 +++++++
 board/denx/m28evk/m28evk.c |  195 ++++++++++++++++++++++++++++++
 boards.cfg                 |    1 +
 include/configs/m28evk.h   |  282 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 522 insertions(+), 0 deletions(-)
 create mode 100644 board/denx/m28evk/Makefile
 create mode 100644 board/denx/m28evk/m28evk.c
 create mode 100644 include/configs/m28evk.h

V2: Use scrub -y instead of scrub.quiet in the scripts.
V3: Use CONFIG_ENV_RANGE
V4: Configure the RAM size to 128MB for V1.1 module
V5: Drop clean and distclean targets

diff --git a/MAINTAINERS b/MAINTAINERS
index bb95e6d..12c9e96 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -841,6 +841,7 @@ Marek Vasut <marek.vasut@gmail.com>
 	palmtc		xscale/pxa
 	vpac270		xscale/pxa
 	zipitz2		xscale/pxa
+	m28evk		i.MX28
  	efikamx		i.MX51
 	efikasb		i.MX51
 
diff --git a/board/denx/m28evk/Makefile b/board/denx/m28evk/Makefile
new file mode 100644
index 0000000..e6aba9a
--- /dev/null
+++ b/board/denx/m28evk/Makefile
@@ -0,0 +1,43 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(BOARD).o
+
+COBJS	:= m28evk.o
+
+SRCS	:= $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/denx/m28evk/m28evk.c b/board/denx/m28evk/m28evk.c
new file mode 100644
index 0000000..118e222
--- /dev/null
+++ b/board/denx/m28evk/m28evk.c
@@ -0,0 +1,195 @@
+/*
+ * DENX M28 module
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/iomux-mx28.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sys_proto.h>
+#include <linux/mii.h>
+#include <miiphy.h>
+#include <netdev.h>
+#include <errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Functions
+ */
+int board_early_init_f(void)
+{
+	/* IO0 clock at 480MHz */
+	mx28_set_ioclk(MXC_IOCLK0, 480000);
+	/* IO1 clock at 480MHz */
+	mx28_set_ioclk(MXC_IOCLK1, 480000);
+
+	/* SSP0 clock at 96MHz */
+	mx28_set_sspclk(MXC_SSPCLK0, 96000, 0);
+	/* SSP2 clock at 96MHz */
+	mx28_set_sspclk(MXC_SSPCLK2, 96000, 0);
+
+	return 0;
+}
+
+int board_init(void)
+{
+	/* Adress of boot parameters */
+	gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
+
+	return 0;
+}
+
+int dram_init(void)
+{
+	/* dram_init must store complete ramsize in gd->ram_size */
+	gd->ram_size = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE);
+	return 0;
+}
+
+#ifdef	CONFIG_CMD_MMC
+static int m28_mmc_wp(int id)
+{
+	if (id != 0) {
+		printf("MXS MMC: Invalid card selected (card id = %d)\n", id);
+		return 1;
+	}
+
+	return gpio_get_value(MX28_PAD_AUART2_CTS__GPIO_3_10);
+}
+
+int board_mmc_init(bd_t *bis)
+{
+	/* Configure WP as output */
+	gpio_direction_input(MX28_PAD_AUART2_CTS__GPIO_3_10);
+
+	return mxsmmc_initialize(bis, 0, m28_mmc_wp);
+}
+#endif
+
+#ifdef	CONFIG_CMD_NET
+
+#define	MII_OPMODE_STRAP_OVERRIDE	0x16
+#define	MII_PHY_CTRL1			0x1e
+#define	MII_PHY_CTRL2			0x1f
+
+int fecmxc_mii_postcall(int phy)
+{
+	miiphy_write("FEC1", phy, MII_BMCR, 0x9000);
+	miiphy_write("FEC1", phy, MII_OPMODE_STRAP_OVERRIDE, 0x0202);
+	if (phy == 3)
+		miiphy_write("FEC1", 3, MII_PHY_CTRL2, 0x8180);
+	return 0;
+}
+
+int board_eth_init(bd_t *bis)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	struct eth_device *dev;
+	int ret;
+
+	ret = cpu_eth_init(bis);
+
+	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_enet,
+		CLKCTRL_ENET_TIME_SEL_MASK | CLKCTRL_ENET_CLK_OUT_EN,
+		CLKCTRL_ENET_TIME_SEL_RMII_CLK);
+
+	ret = fecmxc_initialize_multi(bis, 0, 0, MXS_ENET0_BASE);
+	if (ret) {
+		printf("FEC MXS: Unable to init FEC0\n");
+		return ret;
+	}
+
+	ret = fecmxc_initialize_multi(bis, 1, 3, MXS_ENET1_BASE);
+	if (ret) {
+		printf("FEC MXS: Unable to init FEC1\n");
+		return ret;
+	}
+
+	dev = eth_get_dev_by_name("FEC0");
+	if (!dev) {
+		printf("FEC MXS: Unable to get FEC0 device entry\n");
+		return -EINVAL;
+	}
+
+	ret = fecmxc_register_mii_postcall(dev, fecmxc_mii_postcall);
+	if (ret) {
+		printf("FEC MXS: Unable to register FEC0 mii postcall\n");
+		return ret;
+	}
+
+	dev = eth_get_dev_by_name("FEC1");
+	if (!dev) {
+		printf("FEC MXS: Unable to get FEC1 device entry\n");
+		return -EINVAL;
+	}
+
+	ret = fecmxc_register_mii_postcall(dev, fecmxc_mii_postcall);
+	if (ret) {
+		printf("FEC MXS: Unable to register FEC1 mii postcall\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+#ifdef	CONFIG_M28_FEC_MAC_IN_OCOTP
+
+#define	MXS_OCOTP_MAX_TIMEOUT	1000000
+void imx_get_mac_from_fuse(char *mac)
+{
+	struct mx28_ocotp_regs *ocotp_regs =
+		(struct mx28_ocotp_regs *)MXS_OCOTP_BASE;
+	uint32_t data;
+
+	memset(mac, 0, 6);
+
+	writel(OCOTP_CTRL_RD_BANK_OPEN, &ocotp_regs->hw_ocotp_ctrl_set);
+
+	if (mx28_wait_mask_clr(&ocotp_regs->hw_ocotp_ctrl_reg, OCOTP_CTRL_BUSY,
+				MXS_OCOTP_MAX_TIMEOUT)) {
+		printf("MXS FEC: Can't get MAC from OCOTP\n");
+		return;
+	}
+
+	data = readl(&ocotp_regs->hw_ocotp_cust0);
+
+	mac[0] = 0x00;
+	mac[1] = 0x04;
+	mac[2] = (data >> 24) & 0xff;
+	mac[3] = (data >> 16) & 0xff;
+	mac[4] = (data >> 8) & 0xff;
+	mac[5] = data & 0xff;
+}
+#else
+void imx_get_mac_from_fuse(char *mac)
+{
+	memset(mac, 0, 6);
+}
+#endif
+
+#endif
diff --git a/boards.cfg b/boards.cfg
index 1776a73..c863c82 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -152,6 +152,7 @@ tx25                         arm         arm926ejs   tx25                karo
 zmx25                        arm         arm926ejs   zmx25               syteco         mx25
 imx27lite                    arm         arm926ejs   imx27lite           logicpd        mx27
 magnesium                    arm         arm926ejs   imx27lite           logicpd        mx27
+m28evk                       arm         arm926ejs   -                   denx           mx28
 nhk8815                      arm         arm926ejs   nhk8815             st             nomadik
 nhk8815_onenand              arm         arm926ejs   nhk8815             st             nomadik       nhk8815:BOOT_ONENAND
 omap5912osk                  arm         arm926ejs   -                   ti             omap
diff --git a/include/configs/m28evk.h b/include/configs/m28evk.h
new file mode 100644
index 0000000..d88e09e
--- /dev/null
+++ b/include/configs/m28evk.h
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef __M28_H__
+#define __M28_H__
+
+#include <asm/arch/regs-base.h>
+
+/*
+ * SoC configurations
+ */
+#define	CONFIG_MX28				/* i.MX28 SoC */
+#define	CONFIG_MXS_GPIO				/* GPIO control */
+#define	CONFIG_SYS_HZ		1000		/* Ticks per second */
+
+/*
+ * Define M28EVK machine type by hand until it lands in mach-types
+ */
+#define	MACH_TYPE_M28EVK	3613
+
+#define	CONFIG_MACH_TYPE	MACH_TYPE_M28EVK
+
+#define	CONFIG_SYS_NO_FLASH
+#define	CONFIG_SYS_ICACHE_OFF
+#define	CONFIG_SYS_DCACHE_OFF
+#define	CONFIG_BOARD_EARLY_INIT_F
+#define	CONFIG_ARCH_CPU_INIT
+
+/*
+ * U-Boot Commands
+ */
+#include <config_cmd_default.h>
+#define	CONFIG_DISPLAY_CPUINFO
+#define	CONFIG_DOS_PARTITION
+
+#define	CONFIG_CMD_CACHE
+#define	CONFIG_CMD_DATE
+#define	CONFIG_CMD_DHCP
+#define	CONFIG_CMD_EEPROM
+#define	CONFIG_CMD_EXT2
+#define	CONFIG_CMD_FAT
+#define	CONFIG_CMD_GPIO
+#define	CONFIG_CMD_I2C
+#define	CONFIG_CMD_MII
+#define	CONFIG_CMD_MMC
+#define	CONFIG_CMD_NAND
+#define	CONFIG_CMD_NET
+#define	CONFIG_CMD_NFS
+#define	CONFIG_CMD_PING
+#define	CONFIG_CMD_SETEXPR
+#define	CONFIG_CMD_SF
+#define	CONFIG_CMD_SPI
+
+/*
+ * Memory configurations
+ */
+#define	CONFIG_NR_DRAM_BANKS		1		/* 2 banks of DRAM */
+#define	PHYS_SDRAM_1			0x40000000	/* Base address */
+#define	PHYS_SDRAM_1_SIZE		0x08000000	/* 128 MB */
+#define	CONFIG_STACKSIZE		0x00010000	/* 128 KB stack */
+#define	CONFIG_SYS_MALLOC_LEN		0x00400000	/* 4 MB for malloc */
+#define	CONFIG_SYS_GBL_DATA_SIZE	128		/* Initial data */
+#define	CONFIG_SYS_MEMTEST_START	0x40000000	/* Memtest start adr */
+#define	CONFIG_SYS_MEMTEST_END		0x40400000	/* 4 MB RAM test */
+#define	CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM_1
+/* Point initial SP in SRAM so SPL can use it too. */
+#define	CONFIG_SYS_INIT_SP_ADDR		0x00002000
+/*
+ * We need to sacrifice first 4 bytes of RAM here to avoid triggering some
+ * strange BUG in ROM corrupting first 4 bytes of RAM when loading U-Boot
+ * binary. In case there was more of this mess, 0x100 bytes are skipped.
+ */
+#define	CONFIG_SYS_TEXT_BASE		0x40000100
+
+/*
+ * U-Boot general configurations
+ */
+#define	CONFIG_SYS_LONGHELP
+#define	CONFIG_SYS_PROMPT	"=> "
+#define	CONFIG_SYS_CBSIZE	1024		/* Console I/O buffer size */
+#define	CONFIG_SYS_PBSIZE	\
+	(CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+						/* Print buffer size */
+#define	CONFIG_SYS_MAXARGS	32		/* Max number of command args */
+#define	CONFIG_SYS_BARGSIZE	CONFIG_SYS_CBSIZE
+						/* Boot argument buffer size */
+#define	CONFIG_VERSION_VARIABLE			/* U-BOOT version */
+#define	CONFIG_AUTO_COMPLETE			/* Command auto complete */
+#define	CONFIG_CMDLINE_EDITING			/* Command history etc */
+#define	CONFIG_SYS_HUSH_PARSER
+#define	CONFIG_SYS_PROMPT_HUSH_PS2	"> "
+
+/*
+ * Serial Driver
+ */
+#define	CONFIG_PL011_SERIAL
+#define	CONFIG_PL011_CLOCK		24000000
+#define	CONFIG_PL01x_PORTS		{ (void *)MXS_UARTDBG_BASE }
+#define	CONFIG_CONS_INDEX		0
+#define	CONFIG_BAUDRATE			115200	/* Default baud rate */
+#define	CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 }
+
+/*
+ * MMC Driver
+ */
+#ifdef	CONFIG_CMD_MMC
+#define	CONFIG_MMC
+#define	CONFIG_GENERIC_MMC
+#define	CONFIG_MXS_MMC
+#endif
+
+/*
+ * NAND
+ */
+#ifdef	CONFIG_CMD_NAND
+#define	CONFIG_NAND_MXS
+#define CONFIG_APBH_DMA
+#define	CONFIG_SYS_MAX_NAND_DEVICE	1
+#define	CONFIG_SYS_NAND_BASE		0x60000000
+#define	CONFIG_SYS_NAND_5_ADDR_CYCLE
+#define	NAND_MAX_CHIPS			8
+
+/* Environment is in NAND */
+#define	CONFIG_ENV_IS_IN_NAND
+#define	CONFIG_ENV_SIZE			(16 * 1024)
+#define	CONFIG_ENV_SIZE_REDUND		CONFIG_ENV_SIZE
+#define	CONFIG_ENV_SECT_SIZE		(128 * 1024)
+#define	CONFIG_ENV_RANGE		(512 * 1024)
+#define	CONFIG_ENV_OFFSET		0x300000
+#define	CONFIG_ENV_OFFSET_REDUND	\
+		(CONFIG_ENV_OFFSET + CONFIG_ENV_RANGE)
+
+#define	CONFIG_CMD_UBI
+#define	CONFIG_CMD_UBIFS
+#define	CONFIG_CMD_MTDPARTS
+#define	CONFIG_RBTREE
+#define	CONFIG_LZO
+#define	CONFIG_MTD_DEVICE
+#define	CONFIG_MTD_PARTITIONS
+#define	MTDIDS_DEFAULT			"nand0=gpmi-nand.0"
+#define	MTDPARTS_DEFAULT			\
+	"mtdparts=gpmi-nand.0:"			\
+		"3m(bootloader)ro,"		\
+		"512k(environment),"		\
+		"512k(redundant-environment),"	\
+		"4m(kernel),"			\
+		"-(filesystem)"
+#endif
+
+/*
+ * Ethernet on SOC (FEC)
+ */
+#ifdef	CONFIG_CMD_NET
+#define	CONFIG_NET_MULTI
+#define	CONFIG_ETHPRIME			"FEC0"
+#define	CONFIG_FEC_MXC
+#define	CONFIG_FEC_MXC_MULTI
+#define	CONFIG_MII
+#define	CONFIG_DISCOVER_PHY
+#define	CONFIG_FEC_XCV_TYPE		RMII
+#endif
+
+/*
+ * I2C
+ */
+#ifdef	CONFIG_CMD_I2C
+#define	CONFIG_I2C_MXS
+#define	CONFIG_HARD_I2C
+#define	CONFIG_SYS_I2C_SPEED		400000
+#endif
+
+/*
+ * EEPROM
+ */
+#ifdef	CONFIG_CMD_EEPROM
+#define	CONFIG_SYS_I2C_MULTI_EEPROMS
+#define	CONFIG_SYS_I2C_EEPROM_ADDR_LEN	2
+#endif
+
+/*
+ * RTC
+ */
+#ifdef	CONFIG_CMD_DATE
+/* Use the internal RTC in the MXS chip */
+#define	CONFIG_RTC_INTERNAL
+#ifdef	CONFIG_RTC_INTERNAL
+#define	CONFIG_RTC_MXS
+#else
+#define	CONFIG_RTC_M41T62
+#define	CONFIG_SYS_I2C_RTC_ADDR		0x68
+#define	CONFIG_SYS_M41T11_BASE_YEAR	2000
+#endif
+#endif
+
+/*
+ * SPI
+ */
+#ifdef	CONFIG_CMD_SPI
+#define	CONFIG_HARD_SPI
+#define	CONFIG_MXS_SPI
+#define	CONFIG_SPI_HALF_DUPLEX
+#define	CONFIG_DEFAULT_SPI_BUS		2
+#define	CONFIG_DEFAULT_SPI_MODE		SPI_MODE_0
+
+/* SPI FLASH */
+#ifdef	CONFIG_CMD_SF
+#define	CONFIG_SPI_FLASH
+#define	CONFIG_SPI_FLASH_STMICRO
+#define	CONFIG_SPI_FLASH_CS		2
+#define	CONFIG_SF_DEFAULT_MODE		SPI_MODE_0
+#define	CONFIG_SF_DEFAULT_SPEED		24000000
+
+#define	CONFIG_ENV_SPI_CS		0
+#define	CONFIG_ENV_SPI_BUS		2
+#define	CONFIG_ENV_SPI_MAX_HZ		24000000
+#define	CONFIG_ENV_SPI_MODE		SPI_MODE_0
+#endif
+#endif
+
+/*
+ * Boot Linux
+ */
+#define	CONFIG_CMDLINE_TAG
+#define	CONFIG_SETUP_MEMORY_TAGS
+#define	CONFIG_BOOTDELAY	3
+#define	CONFIG_BOOTFILE		"uImage"
+#define	CONFIG_BOOTARGS		"console=ttyAM0,115200n8 "
+#define	CONFIG_BOOTCOMMAND	"run bootcmd_net"
+#define	CONFIG_LOADADDR		0x42000000
+#define	CONFIG_SYS_LOAD_ADDR	CONFIG_LOADADDR
+
+/*
+ * Extra Environments
+ */
+#define	CONFIG_EXTRA_ENV_SETTINGS					\
+	"update_nand_full_filename=u-boot.nand\0"			\
+	"update_nand_firmware_filename=u-boot.sb\0"			\
+	"update_nand_firmware_maxsz=0x100000\0"				\
+	"update_nand_stride=0x40\0"	/* MX28 datasheet ch. 12.12 */	\
+	"update_nand_count=0x4\0"	/* MX28 datasheet ch. 12.12 */	\
+	"update_nand_get_fcb_size="	/* Get size of FCB blocks */	\
+		"nand device 0 ; "					\
+		"nand info ; "						\
+		"setexpr fcb_sz ${update_nand_stride} * ${update_nand_count};" \
+		"setexpr update_nand_fcb ${fcb_sz} * ${nand_writesize}\0" \
+	"update_nand_full="		/* Update FCB, DBBT and FW */	\
+		"if tftp ${update_nand_full_filename} ; then "		\
+		"run update_nand_get_fcb_size ; "			\
+		"nand scrub -y 0x0 ${filesize} ; "			\
+		"nand write.raw ${loadaddr} 0x0 ${update_nand_fcb} ; "	\
+		"setexpr update_off ${loadaddr} + ${update_nand_fcb} ; " \
+		"setexpr update_sz ${filesize} - ${update_nand_fcb} ; " \
+		"nand write ${update_off} ${update_nand_fcb} ${update_sz} ; " \
+		"fi\0"							\
+	"update_nand_firmware="		/* Update only firmware */	\
+		"if tftp ${update_nand_firmware_filename} ; then "	\
+		"run update_nand_get_fcb_size ; "			\
+		"setexpr fcb_sz ${update_nand_fcb} * 2 ; " /* FCB + DBBT */ \
+		"setexpr fw_sz ${update_nand_firmware_maxsz} * 2 ; "	\
+		"setexpr fw_off ${fcb_sz} + ${update_nand_firmware_maxsz};" \
+		"nand erase ${fcb_sz} ${fw_sz} ; "			\
+		"nand write ${loadaddr} ${fcb_sz} ${filesize} ; "	\
+		"nand write ${loadaddr} ${fw_off} ${filesize} ; "	\
+		"fi\0"
+
+#endif /* __M28_H__ */
-- 
1.7.6.3

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

* [U-Boot] [PATCH 14/17 V5] M28: Add MMC SPL
  2011-10-21 22:44   ` [U-Boot] [PATCH 14/17 V4] M28: Add MMC SPL Marek Vasut
  2011-10-23 21:42     ` Robert Schwebel
@ 2011-10-31 11:44     ` Marek Vasut
  1 sibling, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-10-31 11:44 UTC (permalink / raw)
  To: u-boot

This patch adds SPL code for the M28 board.

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Andy Fleming <afleming@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
---
 board/denx/m28evk/Makefile       |    8 +
 board/denx/m28evk/m28_init.h     |   41 ++
 board/denx/m28evk/mem_init.c     |  213 +++++++++
 board/denx/m28evk/mmc_boot.c     |  273 ++++++++++++
 board/denx/m28evk/power_init.c   |  913 ++++++++++++++++++++++++++++++++++++++
 board/denx/m28evk/start.S        |  396 +++++++++++++++++
 board/denx/m28evk/u-boot-spl.lds |   87 ++++
 board/denx/m28evk/u-boot.bd      |   14 +
 include/configs/m28evk.h         |    8 +
 9 files changed, 1953 insertions(+), 0 deletions(-)
 create mode 100644 board/denx/m28evk/m28_init.h
 create mode 100644 board/denx/m28evk/mem_init.c
 create mode 100644 board/denx/m28evk/mmc_boot.c
 create mode 100644 board/denx/m28evk/power_init.c
 create mode 100644 board/denx/m28evk/start.S
 create mode 100644 board/denx/m28evk/u-boot-spl.lds
 create mode 100644 board/denx/m28evk/u-boot.bd

V2: Make waiting for powerswitch to be pressed configurable
V3: Squash checkpatch warning
V4: Configure DUART on PWM pins for V1.1 module
V5: Drop clean and distclean targets

diff --git a/board/denx/m28evk/Makefile b/board/denx/m28evk/Makefile
index e6aba9a..47229e6 100644
--- a/board/denx/m28evk/Makefile
+++ b/board/denx/m28evk/Makefile
@@ -25,7 +25,13 @@ include $(TOPDIR)/config.mk
 
 LIB	= $(obj)lib$(BOARD).o
 
+ifndef	CONFIG_SPL_BUILD
 COBJS	:= m28evk.o
+endif
+
+ifdef	CONFIG_SPL_BUILD
+COBJS	:= mem_init.o mmc_boot.o power_init.o
+endif
 
 SRCS	:= $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS))
@@ -33,6 +39,8 @@ OBJS	:= $(addprefix $(obj),$(COBJS))
 $(LIB):	$(obj).depend $(OBJS)
 	$(call cmd_link_o_target, $(OBJS))
 
+all:	$(ALL)
+
 #########################################################################
 
 # defines $(obj).depend target
diff --git a/board/denx/m28evk/m28_init.h b/board/denx/m28evk/m28_init.h
new file mode 100644
index 0000000..98d3631
--- /dev/null
+++ b/board/denx/m28evk/m28_init.h
@@ -0,0 +1,41 @@
+/*
+ * Freescale i.MX28 SPL functions
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef	__M28_INIT_H__
+#define	__M28_INIT_H__
+
+void early_delay(int delay);
+
+void mx28_power_init(void);
+
+#ifdef	CONFIG_SPL_MX28_PSWITCH_WAIT
+void mx28_power_wait_pswitch(void);
+#else
+static inline void mx28_power_wait_pswitch(void) { }
+#endif
+
+void mx28_mem_init(void);
+
+#endif	/* __M28_INIT_H__ */
diff --git a/board/denx/m28evk/mem_init.c b/board/denx/m28evk/mem_init.c
new file mode 100644
index 0000000..066fe0d
--- /dev/null
+++ b/board/denx/m28evk/mem_init.c
@@ -0,0 +1,213 @@
+/*
+ * Freescale i.MX28 RAM init
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/io.h>
+#include <asm/arch/iomux-mx28.h>
+#include <asm/arch/imx-regs.h>
+
+#include "m28_init.h"
+
+uint32_t dram_vals[] = {
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000100, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00010101, 0x01010101, 0x000f0f01, 0x0f02020a,
+	0x00000000, 0x00010101, 0x00000100, 0x00000100, 0x00000000,
+	0x00000002, 0x01010000, 0x05060302, 0x06005003, 0x0a0000c8,
+	0x02009c40, 0x0000030c, 0x0036a609, 0x031a0612, 0x02030202,
+	0x00c8001c, 0x00000000, 0x00000000, 0x00012100, 0xffff0303,
+	0x00012100, 0xffff0303, 0x00012100, 0xffff0303, 0x00012100,
+	0xffff0303, 0x00000003, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000612, 0x01000F02, 0x06120612, 0x00000200,
+	0x00020007, 0xf5014b27, 0xf5014b27, 0xf5014b27, 0xf5014b27,
+	0x07000300, 0x07000300, 0x07000300, 0x07000300, 0x00000006,
+	0x00000000, 0x00000000, 0x01000000, 0x01020408, 0x08040201,
+	0x000f1133, 0x00000000, 0x00001f04, 0x00001f04, 0x00001f04,
+	0x00001f04, 0x00001f04, 0x00001f04, 0x00001f04, 0x00001f04,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00010000, 0x00020304, 0x00000004,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x01010000, 0x01000000, 0x03030000, 0x00010303,
+	0x01020202, 0x00000000, 0x02040303, 0x21002103, 0x00061200,
+	0x06120612, 0x04320432, 0x04320432, 0x00040004, 0x00040004,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00010001
+};
+
+void init_m28_200mhz_ddr2(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dram_vals); i++)
+		writel(dram_vals[i], MXS_DRAM_BASE + (4 * i));
+}
+
+void mx28_mem_init_clock(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/* Gate EMI clock */
+	writel(CLKCTRL_FRAC0_CLKGATEEMI,
+		&clkctrl_regs->hw_clkctrl_frac0_set);
+
+	/* EMI = 205MHz */
+	writel(CLKCTRL_FRAC0_EMIFRAC_MASK,
+		&clkctrl_regs->hw_clkctrl_frac0_set);
+	writel((0x2a << CLKCTRL_FRAC0_EMIFRAC_OFFSET) &
+		CLKCTRL_FRAC0_EMIFRAC_MASK,
+		&clkctrl_regs->hw_clkctrl_frac0_clr);
+
+	/* Ungate EMI clock */
+	writel(CLKCTRL_FRAC0_CLKGATEEMI,
+		&clkctrl_regs->hw_clkctrl_frac0_clr);
+
+	early_delay(11000);
+
+	writel((2 << CLKCTRL_EMI_DIV_EMI_OFFSET) |
+		(1 << CLKCTRL_EMI_DIV_XTAL_OFFSET),
+		&clkctrl_regs->hw_clkctrl_emi);
+
+	/* Unbypass EMI */
+	writel(CLKCTRL_CLKSEQ_BYPASS_EMI,
+		&clkctrl_regs->hw_clkctrl_clkseq_clr);
+
+	early_delay(10000);
+}
+
+void mx28_mem_setup_cpu_and_hbus(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/* CPU = 454MHz and ungate CPU clock */
+	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_frac0,
+		CLKCTRL_FRAC0_CPUFRAC_MASK | CLKCTRL_FRAC0_CLKGATECPU,
+		19 << CLKCTRL_FRAC0_CPUFRAC_OFFSET);
+
+	/* Set CPU bypass */
+	writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
+		&clkctrl_regs->hw_clkctrl_clkseq_set);
+
+	/* HBUS = 151MHz */
+	writel(CLKCTRL_HBUS_DIV_MASK, &clkctrl_regs->hw_clkctrl_hbus_set);
+	writel(((~3) << CLKCTRL_HBUS_DIV_OFFSET) & CLKCTRL_HBUS_DIV_MASK,
+		&clkctrl_regs->hw_clkctrl_hbus_clr);
+
+	early_delay(10000);
+
+	/* CPU clock divider = 1 */
+	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_cpu,
+			CLKCTRL_CPU_DIV_CPU_MASK, 1);
+
+	/* Disable CPU bypass */
+	writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
+		&clkctrl_regs->hw_clkctrl_clkseq_clr);
+}
+
+void mx28_mem_setup_vdda(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	writel((0xc << POWER_VDDACTRL_TRG_OFFSET) |
+		(0x7 << POWER_VDDACTRL_BO_OFFSET_OFFSET) |
+		POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW,
+		&power_regs->hw_power_vddactrl);
+}
+
+void mx28_mem_setup_vddd(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	writel((0x1c << POWER_VDDDCTRL_TRG_OFFSET) |
+		(0x7 << POWER_VDDDCTRL_BO_OFFSET_OFFSET) |
+		POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW,
+		&power_regs->hw_power_vdddctrl);
+}
+
+void mx28_mem_init(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+	struct mx28_pinctrl_regs *pinctrl_regs =
+		(struct mx28_pinctrl_regs *)MXS_PINCTRL_BASE;
+
+	/* Set DDR2 mode */
+	writel(PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2,
+		&pinctrl_regs->hw_pinctrl_emi_ds_ctrl_set);
+
+	/* Power up PLL0 */
+	writel(CLKCTRL_PLL0CTRL0_POWER,
+		&clkctrl_regs->hw_clkctrl_pll0ctrl0_set);
+
+	early_delay(11000);
+
+	mx28_mem_init_clock();
+
+	mx28_mem_setup_vdda();
+
+	/*
+	 * Configure the DRAM registers
+	 */
+
+	/* Clear START bit from DRAM_CTL16 */
+	clrbits_le32(MXS_DRAM_BASE + 0x40, 1);
+
+	init_m28_200mhz_ddr2();
+
+	/* Clear SREFRESH bit from DRAM_CTL17 */
+	clrbits_le32(MXS_DRAM_BASE + 0x44, 1);
+
+	/* Set START bit in DRAM_CTL16 */
+	setbits_le32(MXS_DRAM_BASE + 0x40, 1);
+
+	/* Wait for bit 20 (DRAM init complete) in DRAM_CTL58 */
+	while (!(readl(MXS_DRAM_BASE + 0xe8) & (1 << 20)))
+		;
+
+	mx28_mem_setup_vddd();
+
+	early_delay(10000);
+
+	mx28_mem_setup_cpu_and_hbus();
+}
diff --git a/board/denx/m28evk/mmc_boot.c b/board/denx/m28evk/mmc_boot.c
new file mode 100644
index 0000000..86d3ab5
--- /dev/null
+++ b/board/denx/m28evk/mmc_boot.c
@@ -0,0 +1,273 @@
+/*
+ * Freescale i.MX28 Boot setup
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/io.h>
+#include <asm/arch/iomux-mx28.h>
+
+#include "m28_init.h"
+
+/*
+ * This delay function is intended to be used only in early stage of boot, where
+ * clock are not set up yet. The timer used here is reset on every boot and
+ * takes a few seconds to roll. The boot doesn't take that long, so to keep the
+ * code simple, it doesn't take rolling into consideration.
+ */
+#define	HW_DIGCTRL_MICROSECONDS	0x8001c0c0
+void early_delay(int delay)
+{
+	uint32_t st = readl(HW_DIGCTRL_MICROSECONDS);
+	st += delay;
+	while (st > readl(HW_DIGCTRL_MICROSECONDS))
+		;
+}
+
+#define	MUX_CONFIG_LED	(MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL)
+#define	MUX_CONFIG_LCD	(MXS_PAD_3V3 | MXS_PAD_4MA)
+#define	MUX_CONFIG_TSC	(MXS_PAD_3V3 | MXS_PAD_8MA | MXS_PAD_PULLUP)
+#define	MUX_CONFIG_SSP0	(MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_PULLUP)
+#define	MUX_CONFIG_SSP2	(MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_PULLUP)
+#define	MUX_CONFIG_GPMI	(MXS_PAD_1V8 | MXS_PAD_4MA | MXS_PAD_NOPULL)
+#define	MUX_CONFIG_ENET	(MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_PULLUP)
+#define	MUX_CONFIG_EMI	(MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_NOPULL)
+
+const iomux_cfg_t iomux_setup[] = {
+	/* LED */
+	MX28_PAD_ENET0_RXD3__GPIO_4_10 | MUX_CONFIG_LED,
+
+	/* framebuffer */
+	MX28_PAD_LCD_D00__LCD_D0 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D01__LCD_D1 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D02__LCD_D2 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D03__LCD_D3 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D04__LCD_D4 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D05__LCD_D5 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D06__LCD_D6 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D07__LCD_D7 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D08__LCD_D8 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D09__LCD_D9 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D10__LCD_D10 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D11__LCD_D11 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D12__LCD_D12 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D13__LCD_D13 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D14__LCD_D14 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D15__LCD_D15 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D16__LCD_D16 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D17__LCD_D17 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D18__LCD_D18 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D19__LCD_D19 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D20__LCD_D20 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D21__LCD_D21 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D22__LCD_D22 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_D23__LCD_D23 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_RD_E__LCD_VSYNC | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_WR_RWN__LCD_HSYNC | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_RS__LCD_DOTCLK | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_CS__LCD_CS | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_VSYNC__LCD_VSYNC | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_HSYNC__LCD_HSYNC | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_DOTCLK__LCD_DOTCLK | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_ENABLE__GPIO_1_31 | MUX_CONFIG_LCD,
+	MX28_PAD_LCD_RESET__GPIO_3_30 | MUX_CONFIG_LCD,
+
+	/* UART1 */
+	MX28_PAD_PWM0__DUART_RX,
+	MX28_PAD_PWM1__DUART_TX,
+	MX28_PAD_AUART0_TX__DUART_RTS,
+	MX28_PAD_AUART0_RX__DUART_CTS,
+
+	/* UART2 */
+	MX28_PAD_AUART1_RX__AUART1_RX,
+	MX28_PAD_AUART1_TX__AUART1_TX,
+	MX28_PAD_AUART1_RTS__AUART1_RTS,
+	MX28_PAD_AUART1_CTS__AUART1_CTS,
+
+	/* CAN */
+	MX28_PAD_GPMI_RDY2__CAN0_TX,
+	MX28_PAD_GPMI_RDY3__CAN0_RX,
+
+	/* I2C */
+	MX28_PAD_I2C0_SCL__I2C0_SCL,
+	MX28_PAD_I2C0_SDA__I2C0_SDA,
+
+	/* TSC2007 */
+	MX28_PAD_SAIF0_MCLK__GPIO_3_20 | MUX_CONFIG_TSC,
+
+	/* MMC0 */
+	MX28_PAD_SSP0_DATA0__SSP0_D0 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA1__SSP0_D1 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA2__SSP0_D2 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA3__SSP0_D3 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA4__SSP0_D4 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA5__SSP0_D5 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA6__SSP0_D6 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DATA7__SSP0_D7 | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_CMD__SSP0_CMD | MUX_CONFIG_SSP0,
+	MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT |
+		(MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_NOPULL),
+	MX28_PAD_SSP0_SCK__SSP0_SCK |
+		(MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_NOPULL),
+	MX28_PAD_PWM3__GPIO_3_28 | MUX_CONFIG_SSP0,	/* Power .. FIXME */
+	MX28_PAD_AUART2_CTS__GPIO_3_10,	/* WP ... FIXME */
+
+	/* GPMI NAND */
+	MX28_PAD_GPMI_D00__GPMI_D0 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D01__GPMI_D1 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D02__GPMI_D2 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D03__GPMI_D3 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D04__GPMI_D4 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D05__GPMI_D5 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D06__GPMI_D6 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_D07__GPMI_D7 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_CE0N__GPMI_CE0N | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_RDY0__GPMI_READY0 | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_RDN__GPMI_RDN |
+		(MXS_PAD_1V8 | MXS_PAD_8MA | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_WRN__GPMI_WRN | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_ALE__GPMI_ALE | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_CLE__GPMI_CLE | MUX_CONFIG_GPMI,
+	MX28_PAD_GPMI_RESETN__GPMI_RESETN | MUX_CONFIG_GPMI,
+
+	/* FEC Ethernet */
+	MX28_PAD_ENET0_MDC__ENET0_MDC | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_MDIO__ENET0_MDIO | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_RX_EN__ENET0_RX_EN | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_TX_EN__ENET0_TX_EN | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_RXD0__ENET0_RXD0 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_RXD1__ENET0_RXD1 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_TXD0__ENET0_TXD0 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_TXD1__ENET0_TXD1 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET_CLK__CLKCTRL_ENET | MUX_CONFIG_ENET,
+
+	MX28_PAD_ENET0_COL__ENET1_TX_EN | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_CRS__ENET1_RX_EN | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_RXD2__ENET1_RXD0 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_RXD3__ENET1_RXD1 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_TXD2__ENET1_TXD0 | MUX_CONFIG_ENET,
+	MX28_PAD_ENET0_TXD3__ENET1_TXD1 | MUX_CONFIG_ENET,
+
+	/* I2C */
+	MX28_PAD_I2C0_SCL__I2C0_SCL,
+	MX28_PAD_I2C0_SDA__I2C0_SDA,
+
+	/* EMI */
+	MX28_PAD_EMI_D00__EMI_DATA0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D01__EMI_DATA1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D02__EMI_DATA2 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D03__EMI_DATA3 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D04__EMI_DATA4 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D05__EMI_DATA5 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D06__EMI_DATA6 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D07__EMI_DATA7 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D08__EMI_DATA8 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D09__EMI_DATA9 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D10__EMI_DATA10 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D11__EMI_DATA11 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D12__EMI_DATA12 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D13__EMI_DATA13 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D14__EMI_DATA14 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_D15__EMI_DATA15 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_ODT0__EMI_ODT0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DQM0__EMI_DQM0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_ODT1__EMI_ODT1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DQM1__EMI_DQM1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DDR_OPEN_FB__EMI_DDR_OPEN_FEEDBACK | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_CLK__EMI_CLK | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DQS0__EMI_DQS0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DQS1__EMI_DQS1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_DDR_OPEN__EMI_DDR_OPEN | MUX_CONFIG_EMI,
+
+	MX28_PAD_EMI_A00__EMI_ADDR0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A01__EMI_ADDR1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A02__EMI_ADDR2 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A03__EMI_ADDR3 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A04__EMI_ADDR4 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A05__EMI_ADDR5 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A06__EMI_ADDR6 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A07__EMI_ADDR7 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A08__EMI_ADDR8 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A09__EMI_ADDR9 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A10__EMI_ADDR10 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A11__EMI_ADDR11 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A12__EMI_ADDR12 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A13__EMI_ADDR13 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_A14__EMI_ADDR14 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_BA0__EMI_BA0 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_BA1__EMI_BA1 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_BA2__EMI_BA2 | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_CASN__EMI_CASN | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_RASN__EMI_RASN | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_WEN__EMI_WEN | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_CE0N__EMI_CE0N | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_CE1N__EMI_CE1N | MUX_CONFIG_EMI,
+	MX28_PAD_EMI_CKE__EMI_CKE | MUX_CONFIG_EMI,
+
+	/* SPI2 (for flash) */
+	MX28_PAD_SSP2_SCK__SSP2_SCK | MUX_CONFIG_SSP2,
+	MX28_PAD_SSP2_MOSI__SSP2_CMD | MUX_CONFIG_SSP2,
+	MX28_PAD_SSP2_MISO__SSP2_D0 | MUX_CONFIG_SSP2,
+	MX28_PAD_SSP2_SS0__SSP2_D3 |
+		(MXS_PAD_3V3 | MXS_PAD_8MA | MXS_PAD_PULLUP),
+};
+
+void board_init_ll(void)
+{
+	mxs_iomux_setup_multiple_pads(iomux_setup, ARRAY_SIZE(iomux_setup));
+	mx28_power_init();
+	mx28_mem_init();
+	mx28_power_wait_pswitch();
+}
+
+/* Support aparatus */
+inline void board_init_f(unsigned long bootflag)
+{
+	for (;;)
+		;
+}
+
+inline void board_init_r(gd_t *id, ulong dest_addr)
+{
+	for (;;)
+		;
+}
+
+inline int printf(const char *fmt, ...)
+{
+	return 0;
+}
+
+inline void __coloured_LED_init(void) {}
+inline void __red_LED_on(void) {}
+void coloured_LED_init(void)
+	__attribute__((weak, alias("__coloured_LED_init")));
+void red_LED_on(void)
+	__attribute__((weak, alias("__red_LED_on")));
+void hang(void) __attribute__ ((noreturn));
+void hang(void)
+{
+	for (;;)
+		;
+}
diff --git a/board/denx/m28evk/power_init.c b/board/denx/m28evk/power_init.c
new file mode 100644
index 0000000..27322b4
--- /dev/null
+++ b/board/denx/m28evk/power_init.c
@@ -0,0 +1,913 @@
+/*
+ * Freescale i.MX28 Boot PMIC init
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+
+#include "m28_init.h"
+
+void mx28_power_clock2xtal(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	/* Set XTAL as CPU reference clock */
+	writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
+		&clkctrl_regs->hw_clkctrl_clkseq_set);
+}
+
+void mx28_power_clock2pll(void)
+{
+	struct mx28_clkctrl_regs *clkctrl_regs =
+		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+	writel(CLKCTRL_PLL0CTRL0_POWER,
+		&clkctrl_regs->hw_clkctrl_pll0ctrl0_set);
+	early_delay(100);
+	writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
+		&clkctrl_regs->hw_clkctrl_clkseq_clr);
+}
+
+void mx28_power_clear_auto_restart(void)
+{
+	struct mx28_rtc_regs *rtc_regs =
+		(struct mx28_rtc_regs *)MXS_RTC_BASE;
+
+	writel(RTC_CTRL_SFTRST, &rtc_regs->hw_rtc_ctrl_clr);
+	while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_SFTRST)
+		;
+
+	writel(RTC_CTRL_CLKGATE, &rtc_regs->hw_rtc_ctrl_clr);
+	while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_CLKGATE)
+		;
+
+	/*
+	 * Due to the hardware design bug of mx28 EVK-A
+	 * we need to set the AUTO_RESTART bit.
+	 */
+	if (readl(&rtc_regs->hw_rtc_persistent0) & RTC_PERSISTENT0_AUTO_RESTART)
+		return;
+
+	while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK)
+		;
+
+	setbits_le32(&rtc_regs->hw_rtc_persistent0,
+			RTC_PERSISTENT0_AUTO_RESTART);
+	writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_set);
+	writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_clr);
+	while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK)
+		;
+	while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_STALE_REGS_MASK)
+		;
+}
+
+void mx28_power_set_linreg(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/* Set linear regulator 25mV below switching converter */
+	clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+			POWER_VDDDCTRL_LINREG_OFFSET_MASK,
+			POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
+
+	clrsetbits_le32(&power_regs->hw_power_vddactrl,
+			POWER_VDDACTRL_LINREG_OFFSET_MASK,
+			POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW);
+
+	clrsetbits_le32(&power_regs->hw_power_vddioctrl,
+			POWER_VDDIOCTRL_LINREG_OFFSET_MASK,
+			POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW);
+}
+
+void mx28_power_setup_5v_detect(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/* Start 5V detection */
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+			POWER_5VCTRL_VBUSVALID_TRSH_MASK,
+			POWER_5VCTRL_VBUSVALID_TRSH_4V4 |
+			POWER_5VCTRL_PWRUP_VBUS_CMPS);
+}
+
+void mx28_src_power_init(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/* Improve efficieny and reduce transient ripple */
+	writel(POWER_LOOPCTRL_TOGGLE_DIF | POWER_LOOPCTRL_EN_CM_HYST |
+		POWER_LOOPCTRL_EN_DF_HYST, &power_regs->hw_power_loopctrl_set);
+
+	clrsetbits_le32(&power_regs->hw_power_dclimits,
+			POWER_DCLIMITS_POSLIMIT_BUCK_MASK,
+			0x30 << POWER_DCLIMITS_POSLIMIT_BUCK_OFFSET);
+
+	setbits_le32(&power_regs->hw_power_battmonitor,
+			POWER_BATTMONITOR_EN_BATADJ);
+
+	/* Increase the RCSCALE level for quick DCDC response to dynamic load */
+	clrsetbits_le32(&power_regs->hw_power_loopctrl,
+			POWER_LOOPCTRL_EN_RCSCALE_MASK,
+			POWER_LOOPCTRL_RCSCALE_THRESH |
+			POWER_LOOPCTRL_EN_RCSCALE_8X);
+
+	clrsetbits_le32(&power_regs->hw_power_minpwr,
+			POWER_MINPWR_HALFFETS, POWER_MINPWR_DOUBLE_FETS);
+
+	/* 5V to battery handoff ... FIXME */
+	setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
+	early_delay(30);
+	clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
+}
+
+void mx28_power_init_4p2_params(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/* Setup 4P2 parameters */
+	clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
+		POWER_DCDC4P2_CMPTRIP_MASK | POWER_DCDC4P2_TRG_MASK,
+		POWER_DCDC4P2_TRG_4V2 | (31 << POWER_DCDC4P2_CMPTRIP_OFFSET));
+
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+		POWER_5VCTRL_HEADROOM_ADJ_MASK,
+		0x4 << POWER_5VCTRL_HEADROOM_ADJ_OFFSET);
+
+	clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
+		POWER_DCDC4P2_DROPOUT_CTRL_MASK,
+		POWER_DCDC4P2_DROPOUT_CTRL_100MV |
+		POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL);
+
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+		POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
+		0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
+}
+
+void mx28_enable_4p2_dcdc_input(int xfer)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp, vbus_thresh, vbus_5vdetect, pwd_bo;
+	uint32_t prev_5v_brnout, prev_5v_droop;
+
+	prev_5v_brnout = readl(&power_regs->hw_power_5vctrl) &
+				POWER_5VCTRL_PWDN_5VBRNOUT;
+	prev_5v_droop = readl(&power_regs->hw_power_ctrl) &
+				POWER_CTRL_ENIRQ_VDD5V_DROOP;
+
+	clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_PWDN_5VBRNOUT);
+	writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
+		&power_regs->hw_power_reset);
+
+	clrbits_le32(&power_regs->hw_power_ctrl, POWER_CTRL_ENIRQ_VDD5V_DROOP);
+
+	if (xfer && (readl(&power_regs->hw_power_5vctrl) &
+			POWER_5VCTRL_ENABLE_DCDC)) {
+		return;
+	}
+
+	/*
+	 * Recording orignal values that will be modified temporarlily
+	 * to handle a chip bug. See chip errata for CQ ENGR00115837
+	 */
+	tmp = readl(&power_regs->hw_power_5vctrl);
+	vbus_thresh = tmp & POWER_5VCTRL_VBUSVALID_TRSH_MASK;
+	vbus_5vdetect = tmp & POWER_5VCTRL_VBUSVALID_5VDETECT;
+
+	pwd_bo = readl(&power_regs->hw_power_minpwr) & POWER_MINPWR_PWD_BO;
+
+	/*
+	 * Disable mechanisms that get erroneously tripped by when setting
+	 * the DCDC4P2 EN_DCDC
+	 */
+	clrbits_le32(&power_regs->hw_power_5vctrl,
+		POWER_5VCTRL_VBUSVALID_5VDETECT |
+		POWER_5VCTRL_VBUSVALID_TRSH_MASK);
+
+	writel(POWER_MINPWR_PWD_BO, &power_regs->hw_power_minpwr_set);
+
+	if (xfer) {
+		setbits_le32(&power_regs->hw_power_5vctrl,
+				POWER_5VCTRL_DCDC_XFER);
+		early_delay(20);
+		clrbits_le32(&power_regs->hw_power_5vctrl,
+				POWER_5VCTRL_DCDC_XFER);
+
+		setbits_le32(&power_regs->hw_power_5vctrl,
+				POWER_5VCTRL_ENABLE_DCDC);
+	} else {
+		setbits_le32(&power_regs->hw_power_dcdc4p2,
+				POWER_DCDC4P2_ENABLE_DCDC);
+	}
+
+	early_delay(25);
+
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+			POWER_5VCTRL_VBUSVALID_TRSH_MASK, vbus_thresh);
+
+	if (vbus_5vdetect)
+		writel(vbus_5vdetect, &power_regs->hw_power_5vctrl_set);
+
+	if (!pwd_bo)
+		clrbits_le32(&power_regs->hw_power_minpwr, POWER_MINPWR_PWD_BO);
+
+	while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ)
+		clrbits_le32(&power_regs->hw_power_ctrl,
+				POWER_CTRL_VBUS_VALID_IRQ);
+
+	if (prev_5v_brnout) {
+		writel(POWER_5VCTRL_PWDN_5VBRNOUT,
+			&power_regs->hw_power_5vctrl_set);
+		writel(POWER_RESET_UNLOCK_KEY,
+			&power_regs->hw_power_reset);
+	} else {
+		writel(POWER_5VCTRL_PWDN_5VBRNOUT,
+			&power_regs->hw_power_5vctrl_clr);
+		writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
+			&power_regs->hw_power_reset);
+	}
+
+	while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VDD5V_DROOP_IRQ)
+		clrbits_le32(&power_regs->hw_power_ctrl,
+				POWER_CTRL_VDD5V_DROOP_IRQ);
+
+	if (prev_5v_droop)
+		clrbits_le32(&power_regs->hw_power_ctrl,
+				POWER_CTRL_ENIRQ_VDD5V_DROOP);
+	else
+		setbits_le32(&power_regs->hw_power_ctrl,
+				POWER_CTRL_ENIRQ_VDD5V_DROOP);
+}
+
+void mx28_power_init_4p2_regulator(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp, tmp2;
+
+	setbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_ENABLE_4P2);
+
+	writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_set);
+
+	writel(POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
+		&power_regs->hw_power_5vctrl_clr);
+	clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_TRG_MASK);
+
+	/* Power up the 4p2 rail and logic/control */
+	writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+		&power_regs->hw_power_5vctrl_clr);
+
+	/*
+	 * Start charging up the 4p2 capacitor. We ramp of this charge
+	 * gradually to avoid large inrush current from the 5V cable which can
+	 * cause transients/problems
+	 */
+	mx28_enable_4p2_dcdc_input(0);
+
+	if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) {
+		/*
+		 * If we arrived here, we were unable to recover from mx23 chip
+		 * errata 5837. 4P2 is disabled and sufficient battery power is
+		 * not present. Exiting to not enable DCDC power during 5V
+		 * connected state.
+		 */
+		clrbits_le32(&power_regs->hw_power_dcdc4p2,
+			POWER_DCDC4P2_ENABLE_DCDC);
+		writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+			&power_regs->hw_power_5vctrl_set);
+		hang();
+	}
+
+	/*
+	 * Here we set the 4p2 brownout level to something very close to 4.2V.
+	 * We then check the brownout status. If the brownout status is false,
+	 * the voltage is already close to the target voltage of 4.2V so we
+	 * can go ahead and set the 4P2 current limit to our max target limit.
+	 * If the brownout status is true, we need to ramp us the current limit
+	 * so that we don't cause large inrush current issues. We step up the
+	 * current limit until the brownout status is false or until we've
+	 * reached our maximum defined 4p2 current limit.
+	 */
+	clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
+			POWER_DCDC4P2_BO_MASK,
+			22 << POWER_DCDC4P2_BO_OFFSET);	/* 4.15V */
+
+	if (!(readl(&power_regs->hw_power_sts) & POWER_STS_DCDC_4P2_BO)) {
+		setbits_le32(&power_regs->hw_power_5vctrl,
+			0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
+	} else {
+		tmp = (readl(&power_regs->hw_power_5vctrl) &
+			POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK) >>
+			POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET;
+		while (tmp < 0x3f) {
+			if (!(readl(&power_regs->hw_power_sts) &
+					POWER_STS_DCDC_4P2_BO)) {
+				tmp = readl(&power_regs->hw_power_5vctrl);
+				tmp |= POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK;
+				early_delay(100);
+				writel(tmp, &power_regs->hw_power_5vctrl);
+				break;
+			} else {
+				tmp++;
+				tmp2 = readl(&power_regs->hw_power_5vctrl);
+				tmp2 &= ~POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK;
+				tmp2 |= tmp <<
+					POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET;
+				writel(tmp2, &power_regs->hw_power_5vctrl);
+				early_delay(100);
+			}
+		}
+	}
+
+	clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_BO_MASK);
+	writel(POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+}
+
+void mx28_power_init_dcdc_4p2_source(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	if (!(readl(&power_regs->hw_power_dcdc4p2) &
+		POWER_DCDC4P2_ENABLE_DCDC)) {
+		hang();
+	}
+
+	mx28_enable_4p2_dcdc_input(1);
+
+	if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) {
+		clrbits_le32(&power_regs->hw_power_dcdc4p2,
+			POWER_DCDC4P2_ENABLE_DCDC);
+		writel(POWER_5VCTRL_ENABLE_DCDC,
+			&power_regs->hw_power_5vctrl_clr);
+		writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+			&power_regs->hw_power_5vctrl_set);
+	}
+}
+
+void mx28_power_enable_4p2(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t vdddctrl, vddactrl, vddioctrl;
+	uint32_t tmp;
+
+	vdddctrl = readl(&power_regs->hw_power_vdddctrl);
+	vddactrl = readl(&power_regs->hw_power_vddactrl);
+	vddioctrl = readl(&power_regs->hw_power_vddioctrl);
+
+	setbits_le32(&power_regs->hw_power_vdddctrl,
+		POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG |
+		POWER_VDDDCTRL_PWDN_BRNOUT);
+
+	setbits_le32(&power_regs->hw_power_vddactrl,
+		POWER_VDDACTRL_DISABLE_FET | POWER_VDDACTRL_ENABLE_LINREG |
+		POWER_VDDACTRL_PWDN_BRNOUT);
+
+	setbits_le32(&power_regs->hw_power_vddioctrl,
+		POWER_VDDIOCTRL_DISABLE_FET | POWER_VDDIOCTRL_PWDN_BRNOUT);
+
+	mx28_power_init_4p2_params();
+	mx28_power_init_4p2_regulator();
+
+	/* Shutdown battery (none present) */
+	clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_BO_MASK);
+	writel(POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+	writel(POWER_CTRL_ENIRQ_DCDC4P2_BO, &power_regs->hw_power_ctrl_clr);
+
+	mx28_power_init_dcdc_4p2_source();
+
+	writel(vdddctrl, &power_regs->hw_power_vdddctrl);
+	early_delay(20);
+	writel(vddactrl, &power_regs->hw_power_vddactrl);
+	early_delay(20);
+	writel(vddioctrl, &power_regs->hw_power_vddioctrl);
+
+	/*
+	 * Check if FET is enabled on either powerout and if so,
+	 * disable load.
+	 */
+	tmp = 0;
+	tmp |= !(readl(&power_regs->hw_power_vdddctrl) &
+			POWER_VDDDCTRL_DISABLE_FET);
+	tmp |= !(readl(&power_regs->hw_power_vddactrl) &
+			POWER_VDDACTRL_DISABLE_FET);
+	tmp |= !(readl(&power_regs->hw_power_vddioctrl) &
+			POWER_VDDIOCTRL_DISABLE_FET);
+	if (tmp)
+		writel(POWER_CHARGE_ENABLE_LOAD,
+			&power_regs->hw_power_charge_clr);
+}
+
+void mx28_boot_valid_5v(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/*
+	 * Use VBUSVALID level instead of VDD5V_GT_VDDIO level to trigger a 5V
+	 * disconnect event. FIXME
+	 */
+	writel(POWER_5VCTRL_VBUSVALID_5VDETECT,
+		&power_regs->hw_power_5vctrl_set);
+
+	/* Configure polarity to check for 5V disconnection. */
+	writel(POWER_CTRL_POLARITY_VBUSVALID |
+		POWER_CTRL_POLARITY_VDD5V_GT_VDDIO,
+		&power_regs->hw_power_ctrl_clr);
+
+	writel(POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_VDD5V_GT_VDDIO_IRQ,
+		&power_regs->hw_power_ctrl_clr);
+
+	mx28_power_enable_4p2();
+}
+
+void mx28_powerdown(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	writel(POWER_RESET_UNLOCK_KEY, &power_regs->hw_power_reset);
+	writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
+		&power_regs->hw_power_reset);
+}
+
+void mx28_handle_5v_conflict(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp;
+
+	setbits_le32(&power_regs->hw_power_vddioctrl,
+			POWER_VDDIOCTRL_BO_OFFSET_MASK);
+
+	for (;;) {
+		tmp = readl(&power_regs->hw_power_sts);
+
+		if (tmp & POWER_STS_VDDIO_BO) {
+			mx28_powerdown();
+			break;
+		}
+
+		if (tmp & POWER_STS_VDD5V_GT_VDDIO) {
+			mx28_boot_valid_5v();
+			break;
+		} else {
+			mx28_powerdown();
+			break;
+		}
+	}
+}
+
+int mx28_get_batt_volt(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t volt = readl(&power_regs->hw_power_battmonitor);
+	volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
+	volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
+	volt *= 8;
+	return volt;
+}
+
+int mx28_is_batt_ready(void)
+{
+	return (mx28_get_batt_volt() >= 3600);
+}
+
+void mx28_5v_boot(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/*
+	 * NOTE: In original IMX-Bootlets, this also checks for VBUSVALID,
+	 * but their implementation always returns 1 so we omit it here.
+	 */
+	if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+		mx28_boot_valid_5v();
+		return;
+	}
+
+	early_delay(1000);
+	if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+		mx28_boot_valid_5v();
+		return;
+	}
+
+	mx28_handle_5v_conflict();
+}
+
+void mx28_init_batt_bo(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	/* Brownout at 3V */
+	clrsetbits_le32(&power_regs->hw_power_battmonitor,
+		POWER_BATTMONITOR_BRWNOUT_LVL_MASK,
+		15 << POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET);
+
+	writel(POWER_CTRL_BATT_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+	writel(POWER_CTRL_ENIRQ_BATT_BO, &power_regs->hw_power_ctrl_clr);
+}
+
+void mx28_switch_vddd_to_dcdc_source(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+		POWER_VDDDCTRL_LINREG_OFFSET_MASK,
+		POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
+
+	clrbits_le32(&power_regs->hw_power_vdddctrl,
+		POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG |
+		POWER_VDDDCTRL_DISABLE_STEPPING);
+}
+
+int mx28_is_batt_good(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t volt;
+
+	volt = readl(&power_regs->hw_power_battmonitor);
+	volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
+	volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
+	volt *= 8;
+
+	if ((volt >= 2400) && (volt <= 4300))
+		return 1;
+
+	clrsetbits_le32(&power_regs->hw_power_5vctrl,
+		POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
+		0x3 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
+	writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+		&power_regs->hw_power_5vctrl_clr);
+
+	clrsetbits_le32(&power_regs->hw_power_charge,
+		POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
+		POWER_CHARGE_STOP_ILIMIT_10MA | 0x3);
+
+	writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_clr);
+	writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+		&power_regs->hw_power_5vctrl_clr);
+
+	early_delay(500000);
+
+	volt = readl(&power_regs->hw_power_battmonitor);
+	volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
+	volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
+	volt *= 8;
+
+	if (volt >= 3500)
+		return 0;
+
+	if (volt >= 2400)
+		return 1;
+
+	writel(POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
+		&power_regs->hw_power_charge_clr);
+	writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_set);
+
+	return 0;
+}
+
+void mx28_power_configure_power_source(void)
+{
+	mx28_src_power_init();
+
+	mx28_5v_boot();
+	mx28_power_clock2pll();
+
+	mx28_init_batt_bo();
+	mx28_switch_vddd_to_dcdc_source();
+}
+
+void mx28_enable_output_rail_protection(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
+		POWER_CTRL_VDDIO_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+
+	setbits_le32(&power_regs->hw_power_vdddctrl,
+			POWER_VDDDCTRL_PWDN_BRNOUT);
+
+	setbits_le32(&power_regs->hw_power_vddactrl,
+			POWER_VDDACTRL_PWDN_BRNOUT);
+
+	setbits_le32(&power_regs->hw_power_vddioctrl,
+			POWER_VDDIOCTRL_PWDN_BRNOUT);
+}
+
+int mx28_get_vddio_power_source_off(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp;
+
+	if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+		tmp = readl(&power_regs->hw_power_vddioctrl);
+		if (tmp & POWER_VDDIOCTRL_DISABLE_FET) {
+			if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
+				POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
+				return 1;
+			}
+		}
+
+		if (!(readl(&power_regs->hw_power_5vctrl) &
+			POWER_5VCTRL_ENABLE_DCDC)) {
+			if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
+				POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
+				return 1;
+			}
+		}
+	}
+
+	return 0;
+
+}
+
+int mx28_get_vddd_power_source_off(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t tmp;
+
+	tmp = readl(&power_regs->hw_power_vdddctrl);
+	if (tmp & POWER_VDDDCTRL_DISABLE_FET) {
+		if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
+			POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
+			return 1;
+		}
+	}
+
+	if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+		if (!(readl(&power_regs->hw_power_5vctrl) &
+			POWER_5VCTRL_ENABLE_DCDC)) {
+			return 1;
+		}
+	}
+
+	if (!(tmp & POWER_VDDDCTRL_ENABLE_LINREG)) {
+		if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
+			POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW) {
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+void mx28_power_set_vddio(uint32_t new_target, uint32_t new_brownout)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t cur_target, diff, bo_int = 0;
+	uint32_t powered_by_linreg = 0;
+
+	new_brownout = new_target - new_brownout;
+
+	cur_target = readl(&power_regs->hw_power_vddioctrl);
+	cur_target &= POWER_VDDIOCTRL_TRG_MASK;
+	cur_target *= 50;	/* 50 mV step*/
+	cur_target += 2800;	/* 2800 mV lowest */
+
+	powered_by_linreg = mx28_get_vddio_power_source_off();
+	if (new_target > cur_target) {
+
+		if (powered_by_linreg) {
+			bo_int = readl(&power_regs->hw_power_vddioctrl);
+			clrbits_le32(&power_regs->hw_power_vddioctrl,
+					POWER_CTRL_ENIRQ_VDDIO_BO);
+		}
+
+		setbits_le32(&power_regs->hw_power_vddioctrl,
+				POWER_VDDIOCTRL_BO_OFFSET_MASK);
+		do {
+			if (new_target - cur_target > 100)
+				diff = cur_target + 100;
+			else
+				diff = new_target;
+
+			diff -= 2800;
+			diff /= 50;
+
+			clrsetbits_le32(&power_regs->hw_power_vddioctrl,
+				POWER_VDDIOCTRL_TRG_MASK, diff);
+
+			if (powered_by_linreg)
+				early_delay(1500);
+			else {
+				while (!(readl(&power_regs->hw_power_sts) &
+					POWER_STS_DC_OK))
+					;
+
+			}
+
+			cur_target = readl(&power_regs->hw_power_vddioctrl);
+			cur_target &= POWER_VDDIOCTRL_TRG_MASK;
+			cur_target *= 50;	/* 50 mV step*/
+			cur_target += 2800;	/* 2800 mV lowest */
+		} while (new_target > cur_target);
+
+		if (powered_by_linreg) {
+			writel(POWER_CTRL_VDDIO_BO_IRQ,
+				&power_regs->hw_power_ctrl_clr);
+			if (bo_int & POWER_CTRL_ENIRQ_VDDIO_BO)
+				setbits_le32(&power_regs->hw_power_vddioctrl,
+						POWER_CTRL_ENIRQ_VDDIO_BO);
+		}
+	} else {
+		do {
+			if (cur_target - new_target > 100)
+				diff = cur_target - 100;
+			else
+				diff = new_target;
+
+			diff -= 2800;
+			diff /= 50;
+
+			clrsetbits_le32(&power_regs->hw_power_vddioctrl,
+				POWER_VDDIOCTRL_TRG_MASK, diff);
+
+			if (powered_by_linreg)
+				early_delay(1500);
+			else {
+				while (!(readl(&power_regs->hw_power_sts) &
+					POWER_STS_DC_OK))
+					;
+
+			}
+
+			cur_target = readl(&power_regs->hw_power_vddioctrl);
+			cur_target &= POWER_VDDIOCTRL_TRG_MASK;
+			cur_target *= 50;	/* 50 mV step*/
+			cur_target += 2800;	/* 2800 mV lowest */
+		} while (new_target < cur_target);
+	}
+
+	clrsetbits_le32(&power_regs->hw_power_vddioctrl,
+			POWER_VDDDCTRL_BO_OFFSET_MASK,
+			new_brownout << POWER_VDDDCTRL_BO_OFFSET_OFFSET);
+}
+
+void mx28_power_set_vddd(uint32_t new_target, uint32_t new_brownout)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+	uint32_t cur_target, diff, bo_int = 0;
+	uint32_t powered_by_linreg = 0;
+
+	new_brownout = new_target - new_brownout;
+
+	cur_target = readl(&power_regs->hw_power_vdddctrl);
+	cur_target &= POWER_VDDDCTRL_TRG_MASK;
+	cur_target *= 25;	/* 25 mV step*/
+	cur_target += 800;	/* 800 mV lowest */
+
+	powered_by_linreg = mx28_get_vddd_power_source_off();
+	if (new_target > cur_target) {
+		if (powered_by_linreg) {
+			bo_int = readl(&power_regs->hw_power_vdddctrl);
+			clrbits_le32(&power_regs->hw_power_vdddctrl,
+					POWER_CTRL_ENIRQ_VDDD_BO);
+		}
+
+		setbits_le32(&power_regs->hw_power_vdddctrl,
+				POWER_VDDDCTRL_BO_OFFSET_MASK);
+
+		do {
+			if (new_target - cur_target > 100)
+				diff = cur_target + 100;
+			else
+				diff = new_target;
+
+			diff -= 800;
+			diff /= 25;
+
+			clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+				POWER_VDDDCTRL_TRG_MASK, diff);
+
+			if (powered_by_linreg)
+				early_delay(1500);
+			else {
+				while (!(readl(&power_regs->hw_power_sts) &
+					POWER_STS_DC_OK))
+					;
+
+			}
+
+			cur_target = readl(&power_regs->hw_power_vdddctrl);
+			cur_target &= POWER_VDDDCTRL_TRG_MASK;
+			cur_target *= 25;	/* 25 mV step*/
+			cur_target += 800;	/* 800 mV lowest */
+		} while (new_target > cur_target);
+
+		if (powered_by_linreg) {
+			writel(POWER_CTRL_VDDD_BO_IRQ,
+				&power_regs->hw_power_ctrl_clr);
+			if (bo_int & POWER_CTRL_ENIRQ_VDDD_BO)
+				setbits_le32(&power_regs->hw_power_vdddctrl,
+						POWER_CTRL_ENIRQ_VDDD_BO);
+		}
+	} else {
+		do {
+			if (cur_target - new_target > 100)
+				diff = cur_target - 100;
+			else
+				diff = new_target;
+
+			diff -= 800;
+			diff /= 25;
+
+			clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+					POWER_VDDDCTRL_TRG_MASK, diff);
+
+			if (powered_by_linreg)
+				early_delay(1500);
+			else {
+				while (!(readl(&power_regs->hw_power_sts) &
+					POWER_STS_DC_OK))
+					;
+
+			}
+
+			cur_target = readl(&power_regs->hw_power_vdddctrl);
+			cur_target &= POWER_VDDDCTRL_TRG_MASK;
+			cur_target *= 25;	/* 25 mV step*/
+			cur_target += 800;	/* 800 mV lowest */
+		} while (new_target < cur_target);
+	}
+
+	clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+			POWER_VDDDCTRL_BO_OFFSET_MASK,
+			new_brownout << POWER_VDDDCTRL_BO_OFFSET_OFFSET);
+}
+
+void mx28_power_init(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	mx28_power_clock2xtal();
+	mx28_power_clear_auto_restart();
+	mx28_power_set_linreg();
+	mx28_power_setup_5v_detect();
+	mx28_power_configure_power_source();
+	mx28_enable_output_rail_protection();
+
+	mx28_power_set_vddio(3300, 3150);
+
+	mx28_power_set_vddd(1350, 1200);
+
+	writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
+		POWER_CTRL_VDDIO_BO_IRQ | POWER_CTRL_VDD5V_DROOP_IRQ |
+		POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_BATT_BO_IRQ |
+		POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+
+	writel(POWER_5VCTRL_PWDN_5VBRNOUT, &power_regs->hw_power_5vctrl_set);
+
+	early_delay(1000);
+}
+
+#ifdef	CONFIG_SPL_MX28_PSWITCH_WAIT
+void mx28_power_wait_pswitch(void)
+{
+	struct mx28_power_regs *power_regs =
+		(struct mx28_power_regs *)MXS_POWER_BASE;
+
+	while (!(readl(&power_regs->hw_power_sts) & POWER_STS_PSWITCH_MASK))
+		;
+}
+#endif
diff --git a/board/denx/m28evk/start.S b/board/denx/m28evk/start.S
new file mode 100644
index 0000000..cf67599
--- /dev/null
+++ b/board/denx/m28evk/start.S
@@ -0,0 +1,396 @@
+/*
+ *  armboot - Startup Code for ARM926EJS CPU-core
+ *
+ *  Copyright (c) 2003  Texas Instruments
+ *
+ *  ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------
+ *
+ *  Copyright (c) 2001	Marius Groger <mag@sysgo.de>
+ *  Copyright (c) 2002	Alex Zupke <azu@sysgo.de>
+ *  Copyright (c) 2002	Gary Jennejohn <garyj@denx.de>
+ *  Copyright (c) 2003	Richard Woodruff <r-woodruff2@ti.com>
+ *  Copyright (c) 2003	Kshitij <kshitij@ti.com>
+ *  Copyright (c) 2010	Albert Aribaud <albert.u.boot@aribaud.net>
+ *
+ * Change to support call back into iMX28 bootrom
+ * Copyright (c) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <common.h>
+#include <version.h>
+
+#if defined(CONFIG_OMAP1610)
+#include <./configs/omap1510.h>
+#elif defined(CONFIG_OMAP730)
+#include <./configs/omap730.h>
+#endif
+
+/*
+ *************************************************************************
+ *
+ * Jump vector table as in table 3.1 in [1]
+ *
+ *************************************************************************
+ */
+
+
+.globl _start
+_start:
+	b	reset
+#ifdef CONFIG_SPL_BUILD
+/* No exception handlers in preloader */
+	ldr	pc, _hang
+	ldr	pc, _hang
+	ldr	pc, _hang
+	ldr	pc, _hang
+	b	reset
+	ldr	pc, _hang
+	ldr	pc, _hang
+
+_hang:
+	.word	do_hang
+/* pad to 64 byte boundary */
+	.word	0x12345678
+	.word	0x12345678
+	.word	0x12345678
+	.word	0x12345678
+	.word	0x12345678
+	.word	0x12345678
+	.word	0x12345678
+#else
+	ldr	pc, _undefined_instruction
+	ldr	pc, _software_interrupt
+	ldr	pc, _prefetch_abort
+	ldr	pc, _data_abort
+	ldr	pc, _not_used
+	ldr	pc, _irq
+	ldr	pc, _fiq
+
+_undefined_instruction:
+	.word undefined_instruction
+_software_interrupt:
+	.word software_interrupt
+_prefetch_abort:
+	.word prefetch_abort
+_data_abort:
+	.word data_abort
+_not_used:
+	.word not_used
+_irq:
+	.word irq
+_fiq:
+	.word fiq
+
+#endif	/* CONFIG_SPL_BUILD */
+	.balignl 16,0xdeadbeef
+
+
+/*
+ *************************************************************************
+ *
+ * Startup Code (reset vector)
+ *
+ * do important init only if we don't start from memory!
+ * setup Memory and board specific bits prior to relocation.
+ * relocate armboot to ram
+ * setup stack
+ *
+ *************************************************************************
+ */
+
+.globl _TEXT_BASE
+_TEXT_BASE:
+	.word	CONFIG_SYS_TEXT_BASE
+
+/*
+ * These are defined in the board-specific linker script.
+ * Subtracting _start from them lets the linker put their
+ * relative position in the executable instead of leaving
+ * them null.
+ */
+.globl _bss_start_ofs
+_bss_start_ofs:
+	.word __bss_start - _start
+
+.globl _bss_end_ofs
+_bss_end_ofs:
+	.word __bss_end__ - _start
+
+.globl _end_ofs
+_end_ofs:
+	.word _end - _start
+
+#ifdef CONFIG_USE_IRQ
+/* IRQ stack memory (calculated at run-time) */
+.globl IRQ_STACK_START
+IRQ_STACK_START:
+	.word	0x0badc0de
+
+/* IRQ stack memory (calculated at run-time) */
+.globl FIQ_STACK_START
+FIQ_STACK_START:
+	.word 0x0badc0de
+#endif
+
+/* IRQ stack memory (calculated at run-time) + 8 bytes */
+.globl IRQ_STACK_START_IN
+IRQ_STACK_START_IN:
+	.word	0x0badc0de
+
+/*
+ * the actual reset code
+ */
+
+reset:
+	/*
+	 * Store all registers on old stack pointer, this will allow us later to
+	 * return to the BootROM and let the BootROM load U-Boot into RAM.
+	 */
+	push	{r0-r12,r14}
+
+	/*
+	 * set the cpu to SVC32 mode
+	 */
+	mrs	r0,cpsr
+	bic	r0,r0,#0x1f
+	orr	r0,r0,#0xd3
+	msr	cpsr,r0
+
+	/*
+	 * we do sys-critical inits only at reboot,
+	 * not when booting from ram!
+	 */
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+	bl	cpu_init_crit
+#endif
+
+	bl	board_init_ll
+
+	pop	{r0-r12,r14}
+	bx	lr
+
+/*
+ *************************************************************************
+ *
+ * CPU_init_critical registers
+ *
+ * setup important registers
+ * setup memory timing
+ *
+ *************************************************************************
+ */
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+cpu_init_crit:
+	/*
+	 * flush v4 I/D caches
+	 */
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c7, 0	/* flush v3/v4 cache */
+	mcr	p15, 0, r0, c8, c7, 0	/* flush v4 TLB */
+
+	/*
+	 * disable MMU stuff and caches
+	 */
+	mrc	p15, 0, r0, c1, c0, 0
+	bic	r0, r0, #0x00002300	/* clear bits 13, 9:8 (--V- --RS) */
+	bic	r0, r0, #0x00000087	/* clear bits 7, 2:0 (B--- -CAM) */
+	orr	r0, r0, #0x00000002	/* set bit 2 (A) Align */
+	orr	r0, r0, #0x00001000	/* set bit 12 (I) I-Cache */
+	mcr	p15, 0, r0, c1, c0, 0
+
+	mov	pc, lr		/* back to my caller */
+#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
+
+#ifndef CONFIG_SPL_BUILD
+/*
+ *************************************************************************
+ *
+ * Interrupt handling
+ *
+ *************************************************************************
+ */
+
+@
+@ IRQ stack frame.
+@
+#define S_FRAME_SIZE	72
+
+#define S_OLD_R0	68
+#define S_PSR		64
+#define S_PC		60
+#define S_LR		56
+#define S_SP		52
+
+#define S_IP		48
+#define S_FP		44
+#define S_R10		40
+#define S_R9		36
+#define S_R8		32
+#define S_R7		28
+#define S_R6		24
+#define S_R5		20
+#define S_R4		16
+#define S_R3		12
+#define S_R2		8
+#define S_R1		4
+#define S_R0		0
+
+#define MODE_SVC 0x13
+#define I_BIT	 0x80
+
+/*
+ * use bad_save_user_regs for abort/prefetch/undef/swi ...
+ * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
+ */
+
+	.macro	bad_save_user_regs
+	@ carve out a frame on current user stack
+	sub	sp, sp, #S_FRAME_SIZE
+	stmia	sp, {r0 - r12}	@ Save user registers (now in svc mode) r0-r12
+	ldr	r2, IRQ_STACK_START_IN
+	@ get values for "aborted" pc and cpsr (into parm regs)
+	ldmia	r2, {r2 - r3}
+	add	r0, sp, #S_FRAME_SIZE		@ grab pointer to old stack
+	add	r5, sp, #S_SP
+	mov	r1, lr
+	stmia	r5, {r0 - r3}	@ save sp_SVC, lr_SVC, pc, cpsr
+	mov	r0, sp		@ save current stack into r0 (param register)
+	.endm
+
+	.macro	irq_save_user_regs
+	sub	sp, sp, #S_FRAME_SIZE
+	stmia	sp, {r0 - r12}			@ Calling r0-r12
+	@ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
+	add	r8, sp, #S_PC
+	stmdb	r8, {sp, lr}^		@ Calling SP, LR
+	str	lr, [r8, #0]		@ Save calling PC
+	mrs	r6, spsr
+	str	r6, [r8, #4]		@ Save CPSR
+	str	r0, [r8, #8]		@ Save OLD_R0
+	mov	r0, sp
+	.endm
+
+	.macro	irq_restore_user_regs
+	ldmia	sp, {r0 - lr}^			@ Calling r0 - lr
+	mov	r0, r0
+	ldr	lr, [sp, #S_PC]			@ Get PC
+	add	sp, sp, #S_FRAME_SIZE
+	subs	pc, lr, #4		@ return & move spsr_svc into cpsr
+	.endm
+
+	.macro get_bad_stack
+	ldr	r13, IRQ_STACK_START_IN		@ setup our mode stack
+
+	str	lr, [r13]	@ save caller lr in position 0 of saved stack
+	mrs	lr, spsr	@ get the spsr
+	str	lr, [r13, #4]	@ save spsr in position 1 of saved stack
+	mov	r13, #MODE_SVC	@ prepare SVC-Mode
+	@ msr	spsr_c, r13
+	msr	spsr, r13	@ switch modes, make sure moves will execute
+	mov	lr, pc		@ capture return pc
+	movs	pc, lr		@ jump to next instruction & switch modes.
+	.endm
+
+	.macro get_irq_stack			@ setup IRQ stack
+	ldr	sp, IRQ_STACK_START
+	.endm
+
+	.macro get_fiq_stack			@ setup FIQ stack
+	ldr	sp, FIQ_STACK_START
+	.endm
+#endif	/* CONFIG_SPL_BUILD */
+
+/*
+ * exception handlers
+ */
+#ifdef CONFIG_SPL_BUILD
+	.align	5
+do_hang:
+	ldr	sp, _TEXT_BASE			/* switch to abort stack */
+1:
+	bl	1b				/* hang and never return */
+#else	/* !CONFIG_SPL_BUILD */
+	.align  5
+undefined_instruction:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_undefined_instruction
+
+	.align	5
+software_interrupt:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_software_interrupt
+
+	.align	5
+prefetch_abort:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_prefetch_abort
+
+	.align	5
+data_abort:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_data_abort
+
+	.align	5
+not_used:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_not_used
+
+#ifdef CONFIG_USE_IRQ
+
+	.align	5
+irq:
+	get_irq_stack
+	irq_save_user_regs
+	bl	do_irq
+	irq_restore_user_regs
+
+	.align	5
+fiq:
+	get_fiq_stack
+	/* someone ought to write a more effiction fiq_save_user_regs */
+	irq_save_user_regs
+	bl	do_fiq
+	irq_restore_user_regs
+
+#else
+
+	.align	5
+irq:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_irq
+
+	.align	5
+fiq:
+	get_bad_stack
+	bad_save_user_regs
+	bl	do_fiq
+
+#endif
+#endif	/* CONFIG_SPL_BUILD */
diff --git a/board/denx/m28evk/u-boot-spl.lds b/board/denx/m28evk/u-boot-spl.lds
new file mode 100644
index 0000000..e296a92
--- /dev/null
+++ b/board/denx/m28evk/u-boot-spl.lds
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * January 2004 - Changed to support H4 device
+ * Copyright (c) 2004-2008 Texas Instruments
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+	. = 0x00000000;
+
+	. = ALIGN(4);
+	.text	:
+	{
+		board/denx/m28evk/start.o	(.text)
+		*(.text)
+	}
+
+	. = ALIGN(4);
+	.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
+
+	. = ALIGN(4);
+	.data : {
+		*(.data)
+	}
+
+	. = ALIGN(4);
+	__u_boot_cmd_start = .;
+	.u_boot_cmd : { *(.u_boot_cmd) }
+	__u_boot_cmd_end = .;
+
+	. = ALIGN(4);
+
+	.rel.dyn : {
+		__rel_dyn_start = .;
+		*(.rel*)
+		__rel_dyn_end = .;
+	}
+
+	.dynsym : {
+		__dynsym_start = .;
+		*(.dynsym)
+	}
+
+	_end = .;
+
+	.bss __rel_dyn_start (OVERLAY) : {
+		__bss_start = .;
+		*(.bss)
+		 . = ALIGN(4);
+		__bss_end__ = .;
+	}
+
+	/DISCARD/ : { *(.bss*) }
+	/DISCARD/ : { *(.dynstr*) }
+	/DISCARD/ : { *(.dynsym*) }
+	/DISCARD/ : { *(.dynamic*) }
+	/DISCARD/ : { *(.hash*) }
+	/DISCARD/ : { *(.plt*) }
+	/DISCARD/ : { *(.interp*) }
+	/DISCARD/ : { *(.gnu*) }
+}
diff --git a/board/denx/m28evk/u-boot.bd b/board/denx/m28evk/u-boot.bd
new file mode 100644
index 0000000..3ce7f92
--- /dev/null
+++ b/board/denx/m28evk/u-boot.bd
@@ -0,0 +1,14 @@
+sources {
+	u_boot_spl="spl/u-boot-spl.bin";
+	u_boot="u-boot.bin";
+}
+
+section (0) {
+        load u_boot_spl > 0x0000;
+        load ivt (entry = 0x0014) > 0x8000;
+	hab call 0x8000;
+
+        load u_boot > 0x40000100;
+        load ivt (entry = 0x40000100) > 0x8000;
+	hab call 0x8000;
+}
diff --git a/include/configs/m28evk.h b/include/configs/m28evk.h
index d88e09e..59e3e05 100644
--- a/include/configs/m28evk.h
+++ b/include/configs/m28evk.h
@@ -43,6 +43,14 @@
 #define	CONFIG_ARCH_CPU_INIT
 
 /*
+ * SPL
+ */
+#define	CONFIG_SPL
+#define	CONFIG_SPL_NO_CPU_SUPPORT_CODE
+#define	CONFIG_SPL_START_S_PATH		"board/denx/m28evk"
+#define	CONFIG_SPL_LDSCRIPT		"board/denx/m28evk/u-boot-spl.lds"
+
+/*
  * U-Boot Commands
  */
 #include <config_cmd_default.h>
-- 
1.7.6.3

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

* [U-Boot] [PATCH 17/17 V2] M28: Add memory detection into SPL
  2011-10-21 22:44   ` [U-Boot] [PATCH 17/17] M28: Add memory detection into SPL Marek Vasut
@ 2011-10-31 11:45     ` Marek Vasut
  2011-11-05  2:39       ` [U-Boot] [PATCH 17/17 V3] " Marek Vasut
  0 siblings, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-10-31 11:45 UTC (permalink / raw)
  To: u-boot

This code allows the DDR DRAM size to be detected at runtime. The RAM size is
stored into two scratch registers, from which it is then fetched in U-Boot.

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
---
 board/denx/m28evk/Makefile   |    7 ++++++-
 board/denx/m28evk/m28evk.c   |   18 ++++++++++++++++--
 board/denx/m28evk/mem_init.c |   27 +++++++++++++++++++++++++++
 include/configs/m28evk.h     |    2 +-
 4 files changed, 50 insertions(+), 4 deletions(-)

V2: Drop clean and distclean targets

diff --git a/board/denx/m28evk/Makefile b/board/denx/m28evk/Makefile
index 47229e6..b32ce12 100644
--- a/board/denx/m28evk/Makefile
+++ b/board/denx/m28evk/Makefile
@@ -30,7 +30,7 @@ COBJS	:= m28evk.o
 endif
 
 ifdef	CONFIG_SPL_BUILD
-COBJS	:= mem_init.o mmc_boot.o power_init.o
+COBJS	:= mem_init.o mmc_boot.o power_init.o memsize.o
 endif
 
 SRCS	:= $(COBJS:.o=.c)
@@ -41,6 +41,11 @@ $(LIB):	$(obj).depend $(OBJS)
 
 all:	$(ALL)
 
+ifdef	CONFIG_SPL_BUILD
+$(obj)/memsize.c:
+	ln -sf $(TOPDIR)/common/memsize.c $@
+endif
+
 #########################################################################
 
 # defines $(obj).depend target
diff --git a/board/denx/m28evk/m28evk.c b/board/denx/m28evk/m28evk.c
index 118e222..168ceeb 100644
--- a/board/denx/m28evk/m28evk.c
+++ b/board/denx/m28evk/m28evk.c
@@ -63,10 +63,24 @@ int board_init(void)
 	return 0;
 }
 
+#define	HW_DIGCTRL_SCRATCH0	0x8001c280
+#define	HW_DIGCTRL_SCRATCH1	0x8001c290
 int dram_init(void)
 {
-	/* dram_init must store complete ramsize in gd->ram_size */
-	gd->ram_size = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE);
+	uint32_t sz[2];
+
+	sz[0] = readl(HW_DIGCTRL_SCRATCH0);
+	sz[1] = readl(HW_DIGCTRL_SCRATCH1);
+
+	if (sz[0] != sz[1]) {
+		printf("MX28:\n"
+			"Error, the RAM size in HW_DIGCTRL_SCRATCH0 and\n"
+			"HW_DIGCTRL_SCRATCH1 is not the same. Please\n"
+			"verify these two registers contain valid RAM size!\n");
+		hang();
+	}
+
+	gd->ram_size = sz[0];
 	return 0;
 }
 
diff --git a/board/denx/m28evk/mem_init.c b/board/denx/m28evk/mem_init.c
index 066fe0d..17d1f9b 100644
--- a/board/denx/m28evk/mem_init.c
+++ b/board/denx/m28evk/mem_init.c
@@ -165,6 +165,31 @@ void mx28_mem_setup_vddd(void)
 		&power_regs->hw_power_vdddctrl);
 }
 
+#define	HW_DIGCTRL_SCRATCH0	0x8001c280
+#define	HW_DIGCTRL_SCRATCH1	0x8001c290
+void data_abort_memdetect_handler(void) __attribute__((naked));
+void data_abort_memdetect_handler(void)
+{
+	asm volatile("subs pc, r14, #4");
+}
+
+void mx28_mem_get_size(void)
+{
+	uint32_t sz, da;
+	uint32_t *vt = (uint32_t *)0x20;
+
+	/* Replace the DABT handler. */
+	da = vt[4];
+	vt[4] = (uint32_t)&data_abort_memdetect_handler;
+
+	sz = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE);
+	writel(sz, HW_DIGCTRL_SCRATCH0);
+	writel(sz, HW_DIGCTRL_SCRATCH1);
+
+	/* Restore the old DABT handler. */
+	vt[4] = da;
+}
+
 void mx28_mem_init(void)
 {
 	struct mx28_clkctrl_regs *clkctrl_regs =
@@ -210,4 +235,6 @@ void mx28_mem_init(void)
 	early_delay(10000);
 
 	mx28_mem_setup_cpu_and_hbus();
+
+	mx28_mem_get_size();
 }
diff --git a/include/configs/m28evk.h b/include/configs/m28evk.h
index 381b01e..c8b0cf5 100644
--- a/include/configs/m28evk.h
+++ b/include/configs/m28evk.h
@@ -81,7 +81,7 @@
  */
 #define	CONFIG_NR_DRAM_BANKS		1		/* 2 banks of DRAM */
 #define	PHYS_SDRAM_1			0x40000000	/* Base address */
-#define	PHYS_SDRAM_1_SIZE		0x08000000	/* 128 MB */
+#define	PHYS_SDRAM_1_SIZE		0x40000000	/* Max 1 GB RAM */
 #define	CONFIG_STACKSIZE		0x00010000	/* 128 KB stack */
 #define	CONFIG_SYS_MALLOC_LEN		0x00400000	/* 4 MB for malloc */
 #define	CONFIG_SYS_GBL_DATA_SIZE	128		/* Initial data */
-- 
1.7.6.3

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

* [U-Boot] [PATCH 09/17 RESEND V5] iMX28: Add GPMI NAND driver
  2011-10-21 22:44   ` [U-Boot] [PATCH 09/17 RESEND V5] iMX28: Add GPMI NAND driver Marek Vasut
@ 2011-11-04 13:13     ` Veli-Pekka Peltola
  2011-11-04 13:30       ` Marek Vasut
  0 siblings, 1 reply; 116+ messages in thread
From: Veli-Pekka Peltola @ 2011-11-04 13:13 UTC (permalink / raw)
  To: u-boot

Hi Marek,

On 10/22/2011 01:44 AM, Marek Vasut wrote:
> diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c
> new file mode 100644
> index 0000000..ce2a326
> --- /dev/null
> +++ b/drivers/mtd/nand/mxs_nand.c

<snip>

> +	nand->options |= NAND_NO_SUBPAGE_WRITE;

I think we should change this a little bit. Unluckily I don't know what 
is the best way to fix it. As far as I have understood, the 
NAND_NO_SUBPAGE_WRITE is a chip option, not for a driver.

At nand_base.c is
chip->options &= ~NAND_CHIPOPTIONS_MSK;
chip->options |= type->options & NAND_CHIPOPTIONS_MSK;
so the bit is masked out anyway and subpages are enabled.

After that UBI tries to read VID header at 512 by default. I had to use 
"ubi part root 2048" to override it. Besides of that driver seems to 
work fine.

--
Veli-Pekka Peltola
Bluegiga Technologies

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

* [U-Boot] [PATCH 09/17 RESEND V5] iMX28: Add GPMI NAND driver
  2011-11-04 13:13     ` Veli-Pekka Peltola
@ 2011-11-04 13:30       ` Marek Vasut
  2011-11-04 14:02         ` Veli-Pekka Peltola
  0 siblings, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-11-04 13:30 UTC (permalink / raw)
  To: u-boot

> Hi Marek,
> 
> On 10/22/2011 01:44 AM, Marek Vasut wrote:
> > diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c
> > new file mode 100644
> > index 0000000..ce2a326
> > --- /dev/null
> > +++ b/drivers/mtd/nand/mxs_nand.c
> 
> <snip>
> 
> > +	nand->options |= NAND_NO_SUBPAGE_WRITE;
> 
> I think we should change this a little bit. Unluckily I don't know what
> is the best way to fix it. As far as I have understood, the
> NAND_NO_SUBPAGE_WRITE is a chip option, not for a driver.
> 
> At nand_base.c is
> chip->options &= ~NAND_CHIPOPTIONS_MSK;
> chip->options |= type->options & NAND_CHIPOPTIONS_MSK;
> so the bit is masked out anyway and subpages are enabled.
> 
> After that UBI tries to read VID header at 512 by default. I had to use
> "ubi part root 2048" to override it. Besides of that driver seems to
> work fine.

Can you please supply me with the commands that trigger such bug and the 
resulting problem you then see? So I can reproduce it and fix it? Thanks!
> 
> --
> Veli-Pekka Peltola
> Bluegiga Technologies

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

* [U-Boot] [PATCH 09/17 RESEND V5] iMX28: Add GPMI NAND driver
  2011-11-04 13:30       ` Marek Vasut
@ 2011-11-04 14:02         ` Veli-Pekka Peltola
  2011-11-05  2:24           ` Marek Vasut
  0 siblings, 1 reply; 116+ messages in thread
From: Veli-Pekka Peltola @ 2011-11-04 14:02 UTC (permalink / raw)
  To: u-boot

On 11/04/2011 03:30 PM, Marek Vasut wrote:
> Can you please supply me with the commands that trigger such bug and the
> resulting problem you then see? So I can reproduce it and fix it? Thanks!

This procedure should trigger the problem:
mtdparts default; nand erase.part filesystem; ubi part filesystem; ubi 
part filesystem

You should see errors with second "ubi part filesystem" command like UBI 
error: ubi_io_read: error -74 while reading 64 bytes from PEB 0:0, read 
64 bytes.

You can force UBI not to use subpages (change 2048 to full size of your 
NAND page):
mtdparts default; nand erase.part filesystem; ubi part filesystem 2048; 
ubi part filesystem 2048

Please let me know if I can help you more somehow. Thanks!

--
Veli-Pekka Peltola
Bluegiga Technologies

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

* [U-Boot] [PATCH 09/17 RESEND V5] iMX28: Add GPMI NAND driver
  2011-11-04 14:02         ` Veli-Pekka Peltola
@ 2011-11-05  2:24           ` Marek Vasut
  0 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-11-05  2:24 UTC (permalink / raw)
  To: u-boot

> On 11/04/2011 03:30 PM, Marek Vasut wrote:
> > Can you please supply me with the commands that trigger such bug and the
> > resulting problem you then see? So I can reproduce it and fix it? Thanks!
> 
> This procedure should trigger the problem:
> mtdparts default; nand erase.part filesystem; ubi part filesystem; ubi
> part filesystem
> 
> You should see errors with second "ubi part filesystem" command like UBI
> error: ubi_io_read: error -74 while reading 64 bytes from PEB 0:0, read
> 64 bytes.
> 
> You can force UBI not to use subpages (change 2048 to full size of your
> NAND page):
> mtdparts default; nand erase.part filesystem; ubi part filesystem 2048;
> ubi part filesystem 2048
> 
> Please let me know if I can help you more somehow. Thanks!

Hi!

please test patch I just submitted, though I assume there'll be a huge 
discussion around it soon.

> 
> --
> Veli-Pekka Peltola
> Bluegiga Technologies

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

* [U-Boot] [PATCH 17/17 V3] M28: Add memory detection into SPL
  2011-10-31 11:45     ` [U-Boot] [PATCH 17/17 V2] " Marek Vasut
@ 2011-11-05  2:39       ` Marek Vasut
  0 siblings, 0 replies; 116+ messages in thread
From: Marek Vasut @ 2011-11-05  2:39 UTC (permalink / raw)
  To: u-boot

This code allows the DDR DRAM size to be detected at runtime. The RAM size is
stored into two scratch registers, from which it is then fetched in U-Boot.

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
---
 board/denx/m28evk/Makefile   |    7 ++++++-
 board/denx/m28evk/m28evk.c   |   18 ++++++++++++++++--
 board/denx/m28evk/mem_init.c |   27 +++++++++++++++++++++++++++
 include/configs/m28evk.h     |    2 +-
 4 files changed, 50 insertions(+), 4 deletions(-)

V2: Drop clean and distclean targets
V3: Drop $(obj) in front of memsize.c target

diff --git a/board/denx/m28evk/Makefile b/board/denx/m28evk/Makefile
index 47229e6..b6f002f 100644
--- a/board/denx/m28evk/Makefile
+++ b/board/denx/m28evk/Makefile
@@ -30,7 +30,7 @@ COBJS	:= m28evk.o
 endif
 
 ifdef	CONFIG_SPL_BUILD
-COBJS	:= mem_init.o mmc_boot.o power_init.o
+COBJS	:= mem_init.o mmc_boot.o power_init.o memsize.o
 endif
 
 SRCS	:= $(COBJS:.o=.c)
@@ -41,6 +41,11 @@ $(LIB):	$(obj).depend $(OBJS)
 
 all:	$(ALL)
 
+ifdef	CONFIG_SPL_BUILD
+memsize.c:
+	ln -sf $(TOPDIR)/common/memsize.c $@
+endif
+
 #########################################################################
 
 # defines $(obj).depend target
diff --git a/board/denx/m28evk/m28evk.c b/board/denx/m28evk/m28evk.c
index 118e222..168ceeb 100644
--- a/board/denx/m28evk/m28evk.c
+++ b/board/denx/m28evk/m28evk.c
@@ -63,10 +63,24 @@ int board_init(void)
 	return 0;
 }
 
+#define	HW_DIGCTRL_SCRATCH0	0x8001c280
+#define	HW_DIGCTRL_SCRATCH1	0x8001c290
 int dram_init(void)
 {
-	/* dram_init must store complete ramsize in gd->ram_size */
-	gd->ram_size = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE);
+	uint32_t sz[2];
+
+	sz[0] = readl(HW_DIGCTRL_SCRATCH0);
+	sz[1] = readl(HW_DIGCTRL_SCRATCH1);
+
+	if (sz[0] != sz[1]) {
+		printf("MX28:\n"
+			"Error, the RAM size in HW_DIGCTRL_SCRATCH0 and\n"
+			"HW_DIGCTRL_SCRATCH1 is not the same. Please\n"
+			"verify these two registers contain valid RAM size!\n");
+		hang();
+	}
+
+	gd->ram_size = sz[0];
 	return 0;
 }
 
diff --git a/board/denx/m28evk/mem_init.c b/board/denx/m28evk/mem_init.c
index 066fe0d..17d1f9b 100644
--- a/board/denx/m28evk/mem_init.c
+++ b/board/denx/m28evk/mem_init.c
@@ -165,6 +165,31 @@ void mx28_mem_setup_vddd(void)
 		&power_regs->hw_power_vdddctrl);
 }
 
+#define	HW_DIGCTRL_SCRATCH0	0x8001c280
+#define	HW_DIGCTRL_SCRATCH1	0x8001c290
+void data_abort_memdetect_handler(void) __attribute__((naked));
+void data_abort_memdetect_handler(void)
+{
+	asm volatile("subs pc, r14, #4");
+}
+
+void mx28_mem_get_size(void)
+{
+	uint32_t sz, da;
+	uint32_t *vt = (uint32_t *)0x20;
+
+	/* Replace the DABT handler. */
+	da = vt[4];
+	vt[4] = (uint32_t)&data_abort_memdetect_handler;
+
+	sz = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE);
+	writel(sz, HW_DIGCTRL_SCRATCH0);
+	writel(sz, HW_DIGCTRL_SCRATCH1);
+
+	/* Restore the old DABT handler. */
+	vt[4] = da;
+}
+
 void mx28_mem_init(void)
 {
 	struct mx28_clkctrl_regs *clkctrl_regs =
@@ -210,4 +235,6 @@ void mx28_mem_init(void)
 	early_delay(10000);
 
 	mx28_mem_setup_cpu_and_hbus();
+
+	mx28_mem_get_size();
 }
diff --git a/include/configs/m28evk.h b/include/configs/m28evk.h
index 381b01e..c8b0cf5 100644
--- a/include/configs/m28evk.h
+++ b/include/configs/m28evk.h
@@ -81,7 +81,7 @@
  */
 #define	CONFIG_NR_DRAM_BANKS		1		/* 2 banks of DRAM */
 #define	PHYS_SDRAM_1			0x40000000	/* Base address */
-#define	PHYS_SDRAM_1_SIZE		0x08000000	/* 128 MB */
+#define	PHYS_SDRAM_1_SIZE		0x40000000	/* Max 1 GB RAM */
 #define	CONFIG_STACKSIZE		0x00010000	/* 128 KB stack */
 #define	CONFIG_SYS_MALLOC_LEN		0x00400000	/* 4 MB for malloc */
 #define	CONFIG_SYS_GBL_DATA_SIZE	128		/* Initial data */
-- 
1.7.6.3

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

* [U-Boot] [PATCH 02/17 RESEND] iMX28: Add SSP MMC driver
  2011-10-21 22:44   ` [U-Boot] [PATCH 02/17 RESEND] iMX28: Add SSP MMC driver Marek Vasut
@ 2011-11-08 20:45     ` Andy Fleming
  2011-11-08 21:42       ` Marek Vasut
  0 siblings, 1 reply; 116+ messages in thread
From: Andy Fleming @ 2011-11-08 20:45 UTC (permalink / raw)
  To: u-boot

On Fri, Oct 21, 2011 at 5:44 PM, Marek Vasut <marek.vasut@gmail.com> wrote:
> Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
> Cc: Andy Fleming <afleming@gmail.com>
> Cc: Stefano Babic <sbabic@denx.de>
> Cc: Wolfgang Denk <wd@denx.de>
> Cc: Detlev Zundel <dzu@denx.de>

Acked-by: Andy Fleming <afleming@gmail.com>

I can't apply this because of the
arch/arm/include/asm/arch-mx28/sys_proto.h change, which is a file
that doesn't yet exist in mainline.

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

* [U-Boot] [PATCH 02/17 RESEND] iMX28: Add SSP MMC driver
  2011-11-08 20:45     ` Andy Fleming
@ 2011-11-08 21:42       ` Marek Vasut
  2011-11-08 21:50         ` Andy Fleming
  0 siblings, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-11-08 21:42 UTC (permalink / raw)
  To: u-boot

> On Fri, Oct 21, 2011 at 5:44 PM, Marek Vasut <marek.vasut@gmail.com> wrote:
> > Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
> > Cc: Andy Fleming <afleming@gmail.com>
> > Cc: Stefano Babic <sbabic@denx.de>
> > Cc: Wolfgang Denk <wd@denx.de>
> > Cc: Detlev Zundel <dzu@denx.de>
> 
> Acked-by: Andy Fleming <afleming@gmail.com>
> 
> I can't apply this because of the
> arch/arm/include/asm/arch-mx28/sys_proto.h change, which is a file
> that doesn't yet exist in mainline.

Andy, will it be OK to push it all through stefano's tree then ?

M

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

* [U-Boot] [PATCH 02/17 RESEND] iMX28: Add SSP MMC driver
  2011-11-08 21:42       ` Marek Vasut
@ 2011-11-08 21:50         ` Andy Fleming
  2011-11-09  8:18           ` Stefano Babic
  0 siblings, 1 reply; 116+ messages in thread
From: Andy Fleming @ 2011-11-08 21:50 UTC (permalink / raw)
  To: u-boot

On Tue, Nov 8, 2011 at 3:42 PM, Marek Vasut <marek.vasut@gmail.com> wrote:
>> On Fri, Oct 21, 2011 at 5:44 PM, Marek Vasut <marek.vasut@gmail.com> wrote:
>> > Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
>> > Cc: Andy Fleming <afleming@gmail.com>
>> > Cc: Stefano Babic <sbabic@denx.de>
>> > Cc: Wolfgang Denk <wd@denx.de>
>> > Cc: Detlev Zundel <dzu@denx.de>
>>
>> Acked-by: Andy Fleming <afleming@gmail.com>
>>
>> I can't apply this because of the
>> arch/arm/include/asm/arch-mx28/sys_proto.h change, which is a file
>> that doesn't yet exist in mainline.
>
> Andy, will it be OK to push it all through stefano's tree then ?

Sure. I have actually delegated the patch to him.

Andy

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

* [U-Boot] [PATCH 02/17 RESEND] iMX28: Add SSP MMC driver
  2011-11-08 21:50         ` Andy Fleming
@ 2011-11-09  8:18           ` Stefano Babic
  2011-11-09  8:38             ` Marek Vasut
  0 siblings, 1 reply; 116+ messages in thread
From: Stefano Babic @ 2011-11-09  8:18 UTC (permalink / raw)
  To: u-boot

On 11/08/2011 10:50 PM, Andy Fleming wrote:
> On Tue, Nov 8, 2011 at 3:42 PM, Marek Vasut <marek.vasut@gmail.com> wrote:
>>> On Fri, Oct 21, 2011 at 5:44 PM, Marek Vasut <marek.vasut@gmail.com> wrote:
>>>> Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
>>>> Cc: Andy Fleming <afleming@gmail.com>
>>>> Cc: Stefano Babic <sbabic@denx.de>
>>>> Cc: Wolfgang Denk <wd@denx.de>
>>>> Cc: Detlev Zundel <dzu@denx.de>
>>>
>>> Acked-by: Andy Fleming <afleming@gmail.com>
>>>
>>> I can't apply this because of the
>>> arch/arm/include/asm/arch-mx28/sys_proto.h change, which is a file
>>> that doesn't yet exist in mainline.
>>
>> Andy, will it be OK to push it all through stefano's tree then ?
> 
> Sure. I have actually delegated the patch to him.

Ok, thanks . I will do it.

Stefano

-- 
=====================================================================
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de
=====================================================================

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

* [U-Boot] [PATCH 02/17 RESEND] iMX28: Add SSP MMC driver
  2011-11-09  8:18           ` Stefano Babic
@ 2011-11-09  8:38             ` Marek Vasut
  2011-11-09  8:52               ` Stefano Babic
  0 siblings, 1 reply; 116+ messages in thread
From: Marek Vasut @ 2011-11-09  8:38 UTC (permalink / raw)
  To: u-boot

> On 11/08/2011 10:50 PM, Andy Fleming wrote:
> > On Tue, Nov 8, 2011 at 3:42 PM, Marek Vasut <marek.vasut@gmail.com> wrote:
> >>> On Fri, Oct 21, 2011 at 5:44 PM, Marek Vasut <marek.vasut@gmail.com> 
wrote:
> >>>> Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
> >>>> Cc: Andy Fleming <afleming@gmail.com>
> >>>> Cc: Stefano Babic <sbabic@denx.de>
> >>>> Cc: Wolfgang Denk <wd@denx.de>
> >>>> Cc: Detlev Zundel <dzu@denx.de>
> >>> 
> >>> Acked-by: Andy Fleming <afleming@gmail.com>
> >>> 
> >>> I can't apply this because of the
> >>> arch/arm/include/asm/arch-mx28/sys_proto.h change, which is a file
> >>> that doesn't yet exist in mainline.
> >> 
> >> Andy, will it be OK to push it all through stefano's tree then ?
> > 
> > Sure. I have actually delegated the patch to him.
> 
> Ok, thanks . I will do it.
> 
> Stefano

Stefano, I'll rebase the patches and repost so you can apply. Can you rebase 
your u-boot-imx/master on top of u-boot-arm/master so I can use that? Thanks!

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

* [U-Boot] [PATCH 02/17 RESEND] iMX28: Add SSP MMC driver
  2011-11-09  8:38             ` Marek Vasut
@ 2011-11-09  8:52               ` Stefano Babic
  0 siblings, 0 replies; 116+ messages in thread
From: Stefano Babic @ 2011-11-09  8:52 UTC (permalink / raw)
  To: u-boot

On 11/09/2011 09:38 AM, Marek Vasut wrote:
> Stefano, I'll rebase the patches and repost so you can apply. Can you rebase 
> your u-boot-imx/master on top of u-boot-arm/master so I can use that? Thanks!

Done - you can take it

Stefano

-- 
=====================================================================
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de
=====================================================================

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

end of thread, other threads:[~2011-11-09  8:52 UTC | newest]

Thread overview: 116+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-12  4:06 [U-Boot] [PATCH 00/15 V2] Support for the DENX M28 SoM Marek Vasut
2011-09-12  4:06 ` [U-Boot] [PATCH 01/15] iMX28: Initial support for iMX28 CPU Marek Vasut
2011-09-14  7:10   ` Stefano Babic
2011-09-27 13:45   ` [U-Boot] [PATCH 01/15 V2] " Marek Vasut
2011-09-30  9:42     ` [U-Boot] [PATCH 01/15 V3] " Marek Vasut
2011-10-13 16:19       ` Stefano Babic
2011-10-13 18:14         ` Marek Vasut
2011-10-13 20:45           ` Wolfgang Denk
2011-10-14  7:51           ` Stefano Babic
2011-10-14  7:59             ` Marek Vasut
2011-10-14 21:00               ` Wolfgang Denk
2011-10-14 21:06                 ` Marek Vasut
2011-10-13 23:38       ` [U-Boot] [PATCH 01/15 V4] " Marek Vasut
2011-10-14 21:14         ` [U-Boot] [PATCH 01/15 V5] " Marek Vasut
2011-10-14 21:01       ` [U-Boot] [PATCH 01/15 V3] " Wolfgang Denk
2011-10-14 21:10         ` Marek Vasut
2011-09-12  4:06 ` [U-Boot] [PATCH 02/15] iMX28: Add SSP MMC driver Marek Vasut
2011-09-12  4:06 ` [U-Boot] [PATCH 03/15] FEC: Add support for iMX28 quirks Marek Vasut
2011-09-14  7:17   ` Stefano Babic
2011-09-14 12:11     ` Marek Vasut
2011-09-14 15:38       ` Mike Frysinger
2011-09-12  4:06 ` [U-Boot] [PATCH 04/15] iMX28: Add PINMUX control Marek Vasut
2011-09-12  4:06 ` [U-Boot] [PATCH 05/15] iMX28: Add I2C bus driver Marek Vasut
2011-09-12  5:30   ` Heiko Schocher
2011-09-12 13:31     ` Marek Vasut
2011-09-13 12:05   ` Wolfram Sang
2011-09-13 12:56     ` Marek Vasut
2011-09-13 13:12       ` Wolfram Sang
2011-09-13 13:20         ` Marek Vasut
2011-09-13 13:31           ` Wolfram Sang
2011-09-13 22:24   ` [U-Boot] [PATCH 05/15 V2] " Marek Vasut
2011-09-12  4:06 ` [U-Boot] [PATCH 06/15] iMX28: Add GPIO control Marek Vasut
2011-09-14  7:25   ` Stefano Babic
2011-09-12  4:06 ` [U-Boot] [PATCH 07/15] iMX28: Add SPI driver Marek Vasut
2011-09-12 16:35   ` Mike Frysinger
2011-09-12 17:42     ` Marek Vasut
2011-09-12 20:26       ` Mike Frysinger
2011-09-12 22:45         ` Marek Vasut
2011-09-13 22:26   ` [U-Boot] [PATCH 07/15 V2] " Marek Vasut
2011-09-14  2:50     ` Mike Frysinger
2011-09-14  3:14       ` Marek Vasut
2011-09-12  4:06 ` [U-Boot] [PATCH 08/15] iMX28: Add APBH DMA driver Marek Vasut
2011-09-12  4:06 ` [U-Boot] [PATCH 09/15] iMX28: Add GPMI NAND driver Marek Vasut
2011-09-28 21:26   ` Scott Wood
2011-09-28 21:42     ` Marek Vasut
2011-09-28 21:57       ` Scott Wood
2011-09-28 22:09         ` Marek Vasut
2011-09-28 22:13           ` Scott Wood
2011-09-28 22:34             ` Marek Vasut
2011-09-28 22:12     ` Marek Vasut
2011-09-28 22:23       ` Scott Wood
2011-09-28 22:17   ` [U-Boot] [PATCH 09/15 V2] " Marek Vasut
2011-09-28 22:32     ` [U-Boot] [PATCH 09/15 V3] " Marek Vasut
2011-09-29  0:07       ` [U-Boot] [PATCH 09/15 V4] " Marek Vasut
2011-09-30  9:39         ` [U-Boot] [PATCH 09/15 V5] " Marek Vasut
2011-10-10 21:06           ` Scott Wood
2011-09-12  4:06 ` [U-Boot] [PATCH 10/15] iMX28: Add driver for internal RTC Marek Vasut
2011-09-12  4:06 ` [U-Boot] [PATCH 11/15] iMX28: Add image header generator tool Marek Vasut
2011-09-12 16:38   ` Mike Frysinger
2011-09-12 17:40     ` Marek Vasut
2011-09-12 20:24       ` Mike Frysinger
2011-09-12 22:13         ` Marek Vasut
2011-09-13 22:27   ` [U-Boot] [PATCH 11/15 V2] " Marek Vasut
2011-09-12  4:06 ` [U-Boot] [PATCH 12/15] iMX28: Add u-boot.sb target to Makefile Marek Vasut
2011-09-12 16:33   ` Mike Frysinger
2011-09-12 17:40     ` Marek Vasut
2011-09-13 22:28   ` [U-Boot] [PATCH 12/15 V2] " Marek Vasut
2011-09-12  4:06 ` [U-Boot] [PATCH 13/15] iMX28: Add support for DENX M28EVK board Marek Vasut
2011-09-13 22:29   ` [U-Boot] [PATCH 13/15 V2] " Marek Vasut
2011-09-14  2:48     ` Mike Frysinger
2011-09-14  3:17       ` Marek Vasut
2011-09-14  3:33         ` Mike Frysinger
2011-09-14  4:24           ` Marek Vasut
2011-09-14  5:01             ` Mike Frysinger
2011-09-14  5:10               ` Marek Vasut
2011-09-14 22:12                 ` Mike Frysinger
2011-09-14 23:13                   ` Marek Vasut
2011-09-20  2:15     ` [U-Boot] [PATCH 13/15 V3] " Marek Vasut
2011-09-12  4:06 ` [U-Boot] [PATCH 14/15] M28: Add MMC SPL Marek Vasut
2011-09-30  9:40   ` [U-Boot] [PATCH 14/15 V2] " Marek Vasut
2011-10-14 12:09     ` [U-Boot] [PATCH 14/15 V3] " Marek Vasut
2011-09-12  4:06 ` [U-Boot] [PATCH 15/15] M28: Add doc/README.m28 documentation Marek Vasut
2011-10-21 22:44 ` [U-Boot] [PATCH 00/17 V3] Support for the DENX M28 SoM Marek Vasut
2011-10-21 22:44   ` [U-Boot] [PATCH 01/17 RESEND V5] iMX28: Initial support for iMX28 CPU Marek Vasut
2011-10-21 22:44   ` [U-Boot] [PATCH 02/17 RESEND] iMX28: Add SSP MMC driver Marek Vasut
2011-11-08 20:45     ` Andy Fleming
2011-11-08 21:42       ` Marek Vasut
2011-11-08 21:50         ` Andy Fleming
2011-11-09  8:18           ` Stefano Babic
2011-11-09  8:38             ` Marek Vasut
2011-11-09  8:52               ` Stefano Babic
2011-10-21 22:44   ` [U-Boot] [PATCH 03/17 RESEND] FEC: Add support for iMX28 quirks Marek Vasut
2011-10-21 22:44   ` [U-Boot] [PATCH 04/17 RESEND] iMX28: Add PINMUX control Marek Vasut
2011-10-21 22:44   ` [U-Boot] [PATCH 05/17 RESEND V2] iMX28: Add I2C bus driver Marek Vasut
2011-10-21 22:44   ` [U-Boot] [PATCH 06/17 RESEND] iMX28: Add GPIO control Marek Vasut
2011-10-21 22:44   ` [U-Boot] [PATCH 07/17 RESEND V2] iMX28: Add SPI driver Marek Vasut
2011-10-21 22:44   ` [U-Boot] [PATCH 08/17 RESEND] iMX28: Add APBH DMA driver Marek Vasut
2011-10-21 22:44   ` [U-Boot] [PATCH 09/17 RESEND V5] iMX28: Add GPMI NAND driver Marek Vasut
2011-11-04 13:13     ` Veli-Pekka Peltola
2011-11-04 13:30       ` Marek Vasut
2011-11-04 14:02         ` Veli-Pekka Peltola
2011-11-05  2:24           ` Marek Vasut
2011-10-21 22:44   ` [U-Boot] [PATCH 10/17 RESEND] iMX28: Add driver for internal RTC Marek Vasut
2011-10-21 22:44   ` [U-Boot] [PATCH 11/17 RESEND V2] iMX28: Add image header generator tool Marek Vasut
2011-10-21 22:44   ` [U-Boot] [PATCH 12/17 V3] iMX28: Add u-boot.sb target to Makefile Marek Vasut
2011-10-21 22:44   ` [U-Boot] [PATCH 13/17 V4] iMX28: Add support for DENX M28EVK board Marek Vasut
2011-10-31  9:12     ` Igor Grinberg
2011-10-31 11:42     ` [U-Boot] [PATCH 13/17 V5] " Marek Vasut
2011-10-21 22:44   ` [U-Boot] [PATCH 14/17 V4] M28: Add MMC SPL Marek Vasut
2011-10-23 21:42     ` Robert Schwebel
2011-10-31 11:44     ` [U-Boot] [PATCH 14/17 V5] " Marek Vasut
2011-10-21 22:44   ` [U-Boot] [PATCH 15/17 RESEND] M28: Add doc/README.m28 documentation Marek Vasut
2011-10-21 22:44   ` [U-Boot] [PATCH 16/17] iMX28: Fix ARM vector handling Marek Vasut
2011-10-21 22:44   ` [U-Boot] [PATCH 17/17] M28: Add memory detection into SPL Marek Vasut
2011-10-31 11:45     ` [U-Boot] [PATCH 17/17 V2] " Marek Vasut
2011-11-05  2:39       ` [U-Boot] [PATCH 17/17 V3] " Marek Vasut

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.