All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 0/7][v3] Support for LogicPD i.MX27-LITEKIT development board
@ 2009-06-08  0:12 Ilya Yanok
  2009-06-08  0:12 ` [U-Boot] [PATCH 1/7] mx27: basic cpu support Ilya Yanok
                   ` (7 more replies)
  0 siblings, 8 replies; 70+ messages in thread
From: Ilya Yanok @ 2009-06-08  0:12 UTC (permalink / raw)
  To: u-boot

This patch set adds support for LogicPD i.MX27-LITEKIT development board.
It contains support for i.MX27 CPU, support for serial console, FEC
ethernet controller, NFC NAND controller and SDHC controller.

Signed-off-by: Ilya Yanok <yanok@emcraft.com>

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

* [U-Boot] [PATCH 1/7] mx27: basic cpu support
  2009-06-08  0:12 [U-Boot] [PATCH 0/7][v3] Support for LogicPD i.MX27-LITEKIT development board Ilya Yanok
@ 2009-06-08  0:12 ` Ilya Yanok
  2009-06-20 13:13   ` Jean-Christophe PLAGNIOL-VILLARD
  2009-06-08  0:12 ` [U-Boot] [PATCH 2/7] serial_mx31: allow it to work with mx27 too and rename to serial_mxc Ilya Yanok
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 70+ messages in thread
From: Ilya Yanok @ 2009-06-08  0:12 UTC (permalink / raw)
  To: u-boot

This patch adds generic code to support Freescale's i.MX27 SoCs.

Signed-off-by: Ilya Yanok <yanok@emcraft.com>
---
 cpu/arm926ejs/mx27/Makefile             |   44 +++
 cpu/arm926ejs/mx27/generic.c            |  241 +++++++++++++++
 cpu/arm926ejs/mx27/reset.c              |   57 ++++
 cpu/arm926ejs/mx27/timer.c              |  191 ++++++++++++
 include/asm-arm/arch-mx27/asm-offsets.h |   16 +
 include/asm-arm/arch-mx27/clock.h       |   39 +++
 include/asm-arm/arch-mx27/imx-regs.h    |  509 +++++++++++++++++++++++++++++++
 7 files changed, 1097 insertions(+), 0 deletions(-)
 create mode 100644 cpu/arm926ejs/mx27/Makefile
 create mode 100644 cpu/arm926ejs/mx27/generic.c
 create mode 100644 cpu/arm926ejs/mx27/reset.c
 create mode 100644 cpu/arm926ejs/mx27/timer.c
 create mode 100644 include/asm-arm/arch-mx27/asm-offsets.h
 create mode 100644 include/asm-arm/arch-mx27/clock.h
 create mode 100644 include/asm-arm/arch-mx27/imx-regs.h

diff --git a/cpu/arm926ejs/mx27/Makefile b/cpu/arm926ejs/mx27/Makefile
new file mode 100644
index 0000000..67d1b0e
--- /dev/null
+++ b/cpu/arm926ejs/mx27/Makefile
@@ -0,0 +1,44 @@
+#
+# (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).a
+
+COBJS	= generic.o reset.o timer.o
+
+SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
+
+all:	$(obj).depend $(LIB)
+
+$(LIB):	$(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/cpu/arm926ejs/mx27/generic.c b/cpu/arm926ejs/mx27/generic.c
new file mode 100644
index 0000000..eab54d8
--- /dev/null
+++ b/cpu/arm926ejs/mx27/generic.c
@@ -0,0 +1,241 @@
+/*
+ *  Copyright (c) 2008 Eric Jarrige <eric.jarrige@armadeus.org>
+ *  Copyright (c) 2009 Ilya Yanok <yanok@emcraft.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
+ */
+
+#include <common.h>
+#include <div64.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+
+/*
+ *  get the system pll clock in Hz
+ *
+ *                  mfi + mfn / (mfd +1)
+ *  f = 2 * f_ref * --------------------
+ *                        pd + 1
+ */
+unsigned int imx_decode_pll(unsigned int pll, unsigned int f_ref)
+{
+	unsigned int mfi = (pll >> 10) & 0xf;
+	unsigned int mfn = pll & 0x3ff;
+	unsigned int mfd = (pll >> 16) & 0x3ff;
+	unsigned int pd =  (pll >> 26) & 0xf;
+
+	mfi = mfi <= 5 ? 5 : mfi;
+
+	return lldiv(2 * (u64)f_ref * (mfi * (mfd + 1) + mfn),
+			(mfd + 1) * (pd + 1));
+}
+
+static ulong clk_in_32k(void)
+{
+	return 1024 * CONFIG_MX27_CLK32;
+}
+
+static ulong clk_in_26m(void)
+{
+	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+
+	if (readl(&pll->cscr) & CSCR_OSC26M_DIV1P5) {
+		/* divide by 1.5 */
+		return 26000000 * 2 / 3;
+	} else {
+		return 26000000;
+	}
+}
+
+ulong imx_get_mpllclk(void)
+{
+	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+	ulong cscr = readl(&pll->cscr);
+	ulong fref;
+
+	if (cscr & CSCR_MCU_SEL)
+		fref = clk_in_26m();
+	else
+		fref = clk_in_32k();
+
+	return imx_decode_pll(readl(&pll->mpctl0), fref);
+}
+
+ulong imx_get_armclk(void)
+{
+	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+	ulong cscr = readl(&pll->cscr);
+	ulong fref = imx_get_mpllclk();
+	ulong div;
+
+	if (!(cscr & CSCR_ARM_SRC_MPLL))
+		fref = lldiv((fref * 2), 3);
+
+	div = ((cscr >> 12) & 0x3) + 1;
+
+	return lldiv(fref, div);
+}
+
+ulong imx_get_ahbclk(void)
+{
+	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+	ulong cscr = readl(&pll->cscr);
+	ulong fref = imx_get_mpllclk();
+	ulong div;
+
+	div = ((cscr >> 8) & 0x3) + 1;
+
+	return lldiv(fref * 2, 3 * div);
+}
+
+ulong imx_get_spllclk(void)
+{
+	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+	ulong cscr = readl(&pll->cscr);
+	ulong fref;
+
+	if (cscr & CSCR_SP_SEL)
+		fref = clk_in_26m();
+	else
+		fref = clk_in_32k();
+
+	return imx_decode_pll(readl(&pll->spctl0), fref);
+}
+
+static ulong imx_decode_perclk(ulong div)
+{
+	return lldiv((imx_get_mpllclk() * 2), (div * 3));
+}
+
+ulong imx_get_perclk1(void)
+{
+	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+
+	return imx_decode_perclk((readl(&pll->pcdr1) & 0x3f) + 1);
+}
+
+ulong imx_get_perclk2(void)
+{
+	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+
+	return imx_decode_perclk(((readl(&pll->pcdr1) >> 8) & 0x3f) + 1);
+}
+
+ulong imx_get_perclk3(void)
+{
+	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+
+	return imx_decode_perclk(((readl(&pll->pcdr1) >> 16) & 0x3f) + 1);
+}
+
+ulong imx_get_perclk4(void)
+{
+	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+
+	return imx_decode_perclk(((readl(&pll->pcdr1) >> 24) & 0x3f) + 1);
+}
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+int print_cpuinfo (void)
+{
+	char buf[32];
+
+	printf("CPU:   Freescale i.MX27 at %s MHz\n\n",
+			strmhz(buf, imx_get_mpllclk()));
+	return 0;
+}
+#endif
+
+void imx_gpio_mode(int gpio_mode)
+{
+	struct gpio_regs *regs = (struct gpio_regs *)IMX_GPIO_BASE;
+	unsigned int pin = gpio_mode & GPIO_PIN_MASK;
+	unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
+	unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> GPIO_OCR_SHIFT;
+	unsigned int aout = (gpio_mode & GPIO_AOUT_MASK) >> GPIO_AOUT_SHIFT;
+	unsigned int bout = (gpio_mode & GPIO_BOUT_MASK) >> GPIO_BOUT_SHIFT;
+	unsigned int tmp;
+
+	/* Pullup enable */
+	if (gpio_mode & GPIO_PUEN) {
+		writel(readl(&regs->port[port].puen) | (1 << pin),
+				&regs->port[port].puen);
+	} else {
+		writel(readl(&regs->port[port].puen) & ~(1 << pin),
+				&regs->port[port].puen);
+	}
+
+	/* Data direction */
+	if (gpio_mode & GPIO_OUT) {
+		writel(readl(&regs->port[port].ddir) | 1 << pin,
+				&regs->port[port].ddir);
+	} else {
+		writel(readl(&regs->port[port].ddir) & ~(1 << pin),
+				&regs->port[port].ddir);
+	}
+
+	/* Primary / alternate function */
+	if (gpio_mode & GPIO_AF) {
+		writel(readl(&regs->port[port].gpr) | (1 << pin),
+				&regs->port[port].gpr);
+	} else {
+		writel(readl(&regs->port[port].gpr) & ~(1 << pin),
+				&regs->port[port].gpr);
+	}
+
+	/* use as gpio? */
+	if (!(gpio_mode & (GPIO_PF | GPIO_AF))) {
+		writel(readl(&regs->port[port].gius) | (1 << pin),
+				&regs->port[port].gius);
+	} else {
+		writel(readl(&regs->port[port].gius) & ~(1 << pin),
+				&regs->port[port].gius);
+	}
+
+	/* Output / input configuration */
+	if (pin < 16) {
+		tmp = readl(&regs->port[port].ocr1);
+		tmp &= ~(3 << (pin * 2));
+		tmp |= (ocr << (pin * 2));
+		writel(tmp, &regs->port[port].ocr1);
+
+		writel(readl(&regs->port[port].iconfa1) & ~(3 << (pin * 2)),
+				&regs->port[port].iconfa1);
+		writel(readl(&regs->port[port].iconfa1) | aout << (pin * 2),
+				&regs->port[port].iconfa1);
+		writel(readl(&regs->port[port].iconfb1) & ~(3 << (pin * 2)),
+				&regs->port[port].iconfb1);
+		writel(readl(&regs->port[port].iconfb1) | bout << (pin * 2),
+				&regs->port[port].iconfb1);
+	} else {
+		pin -= 16;
+
+		tmp = readl(&regs->port[port].ocr2);
+		tmp &= ~(3 << (pin * 2));
+		tmp |= (ocr << (pin * 2));
+		writel(tmp, &regs->port[port].ocr2);
+
+		writel(readl(&regs->port[port].iconfa2) & ~(3 << (pin * 2)),
+				&regs->port[port].iconfa2);
+		writel(readl(&regs->port[port].iconfa2) | aout << (pin * 2),
+				&regs->port[port].iconfa2);
+		writel(readl(&regs->port[port].iconfb2) & ~(3 << (pin * 2)),
+				&regs->port[port].iconfb2);
+		writel(readl(&regs->port[port].iconfb2) | bout << (pin * 2),
+				&regs->port[port].iconfb2);
+	}
+}
+
diff --git a/cpu/arm926ejs/mx27/reset.c b/cpu/arm926ejs/mx27/reset.c
new file mode 100644
index 0000000..6c54eaf
--- /dev/null
+++ b/cpu/arm926ejs/mx27/reset.c
@@ -0,0 +1,57 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
+ *
+ * (C) Copyright 2009
+ * Ilya Yanok, Emcraft Systems Ltd, <yanok@emcraft.com>
+ *
+ * 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>
+
+/*
+ * Reset the cpu by setting up the watchdog timer and let it time out
+ */
+void reset_cpu (ulong ignored)
+{
+	struct wdog_regs *regs = (struct wdog_regs *)IMX_WDT_BASE;
+	/* Disable watchdog and set Time-Out field to 0 */
+	writel(0x00000000, &regs->wcr);
+
+	/* Write Service Sequence */
+	writel(0x00005555, &regs->wsr);
+	writel(0x0000AAAA, &regs->wsr);
+
+	/* Enable watchdog */
+	writel(WCR_WDE, &regs->wcr);
+
+	while (1);
+	/*NOTREACHED*/
+}
diff --git a/cpu/arm926ejs/mx27/timer.c b/cpu/arm926ejs/mx27/timer.c
new file mode 100644
index 0000000..d22252e
--- /dev/null
+++ b/cpu/arm926ejs/mx27/timer.c
@@ -0,0 +1,191 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
+ *
+ * (C) Copyright 2009
+ * Ilya Yanok, Emcraft Systems Ltd, <yanok@emcraft.com>
+ *
+ * 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 <div64.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+
+/* General purpose timers bitfields */
+#define GPTCR_SWR		(1 << 15)	/* Software reset	*/
+#define GPTCR_FRR		(1 << 8)	/* Freerun / restart	*/
+#define GPTCR_CLKSOURCE_32	(4 << 1)	/* Clock source		*/
+#define GPTCR_TEN		1		/* Timer enable		*/
+
+static ulong timestamp;
+static ulong lastinc;
+
+/*
+ * "time" is measured in 1 / CONFIG_SYS_HZ seconds,
+ * "tick" is internal timer period
+ */
+#ifdef CONFIG_MX27_TIMER_HIGH_PRECISION
+/* ~0.4% error - measured with stop-watch on 100s boot-delay */
+static inline unsigned long long tick_to_time(unsigned long long tick)
+{
+	tick *= CONFIG_SYS_HZ;
+	do_div(tick, CONFIG_MX27_CLK32);
+	return tick;
+}
+
+static inline unsigned long long time_to_tick(unsigned long long time)
+{
+	time *= CONFIG_MX27_CLK32;
+	do_div(time, CONFIG_SYS_HZ);
+	return time;
+}
+
+static inline unsigned long long us_to_tick(unsigned long long us)
+{
+	us = us * CONFIG_MX27_CLK32 + 999999;
+	do_div(us, 1000000);
+	return us;
+}
+#else
+/* ~2% error */
+#define TICK_PER_TIME	((CONFIG_MX27_CLK32 + CONFIG_SYS_HZ / 2) / \
+		CONFIG_SYS_HZ)
+#define US_PER_TICK	(1000000 / CONFIG_MX27_CLK32)
+
+static inline unsigned long long tick_to_time(unsigned long long tick)
+{
+	do_div(tick, TICK_PER_TIME);
+	return tick;
+}
+
+static inline unsigned long long time_to_tick(unsigned long long time)
+{
+	return time * TICK_PER_TIME;
+}
+
+static inline unsigned long long us_to_tick(unsigned long long us)
+{
+	us += US_PER_TICK - 1;
+	do_div(us, US_PER_TICK);
+	return us;
+}
+#endif
+
+/* nothing really to do with interrupts, just starts up a counter. */
+/* The 32768Hz 32-bit timer overruns in 131072 seconds */
+int timer_init(void)
+{
+	int i;
+	struct gpt_regs *regs = (struct gpt_regs *)IMX_TIM1_BASE;
+	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+
+	/* setup GP Timer 1 */
+	writel(GPTCR_SWR, &regs->gpt_tctl);
+
+	writel(readl(&pll->pccr0) | PCCR0_GPT1_EN, &pll->pccr0);
+	writel(readl(&pll->pccr1) | PCCR1_PERCLK1_EN, &pll->pccr1);
+
+	for (i = 0; i < 100; i++)
+		writel(0, &regs->gpt_tctl); /* We have no udelay by now */
+	writel(0, &regs->gpt_tprer); /* 32Khz */
+	/* Freerun Mode, PERCLK1 input */
+	writel(readl(&regs->gpt_tctl) | GPTCR_CLKSOURCE_32 | GPTCR_FRR,
+			&regs->gpt_tctl);
+	writel(readl(&regs->gpt_tctl) | GPTCR_TEN, &regs->gpt_tctl);
+
+	return 0;
+}
+
+void reset_timer_masked(void)
+{
+	struct gpt_regs *regs = (struct gpt_regs *)IMX_TIM1_BASE;
+	/* reset time */
+	/* capture current incrementer value time */
+	lastinc = readl(&regs->gpt_tcn);
+	timestamp = 0; /* start "advancing" time stamp from 0 */
+}
+
+void reset_timer(void)
+{
+	reset_timer_masked();
+}
+
+unsigned long long get_ticks (void)
+{
+	struct gpt_regs *regs = (struct gpt_regs *)IMX_TIM1_BASE;
+	ulong now = readl(&regs->gpt_tcn); /* current tick value */
+
+	if (now >= lastinc) {
+		/*
+		 * normal mode (non roll)
+		 * move stamp forward with absolut diff ticks
+		 */
+		timestamp += (now - lastinc);
+	} else {
+		/* we have rollover of incrementer */
+		timestamp += (0xFFFFFFFF - lastinc) + now;
+	}
+	lastinc = now;
+	return timestamp;
+}
+
+ulong get_timer_masked (void)
+{
+	/*
+	 * get_ticks() returns a long long (64 bit), it wraps in
+	 * 2^64 / CONFIG_MX27_CLK32 = 2^64 / 2^15 = 2^49 ~ 5 * 10^14 (s) ~
+	 * 5 * 10^9 days... and get_ticks() * CONFIG_SYS_HZ wraps in
+	 * 5 * 10^6 days - long enough.
+	 */
+	return tick_to_time(get_ticks());
+}
+
+ulong get_timer (ulong base)
+{
+	return get_timer_masked () - base;
+}
+
+void set_timer (ulong t)
+{
+	timestamp = time_to_tick(t);
+}
+
+/* delay x useconds AND perserve advance timstamp value */
+void udelay (unsigned long usec)
+{
+	unsigned long long tmp;
+	ulong tmo;
+
+	tmo = us_to_tick(usec);
+	tmp = get_ticks() + tmo;	/* get current timestamp */
+
+	while (get_ticks() < tmp)	/* loop till event */
+		 /*NOP*/;
+}
+
diff --git a/include/asm-arm/arch-mx27/asm-offsets.h b/include/asm-arm/arch-mx27/asm-offsets.h
new file mode 100644
index 0000000..497afe5
--- /dev/null
+++ b/include/asm-arm/arch-mx27/asm-offsets.h
@@ -0,0 +1,16 @@
+#define AIPI1_PSR0	0x10000000
+#define AIPI1_PSR1	0x10000004
+#define AIPI2_PSR0	0x10020000
+#define AIPI2_PSR1	0x10020004
+#define CSCR		0x10027000
+#define MPCTL0		0x10027004
+#define SPCTL0		0x1002700c
+#define PCDR0		0x10027018
+#define PCDR1		0x1002701c
+#define PCCR0		0x10027020
+#define PCCR1		0x10027024
+#define ESDCTL0_ROF	0x00
+#define ESDCFG0_ROF	0x04
+#define ESDCTL1_ROF	0x08
+#define ESDCFG1_ROF	0x0C
+#define ESDMISC_ROF	0x10
diff --git a/include/asm-arm/arch-mx27/clock.h b/include/asm-arm/arch-mx27/clock.h
new file mode 100644
index 0000000..5fc75c5
--- /dev/null
+++ b/include/asm-arm/arch-mx27/clock.h
@@ -0,0 +1,39 @@
+/*
+ *
+ * (c) 2009 Ilya Yanok, Emcraft Systems <yanok@emcraft.com>
+ *
+ * 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 __ASM_ARCH_CLOCK_H
+#define __ASM_ARCH_CLOCK_H
+unsigned int imx_decode_pll(unsigned int pll, unsigned int f_ref);
+
+ulong imx_get_mpllclk(void);
+ulong imx_get_armclk(void);
+ulong imx_get_spllclk(void);
+ulong imx_get_fclk(void);
+ulong imx_get_hclk(void);
+ulong imx_get_bclk(void);
+ulong imx_get_perclk1(void);
+ulong imx_get_perclk2(void);
+ulong imx_get_perclk3(void);
+ulong imx_get_ahbclk(void);
+
+#endif /* __ASM_ARCH_CLOCK_H */
diff --git a/include/asm-arm/arch-mx27/imx-regs.h b/include/asm-arm/arch-mx27/imx-regs.h
new file mode 100644
index 0000000..5d2e0b3
--- /dev/null
+++ b/include/asm-arm/arch-mx27/imx-regs.h
@@ -0,0 +1,509 @@
+/*
+ *
+ * (c) 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
+ * (c) 2009 Ilya Yanok, Emcraft Systems <yanok@emcraft.com>
+ *
+ * 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 _IMX_REGS_H
+#define _IMX_REGS_H
+
+#ifndef __ASSEMBLY__
+
+extern void imx_gpio_mode (int gpio_mode);
+
+/* AIPI */
+struct aipi_regs {
+	u32 psr0;
+	u32 psr1;
+};
+
+/* System Control */
+struct system_control_regs {
+	u32 res[5];
+	u32 fmcr;
+	u32 gpcr;
+	u32 wbcr;
+	u32 dscr1;
+	u32 dscr2;
+	u32 dscr3;
+	u32 dscr4;
+	u32 dscr5;
+	u32 dscr6;
+	u32 dscr7;
+	u32 dscr8;
+	u32 dscr9;
+	u32 dscr10;
+	u32 dscr11;
+	u32 dscr12;
+	u32 dscr13;
+	u32 pscr;
+	u32 pmcr;
+	u32 res1;
+	u32 dcvr0;
+	u32 dcvr1;
+	u32 dcvr2;
+	u32 dcvr3;
+};
+
+/* Chip Select Registers */
+struct weim_regs {
+	u32 cs0u;	/* Chip Select 0 Upper Register */
+	u32 cs0l;	/* Chip Select 0 Lower Register */
+	u32 cs0a;	/* Chip Select 0 Addition Register */
+	u32 pad0;
+	u32 cs1u;	/* Chip Select 1 Upper Register */
+	u32 cs1l;	/* Chip Select 1 Lower Register */
+	u32 cs1a;	/* Chip Select 1 Addition Register */
+	u32 pad1;
+	u32 cs2u;	/* Chip Select 2 Upper Register */
+	u32 cs2l;	/* Chip Select 2 Lower Register */
+	u32 cs2a;	/* Chip Select 2 Addition Register */
+	u32 pad2;
+	u32 cs3u;	/* Chip Select 3 Upper Register */
+	u32 cs3l;	/* Chip Select 3 Lower Register */
+	u32 cs3a;	/* Chip Select 3 Addition Register */
+	u32 pad3;
+	u32 cs4u;	/* Chip Select 4 Upper Register */
+	u32 cs4l;	/* Chip Select 4 Lower Register */
+	u32 cs4a;	/* Chip Select 4 Addition Register */
+	u32 pad4;
+	u32 cs5u;	/* Chip Select 5 Upper Register */
+	u32 cs5l;	/* Chip Select 5 Lower Register */
+	u32 cs5a;	/* Chip Select 5 Addition Register */
+	u32 pad5;
+	u32 eim;	/* WEIM Configuration Register */
+};
+
+/* SDRAM Controller registers */
+struct esdramc_regs {
+/* Enhanced SDRAM Control Register 0 */
+	u32 esdctl0;
+/* Enhanced SDRAM Configuration Register 0 */
+	u32 esdcfg0;
+/* Enhanced SDRAM Control Register 1 */
+	u32 esdctl1;
+/* Enhanced SDRAM Configuration Register 1 */
+	u32 esdcfg1;
+/* Enhanced SDRAM Miscellanious Register */
+	u32 esdmisc;
+};
+
+/* Watchdog Registers*/
+struct wdog_regs {
+	u32 wcr;
+	u32 wsr;
+	u32 wstr;
+};
+
+/* PLL registers */
+struct pll_regs {
+	u32 cscr;	/* Clock Source Control Register */
+	u32 mpctl0;	/* MCU PLL Control Register 0 */
+	u32 mpctl1;	/* MCU PLL Control Register 1 */
+	u32 spctl0;	/* System PLL Control Register 0 */
+	u32 spctl1;	/* System PLL Control Register 1 */
+	u32 osc26mctl;	/* Oscillator 26M Register */
+	u32 pcdr0;	/* Peripheral Clock Divider Register 0 */
+	u32 pcdr1;	/* Peripheral Clock Divider Register 1 */
+	u32 pccr0;	/* Peripheral Clock Control Register 0 */
+	u32 pccr1;	/* Peripheral Clock Control Register 1 */
+	u32 ccsr;	/* Clock Control Status Register */
+};
+
+/*
+ * Definitions for the clocksource registers
+ */
+struct gpt_regs {
+	u32 gpt_tctl;
+	u32 gpt_tprer;
+	u32 gpt_tcmp;
+	u32 gpt_tcr;
+	u32 gpt_tcn;
+	u32 gpt_tstat;
+};
+
+/*
+ *  GPIO Module and I/O Multiplexer
+ */
+#define PORTA 0
+#define PORTB 1
+#define PORTC 2
+#define PORTD 3
+#define PORTE 4
+#define PORTF 5
+
+struct gpio_regs {
+	struct {
+		u32 ddir;
+		u32 ocr1;
+		u32 ocr2;
+		u32 iconfa1;
+		u32 iconfa2;
+		u32 iconfb1;
+		u32 iconfb2;
+		u32 dr;
+		u32 gius;
+		u32 ssr;
+		u32 icr1;
+		u32 icr2;
+		u32 imr;
+		u32 isr;
+		u32 gpr;
+		u32 swr;
+		u32 puen;
+		u32 res[0x2f];
+	} port[6];
+};
+
+/* IIM Control Registers */
+struct iim_regs {
+	u32 iim_stat;
+	u32 iim_statm;
+	u32 iim_err;
+	u32 iim_emask;
+	u32 iim_fctl;
+	u32 iim_ua;
+	u32 iim_la;
+	u32 iim_sdat;
+	u32 iim_prev;
+	u32 iim_srev;
+	u32 iim_prog_p;
+	u32 iim_scs0;
+	u32 iim_scs1;
+	u32 iim_scs2;
+	u32 iim_scs3;
+	u32 res[0x1F0];
+	u32 iim_bank_area0[0x100];
+};
+#endif
+
+#define IMX_IO_BASE		0x10000000
+
+#define IMX_AIPI1_BASE		(0x00000 + IMX_IO_BASE)
+#define IMX_WDT_BASE		(0x02000 + IMX_IO_BASE)
+#define IMX_TIM1_BASE		(0x03000 + IMX_IO_BASE)
+#define IMX_TIM2_BASE		(0x04000 + IMX_IO_BASE)
+#define IMX_TIM3_BASE		(0x05000 + IMX_IO_BASE)
+#define IMX_UART1_BASE		(0x0a000 + IMX_IO_BASE)
+#define IMX_UART2_BASE		(0x0b000 + IMX_IO_BASE)
+#define IMX_UART3_BASE		(0x0c000 + IMX_IO_BASE)
+#define IMX_UART4_BASE		(0x0d000 + IMX_IO_BASE)
+#define IMX_I2C1_BASE		(0x12000 + IMX_IO_BASE)
+#define IMX_GPIO_BASE		(0x15000 + IMX_IO_BASE)
+#define IMX_TIM4_BASE		(0x19000 + IMX_IO_BASE)
+#define IMX_TIM5_BASE		(0x1a000 + IMX_IO_BASE)
+#define IMX_UART5_BASE		(0x1b000 + IMX_IO_BASE)
+#define IMX_UART6_BASE		(0x1c000 + IMX_IO_BASE)
+#define IMX_I2C2_BASE		(0x1D000 + IMX_IO_BASE)
+#define IMX_TIM6_BASE		(0x1f000 + IMX_IO_BASE)
+#define IMX_AIPI2_BASE		(0x20000 + IMX_IO_BASE)
+#define IMX_PLL_BASE		(0x27000 + IMX_IO_BASE)
+#define IMX_SYSTEM_CTL_BASE	(0x27800 + IMX_IO_BASE)
+#define IMX_IIM_BASE		(0x28000 + IMX_IO_BASE)
+#define IMX_FEC_BASE		(0x2b000 + IMX_IO_BASE)
+
+#define IMX_ESD_BASE		(0xD8001000)
+#define IMX_WEIM_BASE		(0xD8002000)
+
+/* FMCR System Control bit definition*/
+#define UART4_RXD_CTL	(1 << 25)
+#define UART4_RTS_CTL	(1 << 24)
+#define KP_COL6_CTL	(1 << 18)
+#define KP_ROW7_CTL	(1 << 17)
+#define KP_ROW6_CTL	(1 << 16)
+#define PC_WAIT_B_CTL	(1 << 14)
+#define PC_READY_CTL	(1 << 13)
+#define PC_VS1_CTL	(1 << 12)
+#define PC_VS2_CTL	(1 << 11)
+#define PC_BVD1_CTL	(1 << 10)
+#define PC_BVD2_CTL	(1 << 9)
+#define IOS16_CTL	(1 << 8)
+#define NF_FMS		(1 << 5)
+#define NF_16BIT_SEL	(1 << 4)
+#define SLCDC_SEL	(1 << 2)
+#define SDCS1_SEL	(1 << 1)
+#define SDCS0_SEL	(1 << 0)
+
+
+/* important definition of some bits of WCR */
+#define WCR_WDE 0x04
+
+#define CSCR_MPEN		(1 << 0)
+#define CSCR_SPEN		(1 << 1)
+#define CSCR_FPM_EN		(1 << 2)
+#define CSCR_OSC26M_DIS		(1 << 3)
+#define CSCR_OSC26M_DIV1P5	(1 << 4)
+#define CSCR_AHB_DIV
+#define CSCR_ARM_DIV
+#define CSCR_ARM_SRC_MPLL	(1 << 15)
+#define CSCR_MCU_SEL		(1 << 16)
+#define CSCR_SP_SEL		(1 << 17)
+#define CSCR_MPLL_RESTART	(1 << 18)
+#define CSCR_SPLL_RESTART	(1 << 19)
+#define CSCR_MSHC_SEL		(1 << 20)
+#define CSCR_H264_SEL		(1 << 21)
+#define CSCR_SSI1_SEL		(1 << 22)
+#define CSCR_SSI2_SEL		(1 << 23)
+#define CSCR_SD_CNT
+#define CSCR_USB_DIV
+#define CSCR_UPDATE_DIS		(1 << 31)
+
+#define MPCTL1_BRMO		(1 << 6)
+#define MPCTL1_LF		(1 << 15)
+
+#define PCCR0_SSI2_EN	(1 << 0)
+#define PCCR0_SSI1_EN	(1 << 1)
+#define PCCR0_SLCDC_EN	(1 << 2)
+#define PCCR0_SDHC3_EN	(1 << 3)
+#define PCCR0_SDHC2_EN	(1 << 4)
+#define PCCR0_SDHC1_EN	(1 << 5)
+#define PCCR0_SDC_EN	(1 << 6)
+#define PCCR0_SAHARA_EN	(1 << 7)
+#define PCCR0_RTIC_EN	(1 << 8)
+#define PCCR0_RTC_EN	(1 << 9)
+#define PCCR0_PWM_EN	(1 << 11)
+#define PCCR0_OWIRE_EN	(1 << 12)
+#define PCCR0_MSHC_EN	(1 << 13)
+#define PCCR0_LCDC_EN	(1 << 14)
+#define PCCR0_KPP_EN	(1 << 15)
+#define PCCR0_IIM_EN	(1 << 16)
+#define PCCR0_I2C2_EN	(1 << 17)
+#define PCCR0_I2C1_EN	(1 << 18)
+#define PCCR0_GPT6_EN	(1 << 19)
+#define PCCR0_GPT5_EN	(1 << 20)
+#define PCCR0_GPT4_EN	(1 << 21)
+#define PCCR0_GPT3_EN	(1 << 22)
+#define PCCR0_GPT2_EN	(1 << 23)
+#define PCCR0_GPT1_EN	(1 << 24)
+#define PCCR0_GPIO_EN	(1 << 25)
+#define PCCR0_FEC_EN	(1 << 26)
+#define PCCR0_EMMA_EN	(1 << 27)
+#define PCCR0_DMA_EN	(1 << 28)
+#define PCCR0_CSPI3_EN	(1 << 29)
+#define PCCR0_CSPI2_EN	(1 << 30)
+#define PCCR0_CSPI1_EN	(1 << 31)
+
+#define PCCR1_MSHC_BAUDEN	(1 << 2)
+#define PCCR1_NFC_BAUDEN	(1 << 3)
+#define PCCR1_SSI2_BAUDEN	(1 << 4)
+#define PCCR1_SSI1_BAUDEN	(1 << 5)
+#define PCCR1_H264_BAUDEN	(1 << 6)
+#define PCCR1_PERCLK4_EN	(1 << 7)
+#define PCCR1_PERCLK3_EN	(1 << 8)
+#define PCCR1_PERCLK2_EN	(1 << 9)
+#define PCCR1_PERCLK1_EN	(1 << 10)
+#define PCCR1_HCLK_USB		(1 << 11)
+#define PCCR1_HCLK_SLCDC	(1 << 12)
+#define PCCR1_HCLK_SAHARA	(1 << 13)
+#define PCCR1_HCLK_RTIC		(1 << 14)
+#define PCCR1_HCLK_LCDC		(1 << 15)
+#define PCCR1_HCLK_H264		(1 << 16)
+#define PCCR1_HCLK_FEC		(1 << 17)
+#define PCCR1_HCLK_EMMA		(1 << 18)
+#define PCCR1_HCLK_EMI		(1 << 19)
+#define PCCR1_HCLK_DMA		(1 << 20)
+#define PCCR1_HCLK_CSI		(1 << 21)
+#define PCCR1_HCLK_BROM		(1 << 22)
+#define PCCR1_HCLK_ATA		(1 << 23)
+#define PCCR1_WDT_EN		(1 << 24)
+#define PCCR1_USB_EN		(1 << 25)
+#define PCCR1_UART6_EN		(1 << 26)
+#define PCCR1_UART5_EN		(1 << 27)
+#define PCCR1_UART4_EN		(1 << 28)
+#define PCCR1_UART3_EN		(1 << 29)
+#define PCCR1_UART2_EN		(1 << 30)
+#define PCCR1_UART1_EN		(1 << 31)
+
+/* SDRAM Controller registers bitfields */
+#define ESDCTL_PRCT(x)		(((x) & 0x3f) << 0)
+#define ESDCTL_BL		(1 << 7)
+#define ESDCTL_FP		(1 << 8)
+#define ESDCTL_PWDT(x)		(((x) & 3) << 10)
+#define ESDCTL_SREFR(x)		(((x) & 7) << 13)
+#define ESDCTL_DSIZ_16_UPPER	(0 << 16)
+#define ESDCTL_DSIZ_16_LOWER	(1 << 16)
+#define ESDCTL_DSIZ_32		(2 << 16)
+#define ESDCTL_COL8		(0 << 20)
+#define ESDCTL_COL9		(1 << 20)
+#define ESDCTL_COL10		(2 << 20)
+#define ESDCTL_ROW11		(0 << 24)
+#define ESDCTL_ROW12		(1 << 24)
+#define ESDCTL_ROW13		(2 << 24)
+#define ESDCTL_ROW14		(3 << 24)
+#define ESDCTL_ROW15		(4 << 24)
+#define ESDCTL_SP		(1 << 27)
+#define ESDCTL_SMODE_NORMAL	(0 << 28)
+#define ESDCTL_SMODE_PRECHARGE	(1 << 28)
+#define ESDCTL_SMODE_AUTO_REF	(2 << 28)
+#define ESDCTL_SMODE_LOAD_MODE	(3 << 28)
+#define ESDCTL_SMODE_MAN_REF	(4 << 28)
+#define ESDCTL_SDE		(1 << 31)
+
+#define ESDCFG_TRC(x)		(((x) & 0xf) << 0)
+#define ESDCFG_TRCD(x)		(((x) & 0x7) << 4)
+#define ESDCFG_TCAS(x)		(((x) & 0x3) << 8)
+#define ESDCFG_TRRD(x)		(((x) & 0x3) << 10)
+#define ESDCFG_TRAS(x)		(((x) & 0x7) << 12)
+#define ESDCFG_TWR		(1 << 15)
+#define ESDCFG_TMRD(x)		(((x) & 0x3) << 16)
+#define ESDCFG_TRP(x)		(((x) & 0x3) << 18)
+#define ESDCFG_TWTR		(1 << 20)
+#define ESDCFG_TXP(x)		(((x) & 0x3) << 21)
+
+#define ESDMISC_RST		(1 << 1)
+#define ESDMISC_MDDREN		(1 << 2)
+#define ESDMISC_MDDR_DL_RST	(1 << 3)
+#define ESDMISC_MDDR_MDIS	(1 << 4)
+#define ESDMISC_LHD		(1 << 5)
+#define ESDMISC_MA10_SHARE	(1 << 6)
+#define ESDMISC_SDRAM_RDY	(1 << 31)
+
+#define PC5_PF_I2C2_DATA	(GPIO_PORTC | GPIO_OUT | GPIO_PF | 5)
+#define PC6_PF_I2C2_CLK		(GPIO_PORTC | GPIO_OUT | GPIO_PF | 6)
+#define PC7_PF_USBOTG_DATA5	(GPIO_PORTC | GPIO_OUT | GPIO_PF | 7)
+#define PC8_PF_USBOTG_DATA6	(GPIO_PORTC | GPIO_OUT | GPIO_PF | 8)
+#define PC9_PF_USBOTG_DATA0	(GPIO_PORTC | GPIO_OUT | GPIO_PF | 9)
+#define PC10_PF_USBOTG_DATA2	(GPIO_PORTC | GPIO_OUT | GPIO_PF | 10)
+#define PC11_PF_USBOTG_DATA1	(GPIO_PORTC | GPIO_OUT | GPIO_PF | 11)
+#define PC12_PF_USBOTG_DATA4	(GPIO_PORTC | GPIO_OUT | GPIO_PF | 12)
+#define PC13_PF_USBOTG_DATA3	(GPIO_PORTC | GPIO_OUT | GPIO_PF | 13)
+
+#define PD0_AIN_FEC_TXD0	(GPIO_PORTD | GPIO_OUT | GPIO_AIN | 0)
+#define PD1_AIN_FEC_TXD1	(GPIO_PORTD | GPIO_OUT | GPIO_AIN | 1)
+#define PD2_AIN_FEC_TXD2	(GPIO_PORTD | GPIO_OUT | GPIO_AIN | 2)
+#define PD3_AIN_FEC_TXD3	(GPIO_PORTD | GPIO_OUT | GPIO_AIN | 3)
+#define PD4_AOUT_FEC_RX_ER	(GPIO_PORTD | GPIO_IN | GPIO_AOUT | 4)
+#define PD5_AOUT_FEC_RXD1	(GPIO_PORTD | GPIO_IN | GPIO_AOUT | 5)
+#define PD6_AOUT_FEC_RXD2	(GPIO_PORTD | GPIO_IN | GPIO_AOUT | 6)
+#define PD7_AOUT_FEC_RXD3	(GPIO_PORTD | GPIO_IN | GPIO_AOUT | 7)
+#define PD8_AF_FEC_MDIO		(GPIO_PORTD | GPIO_IN | GPIO_AF | 8)
+#define PD9_AIN_FEC_MDC		(GPIO_PORTD | GPIO_OUT | GPIO_AIN | 9)
+#define PD10_AOUT_FEC_CRS	(GPIO_PORTD | GPIO_IN | GPIO_AOUT | 10)
+#define PD11_AOUT_FEC_TX_CLK	(GPIO_PORTD | GPIO_IN | GPIO_AOUT | 11)
+#define PD12_AOUT_FEC_RXD0	(GPIO_PORTD | GPIO_IN | GPIO_AOUT | 12)
+#define PD13_AOUT_FEC_RX_DV	(GPIO_PORTD | GPIO_IN | GPIO_AOUT | 13)
+#define PD14_AOUT_FEC_CLR	(GPIO_PORTD | GPIO_IN | GPIO_AOUT | 14)
+#define PD15_AOUT_FEC_COL	(GPIO_PORTD | GPIO_IN | GPIO_AOUT | 15)
+#define PD16_AIN_FEC_TX_ER	(GPIO_PORTD | GPIO_OUT | GPIO_AIN | 16)
+#define PF23_AIN_FEC_TX_EN	(GPIO_PORTF | GPIO_OUT | GPIO_AIN | 23)
+
+#define PE0_PF_USBOTG_NXT	(GPIO_PORTE | GPIO_OUT | GPIO_PF | 0)
+#define PE1_PF_USBOTG_STP	(GPIO_PORTE | GPIO_OUT | GPIO_PF | 1)
+#define PE2_PF_USBOTG_DIR	(GPIO_PORTE | GPIO_OUT | GPIO_PF | 2)
+#define PE3_PF_UART2_CTS	(GPIO_PORTE | GPIO_OUT | GPIO_PF | 3)
+#define PE4_PF_UART2_RTS	(GPIO_PORTE | GPIO_IN  | GPIO_PF | 4)
+#define PE6_PF_UART2_TXD	(GPIO_PORTE | GPIO_OUT | GPIO_PF | 6)
+#define PE7_PF_UART2_RXD	(GPIO_PORTE | GPIO_IN  | GPIO_PF | 7)
+#define PE8_PF_UART3_TXD	(GPIO_PORTE | GPIO_OUT | GPIO_PF | 8)
+#define PE9_PF_UART3_RXD	(GPIO_PORTE | GPIO_IN  | GPIO_PF | 9)
+#define PE10_PF_UART3_CTS	(GPIO_PORTE | GPIO_OUT | GPIO_PF | 10)
+#define PE11_PF_UART3_RTS	(GPIO_PORTE | GPIO_IN  | GPIO_PF | 11)
+#define PE12_PF_UART1_TXD	(GPIO_PORTE | GPIO_OUT | GPIO_PF | 12)
+#define PE13_PF_UART1_RXD	(GPIO_PORTE | GPIO_IN  | GPIO_PF | 13)
+#define PE14_PF_UART1_CTS	(GPIO_PORTE | GPIO_OUT | GPIO_PF | 14)
+#define PE15_PF_UART1_RTS	(GPIO_PORTE | GPIO_IN  | GPIO_PF | 15)
+#define PE18_PF_SD1_D0		(GPIO_PORTE | GPIO_PF | 18)
+#define PE19_PF_SD1_D1		(GPIO_PORTE | GPIO_PF | 19)
+#define PE20_PF_SD1_D2		(GPIO_PORTE | GPIO_PF | 20)
+#define PE21_PF_SD1_D3		(GPIO_PORTE | GPIO_PF | 21)
+#define PE22_PF_SD1_CMD		(GPIO_PORTE | GPIO_PF | 22)
+#define PE23_PF_SD1_CLK		(GPIO_PORTE | GPIO_PF | 23)
+#define PB4_PF_SD2_D0		(GPIO_PORTB | GPIO_PF | 4)
+#define PB5_PF_SD2_D1		(GPIO_PORTB | GPIO_PF | 5)
+#define PB6_PF_SD2_D2		(GPIO_PORTB | GPIO_PF | 6)
+#define PB7_PF_SD2_D3		(GPIO_PORTB | GPIO_PF | 7)
+#define PB8_PF_SD2_CMD		(GPIO_PORTB | GPIO_PF | 8)
+#define PB9_PF_SD2_CLK		(GPIO_PORTB | GPIO_PF | 9)
+#define PD17_PF_I2C_DATA	(GPIO_PORTD | GPIO_OUT | GPIO_PF | 17)
+#define PD18_PF_I2C_CLK		(GPIO_PORTD | GPIO_OUT | GPIO_PF | 18)
+#define PE24_PF_USBOTG_CLK	(GPIO_PORTE | GPIO_OUT | GPIO_PF | 24)
+#define PE25_PF_USBOTG_DATA7	(GPIO_PORTE | GPIO_OUT | GPIO_PF | 25)
+
+/* Clocksource Bitfields */
+#define TCTL_SWR	(1 << 15)	/* Software reset */
+#define TCTL_FRR	(1 << 8)	/* Freerun / restart */
+#define TCTL_CAP	(3 << 6)	/* Capture Edge */
+#define TCTL_OM		(1 << 5)	/* output mode */
+#define TCTL_IRQEN	(1 << 4)	/* interrupt enable */
+#define TCTL_CLKSOURCE	1		/* Clock source bit position */
+#define TCTL_TEN	1		/* Timer enable */
+#define TPRER_PRES	0xff		/* Prescale */
+#define TSTAT_CAPT	(1 << 1)	/* Capture event */
+#define TSTAT_COMP	1		/* Compare event */
+
+#define GPIO_PIN_MASK	0x1f
+
+#define GPIO_PORT_SHIFT	5
+#define GPIO_PORT_MASK	(0x7 << GPIO_PORT_SHIFT)
+
+#define GPIO_PORTA	(PORTA << GPIO_PORT_SHIFT)
+#define GPIO_PORTB	(PORTB << GPIO_PORT_SHIFT)
+#define GPIO_PORTC	(PORTC << GPIO_PORT_SHIFT)
+#define GPIO_PORTD	(PORTD << GPIO_PORT_SHIFT)
+#define GPIO_PORTE	(PORTE << GPIO_PORT_SHIFT)
+#define GPIO_PORTF	(PORTF << GPIO_PORT_SHIFT)
+
+#define GPIO_OUT	(1 << 8)
+#define GPIO_IN		(0 << 8)
+#define GPIO_PUEN	(1 << 9)
+
+#define GPIO_PF		(1 << 10)
+#define GPIO_AF		(1 << 11)
+
+#define GPIO_OCR_SHIFT	12
+#define GPIO_OCR_MASK	(3 << GPIO_OCR_SHIFT)
+#define GPIO_AIN	(0 << GPIO_OCR_SHIFT)
+#define GPIO_BIN	(1 << GPIO_OCR_SHIFT)
+#define GPIO_CIN	(2 << GPIO_OCR_SHIFT)
+#define GPIO_GPIO	(3 << GPIO_OCR_SHIFT)
+
+#define GPIO_AOUT_SHIFT	14
+#define GPIO_AOUT_MASK	(3 << GPIO_AOUT_SHIFT)
+#define GPIO_AOUT	(0 << GPIO_AOUT_SHIFT)
+#define GPIO_AOUT_ISR	(1 << GPIO_AOUT_SHIFT)
+#define GPIO_AOUT_0	(2 << GPIO_AOUT_SHIFT)
+#define GPIO_AOUT_1	(3 << GPIO_AOUT_SHIFT)
+
+#define GPIO_BOUT_SHIFT	16
+#define GPIO_BOUT_MASK	(3 << GPIO_BOUT_SHIFT)
+#define GPIO_BOUT	(0 << GPIO_BOUT_SHIFT)
+#define GPIO_BOUT_ISR	(1 << GPIO_BOUT_SHIFT)
+#define GPIO_BOUT_0	(2 << GPIO_BOUT_SHIFT)
+#define GPIO_BOUT_1	(3 << GPIO_BOUT_SHIFT)
+
+#define IIM_STAT_BUSY	(1 << 7)
+#define IIM_STAT_PRGD	(1 << 1)
+#define IIM_STAT_SNSD	(1 << 0)
+#define IIM_ERR_PRGE	(1 << 7)
+#define IIM_ERR_WPE	(1 << 6)
+#define IIM_ERR_OPE	(1 << 5)
+#define IIM_ERR_RPE	(1 << 4)
+#define IIM_ERR_WLRE	(1 << 3)
+#define IIM_ERR_SNSE	(1 << 2)
+#define IIM_ERR_PARITYE	(1 << 1)
+
+/* Definitions for i.MX27 TO2 */
+#define IIM0_MAC		5
+#define IIM0_SCC_KEY		11
+#define IIM1_SUID		1
+
+#endif				/* _IMX_REGS_H */
+
-- 
1.6.0.6

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

* [U-Boot] [PATCH 2/7] serial_mx31: allow it to work with mx27 too and rename to serial_mxc
  2009-06-08  0:12 [U-Boot] [PATCH 0/7][v3] Support for LogicPD i.MX27-LITEKIT development board Ilya Yanok
  2009-06-08  0:12 ` [U-Boot] [PATCH 1/7] mx27: basic cpu support Ilya Yanok
@ 2009-06-08  0:12 ` Ilya Yanok
  2009-06-20 13:18   ` Jean-Christophe PLAGNIOL-VILLARD
  2009-06-08  0:12 ` [U-Boot] [PATCH 3/7] fec_imx27: driver for FEC ethernet controller on i.MX27 Ilya Yanok
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 70+ messages in thread
From: Ilya Yanok @ 2009-06-08  0:12 UTC (permalink / raw)
  To: u-boot

UART hardware on i.MX27 is the same as on the i.MX31 so we just
need to provide the driver with correct address of the registers.

Signed-off-by: Ilya Yanok <yanok@emcraft.com>
---
 drivers/serial/Makefile                        |    2 +-
 drivers/serial/{serial_mx31.c => serial_mxc.c} |   21 +++++++++++++++++++++
 include/configs/imx31_litekit.h                |    2 +-
 include/configs/imx31_phycore.h                |    2 +-
 include/configs/mx31ads.h                      |    2 +-
 include/configs/qong.h                         |    2 +-
 6 files changed, 26 insertions(+), 5 deletions(-)
 rename drivers/serial/{serial_mx31.c => serial_mxc.c} (94%)

diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 14c818d..9a572e9 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -40,7 +40,7 @@ COBJS-$(CONFIG_IXP_SERIAL) += serial_ixp.o
 COBJS-$(CONFIG_KS8695_SERIAL) += serial_ks8695.o
 COBJS-$(CONFIG_LPC2292_SERIAL) += serial_lpc2292.o
 COBJS-$(CONFIG_MAX3100_SERIAL) += serial_max3100.o
-COBJS-$(CONFIG_MX31_UART) += serial_mx31.o
+COBJS-$(CONFIG_MXC_UART) += serial_mxc.o
 COBJS-$(CONFIG_NETARM_SERIAL) += serial_netarm.o
 COBJS-$(CONFIG_PL010_SERIAL) += serial_pl01x.o
 COBJS-$(CONFIG_PL011_SERIAL) += serial_pl01x.o
diff --git a/drivers/serial/serial_mx31.c b/drivers/serial/serial_mxc.c
similarity index 94%
rename from drivers/serial/serial_mx31.c
rename to drivers/serial/serial_mxc.c
index 7c0682a..acc5b7d 100644
--- a/drivers/serial/serial_mx31.c
+++ b/drivers/serial/serial_mxc.c
@@ -18,7 +18,12 @@
  */
 
 #include <common.h>
+#ifdef CONFIG_MX31
 #include <asm/arch/mx31.h>
+#else
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/clock.h>
+#endif
 
 #define __REG(x)     (*((volatile u32 *)(x)))
 
@@ -32,6 +37,18 @@
 #define UART_PHYS 0x43fb0000
 #elif defined(CONFIG_SYS_MX31_UART5)
 #define UART_PHYS 0x43fb4000
+#elif defined(CONFIG_SYS_MX27_UART1)
+#define UART_PHYS 0x1000a000
+#elif defined(CONFIG_SYS_MX27_UART2)
+#define UART_PHYS 0x1000b000
+#elif defined(CONFIG_SYS_MX27_UART3)
+#define UART_PHYS 0x1000c000
+#elif defined(CONFIG_SYS_MX27_UART4)
+#define UART_PHYS 0x1000d000
+#elif defined(CONFIG_SYS_MX27_UART5)
+#define UART_PHYS 0x1001b000
+#elif defined(CONFIG_SYS_MX27_UART6)
+#define UART_PHYS 0x1001c000
 #else
 #error "define CONFIG_SYS_MX31_UARTx to use the mx31 UART driver"
 #endif
@@ -149,7 +166,11 @@ DECLARE_GLOBAL_DATA_PTR;
 
 void serial_setbrg (void)
 {
+#ifdef CONFIG_MX31
 	u32 clk = mx31_get_ipg_clk();
+#else
+	u32 clk = imx_get_perclk1();
+#endif
 
 	if (!gd->baudrate)
 		gd->baudrate = CONFIG_BAUDRATE;
diff --git a/include/configs/imx31_litekit.h b/include/configs/imx31_litekit.h
index 9ac6eec..74f54c0 100644
--- a/include/configs/imx31_litekit.h
+++ b/include/configs/imx31_litekit.h
@@ -60,7 +60,7 @@
  * Hardware drivers
  */
 
-#define CONFIG_MX31_UART	1
+#define CONFIG_MXC_UART	1
 #define CONFIG_SYS_MX31_UART1		1
 
 #define CONFIG_HARD_SPI		1
diff --git a/include/configs/imx31_phycore.h b/include/configs/imx31_phycore.h
index cbc0b92..cb42a7c 100644
--- a/include/configs/imx31_phycore.h
+++ b/include/configs/imx31_phycore.h
@@ -64,7 +64,7 @@
 #define CONFIG_SYS_I2C_SPEED		100000
 #define CONFIG_SYS_I2C_SLAVE		0xfe
 
-#define CONFIG_MX31_UART	1
+#define CONFIG_MXC_UART	1
 #define CONFIG_SYS_MX31_UART1		1
 
 /* allow to overwrite serial and ethaddr */
diff --git a/include/configs/mx31ads.h b/include/configs/mx31ads.h
index c31c06a..363ea1b 100644
--- a/include/configs/mx31ads.h
+++ b/include/configs/mx31ads.h
@@ -57,7 +57,7 @@
  * Hardware drivers
  */
 
-#define CONFIG_MX31_UART	1
+#define CONFIG_MXC_UART	1
 #define CONFIG_SYS_MX31_UART1		1
 
 #define CONFIG_HARD_SPI		1
diff --git a/include/configs/qong.h b/include/configs/qong.h
index a67006a..12bdc69 100644
--- a/include/configs/qong.h
+++ b/include/configs/qong.h
@@ -49,7 +49,7 @@
  * Hardware drivers
  */
 
-#define CONFIG_MX31_UART	1
+#define CONFIG_MXC_UART	1
 #define CONFIG_SYS_MX31_UART1	1
 
 /* FPGA */
-- 
1.6.0.6

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

* [U-Boot] [PATCH 3/7] fec_imx27: driver for FEC ethernet controller on i.MX27
  2009-06-08  0:12 [U-Boot] [PATCH 0/7][v3] Support for LogicPD i.MX27-LITEKIT development board Ilya Yanok
  2009-06-08  0:12 ` [U-Boot] [PATCH 1/7] mx27: basic cpu support Ilya Yanok
  2009-06-08  0:12 ` [U-Boot] [PATCH 2/7] serial_mx31: allow it to work with mx27 too and rename to serial_mxc Ilya Yanok
@ 2009-06-08  0:12 ` Ilya Yanok
  2009-07-17 10:57   ` [U-Boot] [PATCH] fec_mxc: " Ilya Yanok
  2009-06-08  0:12 ` [U-Boot] [PATCH 4/7] mxc_nand: add nand driver for MX2/MX3 Ilya Yanok
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 70+ messages in thread
From: Ilya Yanok @ 2009-06-08  0:12 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Ilya Yanok <yanok@emcraft.com>
---
 cpu/arm926ejs/mx27/generic.c |   10 +
 drivers/net/Makefile         |    1 +
 drivers/net/fec_imx27.c      |  713 ++++++++++++++++++++++++++++++++++++++++++
 drivers/net/fec_imx27.h      |  304 ++++++++++++++++++
 include/netdev.h             |    1 +
 5 files changed, 1029 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/fec_imx27.c
 create mode 100644 drivers/net/fec_imx27.h

diff --git a/cpu/arm926ejs/mx27/generic.c b/cpu/arm926ejs/mx27/generic.c
index eab54d8..b52f934 100644
--- a/cpu/arm926ejs/mx27/generic.c
+++ b/cpu/arm926ejs/mx27/generic.c
@@ -20,6 +20,7 @@
 
 #include <common.h>
 #include <div64.h>
+#include <netdev.h>
 #include <asm/io.h>
 #include <asm/arch/imx-regs.h>
 
@@ -159,6 +160,15 @@ int print_cpuinfo (void)
 }
 #endif
 
+int cpu_eth_init(bd_t *bis)
+{
+#if defined(CONFIG_FEC_IMX27)
+	return fecimx27_initialize(bis);
+#else
+	return 0;
+#endif
+}
+
 void imx_gpio_mode(int gpio_mode)
 {
 	struct gpio_regs *regs = (struct gpio_regs *)IMX_GPIO_BASE;
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index a360a50..8bbbd2b 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -37,6 +37,7 @@ COBJS-$(CONFIG_DNET) += dnet.o
 COBJS-$(CONFIG_E1000) += e1000.o
 COBJS-$(CONFIG_EEPRO100) += eepro100.o
 COBJS-$(CONFIG_ENC28J60) += enc28j60.o
+COBJS-$(CONFIG_FEC_IMX27) += fec_imx27.o
 COBJS-$(CONFIG_FSLDMAFEC) += fsl_mcdmafec.o mcfmii.o
 COBJS-$(CONFIG_GRETH) += greth.o
 COBJS-$(CONFIG_INCA_IP_SWITCH) += inca-ip_sw.o
diff --git a/drivers/net/fec_imx27.c b/drivers/net/fec_imx27.c
new file mode 100644
index 0000000..f26ae9e
--- /dev/null
+++ b/drivers/net/fec_imx27.c
@@ -0,0 +1,713 @@
+/*
+ * (C) Copyright 2009 Ilya Yanok, Emcraft Systems Ltd <yanok@emcraft.com>
+ * (C) Copyright 2008,2009 Eric Jarrige <eric.jarrige@armadeus.org>
+ * (C) Copyright 2008 Armadeus Systems nc
+ * (C) Copyright 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
+ * (C) Copyright 2007 Pengutronix, Juergen Beisert <j.beisert@pengutronix.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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <net.h>
+#include <miiphy.h>
+#include "fec_imx27.h"
+
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifndef CONFIG_MII
+#error "CONFIG_MII has to be defined!"
+#endif
+
+#undef DEBUG
+
+struct nbuf {
+	uint8_t data[1500];	/**< actual data */
+	int length;		/**< actual length */
+	int used;		/**< buffer in use or not */
+	uint8_t head[16];	/**< MAC header(6 + 6 + 2) + 2(aligned) */
+};
+
+struct fec_priv gfec = {
+	.eth       = (struct ethernet_regs *)IMX_FEC_BASE,
+	.xcv_type  = MII100,
+	.rbd_base  = NULL,
+	.rbd_index = 0,
+	.tbd_base  = NULL,
+	.tbd_index = 0,
+	.bd        = NULL,
+};
+
+/*
+ * MII-interface related functions
+ */
+static int fec_miiphy_read(char *dev, uint8_t phyAddr, uint8_t regAddr,
+		uint16_t *retVal)
+{
+	struct eth_device *edev = eth_get_dev_by_name(dev);
+	struct fec_priv *fec = (struct fec_priv *)edev->priv;
+
+	uint32_t reg;		/* convenient holder for the PHY register */
+	uint32_t phy;		/* convenient holder for the PHY */
+	uint32_t start;
+
+	/*
+	 * reading from any PHY's register is done by properly
+	 * programming the FEC's MII data register.
+	 */
+	writel(FEC_IEVENT_MII, &fec->eth->ievent);
+	reg = regAddr << FEC_MII_DATA_RA_SHIFT;
+	phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
+
+	writel(FEC_MII_DATA_ST | FEC_MII_DATA_OP_RD | FEC_MII_DATA_TA |
+			phy | reg, &fec->eth->mii_data);
+
+	/*
+	 * wait for the related interrupt
+	 */
+	start = get_timer_masked();
+	while (!(readl(&fec->eth->ievent) & FEC_IEVENT_MII)) {
+		if (get_timer(start) > (CONFIG_SYS_HZ / 1000)) {
+			printf("Read MDIO failed...\n");
+			return -1;
+		}
+	}
+
+	/*
+	 * clear mii interrupt bit
+	 */
+	writel(FEC_IEVENT_MII, &fec->eth->ievent);
+
+	/*
+	 * it's now safe to read the PHY's register
+	 */
+	*retVal = readl(&fec->eth->mii_data);
+	debug("fec_miiphy_read: phy: %02x reg:%02x val:%#x\n", phyAddr,
+			regAddr, *retVal);
+	return 0;
+}
+
+static int fec_miiphy_write(char *dev, uint8_t phyAddr, uint8_t regAddr,
+		uint16_t data)
+{
+	struct eth_device *edev = eth_get_dev_by_name(dev);
+	struct fec_priv *fec = (struct fec_priv *)edev->priv;
+
+	uint32_t reg;		/* convenient holder for the PHY register */
+	uint32_t phy;		/* convenient holder for the PHY */
+	uint32_t start;
+
+	reg = regAddr << FEC_MII_DATA_RA_SHIFT;
+	phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
+
+	writel(FEC_MII_DATA_ST | FEC_MII_DATA_OP_WR |
+		FEC_MII_DATA_TA | phy | reg | data, &fec->eth->mii_data);
+
+	/*
+	 * wait for the MII interrupt
+	 */
+	start = get_timer_masked();
+	while (!(readl(&fec->eth->ievent) & FEC_IEVENT_MII)) {
+		if (get_timer(start) > (CONFIG_SYS_HZ / 1000)) {
+			printf("Write MDIO failed...\n");
+			return -1;
+		}
+	}
+
+	/*
+	 * clear MII interrupt bit
+	 */
+	writel(FEC_IEVENT_MII, &fec->eth->ievent);
+	debug("fec_miiphy_write: phy: %02x reg:%02x val:%#x\n", phyAddr,
+			regAddr, data);
+
+	return 0;
+}
+
+static int miiphy_restart_aneg(struct eth_device *dev)
+{
+	/*
+	 * Wake up from sleep if necessary
+	 * Reset PHY, then delay 300ns
+	 */
+	miiphy_write(dev->name, 0, PHY_MIPGSR, 0x00FF);
+	miiphy_write(dev->name, 0, PHY_BMCR, PHY_BMCR_RESET);
+	udelay(1000);
+
+	/*
+	 * Set the auto-negotiation advertisement register bits
+	 */
+	miiphy_write(dev->name, 0, PHY_ANAR, 0x1e0);
+	miiphy_write(dev->name, 0, PHY_BMCR, PHY_BMCR_AUTON | PHY_BMCR_RST_NEG);
+
+	return 0;
+}
+
+static int miiphy_wait_aneg(struct eth_device *dev)
+{
+	uint32_t start;
+	uint16_t status;
+
+	/*
+	 * Wait for AN completion
+	 */
+	start = get_timer_masked(); /* get_time_ns(); */
+	do {
+		if (get_timer(start) > (CONFIG_SYS_HZ * 5)) {
+			printf("%s: Autonegotiation timeout\n", dev->name);
+			return -1;
+		}
+
+		if (miiphy_read(dev->name, 0, PHY_BMSR, &status)) {
+			printf("%s: Autonegotiation failed. status: 0x%04x\n",
+					dev->name, status);
+			return -1;
+		}
+	} while (!(status & PHY_BMSR_LS));
+
+	return 0;
+}
+static int fec_rx_task_enable(struct fec_priv *fec)
+{
+	writel(1 << 24, &fec->eth->r_des_active);
+	return 0;
+}
+
+static int fec_rx_task_disable(struct fec_priv *fec)
+{
+	return 0;
+}
+
+static int fec_tx_task_enable(struct fec_priv *fec)
+{
+	writel(1 << 24, &fec->eth->x_des_active);
+	return 0;
+}
+
+static int fec_tx_task_disable(struct fec_priv *fec)
+{
+	return 0;
+}
+
+/**
+ * Initialize receive task's buffer descriptors
+ * @param[in] fec all we know about the device yet
+ * @param[in] count receive buffer count to be allocated
+ * @param[in] size size of each receive buffer
+ * @return 0 on success
+ *
+ * For this task we need additional memory for the data buffers. And each
+ * data buffer requires some alignment. Thy must be aligned to a specific
+ * boundary each (DB_DATA_ALIGNMENT).
+ */
+static int fec_rbd_init(struct fec_priv *fec, int count, int size)
+{
+	int ix;
+	uint32_t p = 0;
+
+	/* reserve data memory and consider alignment */
+	fec->rdb_ptr = malloc(size * count + DB_DATA_ALIGNMENT);
+	p = (uint32_t)fec->rdb_ptr;
+	if (!p) {
+		puts("fec_imx27: not enough malloc memory!\n");
+		return -ENOMEM;
+	}
+	memset((void *)p, 0, size * count + DB_DATA_ALIGNMENT);
+	p += DB_DATA_ALIGNMENT-1;
+	p &= ~(DB_DATA_ALIGNMENT-1);
+
+	for (ix = 0; ix < count; ix++) {
+		writel(p, &fec->rbd_base[ix].data_pointer);
+		p += size;
+		writew(FEC_RBD_EMPTY, &fec->rbd_base[ix].status);
+		writew(0, &fec->rbd_base[ix].data_length);
+	}
+	/*
+	 * mark the last RBD to close the ring
+	 */
+	writew(FEC_RBD_WRAP | FEC_RBD_EMPTY, &fec->rbd_base[ix - 1].status);
+	fec->rbd_index = 0;
+
+	return 0;
+}
+
+/**
+ * Initialize transmit task's buffer descriptors
+ * @param[in] fec all we know about the device yet
+ *
+ * Transmit buffers are created externally. We only have to init the BDs here.\n
+ * Note: There is a race condition in the hardware. When only one BD is in
+ * use it must be marked with the WRAP bit to use it for every transmitt.
+ * This bit in combination with the READY bit results into double transmit
+ * of each data buffer. It seems the state machine checks READY earlier then
+ * resetting it after the first transfer.
+ * Using two BDs solves this issue.
+ */
+static void fec_tbd_init(struct fec_priv *fec)
+{
+	writew(0x0000, &fec->tbd_base[0].status);
+	writew(FEC_TBD_WRAP, &fec->tbd_base[1].status);
+	fec->tbd_index = 0;
+}
+
+/**
+ * Mark the given read buffer descriptor as free
+ * @param[in] last 1 if this is the last buffer descriptor in the chain, else 0
+ * @param[in] pRbd buffer descriptor to mark free again
+ */
+static void fec_rbd_clean(int last, struct fec_bd *pRbd)
+{
+	/*
+	 * Reset buffer descriptor as empty
+	 */
+	if (last)
+		writew(FEC_RBD_WRAP | FEC_RBD_EMPTY, &pRbd->status);
+	else
+		writew(FEC_RBD_EMPTY, &pRbd->status);
+	/*
+	 * no data in it
+	 */
+	writew(0, &pRbd->data_length);
+}
+
+static int fec_get_hwaddr(struct eth_device *dev, unsigned char *mac)
+{
+	struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE;
+	int i;
+
+	for (i = 0; i < 6; i++)
+		mac[6-1-i] = readl(&iim->iim_bank_area0[IIM0_MAC + i]);
+
+	return is_valid_ether_addr(mac);
+}
+
+static int fec_set_hwaddr(struct eth_device *dev, unsigned char *mac)
+{
+	struct fec_priv *fec = (struct fec_priv *)dev->priv;
+
+	writel(0, &fec->eth->iaddr1);
+	writel(0, &fec->eth->iaddr2);
+	writel(0, &fec->eth->gaddr1);
+	writel(0, &fec->eth->gaddr2);
+
+	/*
+	 * Set physical address
+	 */
+	writel((mac[0] << 24) + (mac[1] << 16) + (mac[2] << 8) + mac[3],
+			&fec->eth->paddr1);
+	writel((mac[4] << 24) + (mac[5] << 16) + 0x8808, &fec->eth->paddr2);
+
+	return 0;
+}
+
+/**
+ * Start the FEC engine
+ * @param[in] dev Our device to handle
+ */
+static int fec_open(struct eth_device *edev)
+{
+	struct fec_priv *fec = (struct fec_priv *)edev->priv;
+
+	debug("fec_open: fec_open(dev)\n");
+	/* full-duplex, heartbeat disabled */
+	writel(1 << 2, &fec->eth->x_cntrl);
+	fec->rbd_index = 0;
+
+	/*
+	 * Enable FEC-Lite controller
+	 */
+	writel(FEC_ECNTRL_ETHER_EN, &fec->eth->ecntrl);
+
+	miiphy_wait_aneg(edev);
+	miiphy_speed(edev->name, 0);
+	miiphy_duplex(edev->name, 0);
+
+	/*
+	 * Enable SmartDMA receive task
+	 */
+	fec_rx_task_enable(fec);
+
+	udelay(100000);
+	return 0;
+}
+
+static int fec_init(struct eth_device *dev, bd_t* bd)
+{
+	uint32_t base;
+	struct fec_priv *fec = (struct fec_priv *)dev->priv;
+
+	/*
+	 * reserve memory for both buffer descriptor chains at once
+	 * Datasheet forces the startaddress of each chain is 16 byte
+	 * aligned
+	 */
+	fec->base_ptr = malloc((2 + FEC_RBD_NUM) *
+			sizeof(struct fec_bd) + DB_ALIGNMENT);
+	base = (uint32_t)fec->base_ptr;
+	if (!base) {
+		puts("fec_imx27: not enough malloc memory!\n");
+		return -ENOMEM;
+	}
+	memset((void *)base, 0, (2 + FEC_RBD_NUM) *
+			sizeof(struct fec_bd) + DB_ALIGNMENT);
+	base += (DB_ALIGNMENT-1);
+	base &= ~(DB_ALIGNMENT-1);
+
+	fec->rbd_base = (struct fec_bd *)base;
+
+	base += FEC_RBD_NUM * sizeof(struct fec_bd);
+
+	fec->tbd_base = (struct fec_bd *)base;
+
+	/*
+	 * Set interrupt mask register
+	 */
+	writel(0x00000000, &fec->eth->imask);
+
+	/*
+	 * Clear FEC-Lite interrupt event register(IEVENT)
+	 */
+	writel(0xffffffff, &fec->eth->ievent);
+
+
+	/*
+	 * Set FEC-Lite receive control register(R_CNTRL):
+	 */
+	if (fec->xcv_type == SEVENWIRE) {
+		/*
+		 * Frame length=1518; 7-wire mode
+		 */
+		writel(0x05ee0020, &fec->eth->r_cntrl);	/* FIXME 0x05ee0000 */
+	} else {
+		/*
+		 * Frame length=1518; MII mode;
+		 */
+		writel(0x05ee0024, &fec->eth->r_cntrl);	/* FIXME 0x05ee0004 */
+		/*
+		 * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
+		 * and do not drop the Preamble.
+		 */
+		writel((((imx_get_ahbclk() / 1000000) + 2) / 5) << 1,
+				&fec->eth->mii_speed);
+		debug("fec_init: mii_speed %#lx\n",
+				(((imx_get_ahbclk() / 1000000) + 2) / 5) << 1);
+	}
+	/*
+	 * Set Opcode/Pause Duration Register
+	 */
+	writel(0x00010020, &fec->eth->op_pause);	/* FIXME 0xffff0020; */
+	writel(0x2, &fec->eth->x_wmrk);
+	/*
+	 * Set multicast address filter
+	 */
+	writel(0x00000000, &fec->eth->gaddr1);
+	writel(0x00000000, &fec->eth->gaddr2);
+
+
+	/* clear MIB RAM */
+	long *mib_ptr = (long *)(IMX_FEC_BASE + 0x200);
+	while (mib_ptr <= (long *)(IMX_FEC_BASE + 0x2FC))
+		*mib_ptr++ = 0;
+
+	/* FIFO receive start register */
+	writel(0x520, &fec->eth->r_fstart);
+
+	/* size and address of each buffer */
+	writel(FEC_MAX_PKT_SIZE, &fec->eth->emrbr);
+	writel((uint32_t)fec->tbd_base, &fec->eth->etdsr);
+	writel((uint32_t)fec->rbd_base, &fec->eth->erdsr);
+
+	/*
+	 * Initialize RxBD/TxBD rings
+	 */
+	if (fec_rbd_init(fec, FEC_RBD_NUM, FEC_MAX_PKT_SIZE) < 0) {
+		free(fec->base_ptr);
+		return -ENOMEM;
+	}
+	fec_tbd_init(fec);
+
+
+	if (fec->xcv_type != SEVENWIRE)
+		miiphy_restart_aneg(dev);
+
+	fec_open(dev);
+	return 0;
+}
+
+/**
+ * Halt the FEC engine
+ * @param[in] dev Our device to handle
+ */
+static void fec_halt(struct eth_device *dev)
+{
+	struct fec_priv *fec = &gfec;
+	int counter = 0xffff;
+
+	/*
+	 * issue graceful stop command to the FEC transmitter if necessary
+	 */
+	writel(FEC_ECNTRL_RESET | readl(&fec->eth->x_cntrl),
+			&fec->eth->x_cntrl);
+
+	debug("eth_halt: wait for stop regs\n");
+	/*
+	 * wait for graceful stop to register
+	 */
+	while ((counter--) && (!(readl(&fec->eth->ievent) & FEC_IEVENT_GRA)))
+		;	/* FIXME ensure time */
+
+	/*
+	 * Disable SmartDMA tasks
+	 */
+	fec_tx_task_disable(fec);
+	fec_rx_task_disable(fec);
+
+	/*
+	 * Disable the Ethernet Controller
+	 * Note: this will also reset the BD index counter!
+	 */
+	writel(0, &fec->eth->ecntrl);
+	fec->rbd_index = 0;
+	fec->tbd_index = 0;
+	free(fec->rdb_ptr);
+	free(fec->base_ptr);
+	debug("eth_halt: done\n");
+}
+
+/**
+ * Transmit one frame
+ * @param[in] dev Our ethernet device to handle
+ * @param[in] packet Pointer to the data to be transmitted
+ * @param[in] length Data count in bytes
+ * @return 0 on success
+ */
+static int fec_send(struct eth_device *dev, volatile void* packet, int length)
+{
+	unsigned int status;
+
+	/*
+	 * This routine transmits one frame.  This routine only accepts
+	 * 6-byte Ethernet addresses.
+	 */
+	struct fec_priv *fec = (struct fec_priv *)dev->priv;
+
+	/*
+	 * Check for valid length of data.
+	 */
+	if ((length > 1500) || (length <= 0)) {
+		printf("Payload (%d) to large!\n", length);
+		return -1;
+	}
+
+	/*
+	 * Setup the transmit buffer
+	 * Note: We are always using the first buffer for transmission,
+	 * the second will be empty and only used to stop the DMA engine
+	 */
+	writew(length, &fec->tbd_base[fec->tbd_index].data_length);
+	writel((uint32_t)packet, &fec->tbd_base[fec->tbd_index].data_pointer);
+	/*
+	 * update BD's status now
+	 * This block:
+	 * - is always the last in a chain (means no chain)
+	 * - should transmitt the CRC
+	 * - might be the last BD in the list, so the address counter should
+	 *   wrap (-> keep the WRAP flag)
+	 */
+	status = readw(&fec->tbd_base[fec->tbd_index].status) & FEC_TBD_WRAP;
+	status |= FEC_TBD_LAST | FEC_TBD_TC | FEC_TBD_READY;
+	writew(status, &fec->tbd_base[fec->tbd_index].status);
+
+	/*
+	 * Enable SmartDMA transmit task
+	 */
+	fec_tx_task_enable(fec);
+
+	/*
+	 * wait until frame is sent .
+	 */
+	while (readw(&fec->tbd_base[fec->tbd_index].status) & FEC_TBD_READY) {
+		/* FIXME: Timeout */
+	}
+	debug("fec_send: status 0x%x index %d\n",
+			readw(&fec->tbd_base[fec->tbd_index].status),
+			fec->tbd_index);
+	/* for next transmission use the other buffer */
+	if (fec->tbd_index)
+		fec->tbd_index = 0;
+	else
+		fec->tbd_index = 1;
+
+	return 0;
+}
+
+/**
+ * Pull one frame from the card
+ * @param[in] dev Our ethernet device to handle
+ * @return Length of packet read
+ */
+static int fec_recv(struct eth_device *dev)
+{
+	struct fec_priv *fec = (struct fec_priv *)dev->priv;
+	struct fec_bd *rbd = &fec->rbd_base[fec->rbd_index];
+	unsigned long ievent;
+	int frame_length, len = 0;
+	struct nbuf *frame;
+	uint16_t bd_status;
+	uchar buff[FEC_MAX_PKT_SIZE];
+
+	/*
+	 * Check if any critical events have happened
+	 */
+	ievent = readl(&fec->eth->ievent);
+	writel(ievent, &fec->eth->ievent);
+	debug("fec_recv: ievent 0x%x\n", ievent);
+	if (ievent & FEC_IEVENT_BABR) {
+		fec_halt(dev);
+		fec_init(dev, fec->bd);
+		printf("some error: 0x%08lx\n", ievent);
+		return 0;
+	}
+	if (ievent & FEC_IEVENT_HBERR) {
+		/* Heartbeat error */
+		writel(0x00000001 | readl(&fec->eth->x_cntrl),
+				&fec->eth->x_cntrl);
+	}
+	if (ievent & FEC_IEVENT_GRA) {
+		/* Graceful stop complete */
+		if (readl(&fec->eth->x_cntrl) & 0x00000001) {
+			fec_halt(dev);
+			writel(~0x00000001 & readl(&fec->eth->x_cntrl),
+					&fec->eth->x_cntrl);
+			fec_init(dev, fec->bd);
+		}
+	}
+
+	/*
+	 * ensure reading the right buffer status
+	 */
+	bd_status = readw(&rbd->status);
+	debug("fec_recv: status 0x%x\n", bd_status);
+
+	if (!(bd_status & FEC_RBD_EMPTY)) {
+		if ((bd_status & FEC_RBD_LAST) && !(bd_status & FEC_RBD_ERR) &&
+			((readw(&rbd->data_length) - 4) > 14)) {
+			/*
+			 * Get buffer address and size
+			 */
+			frame = (struct nbuf *)readl(&rbd->data_pointer);
+			frame_length = readw(&rbd->data_length) - 4;
+			/*
+			 *  Fill the buffer and pass it to upper layers
+			 */
+			memcpy(buff, frame->data, frame_length);
+			NetReceive(buff, frame_length);
+			len = frame_length;
+		} else {
+			if (bd_status & FEC_RBD_ERR)
+				printf("error frame: 0x%08lx 0x%08x\n",
+						(ulong)rbd->data_pointer,
+						bd_status);
+		}
+		/*
+		 * free the current buffer, restart the engine
+		 * and move forward to the next buffer
+		 */
+		fec_rbd_clean(fec->rbd_index == (FEC_RBD_NUM - 1) ? 1 : 0, rbd);
+		fec_rx_task_enable(fec);
+		fec->rbd_index = (fec->rbd_index + 1) % FEC_RBD_NUM;
+	}
+	debug("fec_recv: stop\n");
+
+	return len;
+}
+
+static int fec_probe(bd_t *bd)
+{
+	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+	struct eth_device *edev;
+	struct fec_priv *fec = &gfec;
+	unsigned char ethaddr_str[20];
+	unsigned char ethaddr[6];
+	char *tmp = getenv("ethaddr");
+	char *end;
+
+	/* enable FEC clock */
+	writel(readl(&pll->pccr1) | PCCR1_HCLK_FEC, &pll->pccr1);
+	writel(readl(&pll->pccr0) | PCCR0_FEC_EN, &pll->pccr0);
+
+	/* create and fill edev struct */
+	edev = (struct eth_device *)malloc(sizeof(struct eth_device));
+	if (!edev) {
+		puts("fec_imx27: not enough malloc memory!\n");
+		return -ENOMEM;
+	}
+	edev->priv = fec;
+	edev->init = fec_init;
+	edev->send = fec_send;
+	edev->recv = fec_recv;
+	edev->halt = fec_halt;
+
+	fec->eth = (struct ethernet_regs *)IMX_FEC_BASE;
+	fec->bd = bd;
+
+	/* Reset chip. */
+	writel(FEC_ECNTRL_RESET, &fec->eth->ecntrl);
+	while (readl(&fec->eth->ecntrl) & 1)
+		udelay(10);
+
+	fec->xcv_type = MII100;
+
+	sprintf(edev->name, "FEC_i.MX27");
+
+	miiphy_register(edev->name, fec_miiphy_read, fec_miiphy_write);
+
+	eth_register(edev);
+
+	if ((NULL != tmp) && (12 <= strlen(tmp))) {
+		int i;
+		/* convert MAC from string to int */
+		for (i = 0; i < 6; i++) {
+			ethaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0;
+			if (tmp)
+				tmp = (*end) ? end + 1 : end;
+		}
+	} else if (fec_get_hwaddr(edev, ethaddr) == 0) {
+		printf("got MAC address from EEPROM: %pM\n", ethaddr);
+		setenv("ethaddr", (char *)ethaddr_str);
+	}
+	memcpy(edev->enetaddr, ethaddr, 6);
+	fec_set_hwaddr(edev, ethaddr);
+
+	return 0;
+}
+
+int fecimx27_initialize(bd_t *bd)
+{
+	int lout = 1;
+
+	debug("eth_init: fec_probe(bd)\n");
+	lout = fec_probe(bd);
+
+	return lout;
+}
+
diff --git a/drivers/net/fec_imx27.h b/drivers/net/fec_imx27.h
new file mode 100644
index 0000000..57e5427
--- /dev/null
+++ b/drivers/net/fec_imx27.h
@@ -0,0 +1,304 @@
+/*
+ * (C) Copyright 2009 Ilya Yanok, Emcraft Systems Ltd <yanok@emcraft.com>
+ * (C) Copyright 2008 Armadeus Systems, nc
+ * (C) Copyright 2008 Eric Jarrige <eric.jarrige@armadeus.org>
+ * (C) Copyright 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
+ * (C) Copyright 2007 Pengutronix, Juergen Beisert <j.beisert@pengutronix.de>
+ *
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ *
+ * This file is based on mpc4200fec.h
+ * (C) Copyright Motorola, Inc., 2000
+ *
+ * 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 __IMX27_FEC_H
+#define __IMX27_FEC_H
+
+/**
+ * Layout description of the FEC
+ */
+struct ethernet_regs {
+
+/* [10:2]addr = 00 */
+
+/*  Control and status Registers (offset 000-1FF) */
+
+	uint32_t res0[1];		/* MBAR_ETH + 0x000 */
+	uint32_t ievent;		/* MBAR_ETH + 0x004 */
+	uint32_t imask;			/* MBAR_ETH + 0x008 */
+
+	uint32_t res1[1];		/* MBAR_ETH + 0x00C */
+	uint32_t r_des_active;		/* MBAR_ETH + 0x010 */
+	uint32_t x_des_active;		/* MBAR_ETH + 0x014 */
+	uint32_t res2[3];		/* MBAR_ETH + 0x018-20 */
+	uint32_t ecntrl;		/* MBAR_ETH + 0x024 */
+
+	uint32_t res3[6];		/* MBAR_ETH + 0x028-03C */
+	uint32_t mii_data;		/* MBAR_ETH + 0x040 */
+	uint32_t mii_speed;		/* MBAR_ETH + 0x044 */
+	uint32_t res4[7];		/* MBAR_ETH + 0x048-60 */
+	uint32_t mib_control;		/* MBAR_ETH + 0x064 */
+
+	uint32_t res5[7];		/* MBAR_ETH + 0x068-80 */
+	uint32_t r_cntrl;		/* MBAR_ETH + 0x084 */
+	uint32_t res6[15];		/* MBAR_ETH + 0x088-C0 */
+	uint32_t x_cntrl;		/* MBAR_ETH + 0x0C4 */
+	uint32_t res7[7];		/* MBAR_ETH + 0x0C8-E0 */
+	uint32_t paddr1;		/* MBAR_ETH + 0x0E4 */
+	uint32_t paddr2;		/* MBAR_ETH + 0x0E8 */
+	uint32_t op_pause;		/* MBAR_ETH + 0x0EC */
+
+	uint32_t res8[10];		/* MBAR_ETH + 0x0F0-114 */
+	uint32_t iaddr1;		/* MBAR_ETH + 0x118 */
+	uint32_t iaddr2;		/* MBAR_ETH + 0x11C */
+	uint32_t gaddr1;		/* MBAR_ETH + 0x120 */
+	uint32_t gaddr2;		/* MBAR_ETH + 0x124 */
+	uint32_t res9[7];		/* MBAR_ETH + 0x128-140 */
+
+	uint32_t x_wmrk;		/* MBAR_ETH + 0x144 */
+	uint32_t res10[1];		/* MBAR_ETH + 0x148 */
+	uint32_t r_bound;		/* MBAR_ETH + 0x14C */
+	uint32_t r_fstart;		/* MBAR_ETH + 0x150 */
+	uint32_t res11[11];		/* MBAR_ETH + 0x154-17C */
+	uint32_t erdsr;			/* MBAR_ETH + 0x180 */
+	uint32_t etdsr;			/* MBAR_ETH + 0x184 */
+	uint32_t emrbr;			/* MBAR_ETH + 0x188 */
+	uint32_t res12[29];		/* MBAR_ETH + 0x18C-1FC */
+
+/*  MIB COUNTERS (Offset 200-2FF) */
+
+	uint32_t rmon_t_drop;		/* MBAR_ETH + 0x200 */
+	uint32_t rmon_t_packets;	/* MBAR_ETH + 0x204 */
+	uint32_t rmon_t_bc_pkt;		/* MBAR_ETH + 0x208 */
+	uint32_t rmon_t_mc_pkt;		/* MBAR_ETH + 0x20C */
+	uint32_t rmon_t_crc_align;	/* MBAR_ETH + 0x210 */
+	uint32_t rmon_t_undersize;	/* MBAR_ETH + 0x214 */
+	uint32_t rmon_t_oversize;	/* MBAR_ETH + 0x218 */
+	uint32_t rmon_t_frag;		/* MBAR_ETH + 0x21C */
+	uint32_t rmon_t_jab;		/* MBAR_ETH + 0x220 */
+	uint32_t rmon_t_col;		/* MBAR_ETH + 0x224 */
+	uint32_t rmon_t_p64;		/* MBAR_ETH + 0x228 */
+	uint32_t rmon_t_p65to127;	/* MBAR_ETH + 0x22C */
+	uint32_t rmon_t_p128to255;	/* MBAR_ETH + 0x230 */
+	uint32_t rmon_t_p256to511;	/* MBAR_ETH + 0x234 */
+	uint32_t rmon_t_p512to1023;	/* MBAR_ETH + 0x238 */
+	uint32_t rmon_t_p1024to2047;	/* MBAR_ETH + 0x23C */
+	uint32_t rmon_t_p_gte2048;	/* MBAR_ETH + 0x240 */
+	uint32_t rmon_t_octets;		/* MBAR_ETH + 0x244 */
+	uint32_t ieee_t_drop;		/* MBAR_ETH + 0x248 */
+	uint32_t ieee_t_frame_ok;	/* MBAR_ETH + 0x24C */
+	uint32_t ieee_t_1col;		/* MBAR_ETH + 0x250 */
+	uint32_t ieee_t_mcol;		/* MBAR_ETH + 0x254 */
+	uint32_t ieee_t_def;		/* MBAR_ETH + 0x258 */
+	uint32_t ieee_t_lcol;		/* MBAR_ETH + 0x25C */
+	uint32_t ieee_t_excol;		/* MBAR_ETH + 0x260 */
+	uint32_t ieee_t_macerr;		/* MBAR_ETH + 0x264 */
+	uint32_t ieee_t_cserr;		/* MBAR_ETH + 0x268 */
+	uint32_t ieee_t_sqe;		/* MBAR_ETH + 0x26C */
+	uint32_t t_fdxfc;		/* MBAR_ETH + 0x270 */
+	uint32_t ieee_t_octets_ok;	/* MBAR_ETH + 0x274 */
+
+	uint32_t res13[2];		/* MBAR_ETH + 0x278-27C */
+	uint32_t rmon_r_drop;		/* MBAR_ETH + 0x280 */
+	uint32_t rmon_r_packets;	/* MBAR_ETH + 0x284 */
+	uint32_t rmon_r_bc_pkt;		/* MBAR_ETH + 0x288 */
+	uint32_t rmon_r_mc_pkt;		/* MBAR_ETH + 0x28C */
+	uint32_t rmon_r_crc_align;	/* MBAR_ETH + 0x290 */
+	uint32_t rmon_r_undersize;	/* MBAR_ETH + 0x294 */
+	uint32_t rmon_r_oversize;	/* MBAR_ETH + 0x298 */
+	uint32_t rmon_r_frag;		/* MBAR_ETH + 0x29C */
+	uint32_t rmon_r_jab;		/* MBAR_ETH + 0x2A0 */
+
+	uint32_t rmon_r_resvd_0;	/* MBAR_ETH + 0x2A4 */
+
+	uint32_t rmon_r_p64;		/* MBAR_ETH + 0x2A8 */
+	uint32_t rmon_r_p65to127;	/* MBAR_ETH + 0x2AC */
+	uint32_t rmon_r_p128to255;	/* MBAR_ETH + 0x2B0 */
+	uint32_t rmon_r_p256to511;	/* MBAR_ETH + 0x2B4 */
+	uint32_t rmon_r_p512to1023;	/* MBAR_ETH + 0x2B8 */
+	uint32_t rmon_r_p1024to2047;	/* MBAR_ETH + 0x2BC */
+	uint32_t rmon_r_p_gte2048;	/* MBAR_ETH + 0x2C0 */
+	uint32_t rmon_r_octets;		/* MBAR_ETH + 0x2C4 */
+	uint32_t ieee_r_drop;		/* MBAR_ETH + 0x2C8 */
+	uint32_t ieee_r_frame_ok;	/* MBAR_ETH + 0x2CC */
+	uint32_t ieee_r_crc;		/* MBAR_ETH + 0x2D0 */
+	uint32_t ieee_r_align;		/* MBAR_ETH + 0x2D4 */
+	uint32_t r_macerr;		/* MBAR_ETH + 0x2D8 */
+	uint32_t r_fdxfc;		/* MBAR_ETH + 0x2DC */
+	uint32_t ieee_r_octets_ok;	/* MBAR_ETH + 0x2E0 */
+
+	uint32_t res14[6];		/* MBAR_ETH + 0x2E4-2FC */
+
+	uint32_t res15[64];		/* MBAR_ETH + 0x300-3FF */
+};
+
+#define FEC_IEVENT_HBERR		0x80000000
+#define FEC_IEVENT_BABR			0x40000000
+#define FEC_IEVENT_BABT			0x20000000
+#define FEC_IEVENT_GRA			0x10000000
+#define FEC_IEVENT_TXF			0x08000000
+#define FEC_IEVENT_TXB			0x04000000
+#define FEC_IEVENT_RXF			0x02000000
+#define FEC_IEVENT_RXB			0x01000000
+#define FEC_IEVENT_MII			0x00800000
+#define FEC_IEVENT_EBERR		0x00400000
+#define FEC_IEVENT_LC			0x00200000
+#define FEC_IEVENT_RL			0x00100000
+#define FEC_IEVENT_UN			0x00080000
+
+#define FEC_IMASK_HBERR			0x80000000
+#define FEC_IMASK_BABR			0x40000000
+#define FEC_IMASKT_BABT			0x20000000
+#define FEC_IMASK_GRA			0x10000000
+#define FEC_IMASKT_TXF			0x08000000
+#define FEC_IMASK_TXB			0x04000000
+#define FEC_IMASKT_RXF			0x02000000
+#define FEC_IMASK_RXB			0x01000000
+#define FEC_IMASK_MII			0x00800000
+#define FEC_IMASK_EBERR			0x00400000
+#define FEC_IMASK_LC			0x00200000
+#define FEC_IMASKT_RL			0x00100000
+#define FEC_IMASK_UN			0x00080000
+
+
+#define FEC_RCNTRL_MAX_FL_SHIFT		16
+#define FEC_RCNTRL_LOOP			0x00000001
+#define FEC_RCNTRL_DRT			0x00000002
+#define FEC_RCNTRL_MII_MODE		0x00000004
+#define FEC_RCNTRL_PROM			0x00000008
+#define FEC_RCNTRL_BC_REJ		0x00000010
+#define FEC_RCNTRL_FCE			0x00000020
+
+#define FEC_TCNTRL_GTS			0x00000001
+#define FEC_TCNTRL_HBC			0x00000002
+#define FEC_TCNTRL_FDEN			0x00000004
+#define FEC_TCNTRL_TFC_PAUSE		0x00000008
+#define FEC_TCNTRL_RFC_PAUSE		0x00000010
+
+#define FEC_ECNTRL_RESET		0x00000001	/* reset the FEC */
+#define FEC_ECNTRL_ETHER_EN		0x00000002	/* enable the FEC */
+
+/**
+ * @brief Descriptor buffer alignment
+ *
+ * i.MX27 requires a 16 byte alignment (but for the first element only)
+ */
+#define DB_ALIGNMENT		16
+
+/**
+ * @brief Data buffer alignment
+ *
+ * i.MX27 requires a four byte alignment for transmit and 16 bits
+ * alignment for receive so take 16
+ * Note: Valid for member data_pointer in struct buffer_descriptor
+ */
+#define DB_DATA_ALIGNMENT	16
+
+/**
+ * @brief Receive & Transmit Buffer Descriptor definitions
+ *
+ * Note: The first BD must be aligned (see DB_ALIGNMENT)
+ */
+struct fec_bd {
+	uint16_t data_length;		/* payload's length in bytes */
+	uint16_t status;		/* BD's staus (see datasheet) */
+	uint32_t data_pointer;		/* payload's buffer address */
+};
+
+/**
+ * Supported phy types on this platform
+ */
+enum xceiver_type {
+	SEVENWIRE,	/* 7-wire       */
+	MII10,		/* MII 10Mbps   */
+	MII100		/* MII 100Mbps  */
+};
+
+/**
+ * @brief i.MX27-FEC private structure
+ */
+struct fec_priv {
+	struct ethernet_regs *eth;	/* pointer to register'S base */
+	enum xceiver_type xcv_type;	/* transceiver type */
+	struct fec_bd *rbd_base;	/* RBD ring */
+	int rbd_index;			/* next receive BD to read */
+	struct fec_bd *tbd_base;	/* TBD ring */
+	int tbd_index;			/* next transmit BD to write */
+	bd_t *bd;
+	void *rdb_ptr;
+	void *base_ptr;
+};
+
+/**
+ * @brief Numbers of buffer descriptors for receiving
+ *
+ * The number defines the stocked memory buffers for the receiving task.
+ * Larger values makes no sense in this limited environment.
+ */
+#define FEC_RBD_NUM		64
+
+/**
+ * @brief Define the ethernet packet size limit in memory
+ *
+ * Note: Do not shrink this number. This will force the FEC to spread larger
+ * frames in more than one BD. This is nothing to worry about, but the current
+ * driver can't handle it.
+ */
+#define FEC_MAX_PKT_SIZE	1536
+
+/* Receive BD status bits */
+#define FEC_RBD_EMPTY	0x8000	/* Receive BD status: Buffer is empty */
+#define FEC_RBD_WRAP	0x2000	/* Receive BD status: Last BD in ring */
+/* Receive BD status: Buffer is last in frame (useless here!) */
+#define FEC_RBD_LAST	0x0800
+#define FEC_RBD_MISS	0x0100	/* Receive BD status: Miss bit for prom mode */
+/* Receive BD status: The received frame is broadcast frame */
+#define FEC_RBD_BC	0x0080
+/* Receive BD status: The received frame is multicast frame */
+#define FEC_RBD_MC	0x0040
+#define FEC_RBD_LG	0x0020	/* Receive BD status: Frame length violation */
+#define FEC_RBD_NO	0x0010	/* Receive BD status: Nonoctet align frame */
+#define FEC_RBD_CR	0x0004	/* Receive BD status: CRC error */
+#define FEC_RBD_OV	0x0002	/* Receive BD status: Receive FIFO overrun */
+#define FEC_RBD_TR	0x0001	/* Receive BD status: Frame is truncated */
+#define FEC_RBD_ERR	(FEC_RBD_LG | FEC_RBD_NO | FEC_RBD_CR | \
+			FEC_RBD_OV | FEC_RBD_TR)
+
+/* Transmit BD status bits */
+#define FEC_TBD_READY	0x8000	/* Tansmit BD status: Buffer is ready */
+#define FEC_TBD_WRAP	0x2000	/* Tansmit BD status: Mark as last BD in ring */
+#define FEC_TBD_LAST	0x0800	/* Tansmit BD status: Buffer is last in frame */
+#define FEC_TBD_TC	0x0400	/* Tansmit BD status: Transmit the CRC */
+#define FEC_TBD_ABC	0x0200	/* Tansmit BD status: Append bad CRC */
+
+/* MII-related definitios */
+#define FEC_MII_DATA_ST		0x40000000	/* Start of frame delimiter */
+#define FEC_MII_DATA_OP_RD	0x20000000	/* Perform a read operation */
+#define FEC_MII_DATA_OP_WR	0x10000000	/* Perform a write operation */
+#define FEC_MII_DATA_PA_MSK	0x0f800000	/* PHY Address field mask */
+#define FEC_MII_DATA_RA_MSK	0x007c0000	/* PHY Register field mask */
+#define FEC_MII_DATA_TA		0x00020000	/* Turnaround */
+#define FEC_MII_DATA_DATAMSK	0x0000ffff	/* PHY data field */
+
+#define FEC_MII_DATA_RA_SHIFT	18	/* MII Register address bits */
+#define FEC_MII_DATA_PA_SHIFT	23	/* MII PHY address bits */
+
+#endif	/* __IMX27_FEC_H */
diff --git a/include/netdev.h b/include/netdev.h
index 63cf730..2d999ad 100644
--- a/include/netdev.h
+++ b/include/netdev.h
@@ -49,6 +49,7 @@ int e1000_initialize(bd_t *bis);
 int eepro100_initialize(bd_t *bis);
 int eth_3com_initialize (bd_t * bis);
 int fec_initialize (bd_t *bis);
+int fecimx27_initialize (bd_t *bis);
 int greth_initialize(bd_t *bis);
 void gt6426x_eth_initialize(bd_t *bis);
 int inca_switch_initialize(bd_t *bis);
-- 
1.6.0.6

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

* [U-Boot] [PATCH 4/7] mxc_nand: add nand driver for MX2/MX3
  2009-06-08  0:12 [U-Boot] [PATCH 0/7][v3] Support for LogicPD i.MX27-LITEKIT development board Ilya Yanok
                   ` (2 preceding siblings ...)
  2009-06-08  0:12 ` [U-Boot] [PATCH 3/7] fec_imx27: driver for FEC ethernet controller on i.MX27 Ilya Yanok
@ 2009-06-08  0:12 ` Ilya Yanok
  2009-06-20 13:22   ` Jean-Christophe PLAGNIOL-VILLARD
  2009-06-22 23:43   ` Scott Wood
  2009-06-08  0:12 ` [U-Boot] [PATCH 5/7] mxc-mmc: sdhc host driver for MX2 and MX3 proccessor Ilya Yanok
                   ` (3 subsequent siblings)
  7 siblings, 2 replies; 70+ messages in thread
From: Ilya Yanok @ 2009-06-08  0:12 UTC (permalink / raw)
  To: u-boot

Driver for NFC NAND controller found on Freescale's MX2 and MX3
processors. Ported from Linux. Tested only with i.MX27 but should
works with other MX2 and MX3 processors too.

Signed-off-by: Ilya Yanok <yanok@emcraft.com>
---
 drivers/mtd/nand/Makefile   |    1 +
 drivers/mtd/nand/mxc_nand.c |  932 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 933 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/nand/mxc_nand.c

diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 471cd6b..24de947 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -40,6 +40,7 @@ COBJS-$(CONFIG_DRIVER_NAND_BFIN) += bfin_nand.o
 COBJS-$(CONFIG_NAND_DAVINCI) += davinci_nand.o
 COBJS-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_nand.o
 COBJS-$(CONFIG_NAND_FSL_UPM) += fsl_upm.o
+COBJS-$(CONFIG_NAND_MXC) += mxc_nand.o
 COBJS-$(CONFIG_NAND_NOMADIK) += nomadik.o
 COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.c
 COBJS-$(CONFIG_NAND_S3C64XX) += s3c64xx.o
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
new file mode 100644
index 0000000..dc833a0
--- /dev/null
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -0,0 +1,932 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Sascha Hauer, kernel at pengutronix.de
+ * Copyright 2009 Ilya Yanok, <yanok@emcraft.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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <common.h>
+#include <nand.h>
+#include <linux/err.h>
+#include <asm/io.h>
+#ifdef CONFIG_MX27
+#include <asm/arch/imx-regs.h>
+#endif
+
+#define DRIVER_NAME "mxc_nand"
+
+struct nfc_regs {
+/* NFC RAM BUFFER Main area 0 */
+	uint8_t main_area0[0x200];
+	uint8_t main_area1[0x200];
+	uint8_t main_area2[0x200];
+	uint8_t main_area3[0x200];
+/* SPARE BUFFER Spare area 0 */
+	uint8_t spare_area0[0x10];
+	uint8_t spare_area1[0x10];
+	uint8_t spare_area2[0x10];
+	uint8_t spare_area3[0x10];
+	uint8_t pad[0x5c0];
+/* NFC registers */
+	uint16_t nfc_buf_size;
+	uint16_t reserved;
+	uint16_t nfc_buf_addr;
+	uint16_t nfc_flash_addr;
+	uint16_t nfc_flash_cmd;
+	uint16_t nfc_config;
+	uint16_t nfc_ecc_status_result;
+	uint16_t nfc_rsltmain_area;
+	uint16_t nfc_rsltspare_area;
+	uint16_t nfc_wrprot;
+	uint16_t nfc_unlockstart_blkaddr;
+	uint16_t nfc_unlockend_blkaddr;
+	uint16_t nfc_nf_wrprst;
+	uint16_t nfc_config1;
+	uint16_t nfc_config2;
+};
+
+/*
+ * Set INT to 0, FCMD to 1, rest to 0 in NFC_CONFIG2 Register
+ * for Command operation
+ */
+#define NFC_CMD            0x1
+
+/*
+ * Set INT to 0, FADD to 1, rest to 0 in NFC_CONFIG2 Register
+ * for Address operation
+ */
+#define NFC_ADDR           0x2
+
+/*
+ * Set INT to 0, FDI to 1, rest to 0 in NFC_CONFIG2 Register
+ * for Input operation
+ */
+#define NFC_INPUT          0x4
+
+/*
+ * Set INT to 0, FDO to 001, rest to 0 in NFC_CONFIG2 Register
+ * for Data Output operation
+ */
+#define NFC_OUTPUT         0x8
+
+/*
+ * Set INT to 0, FD0 to 010, rest to 0 in NFC_CONFIG2 Register
+ * for Read ID operation
+ */
+#define NFC_ID             0x10
+
+/*
+ * Set INT to 0, FDO to 100, rest to 0 in NFC_CONFIG2 Register
+ * for Read Status operation
+ */
+#define NFC_STATUS         0x20
+
+/*
+ * Set INT to 1, rest to 0 in NFC_CONFIG2 Register for Read
+ * Status operation
+ */
+#define NFC_INT            0x8000
+
+#define NFC_SP_EN           (1 << 2)
+#define NFC_ECC_EN          (1 << 3)
+#define NFC_BIG             (1 << 5)
+#define NFC_RST             (1 << 6)
+#define NFC_CE              (1 << 7)
+#define NFC_ONE_CYCLE       (1 << 8)
+
+typedef enum {false, true} bool;
+
+struct mxc_nand_host {
+	struct mtd_info		mtd;
+	struct nand_chip	*nand;
+
+	struct nfc_regs __iomem	*regs;
+	int			spare_only;
+	int			status_request;
+	int			pagesize_2k;
+	int			clk_act;
+	uint16_t		col_addr;
+};
+
+static struct mxc_nand_host mxc_host;
+static struct mxc_nand_host *host = &mxc_host;
+
+/* Define delays in microsec for NAND device operations */
+#define TROP_US_DELAY   2000
+/* Macros to get byte and bit positions of ECC */
+#define COLPOS(x)  ((x) >> 3)
+#define BITPOS(x) ((x) & 0xf)
+
+/* Define single bit Error positions in Main & Spare area */
+#define MAIN_SINGLEBIT_ERROR 0x4
+#define SPARE_SINGLEBIT_ERROR 0x1
+
+/* OOB placement block for use with hardware ecc generation */
+static struct nand_ecclayout nand_hw_eccoob_8 = {
+	.eccbytes = 5,
+	.eccpos = {6, 7, 8, 9, 10},
+	.oobfree = {{0, 5}, {11, 5}, }
+};
+
+static struct nand_ecclayout nand_hw_eccoob_16 = {
+	.eccbytes = 5,
+	.eccpos = {6, 7, 8, 9, 10},
+	.oobfree = {{0, 6}, {12, 4}, }
+};
+
+static void *mxc_nand_memcpy32(void *dest, void *source, size_t size)
+{
+	uint32_t *s = source, *d = dest;
+
+	size >>= 2;
+	while (size--)
+		*d++ = *s++;
+	return dest;
+}
+
+/*
+ * This function polls the NANDFC to wait for the basic operation to
+ * complete by checking the INT bit of config2 register.
+ */
+static void wait_op_done(struct mxc_nand_host *host, int max_retries,
+				uint16_t param)
+{
+	uint32_t tmp;
+
+	while (max_retries-- > 0) {
+		if (readw(&host->regs->nfc_config2) & NFC_INT) {
+			tmp = readw(&host->regs->nfc_config2);
+			tmp  &= ~NFC_INT;
+			writew(tmp, &host->regs->nfc_config2);
+			break;
+		}
+		udelay(1);
+	}
+	if (max_retries <= 0) {
+		MTDDEBUG(MTD_DEBUG_LEVEL0, "%s(%d): INT not set\n",
+				__func__, param);
+	}
+}
+
+/*
+ * This function issues the specified command to the NAND device and
+ * waits for completion.
+ */
+static void send_cmd(struct mxc_nand_host *host, uint16_t cmd)
+{
+	MTDDEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x)\n", cmd);
+
+	writew(cmd, &host->regs->nfc_flash_cmd);
+	writew(NFC_CMD, &host->regs->nfc_config2);
+
+	/* Wait for operation to complete */
+	wait_op_done(host, TROP_US_DELAY, cmd);
+}
+
+/*
+ * This function sends an address (or partial address) to the
+ * NAND device. The address is used to select the source/destination for
+ * a NAND command.
+ */
+static void send_addr(struct mxc_nand_host *host, uint16_t addr)
+{
+	MTDDEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x)\n", addr);
+
+	writew(addr, &host->regs->nfc_flash_addr);
+	writew(NFC_ADDR, &host->regs->nfc_config2);
+
+	/* Wait for operation to complete */
+	wait_op_done(host, TROP_US_DELAY, addr);
+}
+
+/*
+ * This function requests the NANDFC to initate the transfer
+ * of data currently in the NANDFC RAM buffer to the NAND device.
+ */
+static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id,
+			int spare_only)
+{
+	MTDDEBUG(MTD_DEBUG_LEVEL3, "send_prog_page (%d)\n", spare_only);
+
+	/* NANDFC buffer 0 is used for page read/write */
+	writew(buf_id, &host->regs->nfc_buf_addr);
+
+	/* Configure spare or page+spare access */
+	if (!host->pagesize_2k) {
+		uint16_t config1 = readw(&host->regs->nfc_config1);
+		if (spare_only)
+			config1 |= NFC_SP_EN;
+		else
+			config1 &= ~(NFC_SP_EN);
+		writew(config1, &host->regs->nfc_config1);
+	}
+
+	writew(NFC_INPUT, &host->regs->nfc_config2);
+
+	/* Wait for operation to complete */
+	wait_op_done(host, TROP_US_DELAY, spare_only);
+}
+
+/*
+ * Requests NANDFC to initated the transfer of data from the
+ * NAND device into in the NANDFC ram buffer.
+ */
+static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id,
+		int spare_only)
+{
+	MTDDEBUG(MTD_DEBUG_LEVEL3, "send_read_page (%d)\n", spare_only);
+
+	/* NANDFC buffer 0 is used for page read/write */
+	writew(buf_id, &host->regs->nfc_buf_addr);
+
+	/* Configure spare or page+spare access */
+	if (!host->pagesize_2k) {
+		uint32_t config1 = readw(&host->regs->nfc_config1);
+		if (spare_only)
+			config1 |= NFC_SP_EN;
+		else
+			config1 &= ~NFC_SP_EN;
+		writew(config1, &host->regs->nfc_config1);
+	}
+
+	writew(NFC_OUTPUT, &host->regs->nfc_config2);
+
+	/* Wait for operation to complete */
+	wait_op_done(host, TROP_US_DELAY, spare_only);
+}
+
+/* Request the NANDFC to perform a read of the NAND device ID. */
+static void send_read_id(struct mxc_nand_host *host)
+{
+	struct nand_chip *this = host->nand;
+	uint16_t tmp;
+
+	/* NANDFC buffer 0 is used for device ID output */
+	writew(0x0, &host->regs->nfc_buf_addr);
+
+	/* Read ID into main buffer */
+	tmp = readw(&host->regs->nfc_config1);
+	tmp &= ~NFC_SP_EN;
+	writew(tmp, &host->regs->nfc_config1);
+
+	writew(NFC_ID, &host->regs->nfc_config2);
+
+	/* Wait for operation to complete */
+	wait_op_done(host, TROP_US_DELAY, 0);
+
+	if (this->options & NAND_BUSWIDTH_16) {
+		void __iomem *main_buf = host->regs->main_area0;
+		/* compress the ID info */
+		writeb(readb(main_buf + 2), main_buf + 1);
+		writeb(readb(main_buf + 4), main_buf + 2);
+		writeb(readb(main_buf + 6), main_buf + 3);
+		writeb(readb(main_buf + 8), main_buf + 4);
+		writeb(readb(main_buf + 10), main_buf + 5);
+	}
+}
+
+/*
+ * This function requests the NANDFC to perform a read of the
+ * NAND device status and returns the current status.
+ */
+static uint16_t get_dev_status(struct mxc_nand_host *host)
+{
+	void __iomem *main_buf = host->regs->main_area1;
+	uint32_t store;
+	uint16_t ret, tmp;
+	/* Issue status request to NAND device */
+
+	/* store the main area1 first word, later do recovery */
+	store = readl(main_buf);
+	/*
+	 * NANDFC buffer 1 is used for device status to prevent
+	 * corruption of read/write buffer on status requests.
+	 */
+	writew(1, &host->regs->nfc_buf_addr);
+
+	/* Read status into main buffer */
+	tmp = readw(&host->regs->nfc_config1);
+	tmp &= ~NFC_SP_EN;
+	writew(tmp, &host->regs->nfc_config1);
+
+	writew(NFC_STATUS, &host->regs->nfc_config2);
+
+	/* Wait for operation to complete */
+	wait_op_done(host, TROP_US_DELAY, 0);
+
+	/*
+	 *  Status is placed in first word of main buffer
+	 * get status, then recovery area 1 data
+	 */
+	ret = readw(main_buf);
+	writel(store, main_buf);
+
+	return ret;
+}
+
+/* This functions is used by upper layer to checks if device is ready */
+static int mxc_nand_dev_ready(struct mtd_info *mtd)
+{
+	/*
+	 * NFC handles R/B internally. Therefore, this function
+	 * always returns status as ready.
+	 */
+	return 1;
+}
+
+#ifdef CONFIG_MXC_NAND_HWECC
+static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
+{
+	/*
+	 * If HW ECC is enabled, we turn it on during init. There is
+	 * no need to enable again here.
+	 */
+}
+
+static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
+				 u_char *read_ecc, u_char *calc_ecc)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+
+	/*
+	 * 1-Bit errors are automatically corrected in HW.  No need for
+	 * additional correction.  2-Bit errors cannot be corrected by
+	 * HW ECC, so we need to return failure
+	 */
+	uint16_t ecc_status = readw(&host->regs->nfc_ecc_status_result);
+
+	if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
+		MTDDEBUG(MTD_DEBUG_LEVEL0,
+		      "MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
+				  u_char *ecc_code)
+{
+	return 0;
+}
+#endif
+
+static u_char mxc_nand_read_byte(struct mtd_info *mtd)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+	uint8_t ret = 0;
+	uint16_t col, rd_word;
+	uint16_t __iomem *main_buf =
+		(uint16_t __iomem *)host->regs->main_area0;
+	uint16_t __iomem *spare_buf =
+		(uint16_t __iomem *)host->regs->spare_area0;
+
+	/* Check for status request */
+	if (host->status_request)
+		return get_dev_status(host) & 0xFF;
+
+	/* Get column for 16-bit access */
+	col = host->col_addr >> 1;
+
+	/* If we are accessing the spare region */
+	if (host->spare_only)
+		rd_word = readw(&spare_buf[col]);
+	else
+		rd_word = readw(&main_buf[col]);
+
+	/* Pick upper/lower byte of word from RAM buffer */
+	if (host->col_addr & 0x1)
+		ret = (rd_word >> 8) & 0xFF;
+	else
+		ret = rd_word & 0xFF;
+
+	/* Update saved column address */
+	host->col_addr++;
+
+	return ret;
+}
+
+static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+	uint16_t col, rd_word, ret;
+	uint16_t __iomem *p;
+
+	MTDDEBUG(MTD_DEBUG_LEVEL3,
+	      "mxc_nand_read_word(col = %d)\n", host->col_addr);
+
+	col = host->col_addr;
+	/* Adjust saved column address */
+	if (col < mtd->writesize && host->spare_only)
+		col += mtd->writesize;
+
+	if (col < mtd->writesize) {
+		p = (uint16_t __iomem *)(host->regs->main_area0 + (col >> 1));
+	} else {
+		p = (uint16_t __iomem *)(host->regs->spare_area0 +
+				((col - mtd->writesize) >> 1));
+	}
+
+	if (col & 1) {
+		rd_word = readw(p);
+		ret = (rd_word >> 8) & 0xff;
+		rd_word = readw(&p[1]);
+		ret |= (rd_word << 8) & 0xff00;
+
+	} else {
+		ret = readw(p);
+	}
+
+	/* Update saved column address */
+	host->col_addr = col + 2;
+
+	return ret;
+}
+
+/*
+ * Write data of length len to buffer buf. The data to be
+ * written on NAND Flash is first copied to RAMbuffer. After the Data Input
+ * Operation by the NFC, the data is written to NAND Flash
+ */
+static void mxc_nand_write_buf(struct mtd_info *mtd,
+				const u_char *buf, int len)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+	int n, col, i = 0;
+
+	MTDDEBUG(MTD_DEBUG_LEVEL3,
+	      "mxc_nand_write_buf(col = %d, len = %d)\n", host->col_addr,
+	      len);
+
+	col = host->col_addr;
+
+	/* Adjust saved column address */
+	if (col < mtd->writesize && host->spare_only)
+		col += mtd->writesize;
+
+	n = mtd->writesize + mtd->oobsize - col;
+	n = min(len, n);
+
+	MTDDEBUG(MTD_DEBUG_LEVEL3,
+	      "%s:%d: col = %d, n = %d\n", __func__, __LINE__, col, n);
+
+	while (n) {
+		void __iomem *p;
+
+		if (col < mtd->writesize) {
+			p = host->regs->main_area0 + (col & ~3);
+		} else {
+			p = host->regs->spare_area0 -
+						mtd->writesize + (col & ~3);
+		}
+
+		MTDDEBUG(MTD_DEBUG_LEVEL3, "%s:%d: p = %p\n", __func__,
+		      __LINE__, p);
+
+		if (((col | (int)&buf[i]) & 3) || n < 16) {
+			uint32_t data = 0;
+
+			if (col & 3 || n < 4)
+				data = readl(p);
+
+			switch (col & 3) {
+			case 0:
+				if (n) {
+					data = (data & 0xffffff00) |
+					    (buf[i++] << 0);
+					n--;
+					col++;
+				}
+			case 1:
+				if (n) {
+					data = (data & 0xffff00ff) |
+					    (buf[i++] << 8);
+					n--;
+					col++;
+				}
+			case 2:
+				if (n) {
+					data = (data & 0xff00ffff) |
+					    (buf[i++] << 16);
+					n--;
+					col++;
+				}
+			case 3:
+				if (n) {
+					data = (data & 0x00ffffff) |
+					    (buf[i++] << 24);
+					n--;
+					col++;
+				}
+			}
+
+			writel(data, p);
+		} else {
+			int m = mtd->writesize - col;
+
+			if (col >= mtd->writesize)
+				m += mtd->oobsize;
+
+			m = min(n, m) & ~3;
+
+			MTDDEBUG(MTD_DEBUG_LEVEL3,
+			      "%s:%d: n = %d, m = %d, i = %d, col = %d\n",
+			      __func__,  __LINE__, n, m, i, col);
+
+			mxc_nand_memcpy32(p, (void *)&buf[i], m);
+			col += m;
+			i += m;
+			n -= m;
+		}
+	}
+	/* Update saved column address */
+	host->col_addr = col;
+}
+
+/*
+ * Read the data buffer from the NAND Flash. To read the data from NAND
+ * Flash first the data output cycle is initiated by the NFC, which copies
+ * the data to RAMbuffer. This data of length len is then copied to buffer buf.
+ */
+static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+	int n, col, i = 0;
+
+	MTDDEBUG(MTD_DEBUG_LEVEL3,
+	      "mxc_nand_read_buf(col = %d, len = %d)\n", host->col_addr, len);
+
+	col = host->col_addr;
+
+	/* Adjust saved column address */
+	if (col < mtd->writesize && host->spare_only)
+		col += mtd->writesize;
+
+	n = mtd->writesize + mtd->oobsize - col;
+	n = min(len, n);
+
+	while (n) {
+		void __iomem *p;
+
+		if (col < mtd->writesize) {
+			p = host->regs->main_area0 + (col & ~3);
+		} else {
+			p = host->regs->spare_area0 -
+					mtd->writesize + (col & ~3);
+		}
+
+		if (((col | (int)&buf[i]) & 3) || n < 16) {
+			uint32_t data;
+
+			data = readl(p);
+			switch (col & 3) {
+			case 0:
+				if (n) {
+					buf[i++] = (uint8_t) (data);
+					n--;
+					col++;
+				}
+			case 1:
+				if (n) {
+					buf[i++] = (uint8_t) (data >> 8);
+					n--;
+					col++;
+				}
+			case 2:
+				if (n) {
+					buf[i++] = (uint8_t) (data >> 16);
+					n--;
+					col++;
+				}
+			case 3:
+				if (n) {
+					buf[i++] = (uint8_t) (data >> 24);
+					n--;
+					col++;
+				}
+			}
+		} else {
+			int m = mtd->writesize - col;
+
+			if (col >= mtd->writesize)
+				m += mtd->oobsize;
+
+			m = min(n, m) & ~3;
+			mxc_nand_memcpy32(&buf[i], p, m);
+
+			col += m;
+			i += m;
+			n -= m;
+		}
+	}
+	/* Update saved column address */
+	host->col_addr = col;
+
+}
+
+/*
+ * Used by the upper layer to verify the data in NAND Flash
+ * with the data in the buf.
+ */
+static int mxc_nand_verify_buf(struct mtd_info *mtd,
+				const u_char *buf, int len)
+{
+	return -EFAULT;
+}
+
+/*
+ * This function is used by upper layer for select and
+ * deselect of the NAND chip
+ */
+static void mxc_nand_select_chip(struct mtd_info *mtd, int chip)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+
+#ifdef CONFIG_MTD_NAND_MXC_FORCE_CE
+	if (chip > 0) {
+		MTDDEBUG(MTD_DEBUG_LEVEL0,
+		      "ERROR:  Illegal chip select (chip = %d)\n", chip);
+		return;
+	}
+
+	if (chip == -1) {
+		writew(readw(&host->regs->nfc_config1) & ~NFC_CE,
+				&host->regs->nfc_config1);
+		return;
+	}
+
+	writew(readw(&host->regs->nfc_config1) | NFC_CE,
+			&host->regs->nfc_config1);
+#endif
+
+	switch (chip) {
+	case -1:
+		/* TODO: Disable the NFC clock */
+		if (host->clk_act)
+			host->clk_act = 0;
+		break;
+	case 0:
+		/* TODO: Enable the NFC clock */
+		if (!host->clk_act)
+			host->clk_act = 1;
+		break;
+
+	default:
+		break;
+	}
+}
+
+/*
+ * Used by the upper layer to write command to NAND Flash for
+ * different operations to be carried out on NAND Flash
+ */
+static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
+				int column, int page_addr)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+
+	MTDDEBUG(MTD_DEBUG_LEVEL3,
+	      "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
+	      command, column, page_addr);
+
+	/* Reset command state information */
+	host->status_request = false;
+
+	/* Command pre-processing step */
+	switch (command) {
+
+	case NAND_CMD_STATUS:
+		host->col_addr = 0;
+		host->status_request = true;
+		break;
+
+	case NAND_CMD_READ0:
+		host->col_addr = column;
+		host->spare_only = false;
+		break;
+
+	case NAND_CMD_READOOB:
+		host->col_addr = column;
+		host->spare_only = true;
+		if (host->pagesize_2k)
+			command = NAND_CMD_READ0; /* only READ0 is valid */
+		break;
+
+	case NAND_CMD_SEQIN:
+		if (column >= mtd->writesize) {
+			/*
+			 * FIXME: before send SEQIN command for write OOB,
+			 * We must read one page out.
+			 * For K9F1GXX has no READ1 command to set current HW
+			 * pointer to spare area, we must write the whole page
+			 * including OOB together.
+			 */
+			if (host->pagesize_2k) {
+				/* call ourself to read a page */
+				mxc_nand_command(mtd, NAND_CMD_READ0, 0,
+						page_addr);
+			}
+
+			host->col_addr = column - mtd->writesize;
+			host->spare_only = true;
+
+			/* Set program pointer to spare region */
+			if (!host->pagesize_2k)
+				send_cmd(host, NAND_CMD_READOOB);
+		} else {
+			host->spare_only = false;
+			host->col_addr = column;
+
+			/* Set program pointer to page start */
+			if (!host->pagesize_2k)
+				send_cmd(host, NAND_CMD_READ0);
+		}
+		break;
+
+	case NAND_CMD_PAGEPROG:
+		send_prog_page(host, 0, host->spare_only);
+
+		if (host->pagesize_2k) {
+			/* data in 4 areas datas */
+			send_prog_page(host, 1, host->spare_only);
+			send_prog_page(host, 2, host->spare_only);
+			send_prog_page(host, 3, host->spare_only);
+		}
+
+		break;
+	}
+
+	/* Write out the command to the device. */
+	send_cmd(host, command);
+
+	/* Write out column address, if necessary */
+	if (column != -1) {
+		/*
+		 * MXC NANDFC can only perform full page+spare or
+		 * spare-only read/write.  When the upper layers
+		 * layers perform a read/write buf operation,
+		 * we will used the saved column adress to index into
+		 * the full page.
+		 */
+		send_addr(host, 0);
+		if (host->pagesize_2k)
+			/* another col addr cycle for 2k page */
+			send_addr(host, 0);
+	}
+
+	/* Write out page address, if necessary */
+	if (page_addr != -1) {
+		/* paddr_0 - p_addr_7 */
+		send_addr(host, (page_addr & 0xff));
+
+		if (host->pagesize_2k) {
+			send_addr(host, (page_addr >> 8) & 0xFF);
+			if (mtd->size >= 0x40000000)
+				send_addr(host, (page_addr >> 16) & 0xff);
+		} else {
+			/* One more address cycle for higher density devices */
+			if (mtd->size >= 0x4000000) {
+				/* paddr_8 - paddr_15 */
+				send_addr(host, (page_addr >> 8) & 0xff);
+				send_addr(host, (page_addr >> 16) & 0xff);
+			} else {
+				/* paddr_8 - paddr_15 */
+				send_addr(host, (page_addr >> 8) & 0xff);
+			}
+		}
+	}
+
+	/* Command post-processing step */
+	switch (command) {
+
+	case NAND_CMD_RESET:
+		break;
+
+	case NAND_CMD_READOOB:
+	case NAND_CMD_READ0:
+		if (host->pagesize_2k) {
+			/* send read confirm command */
+			send_cmd(host, NAND_CMD_READSTART);
+			/* read for each AREA */
+			send_read_page(host, 0, host->spare_only);
+			send_read_page(host, 1, host->spare_only);
+			send_read_page(host, 2, host->spare_only);
+			send_read_page(host, 3, host->spare_only);
+		} else {
+			send_read_page(host, 0, host->spare_only);
+		}
+		break;
+
+	case NAND_CMD_READID:
+		host->col_addr = 0;
+		send_read_id(host);
+		break;
+
+	case NAND_CMD_PAGEPROG:
+		break;
+
+	case NAND_CMD_STATUS:
+		break;
+
+	case NAND_CMD_ERASE2:
+		break;
+	}
+}
+
+int board_nand_init(struct nand_chip *this)
+{
+	struct system_control_regs *sc_regs =
+		(struct system_control_regs *)IMX_SYSTEM_CTL_BASE;
+	struct mtd_info *mtd;
+	uint16_t tmp;
+	int err = 0;
+
+	/* structures must be linked */
+	mtd = &host->mtd;
+	mtd->priv = this;
+	host->nand = this;
+
+	/* 50 us command delay time */
+	this->chip_delay = 5;
+
+	this->priv = host;
+	this->dev_ready = mxc_nand_dev_ready;
+	this->cmdfunc = mxc_nand_command;
+	this->select_chip = mxc_nand_select_chip;
+	this->read_byte = mxc_nand_read_byte;
+	this->read_word = mxc_nand_read_word;
+	this->write_buf = mxc_nand_write_buf;
+	this->read_buf = mxc_nand_read_buf;
+	this->verify_buf = mxc_nand_verify_buf;
+
+	host->regs = (struct nfc_regs __iomem *)CONFIG_MXC_NAND_REGS_BASE;
+	host->clk_act = 1;
+
+#ifdef CONFIG_MXC_NAND_HWECC
+	this->ecc.calculate = mxc_nand_calculate_ecc;
+	this->ecc.hwctl = mxc_nand_enable_hwecc;
+	this->ecc.correct = mxc_nand_correct_data;
+	this->ecc.mode = NAND_ECC_HW;
+	this->ecc.size = 512;
+	this->ecc.bytes = 3;
+	this->ecc.layout = &nand_hw_eccoob_8;
+	tmp = readw(&host->regs->nfc_config1);
+	tmp |= NFC_ECC_EN;
+	writew(tmp, &host->regs->nfc_config1);
+#else
+	this->ecc.size = 512;
+	this->ecc.bytes = 3;
+	this->ecc.layout = &nand_hw_eccoob_8;
+	this->ecc.mode = NAND_ECC_SOFT;
+	tmp = readw(&host->regs->nfc_config1);
+	tmp &= ~NFC_ECC_EN;
+	writew(tmp, &host->regs->nfc_config1);
+#endif
+
+	/* Reset NAND */
+	this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
+
+	/*
+	 * preset operation
+	 * Unlock the internal RAM Buffer
+	 */
+	writew(0x2, &host->regs->nfc_config);
+
+	/* Blocks to be unlocked */
+	writew(0x0, &host->regs->nfc_unlockstart_blkaddr);
+	writew(0x4000, &host->regs->nfc_unlockend_blkaddr);
+
+	/* Unlock Block Command for given address range */
+	writew(0x4, &host->regs->nfc_wrprot);
+
+	/* NAND bus width determines access funtions used by upper layer */
+	if (readl(&sc_regs->fmcr) & NF_16BIT_SEL) {
+		this->options |= NAND_BUSWIDTH_16;
+		this->ecc.layout = &nand_hw_eccoob_16;
+	}
+
+	host->pagesize_2k = 0;
+
+	return err;
+}
+
-- 
1.6.0.6

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

* [U-Boot] [PATCH 5/7] mxc-mmc: sdhc host driver for MX2 and MX3 proccessor
  2009-06-08  0:12 [U-Boot] [PATCH 0/7][v3] Support for LogicPD i.MX27-LITEKIT development board Ilya Yanok
                   ` (3 preceding siblings ...)
  2009-06-08  0:12 ` [U-Boot] [PATCH 4/7] mxc_nand: add nand driver for MX2/MX3 Ilya Yanok
@ 2009-06-08  0:12 ` Ilya Yanok
  2009-06-21 11:04   ` Jean-Christophe PLAGNIOL-VILLARD
                     ` (2 more replies)
  2009-06-08  0:12 ` [U-Boot] [PATCH 6/7] arm: add support for CONFIG_GENERIC_MMC Ilya Yanok
                   ` (2 subsequent siblings)
  7 siblings, 3 replies; 70+ messages in thread
From: Ilya Yanok @ 2009-06-08  0:12 UTC (permalink / raw)
  To: u-boot

This is a port of Linux driver for SDHC host controller hardware
found on Freescale's MX2 and MX3 processors. Uses new generic MMC
framework (CONFIG_GENERIC_MMC) and it looks like there are some
problems with a framework (at least on LE cpus). Some of these
problems are addressed in the following patches.

Signed-off-by: Ilya Yanok <yanok@emcraft.com>
---
 cpu/arm926ejs/mx27/generic.c       |   16 ++
 drivers/mmc/Makefile               |    1 +
 drivers/mmc/mxcmmc.c               |  523 ++++++++++++++++++++++++++++++++++++
 include/asm-arm/arch-mx27/mxcmmc.h |   25 ++
 4 files changed, 565 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mmc/mxcmmc.c
 create mode 100644 include/asm-arm/arch-mx27/mxcmmc.h

diff --git a/cpu/arm926ejs/mx27/generic.c b/cpu/arm926ejs/mx27/generic.c
index b52f934..b1c8bed 100644
--- a/cpu/arm926ejs/mx27/generic.c
+++ b/cpu/arm926ejs/mx27/generic.c
@@ -23,6 +23,9 @@
 #include <netdev.h>
 #include <asm/io.h>
 #include <asm/arch/imx-regs.h>
+#ifdef CONFIG_MXC_MMC
+#include <asm/arch/mxcmmc.h>
+#endif
 
 /*
  *  get the system pll clock in Hz
@@ -169,6 +172,19 @@ int cpu_eth_init(bd_t *bis)
 #endif
 }
 
+/*
+ * Initializes on-chip MMC controllers.
+ * to override, implement board_mmc_init()
+ */
+int cpu_mmc_init(bd_t *bis)
+{
+#ifdef CONFIG_MXC_MMC
+	return mxc_mmc_init(bis);
+#else
+	return 0;
+#endif
+}
+
 void imx_gpio_mode(int gpio_mode)
 {
 	struct gpio_regs *regs = (struct gpio_regs *)IMX_GPIO_BASE;
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 1b0af12..6fa04b8 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -30,6 +30,7 @@ COBJS-$(CONFIG_ATMEL_MCI) += atmel_mci.o
 COBJS-$(CONFIG_BFIN_SDH) += bfin_sdh.o
 COBJS-$(CONFIG_OMAP3_MMC) += omap3_mmc.o
 COBJS-$(CONFIG_FSL_ESDHC) += fsl_esdhc.o
+COBJS-$(CONFIG_MXC_MMC) += mxcmmc.o
 COBJS-$(CONFIG_PXA_MMC) += pxa_mmc.o
 
 COBJS	:= $(COBJS-y)
diff --git a/drivers/mmc/mxcmmc.c b/drivers/mmc/mxcmmc.c
new file mode 100644
index 0000000..6282b23
--- /dev/null
+++ b/drivers/mmc/mxcmmc.c
@@ -0,0 +1,523 @@
+/*
+ *  This is a driver for the SDHC controller found in Freescale MX2/MX3
+ *  SoCs. It is basically the same hardware as found on MX1 (imxmmc.c).
+ *  Unlike the hardware found on MX1, this hardware just works and does
+ *  not need all the quirks found in imxmmc.c, hence the seperate driver.
+ *
+ *  Copyright (C) 2009 Ilya Yanok, <yanok@emcraft.com>
+ *  Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
+ *  Copyright (C) 2006 Pavel Pisa, PiKRON <ppisa@pikron.com>
+ *
+ *  derived from pxamci.c by Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <config.h>
+#include <common.h>
+#include <command.h>
+#include <mmc.h>
+#include <part.h>
+#include <malloc.h>
+#include <mmc.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#ifdef CONFIG_MX27
+#include <asm/arch/clock.h>
+#endif
+
+#define DRIVER_NAME "mxc-mmc"
+
+struct mxcmci_regs {
+	u32 str_stp_clk;
+	u32 status;
+	u32 clk_rate;
+	u32 cmd_dat_cont;
+	u32 res_to;
+	u32 read_to;
+	u32 blk_len;
+	u32 nob;
+	u32 rev_no;
+	u32 int_cntr;
+	u32 cmd;
+	u32 arg;
+	u32 pad;
+	u32 res_fifo;
+	u32 buffer_access;
+};
+
+#define STR_STP_CLK_RESET               (1 << 3)
+#define STR_STP_CLK_START_CLK           (1 << 1)
+#define STR_STP_CLK_STOP_CLK            (1 << 0)
+
+#define STATUS_CARD_INSERTION		(1 << 31)
+#define STATUS_CARD_REMOVAL		(1 << 30)
+#define STATUS_YBUF_EMPTY		(1 << 29)
+#define STATUS_XBUF_EMPTY		(1 << 28)
+#define STATUS_YBUF_FULL		(1 << 27)
+#define STATUS_XBUF_FULL		(1 << 26)
+#define STATUS_BUF_UND_RUN		(1 << 25)
+#define STATUS_BUF_OVFL			(1 << 24)
+#define STATUS_SDIO_INT_ACTIVE		(1 << 14)
+#define STATUS_END_CMD_RESP		(1 << 13)
+#define STATUS_WRITE_OP_DONE		(1 << 12)
+#define STATUS_DATA_TRANS_DONE		(1 << 11)
+#define STATUS_READ_OP_DONE		(1 << 11)
+#define STATUS_WR_CRC_ERROR_CODE_MASK	(3 << 10)
+#define STATUS_CARD_BUS_CLK_RUN		(1 << 8)
+#define STATUS_BUF_READ_RDY		(1 << 7)
+#define STATUS_BUF_WRITE_RDY		(1 << 6)
+#define STATUS_RESP_CRC_ERR		(1 << 5)
+#define STATUS_CRC_READ_ERR		(1 << 3)
+#define STATUS_CRC_WRITE_ERR		(1 << 2)
+#define STATUS_TIME_OUT_RESP		(1 << 1)
+#define STATUS_TIME_OUT_READ		(1 << 0)
+#define STATUS_ERR_MASK			0x2f
+
+#define CMD_DAT_CONT_CMD_RESP_LONG_OFF	(1 << 12)
+#define CMD_DAT_CONT_STOP_READWAIT	(1 << 11)
+#define CMD_DAT_CONT_START_READWAIT	(1 << 10)
+#define CMD_DAT_CONT_BUS_WIDTH_4	(2 << 8)
+#define CMD_DAT_CONT_INIT		(1 << 7)
+#define CMD_DAT_CONT_WRITE		(1 << 4)
+#define CMD_DAT_CONT_DATA_ENABLE	(1 << 3)
+#define CMD_DAT_CONT_RESPONSE_48BIT_CRC	(1 << 0)
+#define CMD_DAT_CONT_RESPONSE_136BIT	(2 << 0)
+#define CMD_DAT_CONT_RESPONSE_48BIT	(3 << 0)
+
+#define INT_SDIO_INT_WKP_EN		(1 << 18)
+#define INT_CARD_INSERTION_WKP_EN	(1 << 17)
+#define INT_CARD_REMOVAL_WKP_EN		(1 << 16)
+#define INT_CARD_INSERTION_EN		(1 << 15)
+#define INT_CARD_REMOVAL_EN		(1 << 14)
+#define INT_SDIO_IRQ_EN			(1 << 13)
+#define INT_DAT0_EN			(1 << 12)
+#define INT_BUF_READ_EN			(1 << 4)
+#define INT_BUF_WRITE_EN		(1 << 3)
+#define INT_END_CMD_RES_EN		(1 << 2)
+#define INT_WRITE_OP_DONE_EN		(1 << 1)
+#define INT_READ_OP_EN			(1 << 0)
+
+struct mxcmci_host {
+	struct mmc		*mmc;
+	struct mxcmci_regs	*base;
+	int			irq;
+	int			detect_irq;
+	int			dma;
+	int			do_dma;
+	unsigned int		power_mode;
+
+	struct mmc_cmd		*cmd;
+	struct mmc_data		*data;
+
+	unsigned int		dma_nents;
+	unsigned int		datasize;
+	unsigned int		dma_dir;
+
+	u16			rev_no;
+	unsigned int		cmdat;
+
+	int			clock;
+};
+
+static struct mxcmci_host mxcmci_host;
+static struct mxcmci_host *host = &mxcmci_host;
+
+static inline int mxcmci_use_dma(struct mxcmci_host *host)
+{
+	return host->do_dma;
+}
+
+static void mxcmci_softreset(struct mxcmci_host *host)
+{
+	int i;
+
+	/* reset sequence */
+	writew(STR_STP_CLK_RESET, &host->base->str_stp_clk);
+	writew(STR_STP_CLK_RESET | STR_STP_CLK_START_CLK,
+			&host->base->str_stp_clk);
+
+	for (i = 0; i < 8; i++)
+		writew(STR_STP_CLK_START_CLK, &host->base->str_stp_clk);
+
+	writew(0xff, &host->base->res_to);
+}
+
+static void mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
+{
+	unsigned int nob = data->blocks;
+	unsigned int blksz = data->blocksize;
+	unsigned int datasize = nob * blksz;
+
+	host->data = data;
+
+	writew(nob, &host->base->nob);
+	writew(blksz, &host->base->blk_len);
+	host->datasize = datasize;
+}
+
+static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_cmd *cmd,
+		unsigned int cmdat)
+{
+	if (host->cmd != NULL)
+		printf("mxcmci: error!\n");
+	host->cmd = cmd;
+
+	switch (cmd->resp_type) {
+	case MMC_RSP_R1: /* short CRC, OPCODE */
+	case MMC_RSP_R1b:/* short CRC, OPCODE, BUSY */
+		cmdat |= CMD_DAT_CONT_RESPONSE_48BIT_CRC;
+		break;
+	case MMC_RSP_R2: /* long 136 bit + CRC */
+		cmdat |= CMD_DAT_CONT_RESPONSE_136BIT;
+		break;
+	case MMC_RSP_R3: /* short */
+		cmdat |= CMD_DAT_CONT_RESPONSE_48BIT;
+		break;
+	case MMC_RSP_NONE:
+		break;
+	default:
+		printf("mxcmci: unhandled response type 0x%x\n",
+				cmd->resp_type);
+		return -EINVAL;
+	}
+
+	writew(cmd->cmdidx, &host->base->cmd);
+	writel(cmd->cmdarg, &host->base->arg);
+	writew(cmdat, &host->base->cmd_dat_cont);
+
+	return 0;
+}
+
+static void mxcmci_finish_request(struct mxcmci_host *host,
+		struct mmc_cmd *cmd, struct mmc_data *data)
+{
+	host->cmd = NULL;
+	host->data = NULL;
+}
+
+static int mxcmci_finish_data(struct mxcmci_host *host, unsigned int stat)
+{
+	int data_error = 0;
+
+	if (stat & STATUS_ERR_MASK) {
+		printf("request failed. status: 0x%08x\n",
+				stat);
+		if (stat & STATUS_CRC_READ_ERR) {
+			data_error = -EILSEQ;
+		} else if (stat & STATUS_CRC_WRITE_ERR) {
+			u32 err_code = (stat >> 9) & 0x3;
+			if (err_code == 2) /* No CRC response */
+				data_error = TIMEOUT;
+			else
+				data_error = -EILSEQ;
+		} else if (stat & STATUS_TIME_OUT_READ) {
+			data_error = TIMEOUT;
+		} else {
+			data_error = -EIO;
+		}
+	}
+
+	host->data = NULL;
+
+	return data_error;
+}
+
+static int mxcmci_read_response(struct mxcmci_host *host, unsigned int stat)
+{
+	struct mmc_cmd *cmd = host->cmd;
+	int i;
+	u32 a, b, c;
+	u32 *resp = (u32 *)cmd->response;
+
+	if (!cmd)
+		return 0;
+
+	if (stat & STATUS_TIME_OUT_RESP) {
+		printf("CMD TIMEOUT\n");
+		return TIMEOUT;
+	} else if (stat & STATUS_RESP_CRC_ERR && cmd->resp_type & MMC_RSP_CRC) {
+		printf("cmd crc error\n");
+		return -EILSEQ;
+	}
+
+	if (cmd->resp_type & MMC_RSP_PRESENT) {
+		if (cmd->resp_type & MMC_RSP_136) {
+			for (i = 0; i < 4; i++) {
+				a = readw(&host->base->res_fifo);
+				b = readw(&host->base->res_fifo);
+				resp[i] = a << 16 | b;
+			}
+		} else {
+			a = readw(&host->base->res_fifo);
+			b = readw(&host->base->res_fifo);
+			c = readw(&host->base->res_fifo);
+			resp[0] = a << 24 | b << 8 | c >> 8;
+		}
+	}
+	return 0;
+}
+
+static int mxcmci_poll_status(struct mxcmci_host *host, u32 mask)
+{
+	u32 stat;
+	unsigned long timeout = get_ticks() + CONFIG_SYS_HZ;
+
+	do {
+		stat = readl(&host->base->status);
+		if (stat & STATUS_ERR_MASK)
+			return stat;
+		if (timeout < get_ticks())
+			return STATUS_TIME_OUT_READ;
+		if (stat & mask)
+			return 0;
+	} while (1);
+}
+
+static int mxcmci_pull(struct mxcmci_host *host, void *_buf, int bytes)
+{
+	unsigned int stat;
+	u32 *buf = _buf;
+
+	while (bytes > 3) {
+		stat = mxcmci_poll_status(host,
+				STATUS_BUF_READ_RDY | STATUS_READ_OP_DONE);
+		if (stat)
+			return stat;
+		*buf++ = readl(&host->base->buffer_access);
+		bytes -= 4;
+	}
+
+	if (bytes) {
+		u8 *b = (u8 *)buf;
+		u32 tmp;
+
+		stat = mxcmci_poll_status(host,
+				STATUS_BUF_READ_RDY | STATUS_READ_OP_DONE);
+		if (stat)
+			return stat;
+		tmp = readl(&host->base->buffer_access);
+		memcpy(b, &tmp, bytes);
+	}
+
+	return 0;
+}
+
+static int mxcmci_push(struct mxcmci_host *host, const void *_buf, int bytes)
+{
+	unsigned int stat;
+	const u32 *buf = _buf;
+
+	while (bytes > 3) {
+		stat = mxcmci_poll_status(host, STATUS_BUF_WRITE_RDY);
+		if (stat)
+			return stat;
+		writel(*buf++, &host->base->buffer_access);
+		bytes -= 4;
+	}
+
+	if (bytes) {
+		const u8 *b = (u8 *)buf;
+		u32 tmp;
+
+		stat = mxcmci_poll_status(host, STATUS_BUF_WRITE_RDY);
+		if (stat)
+			return stat;
+
+		memcpy(&tmp, b, bytes);
+		writel(tmp, &host->base->buffer_access);
+	}
+
+	stat = mxcmci_poll_status(host, STATUS_BUF_WRITE_RDY);
+	if (stat)
+		return stat;
+
+	return 0;
+}
+
+static int mxcmci_transfer_data(struct mxcmci_host *host)
+{
+	struct mmc_data *data = host->data;
+	int stat;
+	unsigned long length;
+
+	length = data->blocks * data->blocksize;
+	host->datasize = 0;
+
+	if (data->flags & MMC_DATA_READ) {
+		stat = mxcmci_pull(host, data->dest, length);
+		if (stat)
+			return stat;
+		host->datasize += length;
+	} else {
+		stat = mxcmci_push(host, (const void *)(data->src), length);
+		if (stat)
+			return stat;
+		host->datasize += length;
+		stat = mxcmci_poll_status(host, STATUS_WRITE_OP_DONE);
+		if (stat)
+			return stat;
+	}
+	return 0;
+}
+
+static int mxcmci_cmd_done(struct mxcmci_host *host, unsigned int stat)
+{
+	int datastat;
+	int ret;
+
+	ret = mxcmci_read_response(host, stat);
+
+	if (ret) {
+		mxcmci_finish_request(host, host->cmd, host->data);
+		return ret;
+	}
+
+	if (!host->data) {
+		mxcmci_finish_request(host, host->cmd, host->data);
+		return 0;
+	}
+
+	datastat = mxcmci_transfer_data(host);
+	ret = mxcmci_finish_data(host, datastat);
+	mxcmci_finish_request(host, host->cmd, host->data);
+	return ret;
+}
+
+static int mxcmci_request(struct mmc *mmc, struct mmc_cmd *cmd,
+		struct mmc_data *data)
+{
+	struct mxcmci_host *host = mmc->priv;
+	unsigned int cmdat = host->cmdat;
+	u32 stat;
+	int ret;
+
+	host->cmdat &= ~CMD_DAT_CONT_INIT;
+	if (data) {
+		mxcmci_setup_data(host, data);
+
+		cmdat |= CMD_DAT_CONT_DATA_ENABLE;
+
+		if (data->flags & MMC_DATA_WRITE)
+			cmdat |= CMD_DAT_CONT_WRITE;
+	}
+
+	if ((ret = mxcmci_start_cmd(host, cmd, cmdat))) {
+		mxcmci_finish_request(host, cmd, data);
+		return ret;
+	}
+
+	do {
+		stat = readl(&host->base->status);
+		writel(stat, &host->base->status);
+	} while (!(stat & STATUS_END_CMD_RESP));
+
+	return mxcmci_cmd_done(host, stat);
+}
+
+static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios)
+{
+	unsigned int divider;
+	int prescaler = 0;
+	unsigned long clk_in = imx_get_perclk2();
+
+	while (prescaler <= 0x800) {
+		for (divider = 1; divider <= 0xF; divider++) {
+			int x;
+
+			x = (clk_in / (divider + 1));
+
+			if (prescaler)
+				x /= (prescaler * 2);
+
+			if (x <= clk_ios)
+				break;
+		}
+		if (divider < 0x10)
+			break;
+
+		if (prescaler == 0)
+			prescaler = 1;
+		else
+			prescaler <<= 1;
+	}
+
+	writew((prescaler << 4) | divider, &host->base->clk_rate);
+}
+
+static void mxcmci_set_ios(struct mmc *mmc)
+{
+	struct mxcmci_host *host = mmc->priv;
+	if (mmc->bus_width == 4)
+		host->cmdat |= CMD_DAT_CONT_BUS_WIDTH_4;
+	else
+		host->cmdat &= ~CMD_DAT_CONT_BUS_WIDTH_4;
+
+	if (mmc->clock) {
+		mxcmci_set_clk_rate(host, mmc->clock);
+		writew(STR_STP_CLK_START_CLK, &host->base->str_stp_clk);
+	} else {
+		writew(STR_STP_CLK_STOP_CLK, &host->base->str_stp_clk);
+	}
+
+	host->clock = mmc->clock;
+}
+
+static int mxcmci_init(struct mmc *mmc)
+{
+	struct mxcmci_host *host = mmc->priv;
+
+	mxcmci_softreset(host);
+
+	host->rev_no = readw(&host->base->rev_no);
+	if (host->rev_no != 0x400) {
+		printf("wrong rev.no. 0x%08x. aborting.\n",
+			host->rev_no);
+		return -ENODEV;
+	}
+
+	/* recommended in data sheet */
+	writew(0x2db4, &host->base->read_to);
+
+	writel(0, &host->base->int_cntr);
+
+	return 0;
+}
+
+static int mxcmci_initialize(bd_t *bis)
+{
+	struct mmc *mmc = NULL;
+
+	mmc = malloc(sizeof(struct mmc));
+
+	if (!mmc)
+		return -ENOMEM;
+
+	sprintf(mmc->name, "MXC MCI");
+	mmc->send_cmd = mxcmci_request;
+	mmc->set_ios = mxcmci_set_ios;
+	mmc->init = mxcmci_init;
+	mmc->host_caps = MMC_MODE_4BIT;
+
+	host->base = (struct mxcmci_regs *)CONFIG_MXC_MCI_REGS_BASE;
+	mmc->priv = host;
+	host->mmc = mmc;
+
+	mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
+
+	mmc->f_min = imx_get_perclk2() >> 7;
+	mmc->f_max = imx_get_perclk2() >> 1;
+
+	mmc_register(mmc);
+
+	return 0;
+}
+
+int mxc_mmc_init(bd_t *bis)
+{
+	return mxcmci_initialize(bis);
+}
+
diff --git a/include/asm-arm/arch-mx27/mxcmmc.h b/include/asm-arm/arch-mx27/mxcmmc.h
new file mode 100644
index 0000000..4c83cc7
--- /dev/null
+++ b/include/asm-arm/arch-mx27/mxcmmc.h
@@ -0,0 +1,25 @@
+/*
+ *  Copyright (c) 2009 Ilya Yanok <yanok@emcraft.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 ASM_ARCH_MXCMMC_H
+#define ASM_ARCH_MXCMMC_H
+
+int mxc_mmc_init(bd_t *bis);
+
+#endif
-- 
1.6.0.6

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

* [U-Boot] [PATCH 6/7] arm: add support for CONFIG_GENERIC_MMC
  2009-06-08  0:12 [U-Boot] [PATCH 0/7][v3] Support for LogicPD i.MX27-LITEKIT development board Ilya Yanok
                   ` (4 preceding siblings ...)
  2009-06-08  0:12 ` [U-Boot] [PATCH 5/7] mxc-mmc: sdhc host driver for MX2 and MX3 proccessor Ilya Yanok
@ 2009-06-08  0:12 ` Ilya Yanok
  2009-06-20 13:20   ` Jean-Christophe PLAGNIOL-VILLARD
  2009-06-08  0:12 ` [U-Boot] [PATCH 7/7] imx27lite: add support for imx27lite board from LogicPD Ilya Yanok
  2009-06-28  9:52 ` [U-Boot] [PATCH 0/7][v3] Support for LogicPD i.MX27-LITEKIT development board Jean-Christophe PLAGNIOL-VILLARD
  7 siblings, 1 reply; 70+ messages in thread
From: Ilya Yanok @ 2009-06-08  0:12 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Ilya Yanok <yanok@emcraft.com>
---
 lib_arm/board.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/lib_arm/board.c b/lib_arm/board.c
index 5d05d9b..268532f 100644
--- a/lib_arm/board.c
+++ b/lib_arm/board.c
@@ -48,6 +48,7 @@
 #include <serial.h>
 #include <nand.h>
 #include <onenand_uboot.h>
+#include <mmc.h>
 
 #ifdef CONFIG_DRIVER_SMC91111
 #include "../drivers/net/smc91111.h"
@@ -439,6 +440,12 @@ extern void davinci_eth_set_mac_addr (const u_int8_t *addr);
 #ifdef BOARD_LATE_INIT
 	board_late_init ();
 #endif
+
+#ifdef CONFIG_GENERIC_MMC
+	puts ("MMC:   ");
+	mmc_initialize (gd->bd);
+#endif
+
 #if defined(CONFIG_CMD_NET)
 #if defined(CONFIG_NET_MULTI)
 	puts ("Net:   ");
-- 
1.6.0.6

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

* [U-Boot] [PATCH 7/7] imx27lite: add support for imx27lite board from LogicPD
  2009-06-08  0:12 [U-Boot] [PATCH 0/7][v3] Support for LogicPD i.MX27-LITEKIT development board Ilya Yanok
                   ` (5 preceding siblings ...)
  2009-06-08  0:12 ` [U-Boot] [PATCH 6/7] arm: add support for CONFIG_GENERIC_MMC Ilya Yanok
@ 2009-06-08  0:12 ` Ilya Yanok
  2009-06-21 11:21   ` Jean-Christophe PLAGNIOL-VILLARD
  2009-06-28  9:52 ` [U-Boot] [PATCH 0/7][v3] Support for LogicPD i.MX27-LITEKIT development board Jean-Christophe PLAGNIOL-VILLARD
  7 siblings, 1 reply; 70+ messages in thread
From: Ilya Yanok @ 2009-06-08  0:12 UTC (permalink / raw)
  To: u-boot

This patch adds support for i.MX27-LITEKIT development board from
LogicPD. This board uses i.MX27 SoC and has 2MB NOR flash, 64MB NAND
flash, FEC ethernet controller integrated into i.MX27.

Signed-off-by: Ilya Yanok <yanok@emcraft.com>
---
 MAINTAINERS                             |    1 +
 MAKEALL                                 |    1 +
 Makefile                                |    3 +
 board/logicpd/imx27lite/Makefile        |   51 +++++++
 board/logicpd/imx27lite/config.mk       |    1 +
 board/logicpd/imx27lite/imx27lite.c     |   97 +++++++++++++
 board/logicpd/imx27lite/lowlevel_init.S |  223 +++++++++++++++++++++++++++++++
 board/logicpd/imx27lite/u-boot.lds      |   56 ++++++++
 include/configs/imx27lite.h             |  195 +++++++++++++++++++++++++++
 9 files changed, 628 insertions(+), 0 deletions(-)
 create mode 100644 board/logicpd/imx27lite/Makefile
 create mode 100644 board/logicpd/imx27lite/config.mk
 create mode 100644 board/logicpd/imx27lite/imx27lite.c
 create mode 100644 board/logicpd/imx27lite/lowlevel_init.S
 create mode 100644 board/logicpd/imx27lite/u-boot.lds
 create mode 100644 include/configs/imx27lite.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 3d50668..98efd69 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -519,6 +519,7 @@ George G. Davis <gdavis@mvista.com>
 	gcplus		SA1100
 
 Wolfgang Denk <wd@denx.de>
+	imx27lite	i.MX27
 	qong		i.MX31
 
 Thomas Elste <info@elste.org>
diff --git a/MAKEALL b/MAKEALL
index 57dd425..2aaec13 100755
--- a/MAKEALL
+++ b/MAKEALL
@@ -504,6 +504,7 @@ LIST_ARM9="			\
 	cp926ejs		\
 	cp946es			\
 	cp966			\
+	imx27lite		\
 	lpd7a400		\
 	mx1ads			\
 	mx1fs2			\
diff --git a/Makefile b/Makefile
index 24e6410..cd02a36 100644
--- a/Makefile
+++ b/Makefile
@@ -2790,6 +2790,9 @@ davinci_sffsdr_config :	unconfig
 davinci_sonata_config :	unconfig
 	@$(MKCONFIG) $(@:_config=) arm arm926ejs sonata davinci davinci
 
+imx27lite_config:	unconfig
+	@$(MKCONFIG) $(@:_config=) arm arm926ejs imx27lite logicpd mx27
+
 lpd7a400_config \
 lpd7a404_config:	unconfig
 	@$(MKCONFIG) $(@:_config=) arm lh7a40x lpd7a40x
diff --git a/board/logicpd/imx27lite/Makefile b/board/logicpd/imx27lite/Makefile
new file mode 100644
index 0000000..c404cef
--- /dev/null
+++ b/board/logicpd/imx27lite/Makefile
@@ -0,0 +1,51 @@
+#
+# (C) Copyright 2000-2004
+# 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).a
+
+COBJS	:= imx27lite.o
+SOBJS	:= lowlevel_init.o
+
+SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+SOBJS	:= $(addprefix $(obj),$(SOBJS))
+
+$(LIB):	$(obj).depend $(OBJS) $(SOBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS)
+
+clean:
+	rm -f $(SOBJS) $(OBJS)
+
+distclean:	clean
+	rm -f $(LIB) core *.bak $(obj).depend
+
+#########################################################################
+
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
+
diff --git a/board/logicpd/imx27lite/config.mk b/board/logicpd/imx27lite/config.mk
new file mode 100644
index 0000000..a2e7768
--- /dev/null
+++ b/board/logicpd/imx27lite/config.mk
@@ -0,0 +1 @@
+TEXT_BASE = 0xA7F00000
diff --git a/board/logicpd/imx27lite/imx27lite.c b/board/logicpd/imx27lite/imx27lite.c
new file mode 100644
index 0000000..7c2658c
--- /dev/null
+++ b/board/logicpd/imx27lite/imx27lite.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2007 Sascha Hauer, Pengutronix
+ * Copyright (C) 2008,2009 Eric Jarrige <jorasse@users.sourceforge.net>
+ * Copyright (C) 2009 Ilya Yanok <yanok@emcraft.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
+ *
+ */
+
+#include <common.h>
+#include <asm/arch/imx-regs.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int imx27lite_devices_init(void)
+{
+	int i;
+	unsigned int mode[] = {
+		PD0_AIN_FEC_TXD0,
+		PD1_AIN_FEC_TXD1,
+		PD2_AIN_FEC_TXD2,
+		PD3_AIN_FEC_TXD3,
+		PD4_AOUT_FEC_RX_ER,
+		PD5_AOUT_FEC_RXD1,
+		PD6_AOUT_FEC_RXD2,
+		PD7_AOUT_FEC_RXD3,
+		PD8_AF_FEC_MDIO,
+		PD9_AIN_FEC_MDC | GPIO_PUEN,
+		PD10_AOUT_FEC_CRS,
+		PD11_AOUT_FEC_TX_CLK,
+		PD12_AOUT_FEC_RXD0,
+		PD13_AOUT_FEC_RX_DV,
+		PD14_AOUT_FEC_CLR,
+		PD15_AOUT_FEC_COL,
+		PD16_AIN_FEC_TX_ER,
+		PF23_AIN_FEC_TX_EN,
+		PE12_PF_UART1_TXD,
+		PE13_PF_UART1_RXD,
+		PB4_PF_SD2_D0,
+		PB5_PF_SD2_D1,
+		PB6_PF_SD2_D2,
+		PB7_PF_SD2_D3,
+		PB8_PF_SD2_CMD,
+		PB9_PF_SD2_CLK,
+	};
+
+	for (i = 0; i < ARRAY_SIZE(mode); i++)
+		imx_gpio_mode(mode[i]);
+
+	return 0;
+}
+
+int board_init (void)
+{
+	gd->bd->bi_arch_number = MACH_TYPE_IMX27LITE;
+	gd->bd->bi_boot_params = 0xa0000100;
+
+	imx27lite_devices_init();
+
+	return 0;
+}
+
+int dram_init (void)
+{
+
+#if ( CONFIG_NR_DRAM_BANKS > 0 )
+	gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
+	gd->bd->bi_dram[0].size = get_ram_size((volatile void *)PHYS_SDRAM_1,
+			PHYS_SDRAM_1_SIZE);
+#endif
+#if ( CONFIG_NR_DRAM_BANKS > 1 )
+	gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
+	gd->bd->bi_dram[1].size = get_ram_size((volatile void *)PHYS_SDRAM_2,
+			PHYS_SDRAM_2_SIZE);
+#endif
+
+	return 0;
+}
+
+int checkboard(void)
+{
+	printf("LogicPD imx27lite\n");
+	return 0;
+}
diff --git a/board/logicpd/imx27lite/lowlevel_init.S b/board/logicpd/imx27lite/lowlevel_init.S
new file mode 100644
index 0000000..ba02ad4
--- /dev/null
+++ b/board/logicpd/imx27lite/lowlevel_init.S
@@ -0,0 +1,223 @@
+/*
+ * For clock initialization, see chapter 3 of the "MCIMX27 Multimedia
+ * Applications Processor Reference Manual, Rev. 0.2".
+ *
+ * (C) Copyright 2008 Eric Jarrige <eric.jarrige@armadeus.org>
+ * (C) Copyright 2009 Ilya Yanok <yanok@emcraft.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
+ */
+
+
+#include <config.h>
+#include <version.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/asm-offsets.h>
+
+#define SDRAM_ESDCFG_REGISTER_VAL(cas)	\
+		(ESDCFG_TRC(10) |	\
+		ESDCFG_TRCD(3) |	\
+		ESDCFG_TCAS(cas) |	\
+		ESDCFG_TRRD(1) |	\
+		ESDCFG_TRAS(5) |	\
+		ESDCFG_TWR |		\
+		ESDCFG_TMRD(2) |	\
+		ESDCFG_TRP(2) |		\
+		ESDCFG_TXP(3))
+
+#define SDRAM_ESDCTL_REGISTER_VAL	\
+		(ESDCTL_PRCT(0) |	\
+		 ESDCTL_BL |		\
+		 ESDCTL_PWDT(0) |	\
+		 ESDCTL_SREFR(3) |	\
+		 ESDCTL_DSIZ_32 |	\
+		 ESDCTL_COL10 |		\
+		 ESDCTL_ROW13 |		\
+		 ESDCTL_SDE)
+
+#define SDRAM_ALL_VAL		0xf00
+
+#define SDRAM_MODE_REGISTER_VAL	0x33	/* BL: 8, CAS: 3 */
+#define SDRAM_EXT_MODE_REGISTER_VAL	0x1000000
+
+#define MPCTL0_VAL	0x1ef15d5
+
+#define SPCTL0_VAL	0x043a1c09
+
+#define CSCR_VAL	0x33f08107
+
+#define PCDR0_VAL	0x120470c3
+#define PCDR1_VAL	0x03030303
+#define PCCR0_VAL	0xffffffff
+#define PCCR1_VAL	0xfffffffc
+
+#define AIPI1_PSR0_VAL	0x20040304
+#define AIPI1_PSR1_VAL	0xdffbfcfb
+#define AIPI2_PSR0_VAL	0x07ffc200
+#define AIPI2_PSR1_VAL	0xffffffff
+
+#define writel(reg, val) \
+	ldr		r0,	=reg;	\
+	ldr		r1,	=val;	\
+	str		r1,   [r0];
+
+SOC_ESDCTL_BASE_W:	.word	IMX_ESD_BASE
+SOC_SI_ID_REG_W:	.word	IMX_SYSTEM_CTL_BASE
+SDRAM_ESDCFG_T1_W:	.word	SDRAM_ESDCFG_REGISTER_VAL(0)
+SDRAM_ESDCFG_T2_W:	.word	SDRAM_ESDCFG_REGISTER_VAL(3)
+SDRAM_PRECHARGE_CMD_W:	.word	(ESDCTL_SDE | ESDCTL_SMODE_PRECHARGE | \
+				 ESDCTL_ROW13 | ESDCTL_COL10)
+SDRAM_AUTOREF_CMD_W:	.word	(ESDCTL_SDE | ESDCTL_SMODE_AUTO_REF | \
+				 ESDCTL_ROW13 | ESDCTL_COL10)
+SDRAM_LOADMODE_CMD_W:	.word	(ESDCTL_SDE | ESDCTL_SMODE_LOAD_MODE | \
+				 ESDCTL_ROW13 | ESDCTL_COL10)
+SDRAM_NORMAL_CMD_W:	.word	SDRAM_ESDCTL_REGISTER_VAL
+
+	.macro init_aipi
+	/*
+	 * setup AIPI1 and AIPI2
+	 */
+	writel(AIPI1_PSR0, AIPI1_PSR0_VAL)
+	writel(AIPI1_PSR1, AIPI1_PSR1_VAL)
+	writel(AIPI2_PSR0, AIPI2_PSR0_VAL)
+	writel(AIPI2_PSR1, AIPI2_PSR1_VAL)
+
+	.endm /* init_aipi */
+
+	.macro init_clock
+	ldr r0, =CSCR
+	/* disable MPLL/SPLL first */
+	ldr r1, [r0]
+	bic r1, r1, #(CSCR_MPEN|CSCR_SPEN)
+	str r1, [r0]
+
+	writel(MPCTL0, MPCTL0_VAL)
+	writel(SPCTL0, SPCTL0_VAL)
+
+	writel(CSCR, CSCR_VAL | CSCR_MPLL_RESTART | CSCR_SPLL_RESTART)
+
+	/*
+	 * add some delay here
+	 */
+	mov r1, #0x1000
+1:	subs r1, r1, #0x1
+	bne 1b
+
+	/* peripheral clock divider */
+	writel(PCDR0, PCDR0_VAL)
+	writel(PCDR1, PCDR1_VAL)
+
+	/* Configure PCCR0 and PCCR1 */
+	writel(PCCR0, PCCR0_VAL)
+	writel(PCCR1, PCCR1_VAL)
+
+	.endm /* init_clock */
+
+	.macro sdram_init
+	ldr r0, SOC_ESDCTL_BASE_W
+	mov r2, #PHYS_SDRAM_1
+
+	/* Do initial reset */
+	mov r1, #ESDMISC_MDDR_DL_RST
+	str r1, [r0, #ESDMISC_ROF]
+
+	/* Hold for more than 200ns */
+	ldr r1, =0x10000
+1:
+	subs r1, r1, #0x1
+	bne 1b
+
+	/* Activate LPDDR iface */
+	mov r1, #ESDMISC_MDDREN
+	str r1, [r0, #ESDMISC_ROF]
+
+	/* Check The chip version TO1 or TO2 */
+	ldr r1, SOC_SI_ID_REG_W
+	ldr r1, [r1]
+	ands r1, r1, #0xF0000000
+	/* add Latency on CAS only for TO2 */
+	ldreq r1, SDRAM_ESDCFG_T2_W
+	ldrne r1, SDRAM_ESDCFG_T1_W
+	str r1, [r0, #ESDCFG0_ROF]
+
+	/* Run initialization sequence */
+	ldr r1, SDRAM_PRECHARGE_CMD_W
+	str r1, [r0, #ESDCTL0_ROF]
+	ldr r1, [r2, #SDRAM_ALL_VAL]
+
+	ldr r1, SDRAM_AUTOREF_CMD_W
+	str r1, [r0, #ESDCTL0_ROF]
+	ldr r1, [r2, #SDRAM_ALL_VAL]
+	ldr r1, [r2, #SDRAM_ALL_VAL]
+
+	ldr r1, SDRAM_LOADMODE_CMD_W
+	str r1, [r0, #ESDCTL0_ROF]
+	ldrb r1, [r2, #SDRAM_MODE_REGISTER_VAL]
+	add r3, r2, #SDRAM_EXT_MODE_REGISTER_VAL
+	ldrb r1, [r3]
+
+	ldr r1, SDRAM_NORMAL_CMD_W
+	str r1, [r0, #ESDCTL0_ROF]
+
+#if (CONFIG_NR_DRAM_BANKS > 1)
+	/* 2nd sdram */
+	mov r2, #PHYS_SDRAM_2
+
+	/* Check The chip version TO1 or TO2 */
+	ldr r1, SOC_SI_ID_REG_W
+	ldr r1, [r1]
+	ands r1, r1, #0xF0000000
+	/* add Latency on CAS only for TO2 */
+	ldreq r1, SDRAM_ESDCFG_T2_W
+	ldrne r1, SDRAM_ESDCFG_T1_W
+	str r1, [r0, #ESDCFG1_ROF]
+
+	/* Run initialization sequence */
+	ldr r1, SDRAM_PRECHARGE_CMD_W
+	str r1, [r0, #ESDCTL1_ROF]
+	ldr r1, [r2, #SDRAM_ALL_VAL]
+
+	ldr r1, SDRAM_AUTOREF_CMD_W
+	str r1, [r0, #ESDCTL1_ROF]
+	ldr r1, [r2, #SDRAM_ALL_VAL]
+	ldr r1, [r2, #SDRAM_ALL_VAL]
+
+	ldr r1, SDRAM_LOADMODE_CMD_W
+	str r1, [r0, #ESDCTL1_ROF]
+	ldrb r1, [r2, #SDRAM_MODE_REGISTER_VAL]
+	add r3, r2, #SDRAM_EXT_MODE_REGISTER_VAL
+	ldrb r1, [r3]
+
+	ldr r1, SDRAM_NORMAL_CMD_W
+	str r1, [r0, #ESDCTL1_ROF]
+#endif  /* CONFIG_NR_DRAM_BANKS > 1 */
+
+	.endm /* sdram_init */
+
+	.globl board_init_lowlevel
+	board_init_lowlevel:
+	.globl	lowlevel_init
+	lowlevel_init:
+
+	mov	r10, lr
+
+	init_aipi
+
+	init_clock
+
+	sdram_init
+
+	mov	pc,r10
diff --git a/board/logicpd/imx27lite/u-boot.lds b/board/logicpd/imx27lite/u-boot.lds
new file mode 100644
index 0000000..f66f20e
--- /dev/null
+++ b/board/logicpd/imx27lite/u-boot.lds
@@ -0,0 +1,56 @@
+/*
+ * (C) Copyright 2007
+ * 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
+ */
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+	. = 0x00000000;
+
+	. = ALIGN(4);
+	.text      :
+	{
+		cpu/arm926ejs/start.o	(.text)
+		*(.text)
+	}
+
+	. = ALIGN(4);
+	.rodata : { *(.rodata) }
+
+	. = ALIGN(4);
+	.data : { *(.data) }
+
+	. = ALIGN(4);
+	.got : { *(.got) }
+
+	__u_boot_cmd_start = .;
+	.u_boot_cmd : { *(.u_boot_cmd) }
+	__u_boot_cmd_end = .;
+
+	. = ALIGN(4);
+	__bss_start = .;
+	.bss : { *(.bss) }
+	_end = .;
+}
+
diff --git a/include/configs/imx27lite.h b/include/configs/imx27lite.h
new file mode 100644
index 0000000..570a94d
--- /dev/null
+++ b/include/configs/imx27lite.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2009 Ilya Yanok <yanok@emcraft.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 __CONFIG_H
+#define __CONFIG_H
+
+/*===================*/
+/* SoC Configuration */
+/*===================*/
+#define CONFIG_ARM926EJS			/* arm926ejs CPU core */
+#define CONFIG_MX27
+#define CONFIG_IMX27LITE
+#define CONFIG_MX27_CLK32	32768		/* OSC32K frequency */
+#define CONFIG_SYS_HZ		1000
+
+#define CONFIG_DISPLAY_CPUINFO
+
+#define CONFIG_CMDLINE_TAG		1	/* enable passing of ATAGs */
+#define CONFIG_SETUP_MEMORY_TAGS	1
+#define CONFIG_INITRD_TAG		1
+
+/*=============*/
+/* Memory Info */
+/*=============*/
+/* malloc() len */
+#define CONFIG_SYS_MALLOC_LEN		(0x10000 + 256*1024)
+/* reserved for initial data */
+#define CONFIG_SYS_GBL_DATA_SIZE	128
+/* memtest start address */
+#define CONFIG_SYS_MEMTEST_START	0xA0000000
+#define CONFIG_SYS_MEMTEST_END		0xA1000000	/* 16MB RAM test */
+#define CONFIG_NR_DRAM_BANKS	1		/* we have 1 bank of DRAM */
+#define CONFIG_STACKSIZE	(256*1024)	/* regular stack */
+#define PHYS_SDRAM_1		0xA0000000	/* DDR Start */
+#define PHYS_SDRAM_1_SIZE	0x08000000	/* DDR size 128MB */
+
+/*====================*/
+/* Serial Driver info */
+/*====================*/
+#define CONFIG_MXC_UART
+#define CONFIG_SYS_MX27_UART1
+#define CONFIG_CONS_INDEX	1		/* use UART0 for console */
+#define CONFIG_BAUDRATE		115200		/* Default baud rate */
+#define CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 }
+
+/*=====================*/
+/* Flash & Environment */
+/*=====================*/
+#define CONFIG_ENV_IS_IN_FLASH
+#define CONFIG_FLASH_CFI_DRIVER
+#define CONFIG_SYS_FLASH_CFI
+/* Use buffered writes (~10x faster) */
+#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE	1
+/* Use hardware sector protection */
+#define CONFIG_SYS_FLASH_PROTECTION		1
+#define CONFIG_SYS_MAX_FLASH_BANKS	1	/* max number of flash banks */
+#define CONFIG_SYS_FLASH_SECT_SZ	0x2000	/* 8KB sect size Intel Flash */
+/* end of flash */
+#define CONFIG_ENV_OFFSET		(PHYS_FLASH_SIZE - 0x20000)
+/* CS2 Base address */
+#define PHYS_FLASH_1			0xc0000000
+/* Flash Base for U-Boot */
+#define CONFIG_SYS_FLASH_BASE		PHYS_FLASH_1
+/* Flash size 2MB */
+#define PHYS_FLASH_SIZE			0x200000
+#define CONFIG_SYS_MAX_FLASH_SECT	(PHYS_FLASH_SIZE / \
+		CONFIG_SYS_FLASH_SECT_SZ)
+#define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_FLASH_BASE
+#define CONFIG_SYS_MONITOR_LEN		0x40000		/* Reserve 256KiB */
+#define CONFIG_ENV_SECT_SIZE		0x10000		/* Env sector Size */
+#define CONFIG_ENV_SIZE		CONFIG_ENV_SECT_SIZE
+/* Address and size of Redundant Environment Sector	*/
+#define CONFIG_ENV_OFFSET_REDUND	(CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE)
+#define CONFIG_ENV_SIZE_REDUND	CONFIG_ENV_SIZE
+
+/*
+ * Ethernet
+ */
+#define CONFIG_FEC_IMX27
+#define CONFIG_MII
+#define CONFIG_NET_MULTI
+
+/*
+ * NAND
+ */
+#define CONFIG_NAND_MXC
+#define CONFIG_MXC_NAND_REGS_BASE	0xd8000000
+#define CONFIG_SYS_MAX_NAND_DEVICE	1
+#define CONFIG_SYS_NAND_BASE		0xd8000000
+#define CONFIG_JFFS2_NAND
+#define CONFIG_MXC_NAND_HWECC
+
+/*
+ * SD/MMC
+ */
+#define CONFIG_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_MXC_MMC
+#define CONFIG_MXC_MCI_REGS_BASE	0x10014000
+#define CONFIG_DOS_PARTITION
+
+/*
+ * MTD partitions
+ */
+#define CONFIG_CMD_MTDPARTS
+#define MTDIDS_DEFAULT		"nor0=physmap-flash.0,nand0=mxc_nand.0"
+#define MTDPARTS_DEFAULT	\
+	"mtdparts=physmap-flash.0:256k(U-Boot),1664k(user),64k(env1),"	\
+	"64k(env2);mxc_nand.0:128k(IPL-SPL),4m(kernel),22m(rootfs),-(userfs)"
+
+/*==============================*/
+/* U-Boot general configuration */
+/*==============================*/
+#define CONFIG_BOOTFILE		"uImage"	/* Boot file name */
+#define CONFIG_SYS_PROMPT	"=> "	/* Monitor Command Prompt */
+#define CONFIG_SYS_CBSIZE	1024	/* Console I/O Buffer Size  */
+/* Print buffer sz */
+#define CONFIG_SYS_PBSIZE	(CONFIG_SYS_CBSIZE + \
+		sizeof(CONFIG_SYS_PROMPT) + 16)
+#define CONFIG_SYS_MAXARGS	16	/* max number of command args */
+/* Boot Argument Buffer Size */
+#define CONFIG_SYS_BARGSIZE	CONFIG_SYS_CBSIZE
+#define CONFIG_CMDLINE_EDITING
+#define CONFIG_SYS_LONGHELP
+
+/*=================*/
+/* U-Boot commands */
+/*=================*/
+#include <config_cmd_default.h>
+#define CONFIG_CMD_ASKENV
+#define CONFIG_CMD_BDI
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_DIAG
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_JFFS2
+#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_BOOTDELAY	5
+
+#define CONFIG_LOADADDR		0xa0800000	/* loadaddr env var */
+#define CONFIG_SYS_LOAD_ADDR		CONFIG_LOADADDR
+
+#define xstr(s)	str(s)
+#define str(s)	#s
+
+#define	CONFIG_EXTRA_ENV_SETTINGS					\
+	"netdev=eth0\0"							\
+	"nfsargs=setenv bootargs root=/dev/nfs rw "			\
+		"nfsroot=${serverip}:${rootpath}\0"			\
+	"ramargs=setenv bootargs root=/dev/ram rw\0"			\
+	"addip=setenv bootargs ${bootargs} "				\
+		"ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}"	\
+		":${hostname}:${netdev}:off panic=1\0"			\
+	"addtty=setenv bootargs ${bootargs}"				\
+		" console=ttymxc0,${baudrate}\0"			\
+	"addmtd=setenv bootargs ${bootargs} ${mtdparts}\0"		\
+	"addmisc=setenv bootargs ${bootargs}\0"				\
+	"u-boot=imx27/u-boot.bin\0"					\
+	"kernel_addr_r=a0800000\0"					\
+	"hostname=imx27\0"						\
+	"bootfile=imx27/uImage\0"					\
+	"rootpath=/opt/eldk-4.2-arm/arm\0"				\
+	"net_nfs=tftp ${kernel_addr_r} ${bootfile};"			\
+		"run nfsargs addip addtty addmtd addmisc;"		\
+		"bootm\0"						\
+	"bootcmd=run net_nfs\0"					\
+	"load=tftp ${loadaddr} ${u-boot}\0"				\
+	"update=protect off " xstr(CONFIG_SYS_MONITOR_BASE)		\
+		" +${filesize};era " xstr(CONFIG_SYS_MONITOR_BASE)	\
+		" +${filesize};cp.b ${fileaddr} "			\
+		xstr(CONFIG_SYS_MONITOR_BASE) " ${filesize}\0"		\
+	"upd=run load update\0"						\
+
+#endif /* __CONFIG_H */
-- 
1.6.0.6

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

* [U-Boot] [PATCH 1/7] mx27: basic cpu support
  2009-06-08  0:12 ` [U-Boot] [PATCH 1/7] mx27: basic cpu support Ilya Yanok
@ 2009-06-20 13:13   ` Jean-Christophe PLAGNIOL-VILLARD
  0 siblings, 0 replies; 70+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2009-06-20 13:13 UTC (permalink / raw)
  To: u-boot

> +
> +#ifndef __ASM_ARCH_CLOCK_H
> +#define __ASM_ARCH_CLOCK_H
> +unsigned int imx_decode_pll(unsigned int pll, unsigned int f_ref);
> +
> +ulong imx_get_mpllclk(void);
I want to have common api scheme so I'll like to have this clock
as the folling scheme (already for at91 as example)

get_arm_clk_rate()
get_spm_clk_rate()
etc...

this could be done in a later patch
I'll add a note in the arm readme
> +ulong imx_get_armclk(void);
> +ulong imx_get_spllclk(void);
> +ulong imx_get_fclk(void);
> +ulong imx_get_hclk(void);
> +ulong imx_get_bclk(void);
> +ulong imx_get_perclk1(void);
> +ulong imx_get_perclk2(void);
> +ulong imx_get_perclk3(void);
> +ulong imx_get_ahbclk(void);

applied to u-boot-arm

Best Regards,
J.

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

* [U-Boot] [PATCH 2/7] serial_mx31: allow it to work with mx27 too and rename to serial_mxc
  2009-06-08  0:12 ` [U-Boot] [PATCH 2/7] serial_mx31: allow it to work with mx27 too and rename to serial_mxc Ilya Yanok
@ 2009-06-20 13:18   ` Jean-Christophe PLAGNIOL-VILLARD
  0 siblings, 0 replies; 70+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2009-06-20 13:18 UTC (permalink / raw)
  To: u-boot

On 04:12 Mon 08 Jun     , Ilya Yanok wrote:
> UART hardware on i.MX27 is the same as on the i.MX31 so we just
> need to provide the driver with correct address of the registers.
> 
IIRC the imx1 share the same too
> Signed-off-by: Ilya Yanok <yanok@emcraft.com>
> ---
>  drivers/serial/Makefile                        |    2 +-
>  drivers/serial/{serial_mx31.c => serial_mxc.c} |   21 +++++++++++++++++++++
>  include/configs/imx31_litekit.h                |    2 +-
>  include/configs/imx31_phycore.h                |    2 +-
>  include/configs/mx31ads.h                      |    2 +-
>  include/configs/qong.h                         |    2 +-
>  6 files changed, 26 insertions(+), 5 deletions(-)
>  rename drivers/serial/{serial_mx31.c => serial_mxc.c} (94%)
> 
> diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
> index 14c818d..9a572e9 100644
> --- a/drivers/serial/Makefile
> +++ b/drivers/serial/Makefile
> @@ -40,7 +40,7 @@ COBJS-$(CONFIG_IXP_SERIAL) += serial_ixp.o
>  COBJS-$(CONFIG_KS8695_SERIAL) += serial_ks8695.o
>  COBJS-$(CONFIG_LPC2292_SERIAL) += serial_lpc2292.o
>  COBJS-$(CONFIG_MAX3100_SERIAL) += serial_max3100.o
> -COBJS-$(CONFIG_MX31_UART) += serial_mx31.o
> +COBJS-$(CONFIG_MXC_UART) += serial_mxc.o
>  COBJS-$(CONFIG_NETARM_SERIAL) += serial_netarm.o
>  COBJS-$(CONFIG_PL010_SERIAL) += serial_pl01x.o
>  COBJS-$(CONFIG_PL011_SERIAL) += serial_pl01x.o
> diff --git a/drivers/serial/serial_mx31.c b/drivers/serial/serial_mxc.c
> similarity index 94%
> rename from drivers/serial/serial_mx31.c
> rename to drivers/serial/serial_mxc.c
> index 7c0682a..acc5b7d 100644
> --- a/drivers/serial/serial_mx31.c
> +++ b/drivers/serial/serial_mxc.c
> @@ -18,7 +18,12 @@
>   */
>  
>  #include <common.h>
> +#ifdef CONFIG_MX31
>  #include <asm/arch/mx31.h>
> +#else
> +#include <asm/arch/imx-regs.h>
> +#include <asm/arch/clock.h>
> +#endif
>  
>  #define __REG(x)     (*((volatile u32 *)(x)))
>  
> @@ -32,6 +37,18 @@
>  #define UART_PHYS 0x43fb0000
>  #elif defined(CONFIG_SYS_MX31_UART5)
>  #define UART_PHYS 0x43fb4000
> +#elif defined(CONFIG_SYS_MX27_UART1)
> +#define UART_PHYS 0x1000a000
> +#elif defined(CONFIG_SYS_MX27_UART2)
> +#define UART_PHYS 0x1000b000
> +#elif defined(CONFIG_SYS_MX27_UART3)
> +#define UART_PHYS 0x1000c000
> +#elif defined(CONFIG_SYS_MX27_UART4)
> +#define UART_PHYS 0x1000d000
> +#elif defined(CONFIG_SYS_MX27_UART5)
> +#define UART_PHYS 0x1001b000
> +#elif defined(CONFIG_SYS_MX27_UART6)
> +#define UART_PHYS 0x1001c000
>  #else
>  #error "define CONFIG_SYS_MX31_UARTx to use the mx31 UART driver"
>  #endif
> @@ -149,7 +166,11 @@ DECLARE_GLOBAL_DATA_PTR;
>  
>  void serial_setbrg (void)
>  {
> +#ifdef CONFIG_MX31
>  	u32 clk = mx31_get_ipg_clk();
> +#else
> +	u32 clk = imx_get_perclk1();
> +#endif
here we need to have a common clock rate function name as we do for avr32 &
at91

	this could done in a next patch but mandatory for other board adding

applied to u-boot-arm

Best Regards,
J.

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

* [U-Boot] [PATCH 6/7] arm: add support for CONFIG_GENERIC_MMC
  2009-06-08  0:12 ` [U-Boot] [PATCH 6/7] arm: add support for CONFIG_GENERIC_MMC Ilya Yanok
@ 2009-06-20 13:20   ` Jean-Christophe PLAGNIOL-VILLARD
  0 siblings, 0 replies; 70+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2009-06-20 13:20 UTC (permalink / raw)
  To: u-boot

On 04:12 Mon 08 Jun     , Ilya Yanok wrote:
> Signed-off-by: Ilya Yanok <yanok@emcraft.com>
> ---
>  lib_arm/board.c |    7 +++++++
>  1 files changed, 7 insertions(+), 0 deletions(-)
applied to u-boot-arm

Best Regards,
J.

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

* [U-Boot] [PATCH 4/7] mxc_nand: add nand driver for MX2/MX3
  2009-06-08  0:12 ` [U-Boot] [PATCH 4/7] mxc_nand: add nand driver for MX2/MX3 Ilya Yanok
@ 2009-06-20 13:22   ` Jean-Christophe PLAGNIOL-VILLARD
  2009-06-22 23:43   ` Scott Wood
  1 sibling, 0 replies; 70+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2009-06-20 13:22 UTC (permalink / raw)
  To: u-boot

On 04:12 Mon 08 Jun     , Ilya Yanok wrote:
> Driver for NFC NAND controller found on Freescale's MX2 and MX3
> processors. Ported from Linux. Tested only with i.MX27 but should
> works with other MX2 and MX3 processors too.
> 
> Signed-off-by: Ilya Yanok <yanok@emcraft.com>
> ---
>  drivers/mtd/nand/Makefile   |    1 +
>  drivers/mtd/nand/mxc_nand.c |  932 +++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 933 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/mtd/nand/mxc_nand.c
Scott could you take a look on it?

Best Regards,
J.

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

* [U-Boot] [PATCH 5/7] mxc-mmc: sdhc host driver for MX2 and MX3 proccessor
  2009-06-08  0:12 ` [U-Boot] [PATCH 5/7] mxc-mmc: sdhc host driver for MX2 and MX3 proccessor Ilya Yanok
@ 2009-06-21 11:04   ` Jean-Christophe PLAGNIOL-VILLARD
  2009-06-23 23:02   ` alfred steele
  2009-08-07 20:13   ` Jean-Christophe PLAGNIOL-VILLARD
  2 siblings, 0 replies; 70+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2009-06-21 11:04 UTC (permalink / raw)
  To: u-boot

On 04:12 Mon 08 Jun     , Ilya Yanok wrote:
> This is a port of Linux driver for SDHC host controller hardware
> found on Freescale's MX2 and MX3 processors. Uses new generic MMC
> framework (CONFIG_GENERIC_MMC) and it looks like there are some
> problems with a framework (at least on LE cpus). Some of these
> problems are addressed in the following patches.
> 
> Signed-off-by: Ilya Yanok <yanok@emcraft.com>
> ---
seem ok to mee

Andy, Haavard for you?

Best Regards,
J.

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

* [U-Boot] [PATCH 7/7] imx27lite: add support for imx27lite board from LogicPD
  2009-06-08  0:12 ` [U-Boot] [PATCH 7/7] imx27lite: add support for imx27lite board from LogicPD Ilya Yanok
@ 2009-06-21 11:21   ` Jean-Christophe PLAGNIOL-VILLARD
  2009-06-23 16:55     ` Detlev Zundel
                       ` (2 more replies)
  0 siblings, 3 replies; 70+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2009-06-21 11:21 UTC (permalink / raw)
  To: u-boot

On 04:12 Mon 08 Jun     , Ilya Yanok wrote:
> This patch adds support for i.MX27-LITEKIT development board from
> LogicPD. This board uses i.MX27 SoC and has 2MB NOR flash, 64MB NAND
> flash, FEC ethernet controller integrated into i.MX27.
> 
> Signed-off-by: Ilya Yanok <yanok@emcraft.com>
> ---
>  MAINTAINERS                             |    1 +
>  MAKEALL                                 |    1 +
>  Makefile                                |    3 +
>  board/logicpd/imx27lite/Makefile        |   51 +++++++
>  board/logicpd/imx27lite/config.mk       |    1 +
>  board/logicpd/imx27lite/imx27lite.c     |   97 +++++++++++++
>  board/logicpd/imx27lite/lowlevel_init.S |  223 +++++++++++++++++++++++++++++++
>  board/logicpd/imx27lite/u-boot.lds      |   56 ++++++++
>  include/configs/imx27lite.h             |  195 +++++++++++++++++++++++++++
>  9 files changed, 628 insertions(+), 0 deletions(-)
>  create mode 100644 board/logicpd/imx27lite/Makefile
>  create mode 100644 board/logicpd/imx27lite/config.mk
>  create mode 100644 board/logicpd/imx27lite/imx27lite.c
>  create mode 100644 board/logicpd/imx27lite/lowlevel_init.S
>  create mode 100644 board/logicpd/imx27lite/u-boot.lds
>  create mode 100644 include/configs/imx27lite.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 3d50668..98efd69 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -519,6 +519,7 @@ George G. Davis <gdavis@mvista.com>
>  	gcplus		SA1100
>  
>  Wolfgang Denk <wd@denx.de>
> +	imx27lite	i.MX27
Wolfgang could you ack it?
>  	qong		i.MX31
>  
>  Thomas Elste <info@elste.org>
> diff --git a/MAKEALL b/MAKEALL
> index 57dd425..2aaec13 100755
> --- a/MAKEALL
> +++ b/MAKEALL
> @@ -504,6 +504,7 @@ LIST_ARM9="			\
>  	cp926ejs		\
>  	cp946es			\
>  	cp966			\
> +	imx27lite		\
>  	lpd7a400		\
>  	mx1ads			\
>  	mx1fs2			\
<snip>
> diff --git a/board/logicpd/imx27lite/imx27lite.c b/board/logicpd/imx27lite/imx27lite.c
> new file mode 100644
> index 0000000..7c2658c
> --- /dev/null
> +++ b/board/logicpd/imx27lite/imx27lite.c
> @@ -0,0 +1,97 @@
> +/*
> + * Copyright (C) 2007 Sascha Hauer, Pengutronix
> + * Copyright (C) 2008,2009 Eric Jarrige <jorasse@users.sourceforge.net>
> + * Copyright (C) 2009 Ilya Yanok <yanok@emcraft.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
> + *
> + */
> +
> +#include <common.h>
> +#include <asm/arch/imx-regs.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +static int imx27lite_devices_init(void)
> +{
> +	int i;
> +	unsigned int mode[] = {
> +		PD0_AIN_FEC_TXD0,
> +		PD1_AIN_FEC_TXD1,
> +		PD2_AIN_FEC_TXD2,
> +		PD3_AIN_FEC_TXD3,
> +		PD4_AOUT_FEC_RX_ER,
> +		PD5_AOUT_FEC_RXD1,
> +		PD6_AOUT_FEC_RXD2,
> +		PD7_AOUT_FEC_RXD3,
please create a device init api as done for at91 davinci as example
> +		PD8_AF_FEC_MDIO,
> +		PD9_AIN_FEC_MDC | GPIO_PUEN,
> +		PD10_AOUT_FEC_CRS,
> +		PD11_AOUT_FEC_TX_CLK,
> +		PD12_AOUT_FEC_RXD0,
> +		PD13_AOUT_FEC_RX_DV,
> +		PD14_AOUT_FEC_CLR,
> +		PD15_AOUT_FEC_COL,
> +		PD16_AIN_FEC_TX_ER,
> +		PF23_AIN_FEC_TX_EN,
> +		PE12_PF_UART1_TXD,
> +		PE13_PF_UART1_RXD,
> +		PB4_PF_SD2_D0,
> +		PB5_PF_SD2_D1,
> +		PB6_PF_SD2_D2,
> +		PB7_PF_SD2_D3,
> +		PB8_PF_SD2_CMD,
> +		PB9_PF_SD2_CLK,
> +	};
> +
> +	for (i = 0; i < ARRAY_SIZE(mode); i++)
> +		imx_gpio_mode(mode[i]);
> +
> +	return 0;
> +}
> +
> +int board_init (void)
> +{
> +	gd->bd->bi_arch_number = MACH_TYPE_IMX27LITE;
> +	gd->bd->bi_boot_params = 0xa0000100;
> +
> +	imx27lite_devices_init();
> +
> +	return 0;
> +}
> +
> +int dram_init (void)
> +{
> +
> +#if ( CONFIG_NR_DRAM_BANKS > 0 )
no need of ()
please remove
> +	gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
> +	gd->bd->bi_dram[0].size = get_ram_size((volatile void *)PHYS_SDRAM_1,
> +			PHYS_SDRAM_1_SIZE);
> +#endif
> +#if ( CONFIG_NR_DRAM_BANKS > 1 )
> +	gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
> +	gd->bd->bi_dram[1].size = get_ram_size((volatile void *)PHYS_SDRAM_2,
> +			PHYS_SDRAM_2_SIZE);
> +#endif
> +
> +	return 0;
> +}
> +
> +int checkboard(void)
> +{
> +	printf("LogicPD imx27lite\n");
> +	return 0;
> +}
> diff --git a/board/logicpd/imx27lite/lowlevel_init.S b/board/logicpd/imx27lite/lowlevel_init.S
> new file mode 100644
> index 0000000..ba02ad4
> --- /dev/null
> +++ b/board/logicpd/imx27lite/lowlevel_init.S
> @@ -0,0 +1,223 @@
> +/*
> + * For clock initialization, see chapter 3 of the "MCIMX27 Multimedia
> + * Applications Processor Reference Manual, Rev. 0.2".
> + *
> + * (C) Copyright 2008 Eric Jarrige <eric.jarrige@armadeus.org>
> + * (C) Copyright 2009 Ilya Yanok <yanok@emcraft.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
> + */
> +
> +
> +#include <config.h>
> +#include <version.h>
> +#include <asm/arch/imx-regs.h>
> +#include <asm/arch/asm-offsets.h>
> +
> +#define SDRAM_ESDCFG_REGISTER_VAL(cas)	\
> +		(ESDCFG_TRC(10) |	\
> +		ESDCFG_TRCD(3) |	\
> +		ESDCFG_TCAS(cas) |	\
> +		ESDCFG_TRRD(1) |	\
> +		ESDCFG_TRAS(5) |	\
> +		ESDCFG_TWR |		\
> +		ESDCFG_TMRD(2) |	\
> +		ESDCFG_TRP(2) |		\
> +		ESDCFG_TXP(3))
> +
> +#define SDRAM_ESDCTL_REGISTER_VAL	\
> +		(ESDCTL_PRCT(0) |	\
> +		 ESDCTL_BL |		\
> +		 ESDCTL_PWDT(0) |	\
> +		 ESDCTL_SREFR(3) |	\
> +		 ESDCTL_DSIZ_32 |	\
> +		 ESDCTL_COL10 |		\
> +		 ESDCTL_ROW13 |		\
> +		 ESDCTL_SDE)
> +
> +#define SDRAM_ALL_VAL		0xf00
> +
> +#define SDRAM_MODE_REGISTER_VAL	0x33	/* BL: 8, CAS: 3 */
> +#define SDRAM_EXT_MODE_REGISTER_VAL	0x1000000
> +
> +#define MPCTL0_VAL	0x1ef15d5
> +
> +#define SPCTL0_VAL	0x043a1c09
> +
> +#define CSCR_VAL	0x33f08107
> +
> +#define PCDR0_VAL	0x120470c3
> +#define PCDR1_VAL	0x03030303
> +#define PCCR0_VAL	0xffffffff
> +#define PCCR1_VAL	0xfffffffc
> +
> +#define AIPI1_PSR0_VAL	0x20040304
> +#define AIPI1_PSR1_VAL	0xdffbfcfb
> +#define AIPI2_PSR0_VAL	0x07ffc200
> +#define AIPI2_PSR1_VAL	0xffffffff
> +
please move those define to the config header
> +#define writel(reg, val) \
> +	ldr		r0,	=reg;	\
> +	ldr		r1,	=val;	\
> +	str		r1,   [r0];
please use write32
> +
> +SOC_ESDCTL_BASE_W:	.word	IMX_ESD_BASE
> +SOC_SI_ID_REG_W:	.word	IMX_SYSTEM_CTL_BASE
> +SDRAM_ESDCFG_T1_W:	.word	SDRAM_ESDCFG_REGISTER_VAL(0)
> +SDRAM_ESDCFG_T2_W:	.word	SDRAM_ESDCFG_REGISTER_VAL(3)
> +SDRAM_PRECHARGE_CMD_W:	.word	(ESDCTL_SDE | ESDCTL_SMODE_PRECHARGE | \
> +				 ESDCTL_ROW13 | ESDCTL_COL10)
> +SDRAM_AUTOREF_CMD_W:	.word	(ESDCTL_SDE | ESDCTL_SMODE_AUTO_REF | \
> +				 ESDCTL_ROW13 | ESDCTL_COL10)
> +SDRAM_LOADMODE_CMD_W:	.word	(ESDCTL_SDE | ESDCTL_SMODE_LOAD_MODE | \
> +				 ESDCTL_ROW13 | ESDCTL_COL10)
> +SDRAM_NORMAL_CMD_W:	.word	SDRAM_ESDCTL_REGISTER_VAL
> +
> +	.macro init_aipi
please indent it as
.macro x
	....
.endm
> +	/*
> +	 * setup AIPI1 and AIPI2
> +	 */
> +	writel(AIPI1_PSR0, AIPI1_PSR0_VAL)
> +	writel(AIPI1_PSR1, AIPI1_PSR1_VAL)
> +	writel(AIPI2_PSR0, AIPI2_PSR0_VAL)
> +	writel(AIPI2_PSR1, AIPI2_PSR1_VAL)
> +
> +	.endm /* init_aipi */
> +
> +	.macro init_clock
> +	ldr r0, =CSCR
> +	/* disable MPLL/SPLL first */
> +	ldr r1, [r0]
> +	bic r1, r1, #(CSCR_MPEN|CSCR_SPEN)
> +	str r1, [r0]
> +
> +	writel(MPCTL0, MPCTL0_VAL)
> +	writel(SPCTL0, SPCTL0_VAL)
> +
> +	writel(CSCR, CSCR_VAL | CSCR_MPLL_RESTART | CSCR_SPLL_RESTART)
> +
> +	/*
> +	 * add some delay here
> +	 */
> +	mov r1, #0x1000
> +1:	subs r1, r1, #0x1
> +	bne 1b
> +
> +	/* peripheral clock divider */
> +	writel(PCDR0, PCDR0_VAL)
> +	writel(PCDR1, PCDR1_VAL)
> +
> +	/* Configure PCCR0 and PCCR1 */
> +	writel(PCCR0, PCCR0_VAL)
> +	writel(PCCR1, PCCR1_VAL)
> +
> +	.endm /* init_clock */
> +
> +	.macro sdram_init
> +	ldr r0, SOC_ESDCTL_BASE_W
> +	mov r2, #PHYS_SDRAM_1
> +
> +	/* Do initial reset */
> +	mov r1, #ESDMISC_MDDR_DL_RST
> +	str r1, [r0, #ESDMISC_ROF]
> +
> +	/* Hold for more than 200ns */
> +	ldr r1, =0x10000
> +1:
> +	subs r1, r1, #0x1
> +	bne 1b
please use delay macro
> +
> +	/* Activate LPDDR iface */
> +	mov r1, #ESDMISC_MDDREN
> +	str r1, [r0, #ESDMISC_ROF]
> +
> +	/* Check The chip version TO1 or TO2 */
> +	ldr r1, SOC_SI_ID_REG_W
> +	ldr r1, [r1]
> +	ands r1, r1, #0xF0000000
> +	/* add Latency on CAS only for TO2 */
> +	ldreq r1, SDRAM_ESDCFG_T2_W
> +	ldrne r1, SDRAM_ESDCFG_T1_W
> +	str r1, [r0, #ESDCFG0_ROF]
> +
> +	/* Run initialization sequence */
> +	ldr r1, SDRAM_PRECHARGE_CMD_W
> +	str r1, [r0, #ESDCTL0_ROF]
> +	ldr r1, [r2, #SDRAM_ALL_VAL]
> +
> +	ldr r1, SDRAM_AUTOREF_CMD_W
> +	str r1, [r0, #ESDCTL0_ROF]
> +	ldr r1, [r2, #SDRAM_ALL_VAL]
> +	ldr r1, [r2, #SDRAM_ALL_VAL]
> +
> +	ldr r1, SDRAM_LOADMODE_CMD_W
> +	str r1, [r0, #ESDCTL0_ROF]
> +	ldrb r1, [r2, #SDRAM_MODE_REGISTER_VAL]
> +	add r3, r2, #SDRAM_EXT_MODE_REGISTER_VAL
> +	ldrb r1, [r3]
> +
> +	ldr r1, SDRAM_NORMAL_CMD_W
> +	str r1, [r0, #ESDCTL0_ROF]
> +
> +#if (CONFIG_NR_DRAM_BANKS > 1)
> +	/* 2nd sdram */
> +	mov r2, #PHYS_SDRAM_2
> +
> +	/* Check The chip version TO1 or TO2 */
> +	ldr r1, SOC_SI_ID_REG_W
> +	ldr r1, [r1]
> +	ands r1, r1, #0xF0000000
> +	/* add Latency on CAS only for TO2 */
> +	ldreq r1, SDRAM_ESDCFG_T2_W
> +	ldrne r1, SDRAM_ESDCFG_T1_W
> +	str r1, [r0, #ESDCFG1_ROF]
> +
> +	/* Run initialization sequence */
> +	ldr r1, SDRAM_PRECHARGE_CMD_W
> +	str r1, [r0, #ESDCTL1_ROF]
> +	ldr r1, [r2, #SDRAM_ALL_VAL]
> +
> +	ldr r1, SDRAM_AUTOREF_CMD_W
> +	str r1, [r0, #ESDCTL1_ROF]
> +	ldr r1, [r2, #SDRAM_ALL_VAL]
> +	ldr r1, [r2, #SDRAM_ALL_VAL]
> +
> +	ldr r1, SDRAM_LOADMODE_CMD_W
> +	str r1, [r0, #ESDCTL1_ROF]
> +	ldrb r1, [r2, #SDRAM_MODE_REGISTER_VAL]
> +	add r3, r2, #SDRAM_EXT_MODE_REGISTER_VAL
> +	ldrb r1, [r3]
> +
> +	ldr r1, SDRAM_NORMAL_CMD_W
> +	str r1, [r0, #ESDCTL1_ROF]
> +#endif  /* CONFIG_NR_DRAM_BANKS > 1 */
> +
> +	.endm /* sdram_init */
> +
> +	.globl board_init_lowlevel
> +	board_init_lowlevel:
why do you need dual declaration???
and please indent it as 
.globl lowlevel_init
lowlevel_init:
> +	.globl	lowlevel_init
> +	lowlevel_init:
> +
> +	mov	r10, lr
> +
> +	init_aipi
> +
> +	init_clock
> +
> +	sdram_init
> +
> +	mov	pc,r10
> diff --git a/board/logicpd/imx27lite/u-boot.lds b/board/logicpd/imx27lite/u-boot.lds
> new file mode 100644
> index 0000000..f66f20e
> --- /dev/null
> +++ b/board/logicpd/imx27lite/u-boot.lds
no need please remove

> diff --git a/include/configs/imx27lite.h b/include/configs/imx27lite.h
> new file mode 100644
> index 0000000..570a94d
> --- /dev/null
> +++ b/include/configs/imx27lite.h
> @@ -0,0 +1,195 @@
> +/*
> + * Copyright (C) 2009 Ilya Yanok <yanok@emcraft.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 __CONFIG_H
> +#define __CONFIG_H
> +
> +/*===================*/
> +/* SoC Configuration */
> +/*===================*/
> +#define CONFIG_ARM926EJS			/* arm926ejs CPU core */
> +#define CONFIG_MX27
> +#define CONFIG_IMX27LITE
> +#define CONFIG_MX27_CLK32	32768		/* OSC32K frequency */
> +#define CONFIG_SYS_HZ		1000
> +
> +#define CONFIG_DISPLAY_CPUINFO
> +
> +#define CONFIG_CMDLINE_TAG		1	/* enable passing of ATAGs */
> +#define CONFIG_SETUP_MEMORY_TAGS	1
> +#define CONFIG_INITRD_TAG		1
> +
> +/*=============*/
> +/* Memory Info */
> +/*=============*/
> +/* malloc() len */
> +#define CONFIG_SYS_MALLOC_LEN		(0x10000 + 256*1024)
> +/* reserved for initial data */
> +#define CONFIG_SYS_GBL_DATA_SIZE	128
> +/* memtest start address */
> +#define CONFIG_SYS_MEMTEST_START	0xA0000000
> +#define CONFIG_SYS_MEMTEST_END		0xA1000000	/* 16MB RAM test */
> +#define CONFIG_NR_DRAM_BANKS	1		/* we have 1 bank of DRAM */
> +#define CONFIG_STACKSIZE	(256*1024)	/* regular stack */
please add space before and after '*'
> +#define PHYS_SDRAM_1		0xA0000000	/* DDR Start */
> +#define PHYS_SDRAM_1_SIZE	0x08000000	/* DDR size 128MB */
> +
> +/*====================*/
> +/* Serial Driver info */
> +/*====================*/
please no more of those XXXX comments
please use this style
/*
 *
 */
> +#define CONFIG_MXC_UART
> +#define CONFIG_SYS_MX27_UART1
> +#define CONFIG_CONS_INDEX	1		/* use UART0 for console */
> +#define CONFIG_BAUDRATE		115200		/* Default baud rate */
> +#define CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 }
> +
> +/*=====================*/
> +/* Flash & Environment */
> +/*=====================*/
> +#define CONFIG_ENV_IS_IN_FLASH
> +#define CONFIG_FLASH_CFI_DRIVER
> +#define CONFIG_SYS_FLASH_CFI
> +/* Use buffered writes (~10x faster) */
> +#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE	1
> +/* Use hardware sector protection */
> +#define CONFIG_SYS_FLASH_PROTECTION		1
> +#define CONFIG_SYS_MAX_FLASH_BANKS	1	/* max number of flash banks */
> +#define CONFIG_SYS_FLASH_SECT_SZ	0x2000	/* 8KB sect size Intel Flash */
> +/* end of flash */
> +#define CONFIG_ENV_OFFSET		(PHYS_FLASH_SIZE - 0x20000)
> +/* CS2 Base address */
> +#define PHYS_FLASH_1			0xc0000000
> +/* Flash Base for U-Boot */
> +#define CONFIG_SYS_FLASH_BASE		PHYS_FLASH_1
> +/* Flash size 2MB */
> +#define PHYS_FLASH_SIZE			0x200000
> +#define CONFIG_SYS_MAX_FLASH_SECT	(PHYS_FLASH_SIZE / \
> +		CONFIG_SYS_FLASH_SECT_SZ)
> +#define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_FLASH_BASE
> +#define CONFIG_SYS_MONITOR_LEN		0x40000		/* Reserve 256KiB */
> +#define CONFIG_ENV_SECT_SIZE		0x10000		/* Env sector Size */
> +#define CONFIG_ENV_SIZE		CONFIG_ENV_SECT_SIZE
> +/* Address and size of Redundant Environment Sector	*/
> +#define CONFIG_ENV_OFFSET_REDUND	(CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE)
> +#define CONFIG_ENV_SIZE_REDUND	CONFIG_ENV_SIZE
> +
> +/*
> + * Ethernet
> + */
> +#define CONFIG_FEC_IMX27
> +#define CONFIG_MII
> +#define CONFIG_NET_MULTI
> +
> +/*
> + * NAND
> + */
> +#define CONFIG_NAND_MXC
> +#define CONFIG_MXC_NAND_REGS_BASE	0xd8000000
> +#define CONFIG_SYS_MAX_NAND_DEVICE	1
> +#define CONFIG_SYS_NAND_BASE		0xd8000000
> +#define CONFIG_JFFS2_NAND
> +#define CONFIG_MXC_NAND_HWECC
> +
> +/*
> + * SD/MMC
> + */
> +#define CONFIG_MMC
> +#define CONFIG_GENERIC_MMC
> +#define CONFIG_MXC_MMC
> +#define CONFIG_MXC_MCI_REGS_BASE	0x10014000
> +#define CONFIG_DOS_PARTITION
> +
> +/*
> + * MTD partitions
> + */
> +#define CONFIG_CMD_MTDPARTS
> +#define MTDIDS_DEFAULT		"nor0=physmap-flash.0,nand0=mxc_nand.0"
> +#define MTDPARTS_DEFAULT	\
> +	"mtdparts=physmap-flash.0:256k(U-Boot),1664k(user),64k(env1),"	\
> +	"64k(env2);mxc_nand.0:128k(IPL-SPL),4m(kernel),22m(rootfs),-(userfs)"
something like this will be more readable
	"mtdparts="			\
		"physmap-flash.0:"	\
			"256k(U-Boot),"	\
			"1664k(user),"	\
			"64k(env1),"	\
			"64k(env2);"	\
		"mxc_nand.0:"		\
			"128k(IPL-SPL),"\
			"4m(kernel),"	\
			"22m(rootfs),"	\
			"-(userfs)"

Best Regards,
J.

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

* [U-Boot] [PATCH 4/7] mxc_nand: add nand driver for MX2/MX3
  2009-06-08  0:12 ` [U-Boot] [PATCH 4/7] mxc_nand: add nand driver for MX2/MX3 Ilya Yanok
  2009-06-20 13:22   ` Jean-Christophe PLAGNIOL-VILLARD
@ 2009-06-22 23:43   ` Scott Wood
  2009-06-23 20:03     ` Magnus Lilja
  2009-07-17 10:48     ` Ilya Yanok
  1 sibling, 2 replies; 70+ messages in thread
From: Scott Wood @ 2009-06-22 23:43 UTC (permalink / raw)
  To: u-boot

On Mon, Jun 08, 2009 at 04:12:48AM +0400, Ilya Yanok wrote:
> Driver for NFC NAND controller found on Freescale's MX2 and MX3
> processors. Ported from Linux. Tested only with i.MX27 but should
> works with other MX2 and MX3 processors too.
> 
> Signed-off-by: Ilya Yanok <yanok@emcraft.com>

Please look at drivers/mtd/nand/mpc5121_nfc.c, which AFAICT is very
similar hardware, and see if anything can be factored out into common
code, and try to keep the rest looking the same except where the hardware
actually differs.

> +static struct nand_ecclayout nand_hw_eccoob_16 = {
> +	.eccbytes = 5,
> +	.eccpos = {6, 7, 8, 9, 10},
> +	.oobfree = {{0, 6}, {12, 4}, }
> +};

This implies the bad block marker is one byte at offset 11 (it's all
that's left), but I don't see any override of the bad block pattern.

> +static void *mxc_nand_memcpy32(void *dest, void *source, size_t size)
> +{
> +	uint32_t *s = source, *d = dest;
> +
> +	size >>= 2;
> +	while (size--)
> +		*d++ = *s++;
> +	return dest;
> +}

This should probably be using I/O accessors (possibly raw) -- and should
take uint32_t *, not void *.

> +/*
> + * This function requests the NANDFC to perform a read of the
> + * NAND device status and returns the current status.
> + */
> +static uint16_t get_dev_status(struct mxc_nand_host *host)
> +{
> +	void __iomem *main_buf = host->regs->main_area1;
> +	uint32_t store;
> +	uint16_t ret, tmp;
> +	/* Issue status request to NAND device */
> +
> +	/* store the main area1 first word, later do recovery */
> +	store = readl(main_buf);
> +	/*
> +	 * NANDFC buffer 1 is used for device status to prevent
> +	 * corruption of read/write buffer on status requests.
> +	 */
> +	writew(1, &host->regs->nfc_buf_addr);

But it looks like buffer 1 is used for data with large page flash.

Other drivers don't seem to have any problem with status reads clobbering
the buffer...

> +/* This functions is used by upper layer to checks if device is ready */
> +static int mxc_nand_dev_ready(struct mtd_info *mtd)

"This functions is"?  I'd say this comment is pretty redundant with respect
to the function name anyway...

> +static u_char mxc_nand_read_byte(struct mtd_info *mtd)
> +{
> +	struct nand_chip *nand_chip = mtd->priv;
> +	struct mxc_nand_host *host = nand_chip->priv;
> +	uint8_t ret = 0;
> +	uint16_t col, rd_word;
> +	uint16_t __iomem *main_buf =
> +		(uint16_t __iomem *)host->regs->main_area0;
> +	uint16_t __iomem *spare_buf =
> +		(uint16_t __iomem *)host->regs->spare_area0;

According to Magnus Lilja, "the nand flash controller can only handle 32
bit read/write operations, any other size will cause an abort (or
something like that)".  But now we're accessing it as 16-bit?

> +static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
> +{
> +	struct nand_chip *nand_chip = mtd->priv;
> +	struct mxc_nand_host *host = nand_chip->priv;
> +	uint16_t col, rd_word, ret;
> +	uint16_t __iomem *p;
> +
> +	MTDDEBUG(MTD_DEBUG_LEVEL3,
> +	      "mxc_nand_read_word(col = %d)\n", host->col_addr);
> +
> +	col = host->col_addr;
> +	/* Adjust saved column address */
> +	if (col < mtd->writesize && host->spare_only)
> +		col += mtd->writesize;
> +
> +	if (col < mtd->writesize) {
> +		p = (uint16_t __iomem *)(host->regs->main_area0 + (col >> 1));
> +	} else {
> +		p = (uint16_t __iomem *)(host->regs->spare_area0 +
> +				((col - mtd->writesize) >> 1));
> +	}
> +
> +	if (col & 1) {
> +		rd_word = readw(p);
> +		ret = (rd_word >> 8) & 0xff;
> +		rd_word = readw(&p[1]);
> +		ret |= (rd_word << 8) & 0xff00;
> +

col should never be odd if you're reading words.

> +/*
> + * Write data of length len to buffer buf. The data to be
> + * written on NAND Flash is first copied to RAMbuffer. After the Data Input
> + * Operation by the NFC, the data is written to NAND Flash
> + */
> +static void mxc_nand_write_buf(struct mtd_info *mtd,
> +				const u_char *buf, int len)
> +{
> +	struct nand_chip *nand_chip = mtd->priv;
> +	struct mxc_nand_host *host = nand_chip->priv;
> +	int n, col, i = 0;
> +
> +	MTDDEBUG(MTD_DEBUG_LEVEL3,
> +	      "mxc_nand_write_buf(col = %d, len = %d)\n", host->col_addr,
> +	      len);
> +
> +	col = host->col_addr;
> +
> +	/* Adjust saved column address */
> +	if (col < mtd->writesize && host->spare_only)
> +		col += mtd->writesize;
> +
> +	n = mtd->writesize + mtd->oobsize - col;
> +	n = min(len, n);
> +
> +	MTDDEBUG(MTD_DEBUG_LEVEL3,
> +	      "%s:%d: col = %d, n = %d\n", __func__, __LINE__, col, n);
> +
> +	while (n) {

Safer to do while (n > 0), especially when the code is this complex.

> +		void __iomem *p;
> +
> +		if (col < mtd->writesize) {
> +			p = host->regs->main_area0 + (col & ~3);
> +		} else {
> +			p = host->regs->spare_area0 -
> +						mtd->writesize + (col & ~3);
> +		}
> +
> +		MTDDEBUG(MTD_DEBUG_LEVEL3, "%s:%d: p = %p\n", __func__,
> +		      __LINE__, p);
> +
> +		if (((col | (int)&buf[i]) & 3) || n < 16) {

Do not cast pointers to "int".  Use "uintptr_t" or "unsigned long" if you
must.

Why < 16 and not < 4?

> +			uint32_t data = 0;
> +
> +			if (col & 3 || n < 4)
> +				data = readl(p);

If that condition doesn't hold, the data we use is zero?

> +
> +			switch (col & 3) {
> +			case 0:
> +				if (n) {
> +					data = (data & 0xffffff00) |
> +					    (buf[i++] << 0);
> +					n--;
> +					col++;
> +				}
> +			case 1:
> +				if (n) {
> +					data = (data & 0xffff00ff) |
> +					    (buf[i++] << 8);
> +					n--;
> +					col++;
> +				}
> +			case 2:
> +				if (n) {
> +					data = (data & 0xff00ffff) |
> +					    (buf[i++] << 16);
> +					n--;
> +					col++;
> +				}
> +			case 3:
> +				if (n) {
> +					data = (data & 0x00ffffff) |
> +					    (buf[i++] << 24);
> +					n--;
> +					col++;
> +				}
> +			}
> +			writel(data, p);

Might I suggest this?

union {
	uint32_t word;
	uint8_t bytes[4];
} nfc_word;

nfc_word.word = readl(p);
nfc_word.bytes[col & 3] = buf[i++];
n--;
col++;

writel(nfc_word.word, p);

As a side benefit, you lose the endian dependency.

> +			mxc_nand_memcpy32(p, (void *)&buf[i], m);

Unnecessary cast.

> +	/* Update saved column address */
> +	host->col_addr = col;
> +
> +}

No blank lines before the brace at the end of a block.

> +
> +/*
> + * Used by the upper layer to verify the data in NAND Flash
> + * with the data in the buf.
> + */
> +static int mxc_nand_verify_buf(struct mtd_info *mtd,
> +				const u_char *buf, int len)
> +{
> +	return -EFAULT;
> +}

Umm...

> +	case NAND_CMD_SEQIN:
> +		if (column >= mtd->writesize) {
> +			/*
> +			 * FIXME: before send SEQIN command for write OOB,
> +			 * We must read one page out.
> +			 * For K9F1GXX has no READ1 command to set current HW
> +			 * pointer to spare area, we must write the whole page
> +			 * including OOB together.
> +			 */
> +			if (host->pagesize_2k) {
> +				/* call ourself to read a page */
> +				mxc_nand_command(mtd, NAND_CMD_READ0, 0,
> +						page_addr);
> +			}

Should this be #ifdef HWECC?  And update the comment to indicate the
actual problem, which is the unusual hardware ECC implementation.  I
don't see what the lack of a "READ1" command has to do with it.

And is this actually a FIXME if it's already being done?

> +#ifdef CONFIG_MXC_NAND_HWECC
> +	this->ecc.calculate = mxc_nand_calculate_ecc;
> +	this->ecc.hwctl = mxc_nand_enable_hwecc;
> +	this->ecc.correct = mxc_nand_correct_data;
> +	this->ecc.mode = NAND_ECC_HW;
> +	this->ecc.size = 512;
> +	this->ecc.bytes = 3;
> +	this->ecc.layout = &nand_hw_eccoob_8;
> +	tmp = readw(&host->regs->nfc_config1);
> +	tmp |= NFC_ECC_EN;
> +	writew(tmp, &host->regs->nfc_config1);
> +#else
> +	this->ecc.size = 512;
> +	this->ecc.bytes = 3;
> +	this->ecc.layout = &nand_hw_eccoob_8;
> +	this->ecc.mode = NAND_ECC_SOFT;
> +	tmp = readw(&host->regs->nfc_config1);
> +	tmp &= ~NFC_ECC_EN;
> +	writew(tmp, &host->regs->nfc_config1);
> +#endif

Soft ECC only supports 256-byte ECC blocks (anything you set here to the
contrary will just be overwritten), and you'll need a layout that
accommodates that with enough ECC bytes.

Alternatively, you can implement 512-byte soft ECC if you don't want to
waste those 3 extra OOB bytes. :-)

> +	host->pagesize_2k = 0;

So large page is currently unsupported?

-Scott

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

* [U-Boot] [PATCH 7/7] imx27lite: add support for imx27lite board from LogicPD
  2009-06-21 11:21   ` Jean-Christophe PLAGNIOL-VILLARD
@ 2009-06-23 16:55     ` Detlev Zundel
  2009-07-07 19:24     ` Wolfgang Denk
  2009-07-17 11:00     ` [U-Boot] [PATCH] " Ilya Yanok
  2 siblings, 0 replies; 70+ messages in thread
From: Detlev Zundel @ 2009-06-23 16:55 UTC (permalink / raw)
  To: u-boot

Hi Jean-Christophe,

> On 04:12 Mon 08 Jun     , Ilya Yanok wrote:
>> This patch adds support for i.MX27-LITEKIT development board from
>> LogicPD. This board uses i.MX27 SoC and has 2MB NOR flash, 64MB NAND
>> flash, FEC ethernet controller integrated into i.MX27.
>> 
>> Signed-off-by: Ilya Yanok <yanok@emcraft.com>
>> ---
>>  MAINTAINERS                             |    1 +
>>  MAKEALL                                 |    1 +
>>  Makefile                                |    3 +
>>  board/logicpd/imx27lite/Makefile        |   51 +++++++
>>  board/logicpd/imx27lite/config.mk       |    1 +
>>  board/logicpd/imx27lite/imx27lite.c     |   97 +++++++++++++
>>  board/logicpd/imx27lite/lowlevel_init.S |  223 +++++++++++++++++++++++++++++++
>>  board/logicpd/imx27lite/u-boot.lds      |   56 ++++++++
>>  include/configs/imx27lite.h             |  195 +++++++++++++++++++++++++++
>>  9 files changed, 628 insertions(+), 0 deletions(-)
>>  create mode 100644 board/logicpd/imx27lite/Makefile
>>  create mode 100644 board/logicpd/imx27lite/config.mk
>>  create mode 100644 board/logicpd/imx27lite/imx27lite.c
>>  create mode 100644 board/logicpd/imx27lite/lowlevel_init.S
>>  create mode 100644 board/logicpd/imx27lite/u-boot.lds
>>  create mode 100644 include/configs/imx27lite.h
>> 
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 3d50668..98efd69 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -519,6 +519,7 @@ George G. Davis <gdavis@mvista.com>
>>  	gcplus		SA1100
>>  
>>  Wolfgang Denk <wd@denx.de>
>> +	imx27lite	i.MX27
> Wolfgang could you ack it?

I ack that on behalf of Wolfgang.

Cheers
  Detlev

-- 
Markov does it in chains.
--
DENX Software Engineering GmbH,      MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich,  Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-40 Fax: (+49)-8142-66989-80 Email: dzu at denx.de

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

* [U-Boot] [PATCH 4/7] mxc_nand: add nand driver for MX2/MX3
  2009-06-22 23:43   ` Scott Wood
@ 2009-06-23 20:03     ` Magnus Lilja
  2009-07-03 19:03       ` Paul Thomas
  2009-07-17 10:48     ` Ilya Yanok
  1 sibling, 1 reply; 70+ messages in thread
From: Magnus Lilja @ 2009-06-23 20:03 UTC (permalink / raw)
  To: u-boot

Hi

2009/6/23 Scott Wood <scottwood@freescale.com>:
> On Mon, Jun 08, 2009 at 04:12:48AM +0400, Ilya Yanok wrote:
>> Driver for NFC NAND controller found on Freescale's MX2 and MX3
>> processors. Ported from Linux. Tested only with i.MX27 but should
>> works with other MX2 and MX3 processors too.
>>
>> Signed-off-by: Ilya Yanok <yanok@emcraft.com>
>> +static u_char mxc_nand_read_byte(struct mtd_info *mtd)
>> +{
>> + ? ? struct nand_chip *nand_chip = mtd->priv;
>> + ? ? struct mxc_nand_host *host = nand_chip->priv;
>> + ? ? uint8_t ret = 0;
>> + ? ? uint16_t col, rd_word;
>> + ? ? uint16_t __iomem *main_buf =
>> + ? ? ? ? ? ? (uint16_t __iomem *)host->regs->main_area0;
>> + ? ? uint16_t __iomem *spare_buf =
>> + ? ? ? ? ? ? (uint16_t __iomem *)host->regs->spare_area0;
>
> According to Magnus Lilja, "the nand flash controller can only handle 32
> bit read/write operations, any other size will cause an abort (or
> something like that)". ?But now we're accessing it as 16-bit?

I'm not sure if the controller allows 16 bit accesses or not, don't
remember if I've tried that. 8 bit accesses don't work. Also, I don't
know if it's the controller itself that can't cope with 8 bit accesses
or if it's the bus interface to the NFC block in i.MX31.

Regards, Magnus

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

* [U-Boot] [PATCH 5/7] mxc-mmc: sdhc host driver for MX2 and MX3 proccessor
  2009-06-08  0:12 ` [U-Boot] [PATCH 5/7] mxc-mmc: sdhc host driver for MX2 and MX3 proccessor Ilya Yanok
  2009-06-21 11:04   ` Jean-Christophe PLAGNIOL-VILLARD
@ 2009-06-23 23:02   ` alfred steele
  2009-08-07 20:13   ` Jean-Christophe PLAGNIOL-VILLARD
  2 siblings, 0 replies; 70+ messages in thread
From: alfred steele @ 2009-06-23 23:02 UTC (permalink / raw)
  To: u-boot

Hi Ilya,
> This is a port of Linux driver for SDHC host controller hardware
> found on Freescale's MX2 and MX3 processors. Uses new generic MMC
> framework (CONFIG_GENERIC_MMC) and it looks like there are some
> problems with a framework (at least on LE cpus). Some of these
> problems are addressed in the following patches.
Have you tested this driver interfaces to load a kernel image(uImage)
from the SD card? Does it work for you?
Thanks,
Alfred.

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

* [U-Boot] [PATCH 0/7][v3] Support for LogicPD i.MX27-LITEKIT development board
  2009-06-08  0:12 [U-Boot] [PATCH 0/7][v3] Support for LogicPD i.MX27-LITEKIT development board Ilya Yanok
                   ` (6 preceding siblings ...)
  2009-06-08  0:12 ` [U-Boot] [PATCH 7/7] imx27lite: add support for imx27lite board from LogicPD Ilya Yanok
@ 2009-06-28  9:52 ` Jean-Christophe PLAGNIOL-VILLARD
  7 siblings, 0 replies; 70+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2009-06-28  9:52 UTC (permalink / raw)
  To: u-boot

On 04:12 Mon 08 Jun     , Ilya Yanok wrote:
> This patch set adds support for LogicPD i.MX27-LITEKIT development board.
> It contains support for i.MX27 CPU, support for serial console, FEC
> ethernet controller, NFC NAND controller and SDHC controller.
> 
> Signed-off-by: Ilya Yanok <yanok@emcraft.com>
ping no news for this patch series?

Best Regards,
J.

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

* [U-Boot] [PATCH 4/7] mxc_nand: add nand driver for MX2/MX3
  2009-06-23 20:03     ` Magnus Lilja
@ 2009-07-03 19:03       ` Paul Thomas
  2009-07-03 19:11         ` Paul Thomas
  0 siblings, 1 reply; 70+ messages in thread
From: Paul Thomas @ 2009-07-03 19:03 UTC (permalink / raw)
  To: u-boot

Hello,

I'm using the imx27lite-v2 branch for our opensource imx27 board. Right now
I'm trying to get the nand to work. I'm using a Micron 2Gb x8 part (p/n
MT29F2G08ABDHC). When I do "nand info" I get "Device 0: NAND 256MiB 1,8V
8-bit, sector size 128 KiB" which is correct. mtdparts returns:

device nand0 <mxc_nand.0>, # parts = 4
 #: name                size            offset          mask_flags
 0: IPL-SPL             0x00040000      0x00000000      0
 1: kernel              0x00200000      0x00040000      0
 2: rootfs              0x00b00000      0x00240000      0
 3: userfs              0x0f2c0000      0x00d40000      0

active partition: nand0,0 - (IPL-SPL) 0x00040000 @ 0x00000000

defaults:
mtdids  : nor0=physmap-flash.0,nand0=mxc_nand.0
mtdparts: mtdparts=mxc_nand.0:256k(IPL-SPL),2m(kernel),11m(rootfs),-(userfs)


But when I do other commands like fsinfo or ls I get "read_nand_cached:
error reading nand off 0x2000 size 8192 bytes" errors.

My questions are: should the current driver support this chip? Do I need to
do anything else to prepare the mtd partitions? Is there a low level test I
could run on the NAND?

thanks,
Paul

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

* [U-Boot] [PATCH 4/7] mxc_nand: add nand driver for MX2/MX3
  2009-07-03 19:03       ` Paul Thomas
@ 2009-07-03 19:11         ` Paul Thomas
  0 siblings, 0 replies; 70+ messages in thread
From: Paul Thomas @ 2009-07-03 19:11 UTC (permalink / raw)
  To: u-boot

On Fri, Jul 3, 2009 at 12:03 PM, Paul Thomas <pthomas8589@gmail.com> wrote:

> Hello,
>
> I'm using the imx27lite-v2 branch for our opensource imx27 board. Right now
> I'm trying to get the nand to work. I'm using a Micron 2Gb x8 part (p/n
> MT29F2G08ABDHC). When I do "nand info" I get "Device 0: NAND 256MiB 1,8V
> 8-bit, sector size 128 KiB" which is correct. mtdparts returns:
>
> device nand0 <mxc_nand.0>, # parts = 4
>  #: name                size            offset          mask_flags
>  0: IPL-SPL             0x00040000      0x00000000      0
>  1: kernel              0x00200000      0x00040000      0
>  2: rootfs              0x00b00000      0x00240000      0
>  3: userfs              0x0f2c0000      0x00d40000      0
>
> active partition: nand0,0 - (IPL-SPL) 0x00040000 @ 0x00000000
>
> defaults:
> mtdids  : nor0=physmap-flash.0,nand0=mxc_nand.0
> mtdparts:
> mtdparts=mxc_nand.0:256k(IPL-SPL),2m(kernel),11m(rootfs),-(userfs)
>
>
> But when I do other commands like fsinfo or ls I get "read_nand_cached:
> error reading nand off 0x2000 size 8192 bytes" errors.
>
> My questions are: should the current driver support this chip? Do I need to
> do anything else to prepare the mtd partitions? Is there a low level test I
> could run on the NAND?
>
> thanks,
> Paul
>

Also "nand bad" reports that all the blocks are bad, and if I do "nand
scrub" it says "Erasing at 0xffe0000 -- 100% complete.
OK", but "nand bad" still returns that all the blocks are bad.

thanks,
Paul

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

* [U-Boot] [PATCH 7/7] imx27lite: add support for imx27lite board from LogicPD
  2009-06-21 11:21   ` Jean-Christophe PLAGNIOL-VILLARD
  2009-06-23 16:55     ` Detlev Zundel
@ 2009-07-07 19:24     ` Wolfgang Denk
  2009-07-17 11:00     ` [U-Boot] [PATCH] " Ilya Yanok
  2 siblings, 0 replies; 70+ messages in thread
From: Wolfgang Denk @ 2009-07-07 19:24 UTC (permalink / raw)
  To: u-boot

Dear Jean-Christophe PLAGNIOL-VILLARD,

In message <20090621112124.GH22845@game.jcrosoft.org> you wrote:
>
> >  Wolfgang Denk <wd@denx.de>
> > +	imx27lite	i.MX27
> Wolfgang could you ack it?
> >  	qong		i.MX31

Yes, that's ok with me.

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
Anyone who isn't confused here doesn't really know what's going on.

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

* [U-Boot] [PATCH 4/7] mxc_nand: add nand driver for MX2/MX3
  2009-06-22 23:43   ` Scott Wood
  2009-06-23 20:03     ` Magnus Lilja
@ 2009-07-17 10:48     ` Ilya Yanok
  2009-07-17 10:53       ` [U-Boot] [PATCH] " Ilya Yanok
  2009-07-17 16:00       ` [U-Boot] [PATCH 4/7] " Scott Wood
  1 sibling, 2 replies; 70+ messages in thread
From: Ilya Yanok @ 2009-07-17 10:48 UTC (permalink / raw)
  To: u-boot

Hi Scott,

please review the updated patch (will be posted as a follow-up).

Scott Wood wrote:
> Please look at drivers/mtd/nand/mpc5121_nfc.c, which AFAICT is very
> similar hardware, and see if anything can be factored out into common
> code, and try to keep the rest looking the same except where the hardware
> actually differs.
>   

Hmm... For now we just can't spend enough effort for this...

>> +static struct nand_ecclayout nand_hw_eccoob_16 = {
>> +	.eccbytes = 5,
>> +	.eccpos = {6, 7, 8, 9, 10},
>> +	.oobfree = {{0, 6}, {12, 4}, }
>> +};
>>     
>
> This implies the bad block marker is one byte at offset 11 (it's all
> that's left), but I don't see any override of the bad block pattern.
>   

This is surely a bug. Fixed.

>> +static void *mxc_nand_memcpy32(void *dest, void *source, size_t size)
>> +{
>> +	uint32_t *s = source, *d = dest;
>> +
>> +	size >>= 2;
>> +	while (size--)
>> +		*d++ = *s++;
>> +	return dest;
>> +}
>>     
>
> This should probably be using I/O accessors (possibly raw) -- and should
> take uint32_t *, not void *.
>   

Fixed.

>> +/*
>> + * This function requests the NANDFC to perform a read of the
>> + * NAND device status and returns the current status.
>> + */
>> +static uint16_t get_dev_status(struct mxc_nand_host *host)
>> +{
>> +	void __iomem *main_buf = host->regs->main_area1;
>> +	uint32_t store;
>> +	uint16_t ret, tmp;
>> +	/* Issue status request to NAND device */
>> +
>> +	/* store the main area1 first word, later do recovery */
>> +	store = readl(main_buf);
>> +	/*
>> +	 * NANDFC buffer 1 is used for device status to prevent
>> +	 * corruption of read/write buffer on status requests.
>> +	 */
>> +	writew(1, &host->regs->nfc_buf_addr);
>>     
>
> But it looks like buffer 1 is used for data with large page flash.
>   

Well, we save first word of the buffer and then recover it.

> Other drivers don't seem to have any problem with status reads clobbering
> the buffer...
>
>   
>> +/* This functions is used by upper layer to checks if device is ready */
>> +static int mxc_nand_dev_ready(struct mtd_info *mtd)
>>     
>
> "This functions is"?  I'd say this comment is pretty redundant with respect
> to the function name anyway...
>   

Fixed.

>> +static u_char mxc_nand_read_byte(struct mtd_info *mtd)
>> +{
>> +	struct nand_chip *nand_chip = mtd->priv;
>> +	struct mxc_nand_host *host = nand_chip->priv;
>> +	uint8_t ret = 0;
>> +	uint16_t col, rd_word;
>> +	uint16_t __iomem *main_buf =
>> +		(uint16_t __iomem *)host->regs->main_area0;
>> +	uint16_t __iomem *spare_buf =
>> +		(uint16_t __iomem *)host->regs->spare_area0;
>>     
>
> According to Magnus Lilja, "the nand flash controller can only handle 32
> bit read/write operations, any other size will cause an abort (or
> something like that)".  But now we're accessing it as 16-bit?
>   

16-bit accesses work quite well. Problem was with 8-bit accesses.

>> +static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
>> +{
>> +	struct nand_chip *nand_chip = mtd->priv;
>> +	struct mxc_nand_host *host = nand_chip->priv;
>> +	uint16_t col, rd_word, ret;
>> +	uint16_t __iomem *p;
>> +
>> +	MTDDEBUG(MTD_DEBUG_LEVEL3,
>> +	      "mxc_nand_read_word(col = %d)\n", host->col_addr);
>> +
>> +	col = host->col_addr;
>> +	/* Adjust saved column address */
>> +	if (col < mtd->writesize && host->spare_only)
>> +		col += mtd->writesize;
>> +
>> +	if (col < mtd->writesize) {
>> +		p = (uint16_t __iomem *)(host->regs->main_area0 + (col >> 1));
>> +	} else {
>> +		p = (uint16_t __iomem *)(host->regs->spare_area0 +
>> +				((col - mtd->writesize) >> 1));
>> +	}
>> +
>> +	if (col & 1) {
>> +		rd_word = readw(p);
>> +		ret = (rd_word >> 8) & 0xff;
>> +		rd_word = readw(&p[1]);
>> +		ret |= (rd_word << 8) & 0xff00;
>> +
>>     
>
> col should never be odd if you're reading words.
>   

It can be odd if previously we've read a byte.

>> +/*
>> + * Write data of length len to buffer buf. The data to be
>> + * written on NAND Flash is first copied to RAMbuffer. After the Data Input
>> + * Operation by the NFC, the data is written to NAND Flash
>> + */
>> +static void mxc_nand_write_buf(struct mtd_info *mtd,
>> +				const u_char *buf, int len)
>> +{
>> +	struct nand_chip *nand_chip = mtd->priv;
>> +	struct mxc_nand_host *host = nand_chip->priv;
>> +	int n, col, i = 0;
>> +
>> +	MTDDEBUG(MTD_DEBUG_LEVEL3,
>> +	      "mxc_nand_write_buf(col = %d, len = %d)\n", host->col_addr,
>> +	      len);
>> +
>> +	col = host->col_addr;
>> +
>> +	/* Adjust saved column address */
>> +	if (col < mtd->writesize && host->spare_only)
>> +		col += mtd->writesize;
>> +
>> +	n = mtd->writesize + mtd->oobsize - col;
>> +	n = min(len, n);
>> +
>> +	MTDDEBUG(MTD_DEBUG_LEVEL3,
>> +	      "%s:%d: col = %d, n = %d\n", __func__, __LINE__, col, n);
>> +
>> +	while (n) {
>>     
>
> Safer to do while (n > 0), especially when the code is this complex.
>   

Fixed.

>> +		void __iomem *p;
>> +
>> +		if (col < mtd->writesize) {
>> +			p = host->regs->main_area0 + (col & ~3);
>> +		} else {
>> +			p = host->regs->spare_area0 -
>> +						mtd->writesize + (col & ~3);
>> +		}
>> +
>> +		MTDDEBUG(MTD_DEBUG_LEVEL3, "%s:%d: p = %p\n", __func__,
>> +		      __LINE__, p);
>> +
>> +		if (((col | (int)&buf[i]) & 3) || n < 16) {
>>     
>
> Do not cast pointers to "int".  Use "uintptr_t" or "unsigned long" if you
> must.
>
> Why < 16 and not < 4?
>   

Fixed.

>> +			uint32_t data = 0;
>> +
>> +			if (col & 3 || n < 4)
>> +				data = readl(p);
>>     
>
> If that condition doesn't hold, the data we use is zero?
>   

If that condition doesn't hold we are going to rewrite a whole 32-bit
word so there is no need to read it's old content. But I've changed that
piece of code as you suggested anyway.

>> +
>> +			switch (col & 3) {
>> +			case 0:
>> +				if (n) {
>> +					data = (data & 0xffffff00) |
>> +					    (buf[i++] << 0);
>> +					n--;
>> +					col++;
>> +				}
>> +			case 1:
>> +				if (n) {
>> +					data = (data & 0xffff00ff) |
>> +					    (buf[i++] << 8);
>> +					n--;
>> +					col++;
>> +				}
>> +			case 2:
>> +				if (n) {
>> +					data = (data & 0xff00ffff) |
>> +					    (buf[i++] << 16);
>> +					n--;
>> +					col++;
>> +				}
>> +			case 3:
>> +				if (n) {
>> +					data = (data & 0x00ffffff) |
>> +					    (buf[i++] << 24);
>> +					n--;
>> +					col++;
>> +				}
>> +			}
>> +			writel(data, p);
>>     
>
> Might I suggest this?
>
> union {
> 	uint32_t word;
> 	uint8_t bytes[4];
> } nfc_word;
>
> nfc_word.word = readl(p);
> nfc_word.bytes[col & 3] = buf[i++];
> n--;
> col++;
>
> writel(nfc_word.word, p);
>
> As a side benefit, you lose the endian dependency.
>   

Thanks! I've used your code.

>> +			mxc_nand_memcpy32(p, (void *)&buf[i], m);
>>     
>
> Unnecessary cast.
>   

Fixed.

>> +	/* Update saved column address */
>> +	host->col_addr = col;
>> +
>> +}
>>     
>
> No blank lines before the brace at the end of a block.
>   

Fixed.

>> +
>> +/*
>> + * Used by the upper layer to verify the data in NAND Flash
>> + * with the data in the buf.
>> + */
>> +static int mxc_nand_verify_buf(struct mtd_info *mtd,
>> +				const u_char *buf, int len)
>> +{
>> +	return -EFAULT;
>> +}
>>     
>
> Umm...
>   

I've added verify_buf function.

>> +	case NAND_CMD_SEQIN:
>> +		if (column >= mtd->writesize) {
>> +			/*
>> +			 * FIXME: before send SEQIN command for write OOB,
>> +			 * We must read one page out.
>> +			 * For K9F1GXX has no READ1 command to set current HW
>> +			 * pointer to spare area, we must write the whole page
>> +			 * including OOB together.
>> +			 */
>> +			if (host->pagesize_2k) {
>> +				/* call ourself to read a page */
>> +				mxc_nand_command(mtd, NAND_CMD_READ0, 0,
>> +						page_addr);
>> +			}
>>     
>
> Should this be #ifdef HWECC?  And update the comment to indicate the
> actual problem, which is the unusual hardware ECC implementation.  I
> don't see what the lack of a "READ1" command has to do with it.
>   

I've updated the comment.

> And is this actually a FIXME if it's already being done?
>
>   
>> +#ifdef CONFIG_MXC_NAND_HWECC
>> +	this->ecc.calculate = mxc_nand_calculate_ecc;
>> +	this->ecc.hwctl = mxc_nand_enable_hwecc;
>> +	this->ecc.correct = mxc_nand_correct_data;
>> +	this->ecc.mode = NAND_ECC_HW;
>> +	this->ecc.size = 512;
>> +	this->ecc.bytes = 3;
>> +	this->ecc.layout = &nand_hw_eccoob_8;
>> +	tmp = readw(&host->regs->nfc_config1);
>> +	tmp |= NFC_ECC_EN;
>> +	writew(tmp, &host->regs->nfc_config1);
>> +#else
>> +	this->ecc.size = 512;
>> +	this->ecc.bytes = 3;
>> +	this->ecc.layout = &nand_hw_eccoob_8;
>> +	this->ecc.mode = NAND_ECC_SOFT;
>> +	tmp = readw(&host->regs->nfc_config1);
>> +	tmp &= ~NFC_ECC_EN;
>> +	writew(tmp, &host->regs->nfc_config1);
>> +#endif
>>     
>
> Soft ECC only supports 256-byte ECC blocks (anything you set here to the
> contrary will just be overwritten), and you'll need a layout that
> accommodates that with enough ECC bytes.
>
> Alternatively, you can implement 512-byte soft ECC if you don't want to
> waste those 3 extra OOB bytes. :-)
>
>   
>> +	host->pagesize_2k = 0;
>>     
>
> So large page is currently unsupported?
>   

Linux driver was fixed recently and now it claims to support 2K page
size... I've added all needed fixes but I can understand how this driver
should detect the pagesize... Linux driver calls nand_scan_ident()
itself for this... Do you think I can calls nand_scan_ident() from my
board_nand_init() function?

Regards, Ilya.

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

* [U-Boot] [PATCH] mxc_nand: add nand driver for MX2/MX3
  2009-07-17 10:48     ` Ilya Yanok
@ 2009-07-17 10:53       ` Ilya Yanok
  2009-07-22 21:33         ` Jean-Christophe PLAGNIOL-VILLARD
  2009-07-28 22:37         ` Scott Wood
  2009-07-17 16:00       ` [U-Boot] [PATCH 4/7] " Scott Wood
  1 sibling, 2 replies; 70+ messages in thread
From: Ilya Yanok @ 2009-07-17 10:53 UTC (permalink / raw)
  To: u-boot

Driver for NFC NAND controller found on Freescale's MX2 and MX3
processors. Ported from Linux. Tested only with i.MX27 but should
works with other MX2 and MX3 processors too.

Signed-off-by: Ilya Yanok <yanok@emcraft.com>
---
 drivers/mtd/nand/Makefile   |    1 +
 drivers/mtd/nand/mxc_nand.c |  902 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 903 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/nand/mxc_nand.c

diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index a5680e8..e068676 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -42,6 +42,7 @@ COBJS-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_nand.o
 COBJS-$(CONFIG_NAND_FSL_UPM) += fsl_upm.o
 COBJS-$(CONFIG_NAND_KIRKWOOD) += kirkwood_nand.o
 COBJS-$(CONFIG_NAND_MPC5121_NFC) += mpc5121_nfc.o
+COBJS-$(CONFIG_NAND_MXC) += mxc_nand.o
 COBJS-$(CONFIG_NAND_NOMADIK) += nomadik.o
 COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o
 COBJS-$(CONFIG_NAND_S3C64XX) += s3c64xx.o
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
new file mode 100644
index 0000000..853c718
--- /dev/null
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -0,0 +1,902 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Sascha Hauer, kernel at pengutronix.de
+ * Copyright 2009 Ilya Yanok, <yanok@emcraft.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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <common.h>
+#include <nand.h>
+#include <linux/err.h>
+#include <asm/io.h>
+#ifdef CONFIG_MX27
+#include <asm/arch/imx-regs.h>
+#endif
+
+#define DRIVER_NAME "mxc_nand"
+
+struct nfc_regs {
+/* NFC RAM BUFFER Main area 0 */
+	uint8_t main_area0[0x200];
+	uint8_t main_area1[0x200];
+	uint8_t main_area2[0x200];
+	uint8_t main_area3[0x200];
+/* SPARE BUFFER Spare area 0 */
+	uint8_t spare_area0[0x10];
+	uint8_t spare_area1[0x10];
+	uint8_t spare_area2[0x10];
+	uint8_t spare_area3[0x10];
+	uint8_t pad[0x5c0];
+/* NFC registers */
+	uint16_t nfc_buf_size;
+	uint16_t reserved;
+	uint16_t nfc_buf_addr;
+	uint16_t nfc_flash_addr;
+	uint16_t nfc_flash_cmd;
+	uint16_t nfc_config;
+	uint16_t nfc_ecc_status_result;
+	uint16_t nfc_rsltmain_area;
+	uint16_t nfc_rsltspare_area;
+	uint16_t nfc_wrprot;
+	uint16_t nfc_unlockstart_blkaddr;
+	uint16_t nfc_unlockend_blkaddr;
+	uint16_t nfc_nf_wrprst;
+	uint16_t nfc_config1;
+	uint16_t nfc_config2;
+};
+
+/*
+ * Set INT to 0, FCMD to 1, rest to 0 in NFC_CONFIG2 Register
+ * for Command operation
+ */
+#define NFC_CMD            0x1
+
+/*
+ * Set INT to 0, FADD to 1, rest to 0 in NFC_CONFIG2 Register
+ * for Address operation
+ */
+#define NFC_ADDR           0x2
+
+/*
+ * Set INT to 0, FDI to 1, rest to 0 in NFC_CONFIG2 Register
+ * for Input operation
+ */
+#define NFC_INPUT          0x4
+
+/*
+ * Set INT to 0, FDO to 001, rest to 0 in NFC_CONFIG2 Register
+ * for Data Output operation
+ */
+#define NFC_OUTPUT         0x8
+
+/*
+ * Set INT to 0, FD0 to 010, rest to 0 in NFC_CONFIG2 Register
+ * for Read ID operation
+ */
+#define NFC_ID             0x10
+
+/*
+ * Set INT to 0, FDO to 100, rest to 0 in NFC_CONFIG2 Register
+ * for Read Status operation
+ */
+#define NFC_STATUS         0x20
+
+/*
+ * Set INT to 1, rest to 0 in NFC_CONFIG2 Register for Read
+ * Status operation
+ */
+#define NFC_INT            0x8000
+
+#define NFC_SP_EN           (1 << 2)
+#define NFC_ECC_EN          (1 << 3)
+#define NFC_BIG             (1 << 5)
+#define NFC_RST             (1 << 6)
+#define NFC_CE              (1 << 7)
+#define NFC_ONE_CYCLE       (1 << 8)
+
+typedef enum {false, true} bool;
+
+struct mxc_nand_host {
+	struct mtd_info		mtd;
+	struct nand_chip	*nand;
+
+	struct nfc_regs __iomem	*regs;
+	int			spare_only;
+	int			status_request;
+	int			pagesize_2k;
+	int			clk_act;
+	uint16_t		col_addr;
+};
+
+static struct mxc_nand_host mxc_host;
+static struct mxc_nand_host *host = &mxc_host;
+
+/* Define delays in microsec for NAND device operations */
+#define TROP_US_DELAY   2000
+/* Macros to get byte and bit positions of ECC */
+#define COLPOS(x)  ((x) >> 3)
+#define BITPOS(x) ((x) & 0xf)
+
+/* Define single bit Error positions in Main & Spare area */
+#define MAIN_SINGLEBIT_ERROR 0x4
+#define SPARE_SINGLEBIT_ERROR 0x1
+
+/* OOB placement block for use with hardware ecc generation */
+static struct nand_ecclayout nand_hw_eccoob = {
+	.eccbytes = 5,
+	.eccpos = {6, 7, 8, 9, 10},
+	.oobfree = {{0, 5}, {11, 5}, }
+};
+
+#ifndef CONFIG_MXC_NAND_HWECC
+static struct nand_ecclayout nand_hw_eccoob_soft = {
+	.eccbytes = 6,
+	.eccpos = {6, 7, 8, 9, 10, 11},
+	.oobfree = {{0, 5}, {12, 4}, }
+};
+#endif
+
+static uint32_t *mxc_nand_memcpy32(uint32_t *dest, uint32_t *source, size_t size)
+{
+	uint32_t *d = dest;
+
+	size >>= 2;
+	while (size--)
+		__raw_writel(__raw_readl(source++), d++);
+	return dest;
+}
+
+/*
+ * This function polls the NANDFC to wait for the basic operation to
+ * complete by checking the INT bit of config2 register.
+ */
+static void wait_op_done(struct mxc_nand_host *host, int max_retries,
+				uint16_t param)
+{
+	uint32_t tmp;
+
+	while (max_retries-- > 0) {
+		if (readw(&host->regs->nfc_config2) & NFC_INT) {
+			tmp = readw(&host->regs->nfc_config2);
+			tmp  &= ~NFC_INT;
+			writew(tmp, &host->regs->nfc_config2);
+			break;
+		}
+		udelay(1);
+	}
+	if (max_retries < 0) {
+		MTDDEBUG(MTD_DEBUG_LEVEL0, "%s(%d): INT not set\n",
+				__func__, param);
+	}
+}
+
+/*
+ * This function issues the specified command to the NAND device and
+ * waits for completion.
+ */
+static void send_cmd(struct mxc_nand_host *host, uint16_t cmd)
+{
+	MTDDEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x)\n", cmd);
+
+	writew(cmd, &host->regs->nfc_flash_cmd);
+	writew(NFC_CMD, &host->regs->nfc_config2);
+
+	/* Wait for operation to complete */
+	wait_op_done(host, TROP_US_DELAY, cmd);
+}
+
+/*
+ * This function sends an address (or partial address) to the
+ * NAND device. The address is used to select the source/destination for
+ * a NAND command.
+ */
+static void send_addr(struct mxc_nand_host *host, uint16_t addr)
+{
+	MTDDEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x)\n", addr);
+
+	writew(addr, &host->regs->nfc_flash_addr);
+	writew(NFC_ADDR, &host->regs->nfc_config2);
+
+	/* Wait for operation to complete */
+	wait_op_done(host, TROP_US_DELAY, addr);
+}
+
+/*
+ * This function requests the NANDFC to initate the transfer
+ * of data currently in the NANDFC RAM buffer to the NAND device.
+ */
+static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id,
+			int spare_only)
+{
+	MTDDEBUG(MTD_DEBUG_LEVEL3, "send_prog_page (%d)\n", spare_only);
+
+	/* NANDFC buffer 0 is used for page read/write */
+	writew(buf_id, &host->regs->nfc_buf_addr);
+
+	/* Configure spare or page+spare access */
+	if (!host->pagesize_2k) {
+		uint16_t config1 = readw(&host->regs->nfc_config1);
+		if (spare_only)
+			config1 |= NFC_SP_EN;
+		else
+			config1 &= ~(NFC_SP_EN);
+		writew(config1, &host->regs->nfc_config1);
+	}
+
+	writew(NFC_INPUT, &host->regs->nfc_config2);
+
+	/* Wait for operation to complete */
+	wait_op_done(host, TROP_US_DELAY, spare_only);
+}
+
+/*
+ * Requests NANDFC to initated the transfer of data from the
+ * NAND device into in the NANDFC ram buffer.
+ */
+static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id,
+		int spare_only)
+{
+	MTDDEBUG(MTD_DEBUG_LEVEL3, "send_read_page (%d)\n", spare_only);
+
+	/* NANDFC buffer 0 is used for page read/write */
+	writew(buf_id, &host->regs->nfc_buf_addr);
+
+	/* Configure spare or page+spare access */
+	if (!host->pagesize_2k) {
+		uint32_t config1 = readw(&host->regs->nfc_config1);
+		if (spare_only)
+			config1 |= NFC_SP_EN;
+		else
+			config1 &= ~NFC_SP_EN;
+		writew(config1, &host->regs->nfc_config1);
+	}
+
+	writew(NFC_OUTPUT, &host->regs->nfc_config2);
+
+	/* Wait for operation to complete */
+	wait_op_done(host, TROP_US_DELAY, spare_only);
+}
+
+/* Request the NANDFC to perform a read of the NAND device ID. */
+static void send_read_id(struct mxc_nand_host *host)
+{
+	struct nand_chip *this = host->nand;
+	uint16_t tmp;
+
+	/* NANDFC buffer 0 is used for device ID output */
+	writew(0x0, &host->regs->nfc_buf_addr);
+
+	/* Read ID into main buffer */
+	tmp = readw(&host->regs->nfc_config1);
+	tmp &= ~NFC_SP_EN;
+	writew(tmp, &host->regs->nfc_config1);
+
+	writew(NFC_ID, &host->regs->nfc_config2);
+
+	/* Wait for operation to complete */
+	wait_op_done(host, TROP_US_DELAY, 0);
+
+	if (this->options & NAND_BUSWIDTH_16) {
+		void __iomem *main_buf = host->regs->main_area0;
+		/* compress the ID info */
+		writeb(readb(main_buf + 2), main_buf + 1);
+		writeb(readb(main_buf + 4), main_buf + 2);
+		writeb(readb(main_buf + 6), main_buf + 3);
+		writeb(readb(main_buf + 8), main_buf + 4);
+		writeb(readb(main_buf + 10), main_buf + 5);
+	}
+}
+
+/*
+ * This function requests the NANDFC to perform a read of the
+ * NAND device status and returns the current status.
+ */
+static uint16_t get_dev_status(struct mxc_nand_host *host)
+{
+	void __iomem *main_buf = host->regs->main_area1;
+	uint32_t store;
+	uint16_t ret, tmp;
+	/* Issue status request to NAND device */
+
+	/* store the main area1 first word, later do recovery */
+	store = readl(main_buf);
+	/*
+	 * NANDFC buffer 1 is used for device status to prevent
+	 * corruption of read/write buffer on status requests.
+	 */
+	writew(1, &host->regs->nfc_buf_addr);
+
+	/* Read status into main buffer */
+	tmp = readw(&host->regs->nfc_config1);
+	tmp &= ~NFC_SP_EN;
+	writew(tmp, &host->regs->nfc_config1);
+
+	writew(NFC_STATUS, &host->regs->nfc_config2);
+
+	/* Wait for operation to complete */
+	wait_op_done(host, TROP_US_DELAY, 0);
+
+	/*
+	 *  Status is placed in first word of main buffer
+	 * get status, then recovery area 1 data
+	 */
+	ret = readw(main_buf);
+	writel(store, main_buf);
+
+	return ret;
+}
+
+/* This function is used by upper layer to checks if device is ready */
+static int mxc_nand_dev_ready(struct mtd_info *mtd)
+{
+	/*
+	 * NFC handles R/B internally. Therefore, this function
+	 * always returns status as ready.
+	 */
+	return 1;
+}
+
+#ifdef CONFIG_MXC_NAND_HWECC
+static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
+{
+	/*
+	 * If HW ECC is enabled, we turn it on during init. There is
+	 * no need to enable again here.
+	 */
+}
+
+static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
+				 u_char *read_ecc, u_char *calc_ecc)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+
+	/*
+	 * 1-Bit errors are automatically corrected in HW.  No need for
+	 * additional correction.  2-Bit errors cannot be corrected by
+	 * HW ECC, so we need to return failure
+	 */
+	uint16_t ecc_status = readw(&host->regs->nfc_ecc_status_result);
+
+	if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
+		MTDDEBUG(MTD_DEBUG_LEVEL0,
+		      "MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
+				  u_char *ecc_code)
+{
+	return 0;
+}
+#endif
+
+static u_char mxc_nand_read_byte(struct mtd_info *mtd)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+	uint8_t ret = 0;
+	uint16_t col, rd_word;
+	uint16_t __iomem *main_buf =
+		(uint16_t __iomem *)host->regs->main_area0;
+	uint16_t __iomem *spare_buf =
+		(uint16_t __iomem *)host->regs->spare_area0;
+
+	/* Check for status request */
+	if (host->status_request)
+		return get_dev_status(host) & 0xFF;
+
+	/* Get column for 16-bit access */
+	col = host->col_addr >> 1;
+
+	/* If we are accessing the spare region */
+	if (host->spare_only)
+		rd_word = readw(&spare_buf[col]);
+	else
+		rd_word = readw(&main_buf[col]);
+
+	/* Pick upper/lower byte of word from RAM buffer */
+	if (host->col_addr & 0x1)
+		ret = (rd_word >> 8) & 0xFF;
+	else
+		ret = rd_word & 0xFF;
+
+	/* Update saved column address */
+	host->col_addr++;
+
+	return ret;
+}
+
+static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+	uint16_t col, rd_word, ret;
+	uint16_t __iomem *p;
+
+	MTDDEBUG(MTD_DEBUG_LEVEL3,
+	      "mxc_nand_read_word(col = %d)\n", host->col_addr);
+
+	col = host->col_addr;
+	/* Adjust saved column address */
+	if (col < mtd->writesize && host->spare_only)
+		col += mtd->writesize;
+
+	if (col < mtd->writesize) {
+		p = (uint16_t __iomem *)(host->regs->main_area0 + (col >> 1));
+	} else {
+		p = (uint16_t __iomem *)(host->regs->spare_area0 +
+				((col - mtd->writesize) >> 1));
+	}
+
+	if (col & 1) {
+		rd_word = readw(p);
+		ret = (rd_word >> 8) & 0xff;
+		rd_word = readw(&p[1]);
+		ret |= (rd_word << 8) & 0xff00;
+
+	} else {
+		ret = readw(p);
+	}
+
+	/* Update saved column address */
+	host->col_addr = col + 2;
+
+	return ret;
+}
+
+/*
+ * Write data of length len to buffer buf. The data to be
+ * written on NAND Flash is first copied to RAMbuffer. After the Data Input
+ * Operation by the NFC, the data is written to NAND Flash
+ */
+static void mxc_nand_write_buf(struct mtd_info *mtd,
+				const u_char *buf, int len)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+	int n, col, i = 0;
+
+	MTDDEBUG(MTD_DEBUG_LEVEL3,
+	      "mxc_nand_write_buf(col = %d, len = %d)\n", host->col_addr,
+	      len);
+
+	col = host->col_addr;
+
+	/* Adjust saved column address */
+	if (col < mtd->writesize && host->spare_only)
+		col += mtd->writesize;
+
+	n = mtd->writesize + mtd->oobsize - col;
+	n = min(len, n);
+
+	MTDDEBUG(MTD_DEBUG_LEVEL3,
+	      "%s:%d: col = %d, n = %d\n", __func__, __LINE__, col, n);
+
+	while (n > 0) {
+		void __iomem *p;
+
+		if (col < mtd->writesize) {
+			p = host->regs->main_area0 + (col & ~3);
+		} else {
+			p = host->regs->spare_area0 -
+						mtd->writesize + (col & ~3);
+		}
+
+		MTDDEBUG(MTD_DEBUG_LEVEL3, "%s:%d: p = %p\n", __func__,
+		      __LINE__, p);
+
+		if (((col | (unsigned long)&buf[i]) & 3) || n < 4) {
+			union {
+				uint32_t word;
+				uint8_t bytes[4];
+			} nfc_word;
+
+			nfc_word.word = readl(p);
+			nfc_word.bytes[col & 3] = buf[i++];
+			n--;
+			col++;
+
+			writel(nfc_word.word, p);
+		} else {
+			int m = mtd->writesize - col;
+
+			if (col >= mtd->writesize)
+				m += mtd->oobsize;
+
+			m = min(n, m) & ~3;
+
+			MTDDEBUG(MTD_DEBUG_LEVEL3,
+			      "%s:%d: n = %d, m = %d, i = %d, col = %d\n",
+			      __func__,  __LINE__, n, m, i, col);
+
+			mxc_nand_memcpy32(p, (uint32_t *)&buf[i], m);
+			col += m;
+			i += m;
+			n -= m;
+		}
+	}
+	/* Update saved column address */
+	host->col_addr = col;
+}
+
+/*
+ * Read the data buffer from the NAND Flash. To read the data from NAND
+ * Flash first the data output cycle is initiated by the NFC, which copies
+ * the data to RAMbuffer. This data of length len is then copied to buffer buf.
+ */
+static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+	int n, col, i = 0;
+
+	MTDDEBUG(MTD_DEBUG_LEVEL3,
+	      "mxc_nand_read_buf(col = %d, len = %d)\n", host->col_addr, len);
+
+	col = host->col_addr;
+
+	/* Adjust saved column address */
+	if (col < mtd->writesize && host->spare_only)
+		col += mtd->writesize;
+
+	n = mtd->writesize + mtd->oobsize - col;
+	n = min(len, n);
+
+	while (n > 0) {
+		void __iomem *p;
+
+		if (col < mtd->writesize) {
+			p = host->regs->main_area0 + (col & ~3);
+		} else {
+			p = host->regs->spare_area0 -
+					mtd->writesize + (col & ~3);
+		}
+
+		if (((col | (int)&buf[i]) & 3) || n < 4) {
+			union {
+				uint32_t word;
+				uint8_t bytes[4];
+			} nfc_word;
+
+			nfc_word.word = readl(p);
+			buf[i++] = nfc_word.bytes[col & 3];
+			n--;
+			col++;
+		} else {
+			int m = mtd->writesize - col;
+
+			if (col >= mtd->writesize)
+				m += mtd->oobsize;
+
+			m = min(n, m) & ~3;
+			mxc_nand_memcpy32((uint32_t *)&buf[i], p, m);
+
+			col += m;
+			i += m;
+			n -= m;
+		}
+	}
+	/* Update saved column address */
+	host->col_addr = col;
+}
+
+/*
+ * Used by the upper layer to verify the data in NAND Flash
+ * with the data in the buf.
+ */
+static int mxc_nand_verify_buf(struct mtd_info *mtd,
+				const u_char *buf, int len)
+{
+	u_char tmp[256];
+	uint bsize;
+
+	while (len) {
+		bsize = min(len, 256);
+		mxc_nand_read_buf(mtd, tmp, bsize);
+
+		if (memcmp(buf, tmp, bsize))
+			return 1;
+
+		buf += bsize;
+		len -= bsize;
+	}
+
+	return 0;
+}
+
+/*
+ * This function is used by upper layer for select and
+ * deselect of the NAND chip
+ */
+static void mxc_nand_select_chip(struct mtd_info *mtd, int chip)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+
+#ifdef CONFIG_MTD_NAND_MXC_FORCE_CE
+	if (chip > 0) {
+		MTDDEBUG(MTD_DEBUG_LEVEL0,
+		      "ERROR:  Illegal chip select (chip = %d)\n", chip);
+		return;
+	}
+
+	if (chip == -1) {
+		writew(readw(&host->regs->nfc_config1) & ~NFC_CE,
+				&host->regs->nfc_config1);
+		return;
+	}
+
+	writew(readw(&host->regs->nfc_config1) | NFC_CE,
+			&host->regs->nfc_config1);
+#endif
+
+	switch (chip) {
+	case -1:
+		/* TODO: Disable the NFC clock */
+		if (host->clk_act)
+			host->clk_act = 0;
+		break;
+	case 0:
+		/* TODO: Enable the NFC clock */
+		if (!host->clk_act)
+			host->clk_act = 1;
+		break;
+
+	default:
+		break;
+	}
+}
+
+/*
+ * Used by the upper layer to write command to NAND Flash for
+ * different operations to be carried out on NAND Flash
+ */
+static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
+				int column, int page_addr)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+
+	MTDDEBUG(MTD_DEBUG_LEVEL3,
+	      "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
+	      command, column, page_addr);
+
+	/* Reset command state information */
+	host->status_request = false;
+
+	/* Command pre-processing step */
+	switch (command) {
+
+	case NAND_CMD_STATUS:
+		host->col_addr = 0;
+		host->status_request = true;
+		break;
+
+	case NAND_CMD_READ0:
+		host->col_addr = column;
+		host->spare_only = false;
+		break;
+
+	case NAND_CMD_READOOB:
+		host->col_addr = column;
+		host->spare_only = true;
+		if (host->pagesize_2k)
+			command = NAND_CMD_READ0; /* only READ0 is valid */
+		break;
+
+	case NAND_CMD_SEQIN:
+		if (column >= mtd->writesize) {
+			/*
+			 * before sending SEQIN command for partial write,
+			 * we need read one page out. FSL NFC does not support
+			 * partial write. It alway send out 512+ecc+512+ecc ...
+			 * for large page nand flash. But for small page nand
+			 * flash, it does support SPARE ONLY operation.
+			 */
+			if (host->pagesize_2k) {
+				/* call ourself to read a page */
+				mxc_nand_command(mtd, NAND_CMD_READ0, 0,
+						page_addr);
+			}
+
+			host->col_addr = column - mtd->writesize;
+			host->spare_only = true;
+
+			/* Set program pointer to spare region */
+			if (!host->pagesize_2k)
+				send_cmd(host, NAND_CMD_READOOB);
+		} else {
+			host->spare_only = false;
+			host->col_addr = column;
+
+			/* Set program pointer to page start */
+			if (!host->pagesize_2k)
+				send_cmd(host, NAND_CMD_READ0);
+		}
+		break;
+
+	case NAND_CMD_PAGEPROG:
+		send_prog_page(host, 0, host->spare_only);
+
+		if (host->pagesize_2k) {
+			/* data in 4 areas datas */
+			send_prog_page(host, 1, host->spare_only);
+			send_prog_page(host, 2, host->spare_only);
+			send_prog_page(host, 3, host->spare_only);
+		}
+
+		break;
+	}
+
+	/* Write out the command to the device. */
+	send_cmd(host, command);
+
+	/* Write out column address, if necessary */
+	if (column != -1) {
+		/*
+		 * MXC NANDFC can only perform full page+spare or
+		 * spare-only read/write.  When the upper layers
+		 * layers perform a read/write buf operation,
+		 * we will used the saved column adress to index into
+		 * the full page.
+		 */
+		send_addr(host, 0);
+		if (host->pagesize_2k)
+			/* another col addr cycle for 2k page */
+			send_addr(host, 0);
+	}
+
+	/* Write out page address, if necessary */
+	if (page_addr != -1) {
+		/* paddr_0 - p_addr_7 */
+		send_addr(host, (page_addr & 0xff));
+
+		if (host->pagesize_2k) {
+			send_addr(host, (page_addr >> 8) & 0xFF);
+			if (mtd->size >= 0x10000000) {
+				/* paddr_8 - paddr_15 */
+				send_addr(host, (page_addr >> 8) & 0xff);
+				send_addr(host, (page_addr >> 16) & 0xff);
+			} else {
+				/* paddr_8 - paddr_15 */
+				send_addr(host, (page_addr >> 8) & 0xff);
+			}
+		} else {
+			/* One more address cycle for higher density devices */
+			if (mtd->size >= 0x4000000) {
+				/* paddr_8 - paddr_15 */
+				send_addr(host, (page_addr >> 8) & 0xff);
+				send_addr(host, (page_addr >> 16) & 0xff);
+			} else {
+				/* paddr_8 - paddr_15 */
+				send_addr(host, (page_addr >> 8) & 0xff);
+			}
+		}
+	}
+
+	/* Command post-processing step */
+	switch (command) {
+
+	case NAND_CMD_RESET:
+		break;
+
+	case NAND_CMD_READOOB:
+	case NAND_CMD_READ0:
+		if (host->pagesize_2k) {
+			/* send read confirm command */
+			send_cmd(host, NAND_CMD_READSTART);
+			/* read for each AREA */
+			send_read_page(host, 0, host->spare_only);
+			send_read_page(host, 1, host->spare_only);
+			send_read_page(host, 2, host->spare_only);
+			send_read_page(host, 3, host->spare_only);
+		} else {
+			send_read_page(host, 0, host->spare_only);
+		}
+		break;
+
+	case NAND_CMD_READID:
+		host->col_addr = 0;
+		send_read_id(host);
+		break;
+
+	case NAND_CMD_PAGEPROG:
+		break;
+
+	case NAND_CMD_STATUS:
+		break;
+
+	case NAND_CMD_ERASE2:
+		break;
+	}
+}
+
+int board_nand_init(struct nand_chip *this)
+{
+	struct system_control_regs *sc_regs =
+		(struct system_control_regs *)IMX_SYSTEM_CTL_BASE;
+	struct mtd_info *mtd;
+	uint16_t tmp;
+	int err = 0;
+
+	/* structures must be linked */
+	mtd = &host->mtd;
+	mtd->priv = this;
+	host->nand = this;
+
+	/* 50 us command delay time */
+	this->chip_delay = 5;
+
+	this->priv = host;
+	this->dev_ready = mxc_nand_dev_ready;
+	this->cmdfunc = mxc_nand_command;
+	this->select_chip = mxc_nand_select_chip;
+	this->read_byte = mxc_nand_read_byte;
+	this->read_word = mxc_nand_read_word;
+	this->write_buf = mxc_nand_write_buf;
+	this->read_buf = mxc_nand_read_buf;
+	this->verify_buf = mxc_nand_verify_buf;
+
+	host->regs = (struct nfc_regs __iomem *)CONFIG_MXC_NAND_REGS_BASE;
+	host->clk_act = 1;
+
+#ifdef CONFIG_MXC_NAND_HWECC
+	this->ecc.calculate = mxc_nand_calculate_ecc;
+	this->ecc.hwctl = mxc_nand_enable_hwecc;
+	this->ecc.correct = mxc_nand_correct_data;
+	this->ecc.mode = NAND_ECC_HW;
+	this->ecc.size = 512;
+	this->ecc.bytes = 3;
+	this->ecc.layout = &nand_hw_eccoob;
+	tmp = readw(&host->regs->nfc_config1);
+	tmp |= NFC_ECC_EN;
+	writew(tmp, &host->regs->nfc_config1);
+#else
+	this->ecc.layout = &nand_hw_eccoob_soft;
+	this->ecc.mode = NAND_ECC_SOFT;
+	tmp = readw(&host->regs->nfc_config1);
+	tmp &= ~NFC_ECC_EN;
+	writew(tmp, &host->regs->nfc_config1);
+#endif
+
+	/* Reset NAND */
+	this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
+
+	/*
+	 * preset operation
+	 * Unlock the internal RAM Buffer
+	 */
+	writew(0x2, &host->regs->nfc_config);
+
+	/* Blocks to be unlocked */
+	writew(0x0, &host->regs->nfc_unlockstart_blkaddr);
+	writew(0x4000, &host->regs->nfc_unlockend_blkaddr);
+
+	/* Unlock Block Command for given address range */
+	writew(0x4, &host->regs->nfc_wrprot);
+
+	/* NAND bus width determines access funtions used by upper layer */
+	if (readl(&sc_regs->fmcr) & NF_16BIT_SEL)
+		this->options |= NAND_BUSWIDTH_16;
+
+	host->pagesize_2k = 0;
+
+	return err;
+}
-- 
1.6.0.6

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

* [U-Boot] [PATCH] fec_mxc: driver for FEC ethernet controller on i.MX27
  2009-06-08  0:12 ` [U-Boot] [PATCH 3/7] fec_imx27: driver for FEC ethernet controller on i.MX27 Ilya Yanok
@ 2009-07-17 10:57   ` Ilya Yanok
  2009-07-17 14:05     ` Ben Warren
  0 siblings, 1 reply; 70+ messages in thread
From: Ilya Yanok @ 2009-07-17 10:57 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Ilya Yanok <yanok@emcraft.com>
---
 cpu/arm926ejs/mx27/generic.c |   10 +
 drivers/net/Makefile         |    1 +
 drivers/net/fec_mxc.c        |  742 ++++++++++++++++++++++++++++++++++++++++++
 drivers/net/fec_mxc.h        |  304 +++++++++++++++++
 include/netdev.h             |    1 +
 5 files changed, 1058 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/fec_mxc.c
 create mode 100644 drivers/net/fec_mxc.h

diff --git a/cpu/arm926ejs/mx27/generic.c b/cpu/arm926ejs/mx27/generic.c
index bcf7899..7f6fc69 100644
--- a/cpu/arm926ejs/mx27/generic.c
+++ b/cpu/arm926ejs/mx27/generic.c
@@ -20,6 +20,7 @@
 
 #include <common.h>
 #include <div64.h>
+#include <netdev.h>
 #include <asm/io.h>
 #include <asm/arch/imx-regs.h>
 
@@ -159,6 +160,15 @@ int print_cpuinfo (void)
 }
 #endif
 
+int cpu_eth_init(bd_t *bis)
+{
+#if defined(CONFIG_FEC_IMX27)
+	return fecimx27_initialize(bis);
+#else
+	return 0;
+#endif
+}
+
 void imx_gpio_mode(int gpio_mode)
 {
 	struct gpio_regs *regs = (struct gpio_regs *)IMX_GPIO_BASE;
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index c6097c3..f92dba7 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -37,6 +37,7 @@ COBJS-$(CONFIG_DNET) += dnet.o
 COBJS-$(CONFIG_E1000) += e1000.o
 COBJS-$(CONFIG_EEPRO100) += eepro100.o
 COBJS-$(CONFIG_ENC28J60) += enc28j60.o
+COBJS-$(CONFIG_FEC_MXC) += fec_mxc.o
 COBJS-$(CONFIG_FSLDMAFEC) += fsl_mcdmafec.o mcfmii.o
 COBJS-$(CONFIG_GRETH) += greth.o
 COBJS-$(CONFIG_INCA_IP_SWITCH) += inca-ip_sw.o
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
new file mode 100644
index 0000000..0589e38
--- /dev/null
+++ b/drivers/net/fec_mxc.c
@@ -0,0 +1,742 @@
+/*
+ * (C) Copyright 2009 Ilya Yanok, Emcraft Systems Ltd <yanok@emcraft.com>
+ * (C) Copyright 2008,2009 Eric Jarrige <eric.jarrige@armadeus.org>
+ * (C) Copyright 2008 Armadeus Systems nc
+ * (C) Copyright 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
+ * (C) Copyright 2007 Pengutronix, Juergen Beisert <j.beisert@pengutronix.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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <net.h>
+#include <miiphy.h>
+#include "fec_mxc.h"
+
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifndef CONFIG_MII
+#error "CONFIG_MII has to be defined!"
+#endif
+
+#undef DEBUG
+
+struct nbuf {
+	uint8_t data[1500];	/**< actual data */
+	int length;		/**< actual length */
+	int used;		/**< buffer in use or not */
+	uint8_t head[16];	/**< MAC header(6 + 6 + 2) + 2(aligned) */
+};
+
+struct fec_priv gfec = {
+	.eth       = (struct ethernet_regs *)IMX_FEC_BASE,
+	.xcv_type  = MII100,
+	.rbd_base  = NULL,
+	.rbd_index = 0,
+	.tbd_base  = NULL,
+	.tbd_index = 0,
+	.bd        = NULL,
+};
+
+/*
+ * MII-interface related functions
+ */
+static int fec_miiphy_read(char *dev, uint8_t phyAddr, uint8_t regAddr,
+		uint16_t *retVal)
+{
+	struct eth_device *edev = eth_get_dev_by_name(dev);
+	struct fec_priv *fec = (struct fec_priv *)edev->priv;
+
+	uint32_t reg;		/* convenient holder for the PHY register */
+	uint32_t phy;		/* convenient holder for the PHY */
+	uint32_t start;
+
+	/*
+	 * reading from any PHY's register is done by properly
+	 * programming the FEC's MII data register.
+	 */
+	writel(FEC_IEVENT_MII, &fec->eth->ievent);
+	reg = regAddr << FEC_MII_DATA_RA_SHIFT;
+	phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
+
+	writel(FEC_MII_DATA_ST | FEC_MII_DATA_OP_RD | FEC_MII_DATA_TA |
+			phy | reg, &fec->eth->mii_data);
+
+	/*
+	 * wait for the related interrupt
+	 */
+	start = get_timer_masked();
+	while (!(readl(&fec->eth->ievent) & FEC_IEVENT_MII)) {
+		if (get_timer(start) > (CONFIG_SYS_HZ / 1000)) {
+			printf("Read MDIO failed...\n");
+			return -1;
+		}
+	}
+
+	/*
+	 * clear mii interrupt bit
+	 */
+	writel(FEC_IEVENT_MII, &fec->eth->ievent);
+
+	/*
+	 * it's now safe to read the PHY's register
+	 */
+	*retVal = readl(&fec->eth->mii_data);
+	debug("fec_miiphy_read: phy: %02x reg:%02x val:%#x\n", phyAddr,
+			regAddr, *retVal);
+	return 0;
+}
+
+static int fec_miiphy_write(char *dev, uint8_t phyAddr, uint8_t regAddr,
+		uint16_t data)
+{
+	struct eth_device *edev = eth_get_dev_by_name(dev);
+	struct fec_priv *fec = (struct fec_priv *)edev->priv;
+
+	uint32_t reg;		/* convenient holder for the PHY register */
+	uint32_t phy;		/* convenient holder for the PHY */
+	uint32_t start;
+
+	reg = regAddr << FEC_MII_DATA_RA_SHIFT;
+	phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
+
+	writel(FEC_MII_DATA_ST | FEC_MII_DATA_OP_WR |
+		FEC_MII_DATA_TA | phy | reg | data, &fec->eth->mii_data);
+
+	/*
+	 * wait for the MII interrupt
+	 */
+	start = get_timer_masked();
+	while (!(readl(&fec->eth->ievent) & FEC_IEVENT_MII)) {
+		if (get_timer(start) > (CONFIG_SYS_HZ / 1000)) {
+			printf("Write MDIO failed...\n");
+			return -1;
+		}
+	}
+
+	/*
+	 * clear MII interrupt bit
+	 */
+	writel(FEC_IEVENT_MII, &fec->eth->ievent);
+	debug("fec_miiphy_write: phy: %02x reg:%02x val:%#x\n", phyAddr,
+			regAddr, data);
+
+	return 0;
+}
+
+static int miiphy_restart_aneg(struct eth_device *dev)
+{
+	/*
+	 * Wake up from sleep if necessary
+	 * Reset PHY, then delay 300ns
+	 */
+	miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, PHY_MIPGSR, 0x00FF);
+	miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, PHY_BMCR,
+			PHY_BMCR_RESET);
+	udelay(1000);
+
+	/*
+	 * Set the auto-negotiation advertisement register bits
+	 */
+	miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, PHY_ANAR, 0x1e0);
+	miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, PHY_BMCR,
+			PHY_BMCR_AUTON | PHY_BMCR_RST_NEG);
+
+	return 0;
+}
+
+static int miiphy_wait_aneg(struct eth_device *dev)
+{
+	uint32_t start;
+	uint16_t status;
+
+	/*
+	 * Wait for AN completion
+	 */
+	start = get_timer_masked();
+	do {
+		if (get_timer(start) > (CONFIG_SYS_HZ * 5)) {
+			printf("%s: Autonegotiation timeout\n", dev->name);
+			return -1;
+		}
+
+		if (miiphy_read(dev->name, CONFIG_FEC_MXC_PHYADDR,
+					PHY_BMSR, &status)) {
+			printf("%s: Autonegotiation failed. status: 0x%04x\n",
+					dev->name, status);
+			return -1;
+		}
+	} while (!(status & PHY_BMSR_LS));
+
+	return 0;
+}
+static int fec_rx_task_enable(struct fec_priv *fec)
+{
+	writel(1 << 24, &fec->eth->r_des_active);
+	return 0;
+}
+
+static int fec_rx_task_disable(struct fec_priv *fec)
+{
+	return 0;
+}
+
+static int fec_tx_task_enable(struct fec_priv *fec)
+{
+	writel(1 << 24, &fec->eth->x_des_active);
+	return 0;
+}
+
+static int fec_tx_task_disable(struct fec_priv *fec)
+{
+	return 0;
+}
+
+/**
+ * Initialize receive task's buffer descriptors
+ * @param[in] fec all we know about the device yet
+ * @param[in] count receive buffer count to be allocated
+ * @param[in] size size of each receive buffer
+ * @return 0 on success
+ *
+ * For this task we need additional memory for the data buffers. And each
+ * data buffer requires some alignment. Thy must be aligned to a specific
+ * boundary each (DB_DATA_ALIGNMENT).
+ */
+static int fec_rbd_init(struct fec_priv *fec, int count, int size)
+{
+	int ix;
+	uint32_t p = 0;
+
+	/* reserve data memory and consider alignment */
+	fec->rdb_ptr = malloc(size * count + DB_DATA_ALIGNMENT);
+	p = (uint32_t)fec->rdb_ptr;
+	if (!p) {
+		puts("fec_imx27: not enough malloc memory!\n");
+		return -ENOMEM;
+	}
+	memset((void *)p, 0, size * count + DB_DATA_ALIGNMENT);
+	p += DB_DATA_ALIGNMENT-1;
+	p &= ~(DB_DATA_ALIGNMENT-1);
+
+	for (ix = 0; ix < count; ix++) {
+		writel(p, &fec->rbd_base[ix].data_pointer);
+		p += size;
+		writew(FEC_RBD_EMPTY, &fec->rbd_base[ix].status);
+		writew(0, &fec->rbd_base[ix].data_length);
+	}
+	/*
+	 * mark the last RBD to close the ring
+	 */
+	writew(FEC_RBD_WRAP | FEC_RBD_EMPTY, &fec->rbd_base[ix - 1].status);
+	fec->rbd_index = 0;
+
+	return 0;
+}
+
+/**
+ * Initialize transmit task's buffer descriptors
+ * @param[in] fec all we know about the device yet
+ *
+ * Transmit buffers are created externally. We only have to init the BDs here.\n
+ * Note: There is a race condition in the hardware. When only one BD is in
+ * use it must be marked with the WRAP bit to use it for every transmitt.
+ * This bit in combination with the READY bit results into double transmit
+ * of each data buffer. It seems the state machine checks READY earlier then
+ * resetting it after the first transfer.
+ * Using two BDs solves this issue.
+ */
+static void fec_tbd_init(struct fec_priv *fec)
+{
+	writew(0x0000, &fec->tbd_base[0].status);
+	writew(FEC_TBD_WRAP, &fec->tbd_base[1].status);
+	fec->tbd_index = 0;
+}
+
+/**
+ * Mark the given read buffer descriptor as free
+ * @param[in] last 1 if this is the last buffer descriptor in the chain, else 0
+ * @param[in] pRbd buffer descriptor to mark free again
+ */
+static void fec_rbd_clean(int last, struct fec_bd *pRbd)
+{
+	/*
+	 * Reset buffer descriptor as empty
+	 */
+	if (last)
+		writew(FEC_RBD_WRAP | FEC_RBD_EMPTY, &pRbd->status);
+	else
+		writew(FEC_RBD_EMPTY, &pRbd->status);
+	/*
+	 * no data in it
+	 */
+	writew(0, &pRbd->data_length);
+}
+
+static int fec_get_hwaddr(struct eth_device *dev, unsigned char *mac)
+{
+	struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE;
+	int i;
+
+	for (i = 0; i < 6; i++)
+		mac[6-1-i] = readl(&iim->iim_bank_area0[IIM0_MAC + i]);
+
+	return is_valid_ether_addr(mac);
+}
+
+static int fec_set_hwaddr(struct eth_device *dev, unsigned char *mac)
+{
+	struct fec_priv *fec = (struct fec_priv *)dev->priv;
+
+	writel(0, &fec->eth->iaddr1);
+	writel(0, &fec->eth->iaddr2);
+	writel(0, &fec->eth->gaddr1);
+	writel(0, &fec->eth->gaddr2);
+
+	/*
+	 * Set physical address
+	 */
+	writel((mac[0] << 24) + (mac[1] << 16) + (mac[2] << 8) + mac[3],
+			&fec->eth->paddr1);
+	writel((mac[4] << 24) + (mac[5] << 16) + 0x8808, &fec->eth->paddr2);
+
+	return 0;
+}
+
+/**
+ * Start the FEC engine
+ * @param[in] dev Our device to handle
+ */
+static int fec_open(struct eth_device *edev)
+{
+	struct fec_priv *fec = (struct fec_priv *)edev->priv;
+
+	debug("fec_open: fec_open(dev)\n");
+	/* full-duplex, heartbeat disabled */
+	writel(1 << 2, &fec->eth->x_cntrl);
+	fec->rbd_index = 0;
+
+	/*
+	 * Enable FEC-Lite controller
+	 */
+	writel(FEC_ECNTRL_ETHER_EN, &fec->eth->ecntrl);
+
+	miiphy_wait_aneg(edev);
+	miiphy_speed(edev->name, 0);
+	miiphy_duplex(edev->name, 0);
+
+	/*
+	 * Enable SmartDMA receive task
+	 */
+	fec_rx_task_enable(fec);
+
+	udelay(100000);
+	return 0;
+}
+
+static int fec_init(struct eth_device *dev, bd_t* bd)
+{
+	uint32_t base;
+	struct fec_priv *fec = (struct fec_priv *)dev->priv;
+
+	/*
+	 * reserve memory for both buffer descriptor chains at once
+	 * Datasheet forces the startaddress of each chain is 16 byte
+	 * aligned
+	 */
+	fec->base_ptr = malloc((2 + FEC_RBD_NUM) *
+			sizeof(struct fec_bd) + DB_ALIGNMENT);
+	base = (uint32_t)fec->base_ptr;
+	if (!base) {
+		puts("fec_imx27: not enough malloc memory!\n");
+		return -ENOMEM;
+	}
+	memset((void *)base, 0, (2 + FEC_RBD_NUM) *
+			sizeof(struct fec_bd) + DB_ALIGNMENT);
+	base += (DB_ALIGNMENT-1);
+	base &= ~(DB_ALIGNMENT-1);
+
+	fec->rbd_base = (struct fec_bd *)base;
+
+	base += FEC_RBD_NUM * sizeof(struct fec_bd);
+
+	fec->tbd_base = (struct fec_bd *)base;
+
+	/*
+	 * Set interrupt mask register
+	 */
+	writel(0x00000000, &fec->eth->imask);
+
+	/*
+	 * Clear FEC-Lite interrupt event register(IEVENT)
+	 */
+	writel(0xffffffff, &fec->eth->ievent);
+
+
+	/*
+	 * Set FEC-Lite receive control register(R_CNTRL):
+	 */
+	if (fec->xcv_type == SEVENWIRE) {
+		/*
+		 * Frame length=1518; 7-wire mode
+		 */
+		writel(0x05ee0020, &fec->eth->r_cntrl);	/* FIXME 0x05ee0000 */
+	} else {
+		/*
+		 * Frame length=1518; MII mode;
+		 */
+		writel(0x05ee0024, &fec->eth->r_cntrl);	/* FIXME 0x05ee0004 */
+		/*
+		 * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
+		 * and do not drop the Preamble.
+		 */
+		writel((((imx_get_ahbclk() / 1000000) + 2) / 5) << 1,
+				&fec->eth->mii_speed);
+		debug("fec_init: mii_speed %#lx\n",
+				(((imx_get_ahbclk() / 1000000) + 2) / 5) << 1);
+	}
+	/*
+	 * Set Opcode/Pause Duration Register
+	 */
+	writel(0x00010020, &fec->eth->op_pause);	/* FIXME 0xffff0020; */
+	writel(0x2, &fec->eth->x_wmrk);
+	/*
+	 * Set multicast address filter
+	 */
+	writel(0x00000000, &fec->eth->gaddr1);
+	writel(0x00000000, &fec->eth->gaddr2);
+
+
+	/* clear MIB RAM */
+	long *mib_ptr = (long *)(IMX_FEC_BASE + 0x200);
+	while (mib_ptr <= (long *)(IMX_FEC_BASE + 0x2FC))
+		*mib_ptr++ = 0;
+
+	/* FIFO receive start register */
+	writel(0x520, &fec->eth->r_fstart);
+
+	/* size and address of each buffer */
+	writel(FEC_MAX_PKT_SIZE, &fec->eth->emrbr);
+	writel((uint32_t)fec->tbd_base, &fec->eth->etdsr);
+	writel((uint32_t)fec->rbd_base, &fec->eth->erdsr);
+
+	/*
+	 * Initialize RxBD/TxBD rings
+	 */
+	if (fec_rbd_init(fec, FEC_RBD_NUM, FEC_MAX_PKT_SIZE) < 0) {
+		free(fec->base_ptr);
+		return -ENOMEM;
+	}
+	fec_tbd_init(fec);
+
+
+	if (fec->xcv_type != SEVENWIRE)
+		miiphy_restart_aneg(dev);
+
+	fec_open(dev);
+	return 0;
+}
+
+/**
+ * Halt the FEC engine
+ * @param[in] dev Our device to handle
+ */
+static void fec_halt(struct eth_device *dev)
+{
+	struct fec_priv *fec = &gfec;
+	int counter = 0xffff;
+
+	/*
+	 * issue graceful stop command to the FEC transmitter if necessary
+	 */
+	writel(FEC_ECNTRL_RESET | readl(&fec->eth->x_cntrl),
+			&fec->eth->x_cntrl);
+
+	debug("eth_halt: wait for stop regs\n");
+	/*
+	 * wait for graceful stop to register
+	 */
+	while ((counter--) && (!(readl(&fec->eth->ievent) & FEC_IEVENT_GRA)))
+		;	/* FIXME ensure time */
+
+	/*
+	 * Disable SmartDMA tasks
+	 */
+	fec_tx_task_disable(fec);
+	fec_rx_task_disable(fec);
+
+	/*
+	 * Disable the Ethernet Controller
+	 * Note: this will also reset the BD index counter!
+	 */
+	writel(0, &fec->eth->ecntrl);
+	fec->rbd_index = 0;
+	fec->tbd_index = 0;
+	free(fec->rdb_ptr);
+	free(fec->base_ptr);
+	debug("eth_halt: done\n");
+}
+
+/**
+ * Transmit one frame
+ * @param[in] dev Our ethernet device to handle
+ * @param[in] packet Pointer to the data to be transmitted
+ * @param[in] length Data count in bytes
+ * @return 0 on success
+ */
+static int fec_send(struct eth_device *dev, volatile void* packet, int length)
+{
+	unsigned int status;
+
+	/*
+	 * This routine transmits one frame.  This routine only accepts
+	 * 6-byte Ethernet addresses.
+	 */
+	struct fec_priv *fec = (struct fec_priv *)dev->priv;
+
+	/*
+	 * Check for valid length of data.
+	 */
+	if ((length > 1500) || (length <= 0)) {
+		printf("Payload (%d) to large!\n", length);
+		return -1;
+	}
+
+	/*
+	 * Setup the transmit buffer
+	 * Note: We are always using the first buffer for transmission,
+	 * the second will be empty and only used to stop the DMA engine
+	 */
+	writew(length, &fec->tbd_base[fec->tbd_index].data_length);
+	writel((uint32_t)packet, &fec->tbd_base[fec->tbd_index].data_pointer);
+	/*
+	 * update BD's status now
+	 * This block:
+	 * - is always the last in a chain (means no chain)
+	 * - should transmitt the CRC
+	 * - might be the last BD in the list, so the address counter should
+	 *   wrap (-> keep the WRAP flag)
+	 */
+	status = readw(&fec->tbd_base[fec->tbd_index].status) & FEC_TBD_WRAP;
+	status |= FEC_TBD_LAST | FEC_TBD_TC | FEC_TBD_READY;
+	writew(status, &fec->tbd_base[fec->tbd_index].status);
+
+	/*
+	 * Enable SmartDMA transmit task
+	 */
+	fec_tx_task_enable(fec);
+
+	/*
+	 * wait until frame is sent .
+	 */
+	while (readw(&fec->tbd_base[fec->tbd_index].status) & FEC_TBD_READY) {
+		/* FIXME: Timeout */
+	}
+	debug("fec_send: status 0x%x index %d\n",
+			readw(&fec->tbd_base[fec->tbd_index].status),
+			fec->tbd_index);
+	/* for next transmission use the other buffer */
+	if (fec->tbd_index)
+		fec->tbd_index = 0;
+	else
+		fec->tbd_index = 1;
+
+	return 0;
+}
+
+/**
+ * Pull one frame from the card
+ * @param[in] dev Our ethernet device to handle
+ * @return Length of packet read
+ */
+static int fec_recv(struct eth_device *dev)
+{
+	struct fec_priv *fec = (struct fec_priv *)dev->priv;
+	struct fec_bd *rbd = &fec->rbd_base[fec->rbd_index];
+	unsigned long ievent;
+	int frame_length, len = 0;
+	struct nbuf *frame;
+	uint16_t bd_status;
+	uchar buff[FEC_MAX_PKT_SIZE];
+
+	/*
+	 * Check if any critical events have happened
+	 */
+	ievent = readl(&fec->eth->ievent);
+	writel(ievent, &fec->eth->ievent);
+	debug("fec_recv: ievent 0x%x\n", ievent);
+	if (ievent & FEC_IEVENT_BABR) {
+		fec_halt(dev);
+		fec_init(dev, fec->bd);
+		printf("some error: 0x%08lx\n", ievent);
+		return 0;
+	}
+	if (ievent & FEC_IEVENT_HBERR) {
+		/* Heartbeat error */
+		writel(0x00000001 | readl(&fec->eth->x_cntrl),
+				&fec->eth->x_cntrl);
+	}
+	if (ievent & FEC_IEVENT_GRA) {
+		/* Graceful stop complete */
+		if (readl(&fec->eth->x_cntrl) & 0x00000001) {
+			fec_halt(dev);
+			writel(~0x00000001 & readl(&fec->eth->x_cntrl),
+					&fec->eth->x_cntrl);
+			fec_init(dev, fec->bd);
+		}
+	}
+
+	/*
+	 * ensure reading the right buffer status
+	 */
+	bd_status = readw(&rbd->status);
+	debug("fec_recv: status 0x%x\n", bd_status);
+
+	if (!(bd_status & FEC_RBD_EMPTY)) {
+		if ((bd_status & FEC_RBD_LAST) && !(bd_status & FEC_RBD_ERR) &&
+			((readw(&rbd->data_length) - 4) > 14)) {
+			/*
+			 * Get buffer address and size
+			 */
+			frame = (struct nbuf *)readl(&rbd->data_pointer);
+			frame_length = readw(&rbd->data_length) - 4;
+			/*
+			 *  Fill the buffer and pass it to upper layers
+			 */
+			memcpy(buff, frame->data, frame_length);
+			NetReceive(buff, frame_length);
+			len = frame_length;
+		} else {
+			if (bd_status & FEC_RBD_ERR)
+				printf("error frame: 0x%08lx 0x%08x\n",
+						(ulong)rbd->data_pointer,
+						bd_status);
+		}
+		/*
+		 * free the current buffer, restart the engine
+		 * and move forward to the next buffer
+		 */
+		fec_rbd_clean(fec->rbd_index == (FEC_RBD_NUM - 1) ? 1 : 0, rbd);
+		fec_rx_task_enable(fec);
+		fec->rbd_index = (fec->rbd_index + 1) % FEC_RBD_NUM;
+	}
+	debug("fec_recv: stop\n");
+
+	return len;
+}
+
+static int fec_probe(bd_t *bd)
+{
+	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+	struct eth_device *edev;
+	struct fec_priv *fec = &gfec;
+	unsigned char ethaddr_str[20];
+	unsigned char ethaddr[6];
+	char *tmp = getenv("ethaddr");
+	char *end;
+
+	/* enable FEC clock */
+	writel(readl(&pll->pccr1) | PCCR1_HCLK_FEC, &pll->pccr1);
+	writel(readl(&pll->pccr0) | PCCR0_FEC_EN, &pll->pccr0);
+
+	/* create and fill edev struct */
+	edev = (struct eth_device *)malloc(sizeof(struct eth_device));
+	if (!edev) {
+		puts("fec_imx27: not enough malloc memory!\n");
+		return -ENOMEM;
+	}
+	edev->priv = fec;
+	edev->init = fec_init;
+	edev->send = fec_send;
+	edev->recv = fec_recv;
+	edev->halt = fec_halt;
+
+	fec->eth = (struct ethernet_regs *)IMX_FEC_BASE;
+	fec->bd = bd;
+
+	fec->xcv_type = MII100;
+
+	/* Reset chip. */
+	writel(FEC_ECNTRL_RESET, &fec->eth->ecntrl);
+	while (readl(&fec->eth->ecntrl) & 1)
+		udelay(10);
+
+	/*
+	 * Set interrupt mask register
+	 */
+	writel(0x00000000, &fec->eth->imask);
+
+	/*
+	 * Clear FEC-Lite interrupt event register(IEVENT)
+	 */
+	writel(0xffffffff, &fec->eth->ievent);
+
+	/*
+	 * Set FEC-Lite receive control register(R_CNTRL):
+	 */
+	/*
+	 * Frame length=1518; MII mode;
+	 */
+	writel(0x05ee0024, &fec->eth->r_cntrl);	/* FIXME 0x05ee0004 */
+	/*
+	 * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
+	 * and do not drop the Preamble.
+	 */
+	writel((((imx_get_ahbclk() / 1000000) + 2) / 5) << 1,
+			&fec->eth->mii_speed);
+	debug("fec_init: mii_speed %#lx\n",
+			(((imx_get_ahbclk() / 1000000) + 2) / 5) << 1);
+
+	sprintf(edev->name, "FEC_MXC");
+
+	miiphy_register(edev->name, fec_miiphy_read, fec_miiphy_write);
+
+	eth_register(edev);
+
+	if ((NULL != tmp) && (12 <= strlen(tmp))) {
+		int i;
+		/* convert MAC from string to int */
+		for (i = 0; i < 6; i++) {
+			ethaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0;
+			if (tmp)
+				tmp = (*end) ? end + 1 : end;
+		}
+	} else if (fec_get_hwaddr(edev, ethaddr) == 0) {
+		printf("got MAC address from EEPROM: %pM\n", ethaddr);
+		setenv("ethaddr", (char *)ethaddr_str);
+	}
+	memcpy(edev->enetaddr, ethaddr, 6);
+	fec_set_hwaddr(edev, ethaddr);
+
+	return 0;
+}
+
+int fecimx27_initialize(bd_t *bd)
+{
+	int lout = 1;
+
+	debug("eth_init: fec_probe(bd)\n");
+	lout = fec_probe(bd);
+
+	return lout;
+}
+
diff --git a/drivers/net/fec_mxc.h b/drivers/net/fec_mxc.h
new file mode 100644
index 0000000..6cb1bfc
--- /dev/null
+++ b/drivers/net/fec_mxc.h
@@ -0,0 +1,304 @@
+/*
+ * (C) Copyright 2009 Ilya Yanok, Emcraft Systems Ltd <yanok@emcraft.com>
+ * (C) Copyright 2008 Armadeus Systems, nc
+ * (C) Copyright 2008 Eric Jarrige <eric.jarrige@armadeus.org>
+ * (C) Copyright 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
+ * (C) Copyright 2007 Pengutronix, Juergen Beisert <j.beisert@pengutronix.de>
+ *
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ *
+ * This file is based on mpc4200fec.h
+ * (C) Copyright Motorola, Inc., 2000
+ *
+ * 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 __FEC_MXC_H
+#define __FEC_MXC_H
+
+/**
+ * Layout description of the FEC
+ */
+struct ethernet_regs {
+
+/* [10:2]addr = 00 */
+
+/*  Control and status Registers (offset 000-1FF) */
+
+	uint32_t res0[1];		/* MBAR_ETH + 0x000 */
+	uint32_t ievent;		/* MBAR_ETH + 0x004 */
+	uint32_t imask;			/* MBAR_ETH + 0x008 */
+
+	uint32_t res1[1];		/* MBAR_ETH + 0x00C */
+	uint32_t r_des_active;		/* MBAR_ETH + 0x010 */
+	uint32_t x_des_active;		/* MBAR_ETH + 0x014 */
+	uint32_t res2[3];		/* MBAR_ETH + 0x018-20 */
+	uint32_t ecntrl;		/* MBAR_ETH + 0x024 */
+
+	uint32_t res3[6];		/* MBAR_ETH + 0x028-03C */
+	uint32_t mii_data;		/* MBAR_ETH + 0x040 */
+	uint32_t mii_speed;		/* MBAR_ETH + 0x044 */
+	uint32_t res4[7];		/* MBAR_ETH + 0x048-60 */
+	uint32_t mib_control;		/* MBAR_ETH + 0x064 */
+
+	uint32_t res5[7];		/* MBAR_ETH + 0x068-80 */
+	uint32_t r_cntrl;		/* MBAR_ETH + 0x084 */
+	uint32_t res6[15];		/* MBAR_ETH + 0x088-C0 */
+	uint32_t x_cntrl;		/* MBAR_ETH + 0x0C4 */
+	uint32_t res7[7];		/* MBAR_ETH + 0x0C8-E0 */
+	uint32_t paddr1;		/* MBAR_ETH + 0x0E4 */
+	uint32_t paddr2;		/* MBAR_ETH + 0x0E8 */
+	uint32_t op_pause;		/* MBAR_ETH + 0x0EC */
+
+	uint32_t res8[10];		/* MBAR_ETH + 0x0F0-114 */
+	uint32_t iaddr1;		/* MBAR_ETH + 0x118 */
+	uint32_t iaddr2;		/* MBAR_ETH + 0x11C */
+	uint32_t gaddr1;		/* MBAR_ETH + 0x120 */
+	uint32_t gaddr2;		/* MBAR_ETH + 0x124 */
+	uint32_t res9[7];		/* MBAR_ETH + 0x128-140 */
+
+	uint32_t x_wmrk;		/* MBAR_ETH + 0x144 */
+	uint32_t res10[1];		/* MBAR_ETH + 0x148 */
+	uint32_t r_bound;		/* MBAR_ETH + 0x14C */
+	uint32_t r_fstart;		/* MBAR_ETH + 0x150 */
+	uint32_t res11[11];		/* MBAR_ETH + 0x154-17C */
+	uint32_t erdsr;			/* MBAR_ETH + 0x180 */
+	uint32_t etdsr;			/* MBAR_ETH + 0x184 */
+	uint32_t emrbr;			/* MBAR_ETH + 0x188 */
+	uint32_t res12[29];		/* MBAR_ETH + 0x18C-1FC */
+
+/*  MIB COUNTERS (Offset 200-2FF) */
+
+	uint32_t rmon_t_drop;		/* MBAR_ETH + 0x200 */
+	uint32_t rmon_t_packets;	/* MBAR_ETH + 0x204 */
+	uint32_t rmon_t_bc_pkt;		/* MBAR_ETH + 0x208 */
+	uint32_t rmon_t_mc_pkt;		/* MBAR_ETH + 0x20C */
+	uint32_t rmon_t_crc_align;	/* MBAR_ETH + 0x210 */
+	uint32_t rmon_t_undersize;	/* MBAR_ETH + 0x214 */
+	uint32_t rmon_t_oversize;	/* MBAR_ETH + 0x218 */
+	uint32_t rmon_t_frag;		/* MBAR_ETH + 0x21C */
+	uint32_t rmon_t_jab;		/* MBAR_ETH + 0x220 */
+	uint32_t rmon_t_col;		/* MBAR_ETH + 0x224 */
+	uint32_t rmon_t_p64;		/* MBAR_ETH + 0x228 */
+	uint32_t rmon_t_p65to127;	/* MBAR_ETH + 0x22C */
+	uint32_t rmon_t_p128to255;	/* MBAR_ETH + 0x230 */
+	uint32_t rmon_t_p256to511;	/* MBAR_ETH + 0x234 */
+	uint32_t rmon_t_p512to1023;	/* MBAR_ETH + 0x238 */
+	uint32_t rmon_t_p1024to2047;	/* MBAR_ETH + 0x23C */
+	uint32_t rmon_t_p_gte2048;	/* MBAR_ETH + 0x240 */
+	uint32_t rmon_t_octets;		/* MBAR_ETH + 0x244 */
+	uint32_t ieee_t_drop;		/* MBAR_ETH + 0x248 */
+	uint32_t ieee_t_frame_ok;	/* MBAR_ETH + 0x24C */
+	uint32_t ieee_t_1col;		/* MBAR_ETH + 0x250 */
+	uint32_t ieee_t_mcol;		/* MBAR_ETH + 0x254 */
+	uint32_t ieee_t_def;		/* MBAR_ETH + 0x258 */
+	uint32_t ieee_t_lcol;		/* MBAR_ETH + 0x25C */
+	uint32_t ieee_t_excol;		/* MBAR_ETH + 0x260 */
+	uint32_t ieee_t_macerr;		/* MBAR_ETH + 0x264 */
+	uint32_t ieee_t_cserr;		/* MBAR_ETH + 0x268 */
+	uint32_t ieee_t_sqe;		/* MBAR_ETH + 0x26C */
+	uint32_t t_fdxfc;		/* MBAR_ETH + 0x270 */
+	uint32_t ieee_t_octets_ok;	/* MBAR_ETH + 0x274 */
+
+	uint32_t res13[2];		/* MBAR_ETH + 0x278-27C */
+	uint32_t rmon_r_drop;		/* MBAR_ETH + 0x280 */
+	uint32_t rmon_r_packets;	/* MBAR_ETH + 0x284 */
+	uint32_t rmon_r_bc_pkt;		/* MBAR_ETH + 0x288 */
+	uint32_t rmon_r_mc_pkt;		/* MBAR_ETH + 0x28C */
+	uint32_t rmon_r_crc_align;	/* MBAR_ETH + 0x290 */
+	uint32_t rmon_r_undersize;	/* MBAR_ETH + 0x294 */
+	uint32_t rmon_r_oversize;	/* MBAR_ETH + 0x298 */
+	uint32_t rmon_r_frag;		/* MBAR_ETH + 0x29C */
+	uint32_t rmon_r_jab;		/* MBAR_ETH + 0x2A0 */
+
+	uint32_t rmon_r_resvd_0;	/* MBAR_ETH + 0x2A4 */
+
+	uint32_t rmon_r_p64;		/* MBAR_ETH + 0x2A8 */
+	uint32_t rmon_r_p65to127;	/* MBAR_ETH + 0x2AC */
+	uint32_t rmon_r_p128to255;	/* MBAR_ETH + 0x2B0 */
+	uint32_t rmon_r_p256to511;	/* MBAR_ETH + 0x2B4 */
+	uint32_t rmon_r_p512to1023;	/* MBAR_ETH + 0x2B8 */
+	uint32_t rmon_r_p1024to2047;	/* MBAR_ETH + 0x2BC */
+	uint32_t rmon_r_p_gte2048;	/* MBAR_ETH + 0x2C0 */
+	uint32_t rmon_r_octets;		/* MBAR_ETH + 0x2C4 */
+	uint32_t ieee_r_drop;		/* MBAR_ETH + 0x2C8 */
+	uint32_t ieee_r_frame_ok;	/* MBAR_ETH + 0x2CC */
+	uint32_t ieee_r_crc;		/* MBAR_ETH + 0x2D0 */
+	uint32_t ieee_r_align;		/* MBAR_ETH + 0x2D4 */
+	uint32_t r_macerr;		/* MBAR_ETH + 0x2D8 */
+	uint32_t r_fdxfc;		/* MBAR_ETH + 0x2DC */
+	uint32_t ieee_r_octets_ok;	/* MBAR_ETH + 0x2E0 */
+
+	uint32_t res14[6];		/* MBAR_ETH + 0x2E4-2FC */
+
+	uint32_t res15[64];		/* MBAR_ETH + 0x300-3FF */
+};
+
+#define FEC_IEVENT_HBERR		0x80000000
+#define FEC_IEVENT_BABR			0x40000000
+#define FEC_IEVENT_BABT			0x20000000
+#define FEC_IEVENT_GRA			0x10000000
+#define FEC_IEVENT_TXF			0x08000000
+#define FEC_IEVENT_TXB			0x04000000
+#define FEC_IEVENT_RXF			0x02000000
+#define FEC_IEVENT_RXB			0x01000000
+#define FEC_IEVENT_MII			0x00800000
+#define FEC_IEVENT_EBERR		0x00400000
+#define FEC_IEVENT_LC			0x00200000
+#define FEC_IEVENT_RL			0x00100000
+#define FEC_IEVENT_UN			0x00080000
+
+#define FEC_IMASK_HBERR			0x80000000
+#define FEC_IMASK_BABR			0x40000000
+#define FEC_IMASKT_BABT			0x20000000
+#define FEC_IMASK_GRA			0x10000000
+#define FEC_IMASKT_TXF			0x08000000
+#define FEC_IMASK_TXB			0x04000000
+#define FEC_IMASKT_RXF			0x02000000
+#define FEC_IMASK_RXB			0x01000000
+#define FEC_IMASK_MII			0x00800000
+#define FEC_IMASK_EBERR			0x00400000
+#define FEC_IMASK_LC			0x00200000
+#define FEC_IMASKT_RL			0x00100000
+#define FEC_IMASK_UN			0x00080000
+
+
+#define FEC_RCNTRL_MAX_FL_SHIFT		16
+#define FEC_RCNTRL_LOOP			0x00000001
+#define FEC_RCNTRL_DRT			0x00000002
+#define FEC_RCNTRL_MII_MODE		0x00000004
+#define FEC_RCNTRL_PROM			0x00000008
+#define FEC_RCNTRL_BC_REJ		0x00000010
+#define FEC_RCNTRL_FCE			0x00000020
+
+#define FEC_TCNTRL_GTS			0x00000001
+#define FEC_TCNTRL_HBC			0x00000002
+#define FEC_TCNTRL_FDEN			0x00000004
+#define FEC_TCNTRL_TFC_PAUSE		0x00000008
+#define FEC_TCNTRL_RFC_PAUSE		0x00000010
+
+#define FEC_ECNTRL_RESET		0x00000001	/* reset the FEC */
+#define FEC_ECNTRL_ETHER_EN		0x00000002	/* enable the FEC */
+
+/**
+ * @brief Descriptor buffer alignment
+ *
+ * i.MX27 requires a 16 byte alignment (but for the first element only)
+ */
+#define DB_ALIGNMENT		16
+
+/**
+ * @brief Data buffer alignment
+ *
+ * i.MX27 requires a four byte alignment for transmit and 16 bits
+ * alignment for receive so take 16
+ * Note: Valid for member data_pointer in struct buffer_descriptor
+ */
+#define DB_DATA_ALIGNMENT	16
+
+/**
+ * @brief Receive & Transmit Buffer Descriptor definitions
+ *
+ * Note: The first BD must be aligned (see DB_ALIGNMENT)
+ */
+struct fec_bd {
+	uint16_t data_length;		/* payload's length in bytes */
+	uint16_t status;		/* BD's staus (see datasheet) */
+	uint32_t data_pointer;		/* payload's buffer address */
+};
+
+/**
+ * Supported phy types on this platform
+ */
+enum xceiver_type {
+	SEVENWIRE,	/* 7-wire       */
+	MII10,		/* MII 10Mbps   */
+	MII100		/* MII 100Mbps  */
+};
+
+/**
+ * @brief i.MX27-FEC private structure
+ */
+struct fec_priv {
+	struct ethernet_regs *eth;	/* pointer to register'S base */
+	enum xceiver_type xcv_type;	/* transceiver type */
+	struct fec_bd *rbd_base;	/* RBD ring */
+	int rbd_index;			/* next receive BD to read */
+	struct fec_bd *tbd_base;	/* TBD ring */
+	int tbd_index;			/* next transmit BD to write */
+	bd_t *bd;
+	void *rdb_ptr;
+	void *base_ptr;
+};
+
+/**
+ * @brief Numbers of buffer descriptors for receiving
+ *
+ * The number defines the stocked memory buffers for the receiving task.
+ * Larger values makes no sense in this limited environment.
+ */
+#define FEC_RBD_NUM		64
+
+/**
+ * @brief Define the ethernet packet size limit in memory
+ *
+ * Note: Do not shrink this number. This will force the FEC to spread larger
+ * frames in more than one BD. This is nothing to worry about, but the current
+ * driver can't handle it.
+ */
+#define FEC_MAX_PKT_SIZE	1536
+
+/* Receive BD status bits */
+#define FEC_RBD_EMPTY	0x8000	/* Receive BD status: Buffer is empty */
+#define FEC_RBD_WRAP	0x2000	/* Receive BD status: Last BD in ring */
+/* Receive BD status: Buffer is last in frame (useless here!) */
+#define FEC_RBD_LAST	0x0800
+#define FEC_RBD_MISS	0x0100	/* Receive BD status: Miss bit for prom mode */
+/* Receive BD status: The received frame is broadcast frame */
+#define FEC_RBD_BC	0x0080
+/* Receive BD status: The received frame is multicast frame */
+#define FEC_RBD_MC	0x0040
+#define FEC_RBD_LG	0x0020	/* Receive BD status: Frame length violation */
+#define FEC_RBD_NO	0x0010	/* Receive BD status: Nonoctet align frame */
+#define FEC_RBD_CR	0x0004	/* Receive BD status: CRC error */
+#define FEC_RBD_OV	0x0002	/* Receive BD status: Receive FIFO overrun */
+#define FEC_RBD_TR	0x0001	/* Receive BD status: Frame is truncated */
+#define FEC_RBD_ERR	(FEC_RBD_LG | FEC_RBD_NO | FEC_RBD_CR | \
+			FEC_RBD_OV | FEC_RBD_TR)
+
+/* Transmit BD status bits */
+#define FEC_TBD_READY	0x8000	/* Tansmit BD status: Buffer is ready */
+#define FEC_TBD_WRAP	0x2000	/* Tansmit BD status: Mark as last BD in ring */
+#define FEC_TBD_LAST	0x0800	/* Tansmit BD status: Buffer is last in frame */
+#define FEC_TBD_TC	0x0400	/* Tansmit BD status: Transmit the CRC */
+#define FEC_TBD_ABC	0x0200	/* Tansmit BD status: Append bad CRC */
+
+/* MII-related definitios */
+#define FEC_MII_DATA_ST		0x40000000	/* Start of frame delimiter */
+#define FEC_MII_DATA_OP_RD	0x20000000	/* Perform a read operation */
+#define FEC_MII_DATA_OP_WR	0x10000000	/* Perform a write operation */
+#define FEC_MII_DATA_PA_MSK	0x0f800000	/* PHY Address field mask */
+#define FEC_MII_DATA_RA_MSK	0x007c0000	/* PHY Register field mask */
+#define FEC_MII_DATA_TA		0x00020000	/* Turnaround */
+#define FEC_MII_DATA_DATAMSK	0x0000ffff	/* PHY data field */
+
+#define FEC_MII_DATA_RA_SHIFT	18	/* MII Register address bits */
+#define FEC_MII_DATA_PA_SHIFT	23	/* MII PHY address bits */
+
+#endif	/* __FEC_MXC_H */
diff --git a/include/netdev.h b/include/netdev.h
index aed5c4c..7d88ca4 100644
--- a/include/netdev.h
+++ b/include/netdev.h
@@ -50,6 +50,7 @@ int e1000_initialize(bd_t *bis);
 int eepro100_initialize(bd_t *bis);
 int eth_3com_initialize (bd_t * bis);
 int fec_initialize (bd_t *bis);
+int fecimx27_initialize (bd_t *bis);
 int greth_initialize(bd_t *bis);
 void gt6426x_eth_initialize(bd_t *bis);
 int inca_switch_initialize(bd_t *bis);
-- 
1.6.0.6

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

* [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD
  2009-06-21 11:21   ` Jean-Christophe PLAGNIOL-VILLARD
  2009-06-23 16:55     ` Detlev Zundel
  2009-07-07 19:24     ` Wolfgang Denk
@ 2009-07-17 11:00     ` Ilya Yanok
  2009-07-22 21:37       ` Jean-Christophe PLAGNIOL-VILLARD
  2 siblings, 1 reply; 70+ messages in thread
From: Ilya Yanok @ 2009-07-17 11:00 UTC (permalink / raw)
  To: u-boot

This patch adds support for i.MX27-LITEKIT development board from
LogicPD. This board uses i.MX27 SoC and has 2MB NOR flash, 64MB NAND
flash, FEC ethernet controller integrated into i.MX27.

Signed-off-by: Ilya Yanok <yanok@emcraft.com>
---
 MAINTAINERS                             |    1 +
 MAKEALL                                 |    1 +
 Makefile                                |    3 +
 board/logicpd/imx27lite/Makefile        |   51 ++++++
 board/logicpd/imx27lite/config.mk       |    1 +
 board/logicpd/imx27lite/imx27lite.c     |  102 ++++++++++++
 board/logicpd/imx27lite/lowlevel_init.S |  170 ++++++++++++++++++++
 include/configs/imx27lite.h             |  255 +++++++++++++++++++++++++++++++
 8 files changed, 584 insertions(+), 0 deletions(-)
 create mode 100644 board/logicpd/imx27lite/Makefile
 create mode 100644 board/logicpd/imx27lite/config.mk
 create mode 100644 board/logicpd/imx27lite/imx27lite.c
 create mode 100644 board/logicpd/imx27lite/lowlevel_init.S
 create mode 100644 include/configs/imx27lite.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 575a7ec..61ea2cf 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -533,6 +533,7 @@ George G. Davis <gdavis@mvista.com>
 	gcplus		SA1100
 
 Wolfgang Denk <wd@denx.de>
+	imx27lite	i.MX27
 	qong		i.MX31
 
 Thomas Elste <info@elste.org>
diff --git a/MAKEALL b/MAKEALL
index 020ff73..69520fc 100755
--- a/MAKEALL
+++ b/MAKEALL
@@ -510,6 +510,7 @@ LIST_ARM9="			\
 	cp926ejs		\
 	cp946es			\
 	cp966			\
+	imx27lite		\
 	lpd7a400		\
 	mx1ads			\
 	mx1fs2			\
diff --git a/Makefile b/Makefile
index 090e645..5e95558 100644
--- a/Makefile
+++ b/Makefile
@@ -2888,6 +2888,9 @@ davinci_sonata_config :	unconfig
 davinci_dm355evm_config :	unconfig
 	@$(MKCONFIG) $(@:_config=) arm arm926ejs dm355evm davinci davinci
 
+imx27lite_config:	unconfig
+	@$(MKCONFIG) $(@:_config=) arm arm926ejs imx27lite logicpd mx27
+
 lpd7a400_config \
 lpd7a404_config:	unconfig
 	@$(MKCONFIG) $(@:_config=) arm lh7a40x lpd7a40x
diff --git a/board/logicpd/imx27lite/Makefile b/board/logicpd/imx27lite/Makefile
new file mode 100644
index 0000000..c404cef
--- /dev/null
+++ b/board/logicpd/imx27lite/Makefile
@@ -0,0 +1,51 @@
+#
+# (C) Copyright 2000-2004
+# 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).a
+
+COBJS	:= imx27lite.o
+SOBJS	:= lowlevel_init.o
+
+SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+SOBJS	:= $(addprefix $(obj),$(SOBJS))
+
+$(LIB):	$(obj).depend $(OBJS) $(SOBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS)
+
+clean:
+	rm -f $(SOBJS) $(OBJS)
+
+distclean:	clean
+	rm -f $(LIB) core *.bak $(obj).depend
+
+#########################################################################
+
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
+
diff --git a/board/logicpd/imx27lite/config.mk b/board/logicpd/imx27lite/config.mk
new file mode 100644
index 0000000..a2e7768
--- /dev/null
+++ b/board/logicpd/imx27lite/config.mk
@@ -0,0 +1 @@
+TEXT_BASE = 0xA7F00000
diff --git a/board/logicpd/imx27lite/imx27lite.c b/board/logicpd/imx27lite/imx27lite.c
new file mode 100644
index 0000000..421da17
--- /dev/null
+++ b/board/logicpd/imx27lite/imx27lite.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2007 Sascha Hauer, Pengutronix
+ * Copyright (C) 2008,2009 Eric Jarrige <jorasse@users.sourceforge.net>
+ * Copyright (C) 2009 Ilya Yanok <yanok@emcraft.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
+ *
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int imx27lite_devices_init(void)
+{
+	struct gpio_regs *regs = (struct gpio_regs *)IMX_GPIO_BASE;
+	int i;
+	unsigned int mode[] = {
+		PD0_AIN_FEC_TXD0,
+		PD1_AIN_FEC_TXD1,
+		PD2_AIN_FEC_TXD2,
+		PD3_AIN_FEC_TXD3,
+		PD4_AOUT_FEC_RX_ER,
+		PD5_AOUT_FEC_RXD1,
+		PD6_AOUT_FEC_RXD2,
+		PD7_AOUT_FEC_RXD3,
+		PD8_AF_FEC_MDIO,
+		PD9_AIN_FEC_MDC | GPIO_PUEN,
+		PD10_AOUT_FEC_CRS,
+		PD11_AOUT_FEC_TX_CLK,
+		PD12_AOUT_FEC_RXD0,
+		PD13_AOUT_FEC_RX_DV,
+		PD14_AOUT_FEC_CLR,
+		PD15_AOUT_FEC_COL,
+		PD16_AIN_FEC_TX_ER,
+		PF23_AIN_FEC_TX_EN,
+		PE12_PF_UART1_TXD,
+		PE13_PF_UART1_RXD,
+		PB4_PF_SD2_D0,
+		PB5_PF_SD2_D1,
+		PB6_PF_SD2_D2,
+		PB7_PF_SD2_D3,
+		PB8_PF_SD2_CMD,
+		PB9_PF_SD2_CLK,
+		(GPIO_PORTC | GPIO_OUT | GPIO_PUEN | GPIO_GPIO | 31),
+	};
+
+	for (i = 0; i < ARRAY_SIZE(mode); i++)
+		imx_gpio_mode(mode[i]);
+
+	writel(readl(&regs->port[PORTC].dr) | (1 << 31),
+				&regs->port[PORTC].dr);
+	return 0;
+}
+
+int board_init (void)
+{
+	gd->bd->bi_arch_number = MACH_TYPE_IMX27LITE;
+	gd->bd->bi_boot_params = 0xa0000100;
+
+	imx27lite_devices_init();
+
+	return 0;
+}
+
+int dram_init (void)
+{
+
+#if CONFIG_NR_DRAM_BANKS > 0
+	gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
+	gd->bd->bi_dram[0].size = get_ram_size((volatile void *)PHYS_SDRAM_1,
+			PHYS_SDRAM_1_SIZE);
+#endif
+#if CONFIG_NR_DRAM_BANKS > 1
+	gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
+	gd->bd->bi_dram[1].size = get_ram_size((volatile void *)PHYS_SDRAM_2,
+			PHYS_SDRAM_2_SIZE);
+#endif
+
+	return 0;
+}
+
+int checkboard(void)
+{
+	printf("LogicPD imx27lite\n");
+	return 0;
+}
diff --git a/board/logicpd/imx27lite/lowlevel_init.S b/board/logicpd/imx27lite/lowlevel_init.S
new file mode 100644
index 0000000..e2cdecb
--- /dev/null
+++ b/board/logicpd/imx27lite/lowlevel_init.S
@@ -0,0 +1,170 @@
+/*
+ * For clock initialization, see chapter 3 of the "MCIMX27 Multimedia
+ * Applications Processor Reference Manual, Rev. 0.2".
+ *
+ * (C) Copyright 2008 Eric Jarrige <eric.jarrige@armadeus.org>
+ * (C) Copyright 2009 Ilya Yanok <yanok@emcraft.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
+ */
+
+
+#include <config.h>
+#include <version.h>
+#include <asm/macro.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/asm-offsets.h>
+
+SOC_ESDCTL_BASE_W:	.word	IMX_ESD_BASE
+SOC_SI_ID_REG_W:	.word	IMX_SYSTEM_CTL_BASE
+SDRAM_ESDCFG_T1_W:	.word	SDRAM_ESDCFG_REGISTER_VAL(0)
+SDRAM_ESDCFG_T2_W:	.word	SDRAM_ESDCFG_REGISTER_VAL(3)
+SDRAM_PRECHARGE_CMD_W:	.word	(ESDCTL_SDE | ESDCTL_SMODE_PRECHARGE | \
+				 ESDCTL_ROW13 | ESDCTL_COL10)
+SDRAM_AUTOREF_CMD_W:	.word	(ESDCTL_SDE | ESDCTL_SMODE_AUTO_REF | \
+				 ESDCTL_ROW13 | ESDCTL_COL10)
+SDRAM_LOADMODE_CMD_W:	.word	(ESDCTL_SDE | ESDCTL_SMODE_LOAD_MODE | \
+				 ESDCTL_ROW13 | ESDCTL_COL10)
+SDRAM_NORMAL_CMD_W:	.word	SDRAM_ESDCTL_REGISTER_VAL
+
+.macro init_aipi
+	/*
+	 * setup AIPI1 and AIPI2
+	 */
+	write32 AIPI1_PSR0, AIPI1_PSR0_VAL
+	write32 AIPI1_PSR1, AIPI1_PSR1_VAL
+	write32 AIPI2_PSR0, AIPI2_PSR0_VAL
+	write32 AIPI2_PSR1, AIPI2_PSR1_VAL
+
+.endm /* init_aipi */
+
+.macro init_clock
+	ldr r0, =CSCR
+	/* disable MPLL/SPLL first */
+	ldr r1, [r0]
+	bic r1, r1, #(CSCR_MPEN|CSCR_SPEN)
+	str r1, [r0]
+
+	write32 MPCTL0, MPCTL0_VAL
+	write32 SPCTL0, SPCTL0_VAL
+
+	write32 CSCR, CSCR_VAL | CSCR_MPLL_RESTART | CSCR_SPLL_RESTART
+
+	/*
+	 * add some delay here
+	 */
+	wait_timer 0x1000
+
+	/* peripheral clock divider */
+	write32 PCDR0, PCDR0_VAL
+	write32 PCDR1, PCDR1_VAL
+
+	/* Configure PCCR0 and PCCR1 */
+	write32 PCCR0, PCCR0_VAL
+	write32 PCCR1, PCCR1_VAL
+
+.endm /* init_clock */
+
+.macro sdram_init
+	ldr r0, SOC_ESDCTL_BASE_W
+	mov r2, #PHYS_SDRAM_1
+
+	/* Do initial reset */
+	mov r1, #ESDMISC_MDDR_DL_RST
+	str r1, [r0, #ESDMISC_ROF]
+
+	/* Hold for more than 200ns */
+	wait_timer 0x10000
+
+	/* Activate LPDDR iface */
+	mov r1, #ESDMISC_MDDREN
+	str r1, [r0, #ESDMISC_ROF]
+
+	/* Check The chip version TO1 or TO2 */
+	ldr r1, SOC_SI_ID_REG_W
+	ldr r1, [r1]
+	ands r1, r1, #0xF0000000
+	/* add Latency on CAS only for TO2 */
+	ldreq r1, SDRAM_ESDCFG_T2_W
+	ldrne r1, SDRAM_ESDCFG_T1_W
+	str r1, [r0, #ESDCFG0_ROF]
+
+	/* Run initialization sequence */
+	ldr r1, SDRAM_PRECHARGE_CMD_W
+	str r1, [r0, #ESDCTL0_ROF]
+	ldr r1, [r2, #SDRAM_ALL_VAL]
+
+	ldr r1, SDRAM_AUTOREF_CMD_W
+	str r1, [r0, #ESDCTL0_ROF]
+	ldr r1, [r2, #SDRAM_ALL_VAL]
+	ldr r1, [r2, #SDRAM_ALL_VAL]
+
+	ldr r1, SDRAM_LOADMODE_CMD_W
+	str r1, [r0, #ESDCTL0_ROF]
+	ldrb r1, [r2, #SDRAM_MODE_REGISTER_VAL]
+	add r3, r2, #SDRAM_EXT_MODE_REGISTER_VAL
+	ldrb r1, [r3]
+
+	ldr r1, SDRAM_NORMAL_CMD_W
+	str r1, [r0, #ESDCTL0_ROF]
+
+#if (CONFIG_NR_DRAM_BANKS > 1)
+	/* 2nd sdram */
+	mov r2, #PHYS_SDRAM_2
+
+	/* Check The chip version TO1 or TO2 */
+	ldr r1, SOC_SI_ID_REG_W
+	ldr r1, [r1]
+	ands r1, r1, #0xF0000000
+	/* add Latency on CAS only for TO2 */
+	ldreq r1, SDRAM_ESDCFG_T2_W
+	ldrne r1, SDRAM_ESDCFG_T1_W
+	str r1, [r0, #ESDCFG1_ROF]
+
+	/* Run initialization sequence */
+	ldr r1, SDRAM_PRECHARGE_CMD_W
+	str r1, [r0, #ESDCTL1_ROF]
+	ldr r1, [r2, #SDRAM_ALL_VAL]
+
+	ldr r1, SDRAM_AUTOREF_CMD_W
+	str r1, [r0, #ESDCTL1_ROF]
+	ldr r1, [r2, #SDRAM_ALL_VAL]
+	ldr r1, [r2, #SDRAM_ALL_VAL]
+
+	ldr r1, SDRAM_LOADMODE_CMD_W
+	str r1, [r0, #ESDCTL1_ROF]
+	ldrb r1, [r2, #SDRAM_MODE_REGISTER_VAL]
+	add r3, r2, #SDRAM_EXT_MODE_REGISTER_VAL
+	ldrb r1, [r3]
+
+	ldr r1, SDRAM_NORMAL_CMD_W
+	str r1, [r0, #ESDCTL1_ROF]
+#endif  /* CONFIG_NR_DRAM_BANKS > 1 */
+
+.endm /* sdram_init */
+
+.globl	lowlevel_init
+lowlevel_init:
+
+	mov	r10, lr
+
+	init_aipi
+
+	init_clock
+
+	sdram_init
+
+	mov	pc,r10
diff --git a/include/configs/imx27lite.h b/include/configs/imx27lite.h
new file mode 100644
index 0000000..7822748
--- /dev/null
+++ b/include/configs/imx27lite.h
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2009 Ilya Yanok <yanok@emcraft.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 __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * SoC Configuration
+ */
+#define CONFIG_ARM926EJS			/* arm926ejs CPU core */
+#define CONFIG_MX27
+#define CONFIG_IMX27LITE
+#define CONFIG_MX27_CLK32	32768		/* OSC32K frequency */
+#define CONFIG_SYS_HZ		1000
+
+#define CONFIG_DISPLAY_CPUINFO
+
+#define CONFIG_CMDLINE_TAG		1	/* enable passing of ATAGs */
+#define CONFIG_SETUP_MEMORY_TAGS	1
+#define CONFIG_INITRD_TAG		1
+
+/*
+ * Lowlevel configuration
+ */
+#define SDRAM_ESDCFG_REGISTER_VAL(cas)	\
+		(ESDCFG_TRC(10) |	\
+		ESDCFG_TRCD(3) |	\
+		ESDCFG_TCAS(cas) |	\
+		ESDCFG_TRRD(1) |	\
+		ESDCFG_TRAS(5) |	\
+		ESDCFG_TWR |		\
+		ESDCFG_TMRD(2) |	\
+		ESDCFG_TRP(2) |		\
+		ESDCFG_TXP(3))
+
+#define SDRAM_ESDCTL_REGISTER_VAL	\
+		(ESDCTL_PRCT(0) |	\
+		 ESDCTL_BL |		\
+		 ESDCTL_PWDT(0) |	\
+		 ESDCTL_SREFR(3) |	\
+		 ESDCTL_DSIZ_32 |	\
+		 ESDCTL_COL10 |		\
+		 ESDCTL_ROW13 |		\
+		 ESDCTL_SDE)
+
+#define SDRAM_ALL_VAL		0xf00
+
+#define SDRAM_MODE_REGISTER_VAL	0x33	/* BL: 8, CAS: 3 */
+#define SDRAM_EXT_MODE_REGISTER_VAL	0x1000000
+
+#define MPCTL0_VAL	0x1ef15d5
+
+#define SPCTL0_VAL	0x043a1c09
+
+#define CSCR_VAL	0x33f08107
+
+#define PCDR0_VAL	0x120470c3
+#define PCDR1_VAL	0x03030303
+#define PCCR0_VAL	0xffffffff
+#define PCCR1_VAL	0xfffffffc
+
+#define AIPI1_PSR0_VAL	0x20040304
+#define AIPI1_PSR1_VAL	0xdffbfcfb
+#define AIPI2_PSR0_VAL	0x07ffc200
+#define AIPI2_PSR1_VAL	0xffffffff
+
+/*
+ * Memory Info
+ */
+/* malloc() len */
+#define CONFIG_SYS_MALLOC_LEN		(0x10000 + 256 * 1024)
+/* reserved for initial data */
+#define CONFIG_SYS_GBL_DATA_SIZE	128
+/* memtest start address */
+#define CONFIG_SYS_MEMTEST_START	0xA0000000
+#define CONFIG_SYS_MEMTEST_END		0xA1000000	/* 16MB RAM test */
+#define CONFIG_NR_DRAM_BANKS	1		/* we have 1 bank of DRAM */
+#define CONFIG_STACKSIZE	(256 * 1024)	/* regular stack */
+#define PHYS_SDRAM_1		0xA0000000	/* DDR Start */
+#define PHYS_SDRAM_1_SIZE	0x08000000	/* DDR size 128MB */
+
+/*
+ * Serial Driver info
+ */
+#define CONFIG_MXC_UART
+#define CONFIG_SYS_MX27_UART1
+#define CONFIG_CONS_INDEX	1		/* use UART0 for console */
+#define CONFIG_BAUDRATE		115200		/* Default baud rate */
+#define CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 }
+
+/*
+ * Flash & Environment
+ */
+#define CONFIG_ENV_IS_IN_FLASH
+#define CONFIG_FLASH_CFI_DRIVER
+#define CONFIG_SYS_FLASH_CFI
+/* Use buffered writes (~10x faster) */
+#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE	1
+/* Use hardware sector protection */
+#define CONFIG_SYS_FLASH_PROTECTION		1
+#define CONFIG_SYS_MAX_FLASH_BANKS	1	/* max number of flash banks */
+#define CONFIG_SYS_FLASH_SECT_SZ	0x2000	/* 8KB sect size Intel Flash */
+/* end of flash */
+#define CONFIG_ENV_OFFSET		(PHYS_FLASH_SIZE - 0x20000)
+/* CS2 Base address */
+#define PHYS_FLASH_1			0xc0000000
+/* Flash Base for U-Boot */
+#define CONFIG_SYS_FLASH_BASE		PHYS_FLASH_1
+/* Flash size 2MB */
+#define PHYS_FLASH_SIZE			0x200000
+#define CONFIG_SYS_MAX_FLASH_SECT	(PHYS_FLASH_SIZE / \
+		CONFIG_SYS_FLASH_SECT_SZ)
+#define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_FLASH_BASE
+#define CONFIG_SYS_MONITOR_LEN		0x40000		/* Reserve 256KiB */
+#define CONFIG_ENV_SECT_SIZE		0x10000		/* Env sector Size */
+#define CONFIG_ENV_SIZE		CONFIG_ENV_SECT_SIZE
+/* Address and size of Redundant Environment Sector	*/
+#define CONFIG_ENV_OFFSET_REDUND	(CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE)
+#define CONFIG_ENV_SIZE_REDUND	CONFIG_ENV_SIZE
+
+/*
+ * Ethernet
+ */
+#define CONFIG_FEC_MXC
+#define CONFIG_FEC_MXC_PHYADDR		0x1f
+#define CONFIG_MII
+#define CONFIG_NET_MULTI
+
+/*
+ * MTD
+ */
+#define CONFIG_MTD_DEVICE
+
+/*
+ * NAND
+ */
+#define CONFIG_NAND_MXC
+#define CONFIG_MXC_NAND_REGS_BASE	0xd8000000
+#define CONFIG_SYS_MAX_NAND_DEVICE	1
+#define CONFIG_SYS_NAND_BASE		0xd8000000
+#define CONFIG_JFFS2_NAND
+#define CONFIG_MXC_NAND_HWECC
+
+/*
+ * SD/MMC
+ */
+#define CONFIG_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_MXC_MMC
+#define CONFIG_MXC_MCI_REGS_BASE	0x10014000
+#define CONFIG_DOS_PARTITION
+
+/*
+ * MTD partitions
+ */
+#define CONFIG_CMD_MTDPARTS
+#define MTDIDS_DEFAULT		"nor0=physmap-flash.0,nand0=mxc_nand.0"
+#define MTDPARTS_DEFAULT			\
+	"mtdparts="				\
+		"physmap-flash.0:"		\
+			"256k(U-Boot),"		\
+			"1664k(user),"		\
+			"64k(env1),"		\
+			"64k(env2);"		\
+		"mxc_nand.0:"			\
+			"128k(IPL-SPL),"	\
+			"4m(kernel),"		\
+			"22m(rootfs),"		\
+			"-(userfs)"
+
+/*
+ * U-Boot general configuration
+ */
+#define CONFIG_BOOTFILE		"uImage"	/* Boot file name */
+#define CONFIG_SYS_PROMPT	"=> "	/* Monitor Command Prompt */
+#define CONFIG_SYS_CBSIZE	1024	/* Console I/O Buffer Size  */
+/* Print buffer sz */
+#define CONFIG_SYS_PBSIZE	(CONFIG_SYS_CBSIZE + \
+		sizeof(CONFIG_SYS_PROMPT) + 16)
+#define CONFIG_SYS_MAXARGS	16	/* max number of command args */
+/* Boot Argument Buffer Size */
+#define CONFIG_SYS_BARGSIZE	CONFIG_SYS_CBSIZE
+#define CONFIG_CMDLINE_EDITING
+#define CONFIG_SYS_LONGHELP
+
+/*
+ * U-Boot commands
+ */
+#include <config_cmd_default.h>
+#define CONFIG_CMD_ASKENV
+#define CONFIG_CMD_BDI
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_DIAG
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_JFFS2
+#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_BOOTDELAY	5
+
+#define CONFIG_LOADADDR		0xa0800000	/* loadaddr env var */
+#define CONFIG_SYS_LOAD_ADDR		CONFIG_LOADADDR
+
+#define xstr(s)	str(s)
+#define str(s)	#s
+
+#define	CONFIG_EXTRA_ENV_SETTINGS					\
+	"netdev=eth0\0"							\
+	"nfsargs=setenv bootargs root=/dev/nfs rw "			\
+		"nfsroot=${serverip}:${rootpath}\0"			\
+	"ramargs=setenv bootargs root=/dev/ram rw\0"			\
+	"addip=setenv bootargs ${bootargs} "				\
+		"ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}"	\
+		":${hostname}:${netdev}:off panic=1\0"			\
+	"addtty=setenv bootargs ${bootargs}"				\
+		" console=ttymxc0,${baudrate}\0"			\
+	"addmtd=setenv bootargs ${bootargs} ${mtdparts}\0"		\
+	"addmisc=setenv bootargs ${bootargs}\0"				\
+	"u-boot=imx27/u-boot.bin\0"					\
+	"kernel_addr_r=a0800000\0"					\
+	"hostname=imx27\0"						\
+	"bootfile=imx27/uImage\0"					\
+	"rootpath=/opt/eldk-4.2-arm/arm\0"				\
+	"net_nfs=tftp ${kernel_addr_r} ${bootfile};"			\
+		"run nfsargs addip addtty addmtd addmisc;"		\
+		"bootm\0"						\
+	"bootcmd=run net_nfs\0"					\
+	"load=tftp ${loadaddr} ${u-boot}\0"				\
+	"update=protect off " xstr(CONFIG_SYS_MONITOR_BASE)		\
+		" +${filesize};era " xstr(CONFIG_SYS_MONITOR_BASE)	\
+		" +${filesize};cp.b ${fileaddr} "			\
+		xstr(CONFIG_SYS_MONITOR_BASE) " ${filesize}\0"		\
+	"upd=run load update\0"						\
+
+#endif /* __CONFIG_H */
-- 
1.6.0.6

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

* [U-Boot] [PATCH] fec_mxc: driver for FEC ethernet controller on i.MX27
  2009-07-17 10:57   ` [U-Boot] [PATCH] fec_mxc: " Ilya Yanok
@ 2009-07-17 14:05     ` Ben Warren
  2009-07-21 15:32       ` Ilya Yanok
  0 siblings, 1 reply; 70+ messages in thread
From: Ben Warren @ 2009-07-17 14:05 UTC (permalink / raw)
  To: u-boot

Hi Ilya,

On Fri, Jul 17, 2009 at 3:57 AM, Ilya Yanok <yanok@emcraft.com> wrote:

> Signed-off-by: Ilya Yanok <yanok@emcraft.com>
> ---
>  cpu/arm926ejs/mx27/generic.c |   10 +
>  drivers/net/Makefile         |    1 +
>  drivers/net/fec_mxc.c        |  742
> ++++++++++++++++++++++++++++++++++++++++++
>  drivers/net/fec_mxc.h        |  304 +++++++++++++++++
>  include/netdev.h             |    1 +
>  5 files changed, 1058 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/net/fec_mxc.c
>  create mode 100644 drivers/net/fec_mxc.h
>
> diff --git a/cpu/arm926ejs/mx27/generic.c b/cpu/arm926ejs/mx27/generic.c
> index bcf7899..7f6fc69 100644
> --- a/cpu/arm926ejs/mx27/generic.c
> +++ b/cpu/arm926ejs/mx27/generic.c
> @@ -20,6 +20,7 @@
>
>  #include <common.h>
>  #include <div64.h>
> +#include <netdev.h>
>  #include <asm/io.h>
>  #include <asm/arch/imx-regs.h>
>
> @@ -159,6 +160,15 @@ int print_cpuinfo (void)
>  }
>  #endif
>
> +int cpu_eth_init(bd_t *bis)
> +{
> +#if defined(CONFIG_FEC_IMX27)
> +       return fecimx27_initialize(bis);
> +#else
> +       return 0;
> +#endif
> +}
> +


The main reason why this was rejected previously was because you needlessly
restricted the scope to imx27, when there are other CPUs that apparently
share this FEC.  I see you've changed the name of the driver to something
more appropriately generic, but why not the name of the initialization
function?

Please rationalize this.  If you do so, I'll make sure to get the driver in
this release.

regards,
Ben

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

* [U-Boot] [PATCH 4/7] mxc_nand: add nand driver for MX2/MX3
  2009-07-17 10:48     ` Ilya Yanok
  2009-07-17 10:53       ` [U-Boot] [PATCH] " Ilya Yanok
@ 2009-07-17 16:00       ` Scott Wood
  1 sibling, 0 replies; 70+ messages in thread
From: Scott Wood @ 2009-07-17 16:00 UTC (permalink / raw)
  To: u-boot

On Fri, Jul 17, 2009 at 02:48:38PM +0400, Ilya Yanok wrote:
> Scott Wood wrote:
> > Please look at drivers/mtd/nand/mpc5121_nfc.c, which AFAICT is very
> > similar hardware, and see if anything can be factored out into common
> > code, and try to keep the rest looking the same except where the hardware
> > actually differs.
> >   
> 
> Hmm... For now we just can't spend enough effort for this...

Understood -- but I have to grumble about it regardless. :-)

> >> +/*
> >> + * This function requests the NANDFC to perform a read of the
> >> + * NAND device status and returns the current status.
> >> + */
> >> +static uint16_t get_dev_status(struct mxc_nand_host *host)
> >> +{
> >> +	void __iomem *main_buf = host->regs->main_area1;
> >> +	uint32_t store;
> >> +	uint16_t ret, tmp;
> >> +	/* Issue status request to NAND device */
> >> +
> >> +	/* store the main area1 first word, later do recovery */
> >> +	store = readl(main_buf);
> >> +	/*
> >> +	 * NANDFC buffer 1 is used for device status to prevent
> >> +	 * corruption of read/write buffer on status requests.
> >> +	 */
> >> +	writew(1, &host->regs->nfc_buf_addr);
> >>     
> >
> > But it looks like buffer 1 is used for data with large page flash.
> >   
> 
> Well, we save first word of the buffer and then recover it.

So then there's no longer any special reason to use buffer 1 for status,
and that comment is misleading...

> > Other drivers don't seem to have any problem with status reads clobbering
> > the buffer...

What's different about this hardware in that regard?  I'm wondering if
you're being more tolerant than you need to be of status requests coming
in at odd times.

> > According to Magnus Lilja, "the nand flash controller can only handle 32
> > bit read/write operations, any other size will cause an abort (or
> > something like that)".  But now we're accessing it as 16-bit?
> >   
> 
> 16-bit accesses work quite well. Problem was with 8-bit accesses.

OK.  But in that case I'd think it would have been simpler to use 16-bit
accesses rather than 32-bit when emulating byte accesses in
read_buf()/write_buf().

> > col should never be odd if you're reading words.
> >   
> 
> It can be odd if previously we've read a byte.

I don't think that accesses will ever be mixed in that way -- correct me
if I'm wrong.

In fact, I only see one use of read_word, which is to read the bad block
marker.

> >> +	host->pagesize_2k = 0;
> >>     
> >
> > So large page is currently unsupported?
> >   
> 
> Linux driver was fixed recently and now it claims to support 2K page
> size... I've added all needed fixes but I can understand how this driver
> should detect the pagesize... Linux driver calls nand_scan_ident()
> itself for this... Do you think I can calls nand_scan_ident() from my
> board_nand_init() function?

No, at the moment you should probably just hard code it in the board
config file.  I need to find some time to rework the NAND init mechanism
to be driven more from platform code so that it can split up
nand_scan_ident() and nand_scan_tail().

-Scott

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

* [U-Boot] [PATCH] fec_mxc: driver for FEC ethernet controller on i.MX27
  2009-07-17 14:05     ` Ben Warren
@ 2009-07-21 15:32       ` Ilya Yanok
  2009-07-22 22:23         ` Jean-Christophe PLAGNIOL-VILLARD
  2009-07-23  6:28         ` Ben Warren
  0 siblings, 2 replies; 70+ messages in thread
From: Ilya Yanok @ 2009-07-21 15:32 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Ilya Yanok <yanok@emcraft.com>
---
 cpu/arm926ejs/mx27/generic.c |   10 +
 drivers/net/Makefile         |    1 +
 drivers/net/fec_mxc.c        |  742 ++++++++++++++++++++++++++++++++++++++++++
 drivers/net/fec_mxc.h        |  304 +++++++++++++++++
 include/netdev.h             |    1 +
 5 files changed, 1058 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/fec_mxc.c
 create mode 100644 drivers/net/fec_mxc.h

diff --git a/cpu/arm926ejs/mx27/generic.c b/cpu/arm926ejs/mx27/generic.c
index bcf7899..47fa4b4 100644
--- a/cpu/arm926ejs/mx27/generic.c
+++ b/cpu/arm926ejs/mx27/generic.c
@@ -20,6 +20,7 @@
 
 #include <common.h>
 #include <div64.h>
+#include <netdev.h>
 #include <asm/io.h>
 #include <asm/arch/imx-regs.h>
 
@@ -159,6 +160,15 @@ int print_cpuinfo (void)
 }
 #endif
 
+int cpu_eth_init(bd_t *bis)
+{
+#if defined(CONFIG_FEC_MXC)
+	return fecmxc_initialize(bis);
+#else
+	return 0;
+#endif
+}
+
 void imx_gpio_mode(int gpio_mode)
 {
 	struct gpio_regs *regs = (struct gpio_regs *)IMX_GPIO_BASE;
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index c6097c3..f92dba7 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -37,6 +37,7 @@ COBJS-$(CONFIG_DNET) += dnet.o
 COBJS-$(CONFIG_E1000) += e1000.o
 COBJS-$(CONFIG_EEPRO100) += eepro100.o
 COBJS-$(CONFIG_ENC28J60) += enc28j60.o
+COBJS-$(CONFIG_FEC_MXC) += fec_mxc.o
 COBJS-$(CONFIG_FSLDMAFEC) += fsl_mcdmafec.o mcfmii.o
 COBJS-$(CONFIG_GRETH) += greth.o
 COBJS-$(CONFIG_INCA_IP_SWITCH) += inca-ip_sw.o
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
new file mode 100644
index 0000000..faf008c
--- /dev/null
+++ b/drivers/net/fec_mxc.c
@@ -0,0 +1,742 @@
+/*
+ * (C) Copyright 2009 Ilya Yanok, Emcraft Systems Ltd <yanok@emcraft.com>
+ * (C) Copyright 2008,2009 Eric Jarrige <eric.jarrige@armadeus.org>
+ * (C) Copyright 2008 Armadeus Systems nc
+ * (C) Copyright 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
+ * (C) Copyright 2007 Pengutronix, Juergen Beisert <j.beisert@pengutronix.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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <net.h>
+#include <miiphy.h>
+#include "fec_mxc.h"
+
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifndef CONFIG_MII
+#error "CONFIG_MII has to be defined!"
+#endif
+
+#undef DEBUG
+
+struct nbuf {
+	uint8_t data[1500];	/**< actual data */
+	int length;		/**< actual length */
+	int used;		/**< buffer in use or not */
+	uint8_t head[16];	/**< MAC header(6 + 6 + 2) + 2(aligned) */
+};
+
+struct fec_priv gfec = {
+	.eth       = (struct ethernet_regs *)IMX_FEC_BASE,
+	.xcv_type  = MII100,
+	.rbd_base  = NULL,
+	.rbd_index = 0,
+	.tbd_base  = NULL,
+	.tbd_index = 0,
+	.bd        = NULL,
+};
+
+/*
+ * MII-interface related functions
+ */
+static int fec_miiphy_read(char *dev, uint8_t phyAddr, uint8_t regAddr,
+		uint16_t *retVal)
+{
+	struct eth_device *edev = eth_get_dev_by_name(dev);
+	struct fec_priv *fec = (struct fec_priv *)edev->priv;
+
+	uint32_t reg;		/* convenient holder for the PHY register */
+	uint32_t phy;		/* convenient holder for the PHY */
+	uint32_t start;
+
+	/*
+	 * reading from any PHY's register is done by properly
+	 * programming the FEC's MII data register.
+	 */
+	writel(FEC_IEVENT_MII, &fec->eth->ievent);
+	reg = regAddr << FEC_MII_DATA_RA_SHIFT;
+	phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
+
+	writel(FEC_MII_DATA_ST | FEC_MII_DATA_OP_RD | FEC_MII_DATA_TA |
+			phy | reg, &fec->eth->mii_data);
+
+	/*
+	 * wait for the related interrupt
+	 */
+	start = get_timer_masked();
+	while (!(readl(&fec->eth->ievent) & FEC_IEVENT_MII)) {
+		if (get_timer(start) > (CONFIG_SYS_HZ / 1000)) {
+			printf("Read MDIO failed...\n");
+			return -1;
+		}
+	}
+
+	/*
+	 * clear mii interrupt bit
+	 */
+	writel(FEC_IEVENT_MII, &fec->eth->ievent);
+
+	/*
+	 * it's now safe to read the PHY's register
+	 */
+	*retVal = readl(&fec->eth->mii_data);
+	debug("fec_miiphy_read: phy: %02x reg:%02x val:%#x\n", phyAddr,
+			regAddr, *retVal);
+	return 0;
+}
+
+static int fec_miiphy_write(char *dev, uint8_t phyAddr, uint8_t regAddr,
+		uint16_t data)
+{
+	struct eth_device *edev = eth_get_dev_by_name(dev);
+	struct fec_priv *fec = (struct fec_priv *)edev->priv;
+
+	uint32_t reg;		/* convenient holder for the PHY register */
+	uint32_t phy;		/* convenient holder for the PHY */
+	uint32_t start;
+
+	reg = regAddr << FEC_MII_DATA_RA_SHIFT;
+	phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
+
+	writel(FEC_MII_DATA_ST | FEC_MII_DATA_OP_WR |
+		FEC_MII_DATA_TA | phy | reg | data, &fec->eth->mii_data);
+
+	/*
+	 * wait for the MII interrupt
+	 */
+	start = get_timer_masked();
+	while (!(readl(&fec->eth->ievent) & FEC_IEVENT_MII)) {
+		if (get_timer(start) > (CONFIG_SYS_HZ / 1000)) {
+			printf("Write MDIO failed...\n");
+			return -1;
+		}
+	}
+
+	/*
+	 * clear MII interrupt bit
+	 */
+	writel(FEC_IEVENT_MII, &fec->eth->ievent);
+	debug("fec_miiphy_write: phy: %02x reg:%02x val:%#x\n", phyAddr,
+			regAddr, data);
+
+	return 0;
+}
+
+static int miiphy_restart_aneg(struct eth_device *dev)
+{
+	/*
+	 * Wake up from sleep if necessary
+	 * Reset PHY, then delay 300ns
+	 */
+	miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, PHY_MIPGSR, 0x00FF);
+	miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, PHY_BMCR,
+			PHY_BMCR_RESET);
+	udelay(1000);
+
+	/*
+	 * Set the auto-negotiation advertisement register bits
+	 */
+	miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, PHY_ANAR, 0x1e0);
+	miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, PHY_BMCR,
+			PHY_BMCR_AUTON | PHY_BMCR_RST_NEG);
+
+	return 0;
+}
+
+static int miiphy_wait_aneg(struct eth_device *dev)
+{
+	uint32_t start;
+	uint16_t status;
+
+	/*
+	 * Wait for AN completion
+	 */
+	start = get_timer_masked();
+	do {
+		if (get_timer(start) > (CONFIG_SYS_HZ * 5)) {
+			printf("%s: Autonegotiation timeout\n", dev->name);
+			return -1;
+		}
+
+		if (miiphy_read(dev->name, CONFIG_FEC_MXC_PHYADDR,
+					PHY_BMSR, &status)) {
+			printf("%s: Autonegotiation failed. status: 0x%04x\n",
+					dev->name, status);
+			return -1;
+		}
+	} while (!(status & PHY_BMSR_LS));
+
+	return 0;
+}
+static int fec_rx_task_enable(struct fec_priv *fec)
+{
+	writel(1 << 24, &fec->eth->r_des_active);
+	return 0;
+}
+
+static int fec_rx_task_disable(struct fec_priv *fec)
+{
+	return 0;
+}
+
+static int fec_tx_task_enable(struct fec_priv *fec)
+{
+	writel(1 << 24, &fec->eth->x_des_active);
+	return 0;
+}
+
+static int fec_tx_task_disable(struct fec_priv *fec)
+{
+	return 0;
+}
+
+/**
+ * Initialize receive task's buffer descriptors
+ * @param[in] fec all we know about the device yet
+ * @param[in] count receive buffer count to be allocated
+ * @param[in] size size of each receive buffer
+ * @return 0 on success
+ *
+ * For this task we need additional memory for the data buffers. And each
+ * data buffer requires some alignment. Thy must be aligned to a specific
+ * boundary each (DB_DATA_ALIGNMENT).
+ */
+static int fec_rbd_init(struct fec_priv *fec, int count, int size)
+{
+	int ix;
+	uint32_t p = 0;
+
+	/* reserve data memory and consider alignment */
+	fec->rdb_ptr = malloc(size * count + DB_DATA_ALIGNMENT);
+	p = (uint32_t)fec->rdb_ptr;
+	if (!p) {
+		puts("fec_imx27: not enough malloc memory!\n");
+		return -ENOMEM;
+	}
+	memset((void *)p, 0, size * count + DB_DATA_ALIGNMENT);
+	p += DB_DATA_ALIGNMENT-1;
+	p &= ~(DB_DATA_ALIGNMENT-1);
+
+	for (ix = 0; ix < count; ix++) {
+		writel(p, &fec->rbd_base[ix].data_pointer);
+		p += size;
+		writew(FEC_RBD_EMPTY, &fec->rbd_base[ix].status);
+		writew(0, &fec->rbd_base[ix].data_length);
+	}
+	/*
+	 * mark the last RBD to close the ring
+	 */
+	writew(FEC_RBD_WRAP | FEC_RBD_EMPTY, &fec->rbd_base[ix - 1].status);
+	fec->rbd_index = 0;
+
+	return 0;
+}
+
+/**
+ * Initialize transmit task's buffer descriptors
+ * @param[in] fec all we know about the device yet
+ *
+ * Transmit buffers are created externally. We only have to init the BDs here.\n
+ * Note: There is a race condition in the hardware. When only one BD is in
+ * use it must be marked with the WRAP bit to use it for every transmitt.
+ * This bit in combination with the READY bit results into double transmit
+ * of each data buffer. It seems the state machine checks READY earlier then
+ * resetting it after the first transfer.
+ * Using two BDs solves this issue.
+ */
+static void fec_tbd_init(struct fec_priv *fec)
+{
+	writew(0x0000, &fec->tbd_base[0].status);
+	writew(FEC_TBD_WRAP, &fec->tbd_base[1].status);
+	fec->tbd_index = 0;
+}
+
+/**
+ * Mark the given read buffer descriptor as free
+ * @param[in] last 1 if this is the last buffer descriptor in the chain, else 0
+ * @param[in] pRbd buffer descriptor to mark free again
+ */
+static void fec_rbd_clean(int last, struct fec_bd *pRbd)
+{
+	/*
+	 * Reset buffer descriptor as empty
+	 */
+	if (last)
+		writew(FEC_RBD_WRAP | FEC_RBD_EMPTY, &pRbd->status);
+	else
+		writew(FEC_RBD_EMPTY, &pRbd->status);
+	/*
+	 * no data in it
+	 */
+	writew(0, &pRbd->data_length);
+}
+
+static int fec_get_hwaddr(struct eth_device *dev, unsigned char *mac)
+{
+	struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE;
+	int i;
+
+	for (i = 0; i < 6; i++)
+		mac[6-1-i] = readl(&iim->iim_bank_area0[IIM0_MAC + i]);
+
+	return is_valid_ether_addr(mac);
+}
+
+static int fec_set_hwaddr(struct eth_device *dev, unsigned char *mac)
+{
+	struct fec_priv *fec = (struct fec_priv *)dev->priv;
+
+	writel(0, &fec->eth->iaddr1);
+	writel(0, &fec->eth->iaddr2);
+	writel(0, &fec->eth->gaddr1);
+	writel(0, &fec->eth->gaddr2);
+
+	/*
+	 * Set physical address
+	 */
+	writel((mac[0] << 24) + (mac[1] << 16) + (mac[2] << 8) + mac[3],
+			&fec->eth->paddr1);
+	writel((mac[4] << 24) + (mac[5] << 16) + 0x8808, &fec->eth->paddr2);
+
+	return 0;
+}
+
+/**
+ * Start the FEC engine
+ * @param[in] dev Our device to handle
+ */
+static int fec_open(struct eth_device *edev)
+{
+	struct fec_priv *fec = (struct fec_priv *)edev->priv;
+
+	debug("fec_open: fec_open(dev)\n");
+	/* full-duplex, heartbeat disabled */
+	writel(1 << 2, &fec->eth->x_cntrl);
+	fec->rbd_index = 0;
+
+	/*
+	 * Enable FEC-Lite controller
+	 */
+	writel(FEC_ECNTRL_ETHER_EN, &fec->eth->ecntrl);
+
+	miiphy_wait_aneg(edev);
+	miiphy_speed(edev->name, 0);
+	miiphy_duplex(edev->name, 0);
+
+	/*
+	 * Enable SmartDMA receive task
+	 */
+	fec_rx_task_enable(fec);
+
+	udelay(100000);
+	return 0;
+}
+
+static int fec_init(struct eth_device *dev, bd_t* bd)
+{
+	uint32_t base;
+	struct fec_priv *fec = (struct fec_priv *)dev->priv;
+
+	/*
+	 * reserve memory for both buffer descriptor chains at once
+	 * Datasheet forces the startaddress of each chain is 16 byte
+	 * aligned
+	 */
+	fec->base_ptr = malloc((2 + FEC_RBD_NUM) *
+			sizeof(struct fec_bd) + DB_ALIGNMENT);
+	base = (uint32_t)fec->base_ptr;
+	if (!base) {
+		puts("fec_imx27: not enough malloc memory!\n");
+		return -ENOMEM;
+	}
+	memset((void *)base, 0, (2 + FEC_RBD_NUM) *
+			sizeof(struct fec_bd) + DB_ALIGNMENT);
+	base += (DB_ALIGNMENT-1);
+	base &= ~(DB_ALIGNMENT-1);
+
+	fec->rbd_base = (struct fec_bd *)base;
+
+	base += FEC_RBD_NUM * sizeof(struct fec_bd);
+
+	fec->tbd_base = (struct fec_bd *)base;
+
+	/*
+	 * Set interrupt mask register
+	 */
+	writel(0x00000000, &fec->eth->imask);
+
+	/*
+	 * Clear FEC-Lite interrupt event register(IEVENT)
+	 */
+	writel(0xffffffff, &fec->eth->ievent);
+
+
+	/*
+	 * Set FEC-Lite receive control register(R_CNTRL):
+	 */
+	if (fec->xcv_type == SEVENWIRE) {
+		/*
+		 * Frame length=1518; 7-wire mode
+		 */
+		writel(0x05ee0020, &fec->eth->r_cntrl);	/* FIXME 0x05ee0000 */
+	} else {
+		/*
+		 * Frame length=1518; MII mode;
+		 */
+		writel(0x05ee0024, &fec->eth->r_cntrl);	/* FIXME 0x05ee0004 */
+		/*
+		 * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
+		 * and do not drop the Preamble.
+		 */
+		writel((((imx_get_ahbclk() / 1000000) + 2) / 5) << 1,
+				&fec->eth->mii_speed);
+		debug("fec_init: mii_speed %#lx\n",
+				(((imx_get_ahbclk() / 1000000) + 2) / 5) << 1);
+	}
+	/*
+	 * Set Opcode/Pause Duration Register
+	 */
+	writel(0x00010020, &fec->eth->op_pause);	/* FIXME 0xffff0020; */
+	writel(0x2, &fec->eth->x_wmrk);
+	/*
+	 * Set multicast address filter
+	 */
+	writel(0x00000000, &fec->eth->gaddr1);
+	writel(0x00000000, &fec->eth->gaddr2);
+
+
+	/* clear MIB RAM */
+	long *mib_ptr = (long *)(IMX_FEC_BASE + 0x200);
+	while (mib_ptr <= (long *)(IMX_FEC_BASE + 0x2FC))
+		*mib_ptr++ = 0;
+
+	/* FIFO receive start register */
+	writel(0x520, &fec->eth->r_fstart);
+
+	/* size and address of each buffer */
+	writel(FEC_MAX_PKT_SIZE, &fec->eth->emrbr);
+	writel((uint32_t)fec->tbd_base, &fec->eth->etdsr);
+	writel((uint32_t)fec->rbd_base, &fec->eth->erdsr);
+
+	/*
+	 * Initialize RxBD/TxBD rings
+	 */
+	if (fec_rbd_init(fec, FEC_RBD_NUM, FEC_MAX_PKT_SIZE) < 0) {
+		free(fec->base_ptr);
+		return -ENOMEM;
+	}
+	fec_tbd_init(fec);
+
+
+	if (fec->xcv_type != SEVENWIRE)
+		miiphy_restart_aneg(dev);
+
+	fec_open(dev);
+	return 0;
+}
+
+/**
+ * Halt the FEC engine
+ * @param[in] dev Our device to handle
+ */
+static void fec_halt(struct eth_device *dev)
+{
+	struct fec_priv *fec = &gfec;
+	int counter = 0xffff;
+
+	/*
+	 * issue graceful stop command to the FEC transmitter if necessary
+	 */
+	writel(FEC_ECNTRL_RESET | readl(&fec->eth->x_cntrl),
+			&fec->eth->x_cntrl);
+
+	debug("eth_halt: wait for stop regs\n");
+	/*
+	 * wait for graceful stop to register
+	 */
+	while ((counter--) && (!(readl(&fec->eth->ievent) & FEC_IEVENT_GRA)))
+		;	/* FIXME ensure time */
+
+	/*
+	 * Disable SmartDMA tasks
+	 */
+	fec_tx_task_disable(fec);
+	fec_rx_task_disable(fec);
+
+	/*
+	 * Disable the Ethernet Controller
+	 * Note: this will also reset the BD index counter!
+	 */
+	writel(0, &fec->eth->ecntrl);
+	fec->rbd_index = 0;
+	fec->tbd_index = 0;
+	free(fec->rdb_ptr);
+	free(fec->base_ptr);
+	debug("eth_halt: done\n");
+}
+
+/**
+ * Transmit one frame
+ * @param[in] dev Our ethernet device to handle
+ * @param[in] packet Pointer to the data to be transmitted
+ * @param[in] length Data count in bytes
+ * @return 0 on success
+ */
+static int fec_send(struct eth_device *dev, volatile void* packet, int length)
+{
+	unsigned int status;
+
+	/*
+	 * This routine transmits one frame.  This routine only accepts
+	 * 6-byte Ethernet addresses.
+	 */
+	struct fec_priv *fec = (struct fec_priv *)dev->priv;
+
+	/*
+	 * Check for valid length of data.
+	 */
+	if ((length > 1500) || (length <= 0)) {
+		printf("Payload (%d) to large!\n", length);
+		return -1;
+	}
+
+	/*
+	 * Setup the transmit buffer
+	 * Note: We are always using the first buffer for transmission,
+	 * the second will be empty and only used to stop the DMA engine
+	 */
+	writew(length, &fec->tbd_base[fec->tbd_index].data_length);
+	writel((uint32_t)packet, &fec->tbd_base[fec->tbd_index].data_pointer);
+	/*
+	 * update BD's status now
+	 * This block:
+	 * - is always the last in a chain (means no chain)
+	 * - should transmitt the CRC
+	 * - might be the last BD in the list, so the address counter should
+	 *   wrap (-> keep the WRAP flag)
+	 */
+	status = readw(&fec->tbd_base[fec->tbd_index].status) & FEC_TBD_WRAP;
+	status |= FEC_TBD_LAST | FEC_TBD_TC | FEC_TBD_READY;
+	writew(status, &fec->tbd_base[fec->tbd_index].status);
+
+	/*
+	 * Enable SmartDMA transmit task
+	 */
+	fec_tx_task_enable(fec);
+
+	/*
+	 * wait until frame is sent .
+	 */
+	while (readw(&fec->tbd_base[fec->tbd_index].status) & FEC_TBD_READY) {
+		/* FIXME: Timeout */
+	}
+	debug("fec_send: status 0x%x index %d\n",
+			readw(&fec->tbd_base[fec->tbd_index].status),
+			fec->tbd_index);
+	/* for next transmission use the other buffer */
+	if (fec->tbd_index)
+		fec->tbd_index = 0;
+	else
+		fec->tbd_index = 1;
+
+	return 0;
+}
+
+/**
+ * Pull one frame from the card
+ * @param[in] dev Our ethernet device to handle
+ * @return Length of packet read
+ */
+static int fec_recv(struct eth_device *dev)
+{
+	struct fec_priv *fec = (struct fec_priv *)dev->priv;
+	struct fec_bd *rbd = &fec->rbd_base[fec->rbd_index];
+	unsigned long ievent;
+	int frame_length, len = 0;
+	struct nbuf *frame;
+	uint16_t bd_status;
+	uchar buff[FEC_MAX_PKT_SIZE];
+
+	/*
+	 * Check if any critical events have happened
+	 */
+	ievent = readl(&fec->eth->ievent);
+	writel(ievent, &fec->eth->ievent);
+	debug("fec_recv: ievent 0x%x\n", ievent);
+	if (ievent & FEC_IEVENT_BABR) {
+		fec_halt(dev);
+		fec_init(dev, fec->bd);
+		printf("some error: 0x%08lx\n", ievent);
+		return 0;
+	}
+	if (ievent & FEC_IEVENT_HBERR) {
+		/* Heartbeat error */
+		writel(0x00000001 | readl(&fec->eth->x_cntrl),
+				&fec->eth->x_cntrl);
+	}
+	if (ievent & FEC_IEVENT_GRA) {
+		/* Graceful stop complete */
+		if (readl(&fec->eth->x_cntrl) & 0x00000001) {
+			fec_halt(dev);
+			writel(~0x00000001 & readl(&fec->eth->x_cntrl),
+					&fec->eth->x_cntrl);
+			fec_init(dev, fec->bd);
+		}
+	}
+
+	/*
+	 * ensure reading the right buffer status
+	 */
+	bd_status = readw(&rbd->status);
+	debug("fec_recv: status 0x%x\n", bd_status);
+
+	if (!(bd_status & FEC_RBD_EMPTY)) {
+		if ((bd_status & FEC_RBD_LAST) && !(bd_status & FEC_RBD_ERR) &&
+			((readw(&rbd->data_length) - 4) > 14)) {
+			/*
+			 * Get buffer address and size
+			 */
+			frame = (struct nbuf *)readl(&rbd->data_pointer);
+			frame_length = readw(&rbd->data_length) - 4;
+			/*
+			 *  Fill the buffer and pass it to upper layers
+			 */
+			memcpy(buff, frame->data, frame_length);
+			NetReceive(buff, frame_length);
+			len = frame_length;
+		} else {
+			if (bd_status & FEC_RBD_ERR)
+				printf("error frame: 0x%08lx 0x%08x\n",
+						(ulong)rbd->data_pointer,
+						bd_status);
+		}
+		/*
+		 * free the current buffer, restart the engine
+		 * and move forward to the next buffer
+		 */
+		fec_rbd_clean(fec->rbd_index == (FEC_RBD_NUM - 1) ? 1 : 0, rbd);
+		fec_rx_task_enable(fec);
+		fec->rbd_index = (fec->rbd_index + 1) % FEC_RBD_NUM;
+	}
+	debug("fec_recv: stop\n");
+
+	return len;
+}
+
+static int fec_probe(bd_t *bd)
+{
+	struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
+	struct eth_device *edev;
+	struct fec_priv *fec = &gfec;
+	unsigned char ethaddr_str[20];
+	unsigned char ethaddr[6];
+	char *tmp = getenv("ethaddr");
+	char *end;
+
+	/* enable FEC clock */
+	writel(readl(&pll->pccr1) | PCCR1_HCLK_FEC, &pll->pccr1);
+	writel(readl(&pll->pccr0) | PCCR0_FEC_EN, &pll->pccr0);
+
+	/* create and fill edev struct */
+	edev = (struct eth_device *)malloc(sizeof(struct eth_device));
+	if (!edev) {
+		puts("fec_imx27: not enough malloc memory!\n");
+		return -ENOMEM;
+	}
+	edev->priv = fec;
+	edev->init = fec_init;
+	edev->send = fec_send;
+	edev->recv = fec_recv;
+	edev->halt = fec_halt;
+
+	fec->eth = (struct ethernet_regs *)IMX_FEC_BASE;
+	fec->bd = bd;
+
+	fec->xcv_type = MII100;
+
+	/* Reset chip. */
+	writel(FEC_ECNTRL_RESET, &fec->eth->ecntrl);
+	while (readl(&fec->eth->ecntrl) & 1)
+		udelay(10);
+
+	/*
+	 * Set interrupt mask register
+	 */
+	writel(0x00000000, &fec->eth->imask);
+
+	/*
+	 * Clear FEC-Lite interrupt event register(IEVENT)
+	 */
+	writel(0xffffffff, &fec->eth->ievent);
+
+	/*
+	 * Set FEC-Lite receive control register(R_CNTRL):
+	 */
+	/*
+	 * Frame length=1518; MII mode;
+	 */
+	writel(0x05ee0024, &fec->eth->r_cntrl);	/* FIXME 0x05ee0004 */
+	/*
+	 * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
+	 * and do not drop the Preamble.
+	 */
+	writel((((imx_get_ahbclk() / 1000000) + 2) / 5) << 1,
+			&fec->eth->mii_speed);
+	debug("fec_init: mii_speed %#lx\n",
+			(((imx_get_ahbclk() / 1000000) + 2) / 5) << 1);
+
+	sprintf(edev->name, "FEC_MXC");
+
+	miiphy_register(edev->name, fec_miiphy_read, fec_miiphy_write);
+
+	eth_register(edev);
+
+	if ((NULL != tmp) && (12 <= strlen(tmp))) {
+		int i;
+		/* convert MAC from string to int */
+		for (i = 0; i < 6; i++) {
+			ethaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0;
+			if (tmp)
+				tmp = (*end) ? end + 1 : end;
+		}
+	} else if (fec_get_hwaddr(edev, ethaddr) == 0) {
+		printf("got MAC address from EEPROM: %pM\n", ethaddr);
+		setenv("ethaddr", (char *)ethaddr_str);
+	}
+	memcpy(edev->enetaddr, ethaddr, 6);
+	fec_set_hwaddr(edev, ethaddr);
+
+	return 0;
+}
+
+int fecmxc_initialize(bd_t *bd)
+{
+	int lout = 1;
+
+	debug("eth_init: fec_probe(bd)\n");
+	lout = fec_probe(bd);
+
+	return lout;
+}
+
diff --git a/drivers/net/fec_mxc.h b/drivers/net/fec_mxc.h
new file mode 100644
index 0000000..6cb1bfc
--- /dev/null
+++ b/drivers/net/fec_mxc.h
@@ -0,0 +1,304 @@
+/*
+ * (C) Copyright 2009 Ilya Yanok, Emcraft Systems Ltd <yanok@emcraft.com>
+ * (C) Copyright 2008 Armadeus Systems, nc
+ * (C) Copyright 2008 Eric Jarrige <eric.jarrige@armadeus.org>
+ * (C) Copyright 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
+ * (C) Copyright 2007 Pengutronix, Juergen Beisert <j.beisert@pengutronix.de>
+ *
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ *
+ * This file is based on mpc4200fec.h
+ * (C) Copyright Motorola, Inc., 2000
+ *
+ * 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 __FEC_MXC_H
+#define __FEC_MXC_H
+
+/**
+ * Layout description of the FEC
+ */
+struct ethernet_regs {
+
+/* [10:2]addr = 00 */
+
+/*  Control and status Registers (offset 000-1FF) */
+
+	uint32_t res0[1];		/* MBAR_ETH + 0x000 */
+	uint32_t ievent;		/* MBAR_ETH + 0x004 */
+	uint32_t imask;			/* MBAR_ETH + 0x008 */
+
+	uint32_t res1[1];		/* MBAR_ETH + 0x00C */
+	uint32_t r_des_active;		/* MBAR_ETH + 0x010 */
+	uint32_t x_des_active;		/* MBAR_ETH + 0x014 */
+	uint32_t res2[3];		/* MBAR_ETH + 0x018-20 */
+	uint32_t ecntrl;		/* MBAR_ETH + 0x024 */
+
+	uint32_t res3[6];		/* MBAR_ETH + 0x028-03C */
+	uint32_t mii_data;		/* MBAR_ETH + 0x040 */
+	uint32_t mii_speed;		/* MBAR_ETH + 0x044 */
+	uint32_t res4[7];		/* MBAR_ETH + 0x048-60 */
+	uint32_t mib_control;		/* MBAR_ETH + 0x064 */
+
+	uint32_t res5[7];		/* MBAR_ETH + 0x068-80 */
+	uint32_t r_cntrl;		/* MBAR_ETH + 0x084 */
+	uint32_t res6[15];		/* MBAR_ETH + 0x088-C0 */
+	uint32_t x_cntrl;		/* MBAR_ETH + 0x0C4 */
+	uint32_t res7[7];		/* MBAR_ETH + 0x0C8-E0 */
+	uint32_t paddr1;		/* MBAR_ETH + 0x0E4 */
+	uint32_t paddr2;		/* MBAR_ETH + 0x0E8 */
+	uint32_t op_pause;		/* MBAR_ETH + 0x0EC */
+
+	uint32_t res8[10];		/* MBAR_ETH + 0x0F0-114 */
+	uint32_t iaddr1;		/* MBAR_ETH + 0x118 */
+	uint32_t iaddr2;		/* MBAR_ETH + 0x11C */
+	uint32_t gaddr1;		/* MBAR_ETH + 0x120 */
+	uint32_t gaddr2;		/* MBAR_ETH + 0x124 */
+	uint32_t res9[7];		/* MBAR_ETH + 0x128-140 */
+
+	uint32_t x_wmrk;		/* MBAR_ETH + 0x144 */
+	uint32_t res10[1];		/* MBAR_ETH + 0x148 */
+	uint32_t r_bound;		/* MBAR_ETH + 0x14C */
+	uint32_t r_fstart;		/* MBAR_ETH + 0x150 */
+	uint32_t res11[11];		/* MBAR_ETH + 0x154-17C */
+	uint32_t erdsr;			/* MBAR_ETH + 0x180 */
+	uint32_t etdsr;			/* MBAR_ETH + 0x184 */
+	uint32_t emrbr;			/* MBAR_ETH + 0x188 */
+	uint32_t res12[29];		/* MBAR_ETH + 0x18C-1FC */
+
+/*  MIB COUNTERS (Offset 200-2FF) */
+
+	uint32_t rmon_t_drop;		/* MBAR_ETH + 0x200 */
+	uint32_t rmon_t_packets;	/* MBAR_ETH + 0x204 */
+	uint32_t rmon_t_bc_pkt;		/* MBAR_ETH + 0x208 */
+	uint32_t rmon_t_mc_pkt;		/* MBAR_ETH + 0x20C */
+	uint32_t rmon_t_crc_align;	/* MBAR_ETH + 0x210 */
+	uint32_t rmon_t_undersize;	/* MBAR_ETH + 0x214 */
+	uint32_t rmon_t_oversize;	/* MBAR_ETH + 0x218 */
+	uint32_t rmon_t_frag;		/* MBAR_ETH + 0x21C */
+	uint32_t rmon_t_jab;		/* MBAR_ETH + 0x220 */
+	uint32_t rmon_t_col;		/* MBAR_ETH + 0x224 */
+	uint32_t rmon_t_p64;		/* MBAR_ETH + 0x228 */
+	uint32_t rmon_t_p65to127;	/* MBAR_ETH + 0x22C */
+	uint32_t rmon_t_p128to255;	/* MBAR_ETH + 0x230 */
+	uint32_t rmon_t_p256to511;	/* MBAR_ETH + 0x234 */
+	uint32_t rmon_t_p512to1023;	/* MBAR_ETH + 0x238 */
+	uint32_t rmon_t_p1024to2047;	/* MBAR_ETH + 0x23C */
+	uint32_t rmon_t_p_gte2048;	/* MBAR_ETH + 0x240 */
+	uint32_t rmon_t_octets;		/* MBAR_ETH + 0x244 */
+	uint32_t ieee_t_drop;		/* MBAR_ETH + 0x248 */
+	uint32_t ieee_t_frame_ok;	/* MBAR_ETH + 0x24C */
+	uint32_t ieee_t_1col;		/* MBAR_ETH + 0x250 */
+	uint32_t ieee_t_mcol;		/* MBAR_ETH + 0x254 */
+	uint32_t ieee_t_def;		/* MBAR_ETH + 0x258 */
+	uint32_t ieee_t_lcol;		/* MBAR_ETH + 0x25C */
+	uint32_t ieee_t_excol;		/* MBAR_ETH + 0x260 */
+	uint32_t ieee_t_macerr;		/* MBAR_ETH + 0x264 */
+	uint32_t ieee_t_cserr;		/* MBAR_ETH + 0x268 */
+	uint32_t ieee_t_sqe;		/* MBAR_ETH + 0x26C */
+	uint32_t t_fdxfc;		/* MBAR_ETH + 0x270 */
+	uint32_t ieee_t_octets_ok;	/* MBAR_ETH + 0x274 */
+
+	uint32_t res13[2];		/* MBAR_ETH + 0x278-27C */
+	uint32_t rmon_r_drop;		/* MBAR_ETH + 0x280 */
+	uint32_t rmon_r_packets;	/* MBAR_ETH + 0x284 */
+	uint32_t rmon_r_bc_pkt;		/* MBAR_ETH + 0x288 */
+	uint32_t rmon_r_mc_pkt;		/* MBAR_ETH + 0x28C */
+	uint32_t rmon_r_crc_align;	/* MBAR_ETH + 0x290 */
+	uint32_t rmon_r_undersize;	/* MBAR_ETH + 0x294 */
+	uint32_t rmon_r_oversize;	/* MBAR_ETH + 0x298 */
+	uint32_t rmon_r_frag;		/* MBAR_ETH + 0x29C */
+	uint32_t rmon_r_jab;		/* MBAR_ETH + 0x2A0 */
+
+	uint32_t rmon_r_resvd_0;	/* MBAR_ETH + 0x2A4 */
+
+	uint32_t rmon_r_p64;		/* MBAR_ETH + 0x2A8 */
+	uint32_t rmon_r_p65to127;	/* MBAR_ETH + 0x2AC */
+	uint32_t rmon_r_p128to255;	/* MBAR_ETH + 0x2B0 */
+	uint32_t rmon_r_p256to511;	/* MBAR_ETH + 0x2B4 */
+	uint32_t rmon_r_p512to1023;	/* MBAR_ETH + 0x2B8 */
+	uint32_t rmon_r_p1024to2047;	/* MBAR_ETH + 0x2BC */
+	uint32_t rmon_r_p_gte2048;	/* MBAR_ETH + 0x2C0 */
+	uint32_t rmon_r_octets;		/* MBAR_ETH + 0x2C4 */
+	uint32_t ieee_r_drop;		/* MBAR_ETH + 0x2C8 */
+	uint32_t ieee_r_frame_ok;	/* MBAR_ETH + 0x2CC */
+	uint32_t ieee_r_crc;		/* MBAR_ETH + 0x2D0 */
+	uint32_t ieee_r_align;		/* MBAR_ETH + 0x2D4 */
+	uint32_t r_macerr;		/* MBAR_ETH + 0x2D8 */
+	uint32_t r_fdxfc;		/* MBAR_ETH + 0x2DC */
+	uint32_t ieee_r_octets_ok;	/* MBAR_ETH + 0x2E0 */
+
+	uint32_t res14[6];		/* MBAR_ETH + 0x2E4-2FC */
+
+	uint32_t res15[64];		/* MBAR_ETH + 0x300-3FF */
+};
+
+#define FEC_IEVENT_HBERR		0x80000000
+#define FEC_IEVENT_BABR			0x40000000
+#define FEC_IEVENT_BABT			0x20000000
+#define FEC_IEVENT_GRA			0x10000000
+#define FEC_IEVENT_TXF			0x08000000
+#define FEC_IEVENT_TXB			0x04000000
+#define FEC_IEVENT_RXF			0x02000000
+#define FEC_IEVENT_RXB			0x01000000
+#define FEC_IEVENT_MII			0x00800000
+#define FEC_IEVENT_EBERR		0x00400000
+#define FEC_IEVENT_LC			0x00200000
+#define FEC_IEVENT_RL			0x00100000
+#define FEC_IEVENT_UN			0x00080000
+
+#define FEC_IMASK_HBERR			0x80000000
+#define FEC_IMASK_BABR			0x40000000
+#define FEC_IMASKT_BABT			0x20000000
+#define FEC_IMASK_GRA			0x10000000
+#define FEC_IMASKT_TXF			0x08000000
+#define FEC_IMASK_TXB			0x04000000
+#define FEC_IMASKT_RXF			0x02000000
+#define FEC_IMASK_RXB			0x01000000
+#define FEC_IMASK_MII			0x00800000
+#define FEC_IMASK_EBERR			0x00400000
+#define FEC_IMASK_LC			0x00200000
+#define FEC_IMASKT_RL			0x00100000
+#define FEC_IMASK_UN			0x00080000
+
+
+#define FEC_RCNTRL_MAX_FL_SHIFT		16
+#define FEC_RCNTRL_LOOP			0x00000001
+#define FEC_RCNTRL_DRT			0x00000002
+#define FEC_RCNTRL_MII_MODE		0x00000004
+#define FEC_RCNTRL_PROM			0x00000008
+#define FEC_RCNTRL_BC_REJ		0x00000010
+#define FEC_RCNTRL_FCE			0x00000020
+
+#define FEC_TCNTRL_GTS			0x00000001
+#define FEC_TCNTRL_HBC			0x00000002
+#define FEC_TCNTRL_FDEN			0x00000004
+#define FEC_TCNTRL_TFC_PAUSE		0x00000008
+#define FEC_TCNTRL_RFC_PAUSE		0x00000010
+
+#define FEC_ECNTRL_RESET		0x00000001	/* reset the FEC */
+#define FEC_ECNTRL_ETHER_EN		0x00000002	/* enable the FEC */
+
+/**
+ * @brief Descriptor buffer alignment
+ *
+ * i.MX27 requires a 16 byte alignment (but for the first element only)
+ */
+#define DB_ALIGNMENT		16
+
+/**
+ * @brief Data buffer alignment
+ *
+ * i.MX27 requires a four byte alignment for transmit and 16 bits
+ * alignment for receive so take 16
+ * Note: Valid for member data_pointer in struct buffer_descriptor
+ */
+#define DB_DATA_ALIGNMENT	16
+
+/**
+ * @brief Receive & Transmit Buffer Descriptor definitions
+ *
+ * Note: The first BD must be aligned (see DB_ALIGNMENT)
+ */
+struct fec_bd {
+	uint16_t data_length;		/* payload's length in bytes */
+	uint16_t status;		/* BD's staus (see datasheet) */
+	uint32_t data_pointer;		/* payload's buffer address */
+};
+
+/**
+ * Supported phy types on this platform
+ */
+enum xceiver_type {
+	SEVENWIRE,	/* 7-wire       */
+	MII10,		/* MII 10Mbps   */
+	MII100		/* MII 100Mbps  */
+};
+
+/**
+ * @brief i.MX27-FEC private structure
+ */
+struct fec_priv {
+	struct ethernet_regs *eth;	/* pointer to register'S base */
+	enum xceiver_type xcv_type;	/* transceiver type */
+	struct fec_bd *rbd_base;	/* RBD ring */
+	int rbd_index;			/* next receive BD to read */
+	struct fec_bd *tbd_base;	/* TBD ring */
+	int tbd_index;			/* next transmit BD to write */
+	bd_t *bd;
+	void *rdb_ptr;
+	void *base_ptr;
+};
+
+/**
+ * @brief Numbers of buffer descriptors for receiving
+ *
+ * The number defines the stocked memory buffers for the receiving task.
+ * Larger values makes no sense in this limited environment.
+ */
+#define FEC_RBD_NUM		64
+
+/**
+ * @brief Define the ethernet packet size limit in memory
+ *
+ * Note: Do not shrink this number. This will force the FEC to spread larger
+ * frames in more than one BD. This is nothing to worry about, but the current
+ * driver can't handle it.
+ */
+#define FEC_MAX_PKT_SIZE	1536
+
+/* Receive BD status bits */
+#define FEC_RBD_EMPTY	0x8000	/* Receive BD status: Buffer is empty */
+#define FEC_RBD_WRAP	0x2000	/* Receive BD status: Last BD in ring */
+/* Receive BD status: Buffer is last in frame (useless here!) */
+#define FEC_RBD_LAST	0x0800
+#define FEC_RBD_MISS	0x0100	/* Receive BD status: Miss bit for prom mode */
+/* Receive BD status: The received frame is broadcast frame */
+#define FEC_RBD_BC	0x0080
+/* Receive BD status: The received frame is multicast frame */
+#define FEC_RBD_MC	0x0040
+#define FEC_RBD_LG	0x0020	/* Receive BD status: Frame length violation */
+#define FEC_RBD_NO	0x0010	/* Receive BD status: Nonoctet align frame */
+#define FEC_RBD_CR	0x0004	/* Receive BD status: CRC error */
+#define FEC_RBD_OV	0x0002	/* Receive BD status: Receive FIFO overrun */
+#define FEC_RBD_TR	0x0001	/* Receive BD status: Frame is truncated */
+#define FEC_RBD_ERR	(FEC_RBD_LG | FEC_RBD_NO | FEC_RBD_CR | \
+			FEC_RBD_OV | FEC_RBD_TR)
+
+/* Transmit BD status bits */
+#define FEC_TBD_READY	0x8000	/* Tansmit BD status: Buffer is ready */
+#define FEC_TBD_WRAP	0x2000	/* Tansmit BD status: Mark as last BD in ring */
+#define FEC_TBD_LAST	0x0800	/* Tansmit BD status: Buffer is last in frame */
+#define FEC_TBD_TC	0x0400	/* Tansmit BD status: Transmit the CRC */
+#define FEC_TBD_ABC	0x0200	/* Tansmit BD status: Append bad CRC */
+
+/* MII-related definitios */
+#define FEC_MII_DATA_ST		0x40000000	/* Start of frame delimiter */
+#define FEC_MII_DATA_OP_RD	0x20000000	/* Perform a read operation */
+#define FEC_MII_DATA_OP_WR	0x10000000	/* Perform a write operation */
+#define FEC_MII_DATA_PA_MSK	0x0f800000	/* PHY Address field mask */
+#define FEC_MII_DATA_RA_MSK	0x007c0000	/* PHY Register field mask */
+#define FEC_MII_DATA_TA		0x00020000	/* Turnaround */
+#define FEC_MII_DATA_DATAMSK	0x0000ffff	/* PHY data field */
+
+#define FEC_MII_DATA_RA_SHIFT	18	/* MII Register address bits */
+#define FEC_MII_DATA_PA_SHIFT	23	/* MII PHY address bits */
+
+#endif	/* __FEC_MXC_H */
diff --git a/include/netdev.h b/include/netdev.h
index aed5c4c..842525f 100644
--- a/include/netdev.h
+++ b/include/netdev.h
@@ -50,6 +50,7 @@ int e1000_initialize(bd_t *bis);
 int eepro100_initialize(bd_t *bis);
 int eth_3com_initialize (bd_t * bis);
 int fec_initialize (bd_t *bis);
+int fecmxc_initialize (bd_t *bis);
 int greth_initialize(bd_t *bis);
 void gt6426x_eth_initialize(bd_t *bis);
 int inca_switch_initialize(bd_t *bis);
-- 
1.6.0.6

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

* [U-Boot] [PATCH] mxc_nand: add nand driver for MX2/MX3
  2009-07-17 10:53       ` [U-Boot] [PATCH] " Ilya Yanok
@ 2009-07-22 21:33         ` Jean-Christophe PLAGNIOL-VILLARD
  2009-07-28 22:37         ` Scott Wood
  1 sibling, 0 replies; 70+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2009-07-22 21:33 UTC (permalink / raw)
  To: u-boot

On 14:53 Fri 17 Jul     , Ilya Yanok wrote:
> Driver for NFC NAND controller found on Freescale's MX2 and MX3
> processors. Ported from Linux. Tested only with i.MX27 but should
> works with other MX2 and MX3 processors too.
> 
> Signed-off-by: Ilya Yanok <yanok@emcraft.com>
> ---
>  drivers/mtd/nand/Makefile   |    1 +
>  drivers/mtd/nand/mxc_nand.c |  902 +++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 903 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/mtd/nand/mxc_nand.c
Scott for you is it fine?

Best Regards,
J.

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

* [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD
  2009-07-17 11:00     ` [U-Boot] [PATCH] " Ilya Yanok
@ 2009-07-22 21:37       ` Jean-Christophe PLAGNIOL-VILLARD
  2009-07-22 22:17         ` Ilya Yanok
  0 siblings, 1 reply; 70+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2009-07-22 21:37 UTC (permalink / raw)
  To: u-boot

> + */
> +
> +#include <common.h>
> +#include <asm/io.h>
> +#include <asm/arch/imx-regs.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +static int imx27lite_devices_init(void)
> +{
> +	struct gpio_regs *regs = (struct gpio_regs *)IMX_GPIO_BASE;
> +	int i;
> +	unsigned int mode[] = {
> +		PD0_AIN_FEC_TXD0,
> +		PD1_AIN_FEC_TXD1,
> +		PD2_AIN_FEC_TXD2,
> +		PD3_AIN_FEC_TXD3,
> +		PD4_AOUT_FEC_RX_ER,
> +		PD5_AOUT_FEC_RXD1,
> +		PD6_AOUT_FEC_RXD2,
> +		PD7_AOUT_FEC_RXD3,
> +		PD8_AF_FEC_MDIO,
> +		PD9_AIN_FEC_MDC | GPIO_PUEN,
> +		PD10_AOUT_FEC_CRS,
> +		PD11_AOUT_FEC_TX_CLK,
> +		PD12_AOUT_FEC_RXD0,
> +		PD13_AOUT_FEC_RX_DV,
> +		PD14_AOUT_FEC_CLR,
> +		PD15_AOUT_FEC_COL,
> +		PD16_AIN_FEC_TX_ER,
> +		PF23_AIN_FEC_TX_EN,
> +		PE12_PF_UART1_TXD,
> +		PE13_PF_UART1_RXD,
> +		PB4_PF_SD2_D0,
> +		PB5_PF_SD2_D1,
> +		PB6_PF_SD2_D2,
> +		PB7_PF_SD2_D3,
> +		PB8_PF_SD2_CMD,
> +		PB9_PF_SD2_CLK,
> +		(GPIO_PORTC | GPIO_OUT | GPIO_PUEN | GPIO_GPIO | 31),
> +	};
> +
> +	for (i = 0; i < ARRAY_SIZE(mode); i++)
> +		imx_gpio_mode(mode[i]);
you do not answer about my api comment?
do you plan to create one for device init?

otherwise ok

Best Regards,
J.

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

* [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD
  2009-07-22 21:37       ` Jean-Christophe PLAGNIOL-VILLARD
@ 2009-07-22 22:17         ` Ilya Yanok
  2009-07-23 21:37           ` Jean-Christophe PLAGNIOL-VILLARD
  0 siblings, 1 reply; 70+ messages in thread
From: Ilya Yanok @ 2009-07-22 22:17 UTC (permalink / raw)
  To: u-boot

Hi Jean-Christophe,

Jean-Christophe PLAGNIOL-VILLARD wrote:
>> +static int imx27lite_devices_init(void)
>> +{
>> +	struct gpio_regs *regs = (struct gpio_regs *)IMX_GPIO_BASE;
>> +	int i;
>> +	unsigned int mode[] = {
>> +		PD0_AIN_FEC_TXD0,
>> +		PD1_AIN_FEC_TXD1,
>> +		PD2_AIN_FEC_TXD2,
>> +		PD3_AIN_FEC_TXD3,
>> +		PD4_AOUT_FEC_RX_ER,
>> +		PD5_AOUT_FEC_RXD1,
>> +		PD6_AOUT_FEC_RXD2,
>> +		PD7_AOUT_FEC_RXD3,
>> +		PD8_AF_FEC_MDIO,
>> +		PD9_AIN_FEC_MDC | GPIO_PUEN,
>> +		PD10_AOUT_FEC_CRS,
>> +		PD11_AOUT_FEC_TX_CLK,
>> +		PD12_AOUT_FEC_RXD0,
>> +		PD13_AOUT_FEC_RX_DV,
>> +		PD14_AOUT_FEC_CLR,
>> +		PD15_AOUT_FEC_COL,
>> +		PD16_AIN_FEC_TX_ER,
>> +		PF23_AIN_FEC_TX_EN,
>> +		PE12_PF_UART1_TXD,
>> +		PE13_PF_UART1_RXD,
>> +		PB4_PF_SD2_D0,
>> +		PB5_PF_SD2_D1,
>> +		PB6_PF_SD2_D2,
>> +		PB7_PF_SD2_D3,
>> +		PB8_PF_SD2_CMD,
>> +		PB9_PF_SD2_CLK,
>> +		(GPIO_PORTC | GPIO_OUT | GPIO_PUEN | GPIO_GPIO | 31),
>> +	};
>> +
>> +	for (i = 0; i < ARRAY_SIZE(mode); i++)
>> +		imx_gpio_mode(mode[i]);
>>     
> you do not answer about my api comment?
>   

Sorry, I forgot to write a separate mail to ask you.

> do you plan to create one for device init?
>   

What kind of API you expect me to create here? It's just IO pins
initialization...

Regards, Ilya.

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

* [U-Boot] [PATCH] fec_mxc: driver for FEC ethernet controller on i.MX27
  2009-07-21 15:32       ` Ilya Yanok
@ 2009-07-22 22:23         ` Jean-Christophe PLAGNIOL-VILLARD
  2009-07-22 23:03           ` Ben Warren
  2009-07-23  6:28         ` Ben Warren
  1 sibling, 1 reply; 70+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2009-07-22 22:23 UTC (permalink / raw)
  To: u-boot

On 19:32 Tue 21 Jul     , Ilya Yanok wrote:
> Signed-off-by: Ilya Yanok <yanok@emcraft.com>
> ---
>  cpu/arm926ejs/mx27/generic.c |   10 +
>  drivers/net/Makefile         |    1 +
>  drivers/net/fec_mxc.c        |  742 ++++++++++++++++++++++++++++++++++++++++++
>  drivers/net/fec_mxc.h        |  304 +++++++++++++++++
>  include/netdev.h             |    1 +
>  5 files changed, 1058 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/net/fec_mxc.c
>  create mode 100644 drivers/net/fec_mxc.h
Ben ping

Best Regards,
J.

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

* [U-Boot] [PATCH] fec_mxc: driver for FEC ethernet controller on i.MX27
  2009-07-22 22:23         ` Jean-Christophe PLAGNIOL-VILLARD
@ 2009-07-22 23:03           ` Ben Warren
  0 siblings, 0 replies; 70+ messages in thread
From: Ben Warren @ 2009-07-22 23:03 UTC (permalink / raw)
  To: u-boot

Jean-Christophe PLAGNIOL-VILLARD wrote:
> On 19:32 Tue 21 Jul     , Ilya Yanok wrote:
>   
>> Signed-off-by: Ilya Yanok <yanok@emcraft.com>
>> ---
>>  cpu/arm926ejs/mx27/generic.c |   10 +
>>  drivers/net/Makefile         |    1 +
>>  drivers/net/fec_mxc.c        |  742 ++++++++++++++++++++++++++++++++++++++++++
>>  drivers/net/fec_mxc.h        |  304 +++++++++++++++++
>>  include/netdev.h             |    1 +
>>  5 files changed, 1058 insertions(+), 0 deletions(-)
>>  create mode 100644 drivers/net/fec_mxc.c
>>  create mode 100644 drivers/net/fec_mxc.h
>>     
> Ben ping
>
> Best Regards,
> J.
>   
Planning on getting to it tonight.

Ben

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

* [U-Boot] [PATCH] fec_mxc: driver for FEC ethernet controller on i.MX27
  2009-07-21 15:32       ` Ilya Yanok
  2009-07-22 22:23         ` Jean-Christophe PLAGNIOL-VILLARD
@ 2009-07-23  6:28         ` Ben Warren
  1 sibling, 0 replies; 70+ messages in thread
From: Ben Warren @ 2009-07-23  6:28 UTC (permalink / raw)
  To: u-boot

Ilya Yanok wrote:
> Signed-off-by: Ilya Yanok <yanok@emcraft.com>
> ---
>  cpu/arm926ejs/mx27/generic.c |   10 +
>  drivers/net/Makefile         |    1 +
>  drivers/net/fec_mxc.c        |  742 ++++++++++++++++++++++++++++++++++++++++++
>  drivers/net/fec_mxc.h        |  304 +++++++++++++++++
>  include/netdev.h             |    1 +
>  5 files changed, 1058 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/net/fec_mxc.c
>  create mode 100644 drivers/net/fec_mxc.h
>   
Applied to net repo.

thanks,
Ben

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

* [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD
  2009-07-22 22:17         ` Ilya Yanok
@ 2009-07-23 21:37           ` Jean-Christophe PLAGNIOL-VILLARD
  2009-08-03  1:46             ` Ilya Yanok
  0 siblings, 1 reply; 70+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2009-07-23 21:37 UTC (permalink / raw)
  To: u-boot

On 02:17 Thu 23 Jul     , Ilya Yanok wrote:
> Hi Jean-Christophe,
> 
> Jean-Christophe PLAGNIOL-VILLARD wrote:
> >> +static int imx27lite_devices_init(void)
> >> +{
> >> +	struct gpio_regs *regs = (struct gpio_regs *)IMX_GPIO_BASE;
> >> +	int i;
> >> +	unsigned int mode[] = {
> >> +		PD0_AIN_FEC_TXD0,
> >> +		PD1_AIN_FEC_TXD1,
> >> +		PD2_AIN_FEC_TXD2,
> >> +		PD3_AIN_FEC_TXD3,
> >> +		PD4_AOUT_FEC_RX_ER,
> >> +		PD5_AOUT_FEC_RXD1,
> >> +		PD6_AOUT_FEC_RXD2,
> >> +		PD7_AOUT_FEC_RXD3,
> >> +		PD8_AF_FEC_MDIO,
> >> +		PD9_AIN_FEC_MDC | GPIO_PUEN,
> >> +		PD10_AOUT_FEC_CRS,
> >> +		PD11_AOUT_FEC_TX_CLK,
> >> +		PD12_AOUT_FEC_RXD0,
> >> +		PD13_AOUT_FEC_RX_DV,
> >> +		PD14_AOUT_FEC_CLR,
> >> +		PD15_AOUT_FEC_COL,
> >> +		PD16_AIN_FEC_TX_ER,
> >> +		PF23_AIN_FEC_TX_EN,
> >> +		PE12_PF_UART1_TXD,
> >> +		PE13_PF_UART1_RXD,
> >> +		PB4_PF_SD2_D0,
> >> +		PB5_PF_SD2_D1,
> >> +		PB6_PF_SD2_D2,
> >> +		PB7_PF_SD2_D3,
> >> +		PB8_PF_SD2_CMD,
> >> +		PB9_PF_SD2_CLK,
> >> +		(GPIO_PORTC | GPIO_OUT | GPIO_PUEN | GPIO_GPIO | 31),
> >> +	};
> >> +
> >> +	for (i = 0; i < ARRAY_SIZE(mode); i++)
> >> +		imx_gpio_mode(mode[i]);
> >>     
> > you do not answer about my api comment?
> >   
> 
> Sorry, I forgot to write a separate mail to ask you.
> 
> > do you plan to create one for device init?
> >   
> 
> What kind of API you expect me to create here? It's just IO pins
> initialization...
do as at91, davinci all related init for rs232, usb, net in one function
per init

Best Regards,
J.

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

* [U-Boot] [PATCH] mxc_nand: add nand driver for MX2/MX3
  2009-07-17 10:53       ` [U-Boot] [PATCH] " Ilya Yanok
  2009-07-22 21:33         ` Jean-Christophe PLAGNIOL-VILLARD
@ 2009-07-28 22:37         ` Scott Wood
  2009-08-03  1:45           ` Ilya Yanok
  2009-08-03  2:01           ` Ilya Yanok
  1 sibling, 2 replies; 70+ messages in thread
From: Scott Wood @ 2009-07-28 22:37 UTC (permalink / raw)
  To: u-boot

On Fri, Jul 17, 2009 at 02:53:55PM +0400, Ilya Yanok wrote:
> +/* OOB placement block for use with hardware ecc generation */
> +static struct nand_ecclayout nand_hw_eccoob = {
> +	.eccbytes = 5,
> +	.eccpos = {6, 7, 8, 9, 10},
> +	.oobfree = {{0, 5}, {11, 5}, }
> +};
> +
> +#ifndef CONFIG_MXC_NAND_HWECC
> +static struct nand_ecclayout nand_hw_eccoob_soft = {
> +	.eccbytes = 6,
> +	.eccpos = {6, 7, 8, 9, 10, 11},
> +	.oobfree = {{0, 5}, {12, 4}, }
> +};
> +#endif

Why is one struct #ifndef, but the other isn't #ifdef?

> +/*
> + * This function requests the NANDFC to initate the transfer
> + * of data currently in the NANDFC RAM buffer to the NAND device.
> + */
> +static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id,
> +			int spare_only)
> +{
> +	MTDDEBUG(MTD_DEBUG_LEVEL3, "send_prog_page (%d)\n", spare_only);
> +
> +	/* NANDFC buffer 0 is used for page read/write */
> +	writew(buf_id, &host->regs->nfc_buf_addr);

Comment does not match code.

> +	/*
> +	 * NANDFC buffer 1 is used for device status to prevent
> +	 * corruption of read/write buffer on status requests.
> +	 */
> +	writew(1, &host->regs->nfc_buf_addr);

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

* [U-Boot] [PATCH] mxc_nand: add nand driver for MX2/MX3
  2009-07-28 22:37         ` Scott Wood
@ 2009-08-03  1:45           ` Ilya Yanok
  2009-08-04 23:32             ` Scott Wood
  2009-08-03  2:01           ` Ilya Yanok
  1 sibling, 1 reply; 70+ messages in thread
From: Ilya Yanok @ 2009-08-03  1:45 UTC (permalink / raw)
  To: u-boot

Driver for NFC NAND controller found on Freescale's MX2 and MX3
processors. Ported from Linux. Tested only with i.MX27 but should
works with other MX2 and MX3 processors too.

Signed-off-by: Ilya Yanok <yanok@emcraft.com>
---
 drivers/mtd/nand/Makefile   |    1 +
 drivers/mtd/nand/mxc_nand.c |  902 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 903 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/nand/mxc_nand.c

diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 89ccec2..ea8572f 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -40,6 +40,7 @@ COBJS-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_nand.o
 COBJS-$(CONFIG_NAND_FSL_UPM) += fsl_upm.o
 COBJS-$(CONFIG_NAND_KIRKWOOD) += kirkwood_nand.o
 COBJS-$(CONFIG_NAND_MPC5121_NFC) += mpc5121_nfc.o
+COBJS-$(CONFIG_NAND_MXC) += mxc_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/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
new file mode 100644
index 0000000..6a25012
--- /dev/null
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -0,0 +1,902 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Sascha Hauer, kernel at pengutronix.de
+ * Copyright 2009 Ilya Yanok, <yanok@emcraft.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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <common.h>
+#include <nand.h>
+#include <linux/err.h>
+#include <asm/io.h>
+#ifdef CONFIG_MX27
+#include <asm/arch/imx-regs.h>
+#endif
+
+#define DRIVER_NAME "mxc_nand"
+
+struct nfc_regs {
+/* NFC RAM BUFFER Main area 0 */
+	uint8_t main_area0[0x200];
+	uint8_t main_area1[0x200];
+	uint8_t main_area2[0x200];
+	uint8_t main_area3[0x200];
+/* SPARE BUFFER Spare area 0 */
+	uint8_t spare_area0[0x10];
+	uint8_t spare_area1[0x10];
+	uint8_t spare_area2[0x10];
+	uint8_t spare_area3[0x10];
+	uint8_t pad[0x5c0];
+/* NFC registers */
+	uint16_t nfc_buf_size;
+	uint16_t reserved;
+	uint16_t nfc_buf_addr;
+	uint16_t nfc_flash_addr;
+	uint16_t nfc_flash_cmd;
+	uint16_t nfc_config;
+	uint16_t nfc_ecc_status_result;
+	uint16_t nfc_rsltmain_area;
+	uint16_t nfc_rsltspare_area;
+	uint16_t nfc_wrprot;
+	uint16_t nfc_unlockstart_blkaddr;
+	uint16_t nfc_unlockend_blkaddr;
+	uint16_t nfc_nf_wrprst;
+	uint16_t nfc_config1;
+	uint16_t nfc_config2;
+};
+
+/*
+ * Set INT to 0, FCMD to 1, rest to 0 in NFC_CONFIG2 Register
+ * for Command operation
+ */
+#define NFC_CMD            0x1
+
+/*
+ * Set INT to 0, FADD to 1, rest to 0 in NFC_CONFIG2 Register
+ * for Address operation
+ */
+#define NFC_ADDR           0x2
+
+/*
+ * Set INT to 0, FDI to 1, rest to 0 in NFC_CONFIG2 Register
+ * for Input operation
+ */
+#define NFC_INPUT          0x4
+
+/*
+ * Set INT to 0, FDO to 001, rest to 0 in NFC_CONFIG2 Register
+ * for Data Output operation
+ */
+#define NFC_OUTPUT         0x8
+
+/*
+ * Set INT to 0, FD0 to 010, rest to 0 in NFC_CONFIG2 Register
+ * for Read ID operation
+ */
+#define NFC_ID             0x10
+
+/*
+ * Set INT to 0, FDO to 100, rest to 0 in NFC_CONFIG2 Register
+ * for Read Status operation
+ */
+#define NFC_STATUS         0x20
+
+/*
+ * Set INT to 1, rest to 0 in NFC_CONFIG2 Register for Read
+ * Status operation
+ */
+#define NFC_INT            0x8000
+
+#define NFC_SP_EN           (1 << 2)
+#define NFC_ECC_EN          (1 << 3)
+#define NFC_BIG             (1 << 5)
+#define NFC_RST             (1 << 6)
+#define NFC_CE              (1 << 7)
+#define NFC_ONE_CYCLE       (1 << 8)
+
+typedef enum {false, true} bool;
+
+struct mxc_nand_host {
+	struct mtd_info		mtd;
+	struct nand_chip	*nand;
+
+	struct nfc_regs __iomem	*regs;
+	int			spare_only;
+	int			status_request;
+	int			pagesize_2k;
+	int			clk_act;
+	uint16_t		col_addr;
+};
+
+static struct mxc_nand_host mxc_host;
+static struct mxc_nand_host *host = &mxc_host;
+
+/* Define delays in microsec for NAND device operations */
+#define TROP_US_DELAY   2000
+/* Macros to get byte and bit positions of ECC */
+#define COLPOS(x)  ((x) >> 3)
+#define BITPOS(x) ((x) & 0xf)
+
+/* Define single bit Error positions in Main & Spare area */
+#define MAIN_SINGLEBIT_ERROR 0x4
+#define SPARE_SINGLEBIT_ERROR 0x1
+
+/* OOB placement block for use with hardware ecc generation */
+#ifdef CONFIG_MXC_NAND_HWECC
+static struct nand_ecclayout nand_hw_eccoob = {
+	.eccbytes = 5,
+	.eccpos = {6, 7, 8, 9, 10},
+	.oobfree = {{0, 5}, {11, 5}, }
+};
+#else
+static struct nand_ecclayout nand_soft_eccoob = {
+	.eccbytes = 6,
+	.eccpos = {6, 7, 8, 9, 10, 11},
+	.oobfree = {{0, 5}, {12, 4}, }
+};
+#endif
+
+static uint32_t *mxc_nand_memcpy32(uint32_t *dest, uint32_t *source, size_t size)
+{
+	uint32_t *d = dest;
+
+	size >>= 2;
+	while (size--)
+		__raw_writel(__raw_readl(source++), d++);
+	return dest;
+}
+
+/*
+ * This function polls the NANDFC to wait for the basic operation to
+ * complete by checking the INT bit of config2 register.
+ */
+static void wait_op_done(struct mxc_nand_host *host, int max_retries,
+				uint16_t param)
+{
+	uint32_t tmp;
+
+	while (max_retries-- > 0) {
+		if (readw(&host->regs->nfc_config2) & NFC_INT) {
+			tmp = readw(&host->regs->nfc_config2);
+			tmp  &= ~NFC_INT;
+			writew(tmp, &host->regs->nfc_config2);
+			break;
+		}
+		udelay(1);
+	}
+	if (max_retries < 0) {
+		MTDDEBUG(MTD_DEBUG_LEVEL0, "%s(%d): INT not set\n",
+				__func__, param);
+	}
+}
+
+/*
+ * This function issues the specified command to the NAND device and
+ * waits for completion.
+ */
+static void send_cmd(struct mxc_nand_host *host, uint16_t cmd)
+{
+	MTDDEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x)\n", cmd);
+
+	writew(cmd, &host->regs->nfc_flash_cmd);
+	writew(NFC_CMD, &host->regs->nfc_config2);
+
+	/* Wait for operation to complete */
+	wait_op_done(host, TROP_US_DELAY, cmd);
+}
+
+/*
+ * This function sends an address (or partial address) to the
+ * NAND device. The address is used to select the source/destination for
+ * a NAND command.
+ */
+static void send_addr(struct mxc_nand_host *host, uint16_t addr)
+{
+	MTDDEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x)\n", addr);
+
+	writew(addr, &host->regs->nfc_flash_addr);
+	writew(NFC_ADDR, &host->regs->nfc_config2);
+
+	/* Wait for operation to complete */
+	wait_op_done(host, TROP_US_DELAY, addr);
+}
+
+/*
+ * This function requests the NANDFC to initate the transfer
+ * of data currently in the NANDFC RAM buffer to the NAND device.
+ */
+static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id,
+			int spare_only)
+{
+	MTDDEBUG(MTD_DEBUG_LEVEL3, "send_prog_page (%d)\n", spare_only);
+
+	writew(buf_id, &host->regs->nfc_buf_addr);
+
+	/* Configure spare or page+spare access */
+	if (!host->pagesize_2k) {
+		uint16_t config1 = readw(&host->regs->nfc_config1);
+		if (spare_only)
+			config1 |= NFC_SP_EN;
+		else
+			config1 &= ~(NFC_SP_EN);
+		writew(config1, &host->regs->nfc_config1);
+	}
+
+	writew(NFC_INPUT, &host->regs->nfc_config2);
+
+	/* Wait for operation to complete */
+	wait_op_done(host, TROP_US_DELAY, spare_only);
+}
+
+/*
+ * Requests NANDFC to initated the transfer of data from the
+ * NAND device into in the NANDFC ram buffer.
+ */
+static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id,
+		int spare_only)
+{
+	MTDDEBUG(MTD_DEBUG_LEVEL3, "send_read_page (%d)\n", spare_only);
+
+	writew(buf_id, &host->regs->nfc_buf_addr);
+
+	/* Configure spare or page+spare access */
+	if (!host->pagesize_2k) {
+		uint32_t config1 = readw(&host->regs->nfc_config1);
+		if (spare_only)
+			config1 |= NFC_SP_EN;
+		else
+			config1 &= ~NFC_SP_EN;
+		writew(config1, &host->regs->nfc_config1);
+	}
+
+	writew(NFC_OUTPUT, &host->regs->nfc_config2);
+
+	/* Wait for operation to complete */
+	wait_op_done(host, TROP_US_DELAY, spare_only);
+}
+
+/* Request the NANDFC to perform a read of the NAND device ID. */
+static void send_read_id(struct mxc_nand_host *host)
+{
+	struct nand_chip *this = host->nand;
+	uint16_t tmp;
+
+	/* NANDFC buffer 0 is used for device ID output */
+	writew(0x0, &host->regs->nfc_buf_addr);
+
+	/* Read ID into main buffer */
+	tmp = readw(&host->regs->nfc_config1);
+	tmp &= ~NFC_SP_EN;
+	writew(tmp, &host->regs->nfc_config1);
+
+	writew(NFC_ID, &host->regs->nfc_config2);
+
+	/* Wait for operation to complete */
+	wait_op_done(host, TROP_US_DELAY, 0);
+
+	if (this->options & NAND_BUSWIDTH_16) {
+		void __iomem *main_buf = host->regs->main_area0;
+		/* compress the ID info */
+		writeb(readb(main_buf + 2), main_buf + 1);
+		writeb(readb(main_buf + 4), main_buf + 2);
+		writeb(readb(main_buf + 6), main_buf + 3);
+		writeb(readb(main_buf + 8), main_buf + 4);
+		writeb(readb(main_buf + 10), main_buf + 5);
+	}
+}
+
+/*
+ * This function requests the NANDFC to perform a read of the
+ * NAND device status and returns the current status.
+ */
+static uint16_t get_dev_status(struct mxc_nand_host *host)
+{
+	void __iomem *main_buf = host->regs->main_area1;
+	uint32_t store;
+	uint16_t ret, tmp;
+	/* Issue status request to NAND device */
+
+	/* store the main area1 first word, later do recovery */
+	store = readl(main_buf);
+	/* NANDFC buffer 1 is used for device status */
+	writew(1, &host->regs->nfc_buf_addr);
+
+	/* Read status into main buffer */
+	tmp = readw(&host->regs->nfc_config1);
+	tmp &= ~NFC_SP_EN;
+	writew(tmp, &host->regs->nfc_config1);
+
+	writew(NFC_STATUS, &host->regs->nfc_config2);
+
+	/* Wait for operation to complete */
+	wait_op_done(host, TROP_US_DELAY, 0);
+
+	/*
+	 *  Status is placed in first word of main buffer
+	 * get status, then recovery area 1 data
+	 */
+	ret = readw(main_buf);
+	writel(store, main_buf);
+
+	return ret;
+}
+
+/* This function is used by upper layer to checks if device is ready */
+static int mxc_nand_dev_ready(struct mtd_info *mtd)
+{
+	/*
+	 * NFC handles R/B internally. Therefore, this function
+	 * always returns status as ready.
+	 */
+	return 1;
+}
+
+#ifdef CONFIG_MXC_NAND_HWECC
+static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
+{
+	/*
+	 * If HW ECC is enabled, we turn it on during init. There is
+	 * no need to enable again here.
+	 */
+}
+
+static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
+				 u_char *read_ecc, u_char *calc_ecc)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+
+	/*
+	 * 1-Bit errors are automatically corrected in HW.  No need for
+	 * additional correction.  2-Bit errors cannot be corrected by
+	 * HW ECC, so we need to return failure
+	 */
+	uint16_t ecc_status = readw(&host->regs->nfc_ecc_status_result);
+
+	if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
+		MTDDEBUG(MTD_DEBUG_LEVEL0,
+		      "MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
+				  u_char *ecc_code)
+{
+	return 0;
+}
+#endif
+
+static u_char mxc_nand_read_byte(struct mtd_info *mtd)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+	uint8_t ret = 0;
+	uint16_t col, rd_word;
+	uint16_t __iomem *main_buf =
+		(uint16_t __iomem *)host->regs->main_area0;
+	uint16_t __iomem *spare_buf =
+		(uint16_t __iomem *)host->regs->spare_area0;
+	union {
+		uint16_t word;
+		uint8_t bytes[2];
+	} nfc_word;
+
+	/* Check for status request */
+	if (host->status_request)
+		return get_dev_status(host) & 0xFF;
+
+	/* Get column for 16-bit access */
+	col = host->col_addr >> 1;
+
+	/* If we are accessing the spare region */
+	if (host->spare_only)
+		nfc_word.word = readw(&spare_buf[col]);
+	else
+		nfc_word.word = readw(&main_buf[col]);
+
+	/* Pick upper/lower byte of word from RAM buffer */
+	ret = nfc_word.bytes[host->col_addr & 0x1];
+
+	/* Update saved column address */
+	host->col_addr++;
+
+	return ret;
+}
+
+static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+	uint16_t col, ret;
+	uint16_t __iomem *p;
+
+	MTDDEBUG(MTD_DEBUG_LEVEL3,
+	      "mxc_nand_read_word(col = %d)\n", host->col_addr);
+
+	col = host->col_addr;
+	/* Adjust saved column address */
+	if (col < mtd->writesize && host->spare_only)
+		col += mtd->writesize;
+
+	if (col < mtd->writesize) {
+		p = (uint16_t __iomem *)(host->regs->main_area0 + (col >> 1));
+	} else {
+		p = (uint16_t __iomem *)(host->regs->spare_area0 +
+				((col - mtd->writesize) >> 1));
+	}
+
+	if (col & 1) {
+		union {
+			uint16_t word;
+			uint8_t bytes[2];
+		} nfc_word;
+
+		nfc_word.word = readw(p);
+		ret = nfc_word.bytes[1];
+		nfc_word.word = readw(&p[1]);
+		ret |= nfc_word.bytes[0] << 16;
+	} else {
+		ret = readw(p);
+	}
+
+	/* Update saved column address */
+	host->col_addr = col + 2;
+
+	return ret;
+}
+
+/*
+ * Write data of length len to buffer buf. The data to be
+ * written on NAND Flash is first copied to RAMbuffer. After the Data Input
+ * Operation by the NFC, the data is written to NAND Flash
+ */
+static void mxc_nand_write_buf(struct mtd_info *mtd,
+				const u_char *buf, int len)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+	int n, col, i = 0;
+
+	MTDDEBUG(MTD_DEBUG_LEVEL3,
+	      "mxc_nand_write_buf(col = %d, len = %d)\n", host->col_addr,
+	      len);
+
+	col = host->col_addr;
+
+	/* Adjust saved column address */
+	if (col < mtd->writesize && host->spare_only)
+		col += mtd->writesize;
+
+	n = mtd->writesize + mtd->oobsize - col;
+	n = min(len, n);
+
+	MTDDEBUG(MTD_DEBUG_LEVEL3,
+	      "%s:%d: col = %d, n = %d\n", __func__, __LINE__, col, n);
+
+	while (n > 0) {
+		void __iomem *p;
+
+		if (col < mtd->writesize) {
+			p = host->regs->main_area0 + (col & ~3);
+		} else {
+			p = host->regs->spare_area0 -
+						mtd->writesize + (col & ~3);
+		}
+
+		MTDDEBUG(MTD_DEBUG_LEVEL3, "%s:%d: p = %p\n", __func__,
+		      __LINE__, p);
+
+		if (((col | (unsigned long)&buf[i]) & 3) || n < 4) {
+			union {
+				uint32_t word;
+				uint8_t bytes[4];
+			} nfc_word;
+
+			nfc_word.word = readl(p);
+			nfc_word.bytes[col & 3] = buf[i++];
+			n--;
+			col++;
+
+			writel(nfc_word.word, p);
+		} else {
+			int m = mtd->writesize - col;
+
+			if (col >= mtd->writesize)
+				m += mtd->oobsize;
+
+			m = min(n, m) & ~3;
+
+			MTDDEBUG(MTD_DEBUG_LEVEL3,
+			      "%s:%d: n = %d, m = %d, i = %d, col = %d\n",
+			      __func__,  __LINE__, n, m, i, col);
+
+			mxc_nand_memcpy32(p, (uint32_t *)&buf[i], m);
+			col += m;
+			i += m;
+			n -= m;
+		}
+	}
+	/* Update saved column address */
+	host->col_addr = col;
+}
+
+/*
+ * Read the data buffer from the NAND Flash. To read the data from NAND
+ * Flash first the data output cycle is initiated by the NFC, which copies
+ * the data to RAMbuffer. This data of length len is then copied to buffer buf.
+ */
+static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+	int n, col, i = 0;
+
+	MTDDEBUG(MTD_DEBUG_LEVEL3,
+	      "mxc_nand_read_buf(col = %d, len = %d)\n", host->col_addr, len);
+
+	col = host->col_addr;
+
+	/* Adjust saved column address */
+	if (col < mtd->writesize && host->spare_only)
+		col += mtd->writesize;
+
+	n = mtd->writesize + mtd->oobsize - col;
+	n = min(len, n);
+
+	while (n > 0) {
+		void __iomem *p;
+
+		if (col < mtd->writesize) {
+			p = host->regs->main_area0 + (col & ~3);
+		} else {
+			p = host->regs->spare_area0 -
+					mtd->writesize + (col & ~3);
+		}
+
+		if (((col | (int)&buf[i]) & 3) || n < 4) {
+			union {
+				uint32_t word;
+				uint8_t bytes[4];
+			} nfc_word;
+
+			nfc_word.word = readl(p);
+			buf[i++] = nfc_word.bytes[col & 3];
+			n--;
+			col++;
+		} else {
+			int m = mtd->writesize - col;
+
+			if (col >= mtd->writesize)
+				m += mtd->oobsize;
+
+			m = min(n, m) & ~3;
+			mxc_nand_memcpy32((uint32_t *)&buf[i], p, m);
+
+			col += m;
+			i += m;
+			n -= m;
+		}
+	}
+	/* Update saved column address */
+	host->col_addr = col;
+}
+
+/*
+ * Used by the upper layer to verify the data in NAND Flash
+ * with the data in the buf.
+ */
+static int mxc_nand_verify_buf(struct mtd_info *mtd,
+				const u_char *buf, int len)
+{
+	u_char tmp[256];
+	uint bsize;
+
+	while (len) {
+		bsize = min(len, 256);
+		mxc_nand_read_buf(mtd, tmp, bsize);
+
+		if (memcmp(buf, tmp, bsize))
+			return 1;
+
+		buf += bsize;
+		len -= bsize;
+	}
+
+	return 0;
+}
+
+/*
+ * This function is used by upper layer for select and
+ * deselect of the NAND chip
+ */
+static void mxc_nand_select_chip(struct mtd_info *mtd, int chip)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+
+#ifdef CONFIG_MTD_NAND_MXC_FORCE_CE
+	if (chip > 0) {
+		printf("mxc_nand: ERROR: Illegal chip select (chip = %d)\n",
+				chip);
+		return;
+	}
+
+	if (chip == -1) {
+		writew(readw(&host->regs->nfc_config1) & ~NFC_CE,
+				&host->regs->nfc_config1);
+		return;
+	}
+
+	writew(readw(&host->regs->nfc_config1) | NFC_CE,
+			&host->regs->nfc_config1);
+#endif
+
+	switch (chip) {
+	case -1:
+		/* TODO: Disable the NFC clock */
+		if (host->clk_act)
+			host->clk_act = 0;
+		break;
+	case 0:
+		/* TODO: Enable the NFC clock */
+		if (!host->clk_act)
+			host->clk_act = 1;
+		break;
+
+	default:
+		break;
+	}
+}
+
+/*
+ * Used by the upper layer to write command to NAND Flash for
+ * different operations to be carried out on NAND Flash
+ */
+static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
+				int column, int page_addr)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+
+	MTDDEBUG(MTD_DEBUG_LEVEL3,
+	      "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
+	      command, column, page_addr);
+
+	/* Reset command state information */
+	host->status_request = false;
+
+	/* Command pre-processing step */
+	switch (command) {
+
+	case NAND_CMD_STATUS:
+		host->col_addr = 0;
+		host->status_request = true;
+		break;
+
+	case NAND_CMD_READ0:
+		host->col_addr = column;
+		host->spare_only = false;
+		break;
+
+	case NAND_CMD_READOOB:
+		host->col_addr = column;
+		host->spare_only = true;
+		if (host->pagesize_2k)
+			command = NAND_CMD_READ0; /* only READ0 is valid */
+		break;
+
+	case NAND_CMD_SEQIN:
+		if (column >= mtd->writesize) {
+			/*
+			 * before sending SEQIN command for partial write,
+			 * we need read one page out. FSL NFC does not support
+			 * partial write. It alway send out 512+ecc+512+ecc ...
+			 * for large page nand flash. But for small page nand
+			 * flash, it does support SPARE ONLY operation.
+			 */
+			if (host->pagesize_2k) {
+				/* call ourself to read a page */
+				mxc_nand_command(mtd, NAND_CMD_READ0, 0,
+						page_addr);
+			}
+
+			host->col_addr = column - mtd->writesize;
+			host->spare_only = true;
+
+			/* Set program pointer to spare region */
+			if (!host->pagesize_2k)
+				send_cmd(host, NAND_CMD_READOOB);
+		} else {
+			host->spare_only = false;
+			host->col_addr = column;
+
+			/* Set program pointer to page start */
+			if (!host->pagesize_2k)
+				send_cmd(host, NAND_CMD_READ0);
+		}
+		break;
+
+	case NAND_CMD_PAGEPROG:
+		send_prog_page(host, 0, host->spare_only);
+
+		if (host->pagesize_2k) {
+			/* data in 4 areas datas */
+			send_prog_page(host, 1, host->spare_only);
+			send_prog_page(host, 2, host->spare_only);
+			send_prog_page(host, 3, host->spare_only);
+		}
+
+		break;
+	}
+
+	/* Write out the command to the device. */
+	send_cmd(host, command);
+
+	/* Write out column address, if necessary */
+	if (column != -1) {
+		/*
+		 * MXC NANDFC can only perform full page+spare or
+		 * spare-only read/write.  When the upper layers
+		 * layers perform a read/write buf operation,
+		 * we will used the saved column adress to index into
+		 * the full page.
+		 */
+		send_addr(host, 0);
+		if (host->pagesize_2k)
+			/* another col addr cycle for 2k page */
+			send_addr(host, 0);
+	}
+
+	/* Write out page address, if necessary */
+	if (page_addr != -1) {
+		/* paddr_0 - p_addr_7 */
+		send_addr(host, (page_addr & 0xff));
+
+		if (host->pagesize_2k) {
+			send_addr(host, (page_addr >> 8) & 0xFF);
+			if (mtd->size >= 0x10000000) {
+				/* paddr_8 - paddr_15 */
+				send_addr(host, (page_addr >> 8) & 0xff);
+				send_addr(host, (page_addr >> 16) & 0xff);
+			} else {
+				/* paddr_8 - paddr_15 */
+				send_addr(host, (page_addr >> 8) & 0xff);
+			}
+		} else {
+			/* One more address cycle for higher density devices */
+			if (mtd->size >= 0x4000000) {
+				/* paddr_8 - paddr_15 */
+				send_addr(host, (page_addr >> 8) & 0xff);
+				send_addr(host, (page_addr >> 16) & 0xff);
+			} else {
+				/* paddr_8 - paddr_15 */
+				send_addr(host, (page_addr >> 8) & 0xff);
+			}
+		}
+	}
+
+	/* Command post-processing step */
+	switch (command) {
+
+	case NAND_CMD_RESET:
+		break;
+
+	case NAND_CMD_READOOB:
+	case NAND_CMD_READ0:
+		if (host->pagesize_2k) {
+			/* send read confirm command */
+			send_cmd(host, NAND_CMD_READSTART);
+			/* read for each AREA */
+			send_read_page(host, 0, host->spare_only);
+			send_read_page(host, 1, host->spare_only);
+			send_read_page(host, 2, host->spare_only);
+			send_read_page(host, 3, host->spare_only);
+		} else {
+			send_read_page(host, 0, host->spare_only);
+		}
+		break;
+
+	case NAND_CMD_READID:
+		host->col_addr = 0;
+		send_read_id(host);
+		break;
+
+	case NAND_CMD_PAGEPROG:
+		break;
+
+	case NAND_CMD_STATUS:
+		break;
+
+	case NAND_CMD_ERASE2:
+		break;
+	}
+}
+
+int board_nand_init(struct nand_chip *this)
+{
+	struct system_control_regs *sc_regs =
+		(struct system_control_regs *)IMX_SYSTEM_CTL_BASE;
+	struct mtd_info *mtd;
+	uint16_t tmp;
+	int err = 0;
+
+	/* structures must be linked */
+	mtd = &host->mtd;
+	mtd->priv = this;
+	host->nand = this;
+
+	/* 5 us command delay time */
+	this->chip_delay = 5;
+
+	this->priv = host;
+	this->dev_ready = mxc_nand_dev_ready;
+	this->cmdfunc = mxc_nand_command;
+	this->select_chip = mxc_nand_select_chip;
+	this->read_byte = mxc_nand_read_byte;
+	this->read_word = mxc_nand_read_word;
+	this->write_buf = mxc_nand_write_buf;
+	this->read_buf = mxc_nand_read_buf;
+	this->verify_buf = mxc_nand_verify_buf;
+
+	host->regs = (struct nfc_regs __iomem *)CONFIG_MXC_NAND_REGS_BASE;
+	host->clk_act = 1;
+
+#ifdef CONFIG_MXC_NAND_HWECC
+	this->ecc.calculate = mxc_nand_calculate_ecc;
+	this->ecc.hwctl = mxc_nand_enable_hwecc;
+	this->ecc.correct = mxc_nand_correct_data;
+	this->ecc.mode = NAND_ECC_HW;
+	this->ecc.size = 512;
+	this->ecc.bytes = 3;
+	this->ecc.layout = &nand_hw_eccoob;
+	tmp = readw(&host->regs->nfc_config1);
+	tmp |= NFC_ECC_EN;
+	writew(tmp, &host->regs->nfc_config1);
+#else
+	this->ecc.layout = &nand_soft_eccoob;
+	this->ecc.mode = NAND_ECC_SOFT;
+	tmp = readw(&host->regs->nfc_config1);
+	tmp &= ~NFC_ECC_EN;
+	writew(tmp, &host->regs->nfc_config1);
+#endif
+
+	/* Reset NAND */
+	this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
+
+	/*
+	 * preset operation
+	 * Unlock the internal RAM Buffer
+	 */
+	writew(0x2, &host->regs->nfc_config);
+
+	/* Blocks to be unlocked */
+	writew(0x0, &host->regs->nfc_unlockstart_blkaddr);
+	writew(0x4000, &host->regs->nfc_unlockend_blkaddr);
+
+	/* Unlock Block Command for given address range */
+	writew(0x4, &host->regs->nfc_wrprot);
+
+	/* NAND bus width determines access funtions used by upper layer */
+	if (readl(&sc_regs->fmcr) & NF_16BIT_SEL)
+		this->options |= NAND_BUSWIDTH_16;
+
+	host->pagesize_2k = 0;
+
+	return err;
+}
-- 
1.6.0.6

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

* [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD
  2009-07-23 21:37           ` Jean-Christophe PLAGNIOL-VILLARD
@ 2009-08-03  1:46             ` Ilya Yanok
  2009-08-03  5:32               ` Jean-Christophe PLAGNIOL-VILLARD
  0 siblings, 1 reply; 70+ messages in thread
From: Ilya Yanok @ 2009-08-03  1:46 UTC (permalink / raw)
  To: u-boot

This patch adds support for i.MX27-LITEKIT development board from
LogicPD. This board uses i.MX27 SoC and has 2MB NOR flash, 64MB NAND
flash, FEC ethernet controller integrated into i.MX27.

Signed-off-by: Ilya Yanok <yanok@emcraft.com>
---
 MAINTAINERS                             |    1 +
 MAKEALL                                 |    1 +
 Makefile                                |    3 +
 board/logicpd/imx27lite/Makefile        |   51 ++++++
 board/logicpd/imx27lite/config.mk       |    1 +
 board/logicpd/imx27lite/imx27lite.c     |  137 +++++++++++++++++
 board/logicpd/imx27lite/lowlevel_init.S |  170 ++++++++++++++++++++
 include/configs/imx27lite.h             |  255 +++++++++++++++++++++++++++++++
 8 files changed, 619 insertions(+), 0 deletions(-)
 create mode 100644 board/logicpd/imx27lite/Makefile
 create mode 100644 board/logicpd/imx27lite/config.mk
 create mode 100644 board/logicpd/imx27lite/imx27lite.c
 create mode 100644 board/logicpd/imx27lite/lowlevel_init.S
 create mode 100644 include/configs/imx27lite.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 620604c..60185ab 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -539,6 +539,7 @@ George G. Davis <gdavis@mvista.com>
 	gcplus		SA1100
 
 Wolfgang Denk <wd@denx.de>
+	imx27lite	i.MX27
 	qong		i.MX31
 
 Thomas Elste <info@elste.org>
diff --git a/MAKEALL b/MAKEALL
index dd0b761..48c3bc2 100755
--- a/MAKEALL
+++ b/MAKEALL
@@ -515,6 +515,7 @@ LIST_ARM9="			\
 	cp926ejs		\
 	cp946es			\
 	cp966			\
+	imx27lite		\
 	lpd7a400		\
 	mv88f6281gtw_ge		\
 	mx1ads			\
diff --git a/Makefile b/Makefile
index 8096f91..01e93c4 100644
--- a/Makefile
+++ b/Makefile
@@ -2879,6 +2879,9 @@ davinci_sonata_config :	unconfig
 davinci_dm355evm_config :	unconfig
 	@$(MKCONFIG) $(@:_config=) arm arm926ejs dm355evm davinci davinci
 
+imx27lite_config:	unconfig
+	@$(MKCONFIG) $(@:_config=) arm arm926ejs imx27lite logicpd mx27
+
 lpd7a400_config \
 lpd7a404_config:	unconfig
 	@$(MKCONFIG) $(@:_config=) arm lh7a40x lpd7a40x
diff --git a/board/logicpd/imx27lite/Makefile b/board/logicpd/imx27lite/Makefile
new file mode 100644
index 0000000..c404cef
--- /dev/null
+++ b/board/logicpd/imx27lite/Makefile
@@ -0,0 +1,51 @@
+#
+# (C) Copyright 2000-2004
+# 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).a
+
+COBJS	:= imx27lite.o
+SOBJS	:= lowlevel_init.o
+
+SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+SOBJS	:= $(addprefix $(obj),$(SOBJS))
+
+$(LIB):	$(obj).depend $(OBJS) $(SOBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS)
+
+clean:
+	rm -f $(SOBJS) $(OBJS)
+
+distclean:	clean
+	rm -f $(LIB) core *.bak $(obj).depend
+
+#########################################################################
+
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
+
diff --git a/board/logicpd/imx27lite/config.mk b/board/logicpd/imx27lite/config.mk
new file mode 100644
index 0000000..a2e7768
--- /dev/null
+++ b/board/logicpd/imx27lite/config.mk
@@ -0,0 +1 @@
+TEXT_BASE = 0xA7F00000
diff --git a/board/logicpd/imx27lite/imx27lite.c b/board/logicpd/imx27lite/imx27lite.c
new file mode 100644
index 0000000..6ab9708
--- /dev/null
+++ b/board/logicpd/imx27lite/imx27lite.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2007 Sascha Hauer, Pengutronix
+ * Copyright (C) 2008,2009 Eric Jarrige <jorasse@users.sourceforge.net>
+ * Copyright (C) 2009 Ilya Yanok <yanok@emcraft.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
+ *
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_MXC_UART
+static void imx27lite_uart_init()
+{
+	int i;
+	unsigned int mode[] = {
+		PE12_PF_UART1_TXD,
+		PE13_PF_UART1_RXD,
+	};
+
+	for (i = 0; i < ARRAY_SIZE(mode); i++)
+		imx_gpio_mode(mode[i]);
+
+}
+#endif /* CONFIGL_MXC_UART */
+
+#ifdef CONFIG_FEC_MXC
+static void imx27lite_fec_init()
+{
+	struct gpio_regs *regs = (struct gpio_regs *)IMX_GPIO_BASE;
+	int i;
+	unsigned int mode[] = {
+		PD0_AIN_FEC_TXD0,
+		PD1_AIN_FEC_TXD1,
+		PD2_AIN_FEC_TXD2,
+		PD3_AIN_FEC_TXD3,
+		PD4_AOUT_FEC_RX_ER,
+		PD5_AOUT_FEC_RXD1,
+		PD6_AOUT_FEC_RXD2,
+		PD7_AOUT_FEC_RXD3,
+		PD8_AF_FEC_MDIO,
+		PD9_AIN_FEC_MDC | GPIO_PUEN,
+		PD10_AOUT_FEC_CRS,
+		PD11_AOUT_FEC_TX_CLK,
+		PD12_AOUT_FEC_RXD0,
+		PD13_AOUT_FEC_RX_DV,
+		PD14_AOUT_FEC_CLR,
+		PD15_AOUT_FEC_COL,
+		PD16_AIN_FEC_TX_ER,
+		PF23_AIN_FEC_TX_EN,
+		(GPIO_PORTC | GPIO_OUT | GPIO_PUEN | GPIO_GPIO | 31),
+	};
+
+	for (i = 0; i < ARRAY_SIZE(mode); i++)
+		imx_gpio_mode(mode[i]);
+
+	writel(readl(&regs->port[PORTC].dr) | (1 << 31),
+				&regs->port[PORTC].dr);
+}
+#endif /* CONFIG_FEC_MXC */
+
+#ifdef CONFIG_MXC_MMC
+static void imx27lite_sd_init()
+{
+	int i;
+	unsigned int mode[] = {
+		PB4_PF_SD2_D0,
+		PB5_PF_SD2_D1,
+		PB6_PF_SD2_D2,
+		PB7_PF_SD2_D3,
+		PB8_PF_SD2_CMD,
+		PB9_PF_SD2_CLK,
+	};
+
+	for (i = 0; i < ARRAY_SIZE(mode); i++)
+		imx_gpio_mode(mode[i]);
+
+}
+#endif /* CONFIG_MXC_MMC */
+
+int board_init (void)
+{
+	gd->bd->bi_arch_number = MACH_TYPE_IMX27LITE;
+	gd->bd->bi_boot_params = 0xa0000100;
+
+#ifdef CONFIG_MXC_UART
+	imx27lite_uart_init();
+#endif
+#ifdef CONFIG_FEC_MXC
+	imx27lite_fec_init();
+#endif
+#ifdef CONFIG_MXC_MMC
+	imx27lite_sd_init();
+#endif
+
+	return 0;
+}
+
+int dram_init (void)
+{
+
+#if CONFIG_NR_DRAM_BANKS > 0
+	gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
+	gd->bd->bi_dram[0].size = get_ram_size((volatile void *)PHYS_SDRAM_1,
+			PHYS_SDRAM_1_SIZE);
+#endif
+#if CONFIG_NR_DRAM_BANKS > 1
+	gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
+	gd->bd->bi_dram[1].size = get_ram_size((volatile void *)PHYS_SDRAM_2,
+			PHYS_SDRAM_2_SIZE);
+#endif
+
+	return 0;
+}
+
+int checkboard(void)
+{
+	printf("LogicPD imx27lite\n");
+	return 0;
+}
diff --git a/board/logicpd/imx27lite/lowlevel_init.S b/board/logicpd/imx27lite/lowlevel_init.S
new file mode 100644
index 0000000..e2cdecb
--- /dev/null
+++ b/board/logicpd/imx27lite/lowlevel_init.S
@@ -0,0 +1,170 @@
+/*
+ * For clock initialization, see chapter 3 of the "MCIMX27 Multimedia
+ * Applications Processor Reference Manual, Rev. 0.2".
+ *
+ * (C) Copyright 2008 Eric Jarrige <eric.jarrige@armadeus.org>
+ * (C) Copyright 2009 Ilya Yanok <yanok@emcraft.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
+ */
+
+
+#include <config.h>
+#include <version.h>
+#include <asm/macro.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/asm-offsets.h>
+
+SOC_ESDCTL_BASE_W:	.word	IMX_ESD_BASE
+SOC_SI_ID_REG_W:	.word	IMX_SYSTEM_CTL_BASE
+SDRAM_ESDCFG_T1_W:	.word	SDRAM_ESDCFG_REGISTER_VAL(0)
+SDRAM_ESDCFG_T2_W:	.word	SDRAM_ESDCFG_REGISTER_VAL(3)
+SDRAM_PRECHARGE_CMD_W:	.word	(ESDCTL_SDE | ESDCTL_SMODE_PRECHARGE | \
+				 ESDCTL_ROW13 | ESDCTL_COL10)
+SDRAM_AUTOREF_CMD_W:	.word	(ESDCTL_SDE | ESDCTL_SMODE_AUTO_REF | \
+				 ESDCTL_ROW13 | ESDCTL_COL10)
+SDRAM_LOADMODE_CMD_W:	.word	(ESDCTL_SDE | ESDCTL_SMODE_LOAD_MODE | \
+				 ESDCTL_ROW13 | ESDCTL_COL10)
+SDRAM_NORMAL_CMD_W:	.word	SDRAM_ESDCTL_REGISTER_VAL
+
+.macro init_aipi
+	/*
+	 * setup AIPI1 and AIPI2
+	 */
+	write32 AIPI1_PSR0, AIPI1_PSR0_VAL
+	write32 AIPI1_PSR1, AIPI1_PSR1_VAL
+	write32 AIPI2_PSR0, AIPI2_PSR0_VAL
+	write32 AIPI2_PSR1, AIPI2_PSR1_VAL
+
+.endm /* init_aipi */
+
+.macro init_clock
+	ldr r0, =CSCR
+	/* disable MPLL/SPLL first */
+	ldr r1, [r0]
+	bic r1, r1, #(CSCR_MPEN|CSCR_SPEN)
+	str r1, [r0]
+
+	write32 MPCTL0, MPCTL0_VAL
+	write32 SPCTL0, SPCTL0_VAL
+
+	write32 CSCR, CSCR_VAL | CSCR_MPLL_RESTART | CSCR_SPLL_RESTART
+
+	/*
+	 * add some delay here
+	 */
+	wait_timer 0x1000
+
+	/* peripheral clock divider */
+	write32 PCDR0, PCDR0_VAL
+	write32 PCDR1, PCDR1_VAL
+
+	/* Configure PCCR0 and PCCR1 */
+	write32 PCCR0, PCCR0_VAL
+	write32 PCCR1, PCCR1_VAL
+
+.endm /* init_clock */
+
+.macro sdram_init
+	ldr r0, SOC_ESDCTL_BASE_W
+	mov r2, #PHYS_SDRAM_1
+
+	/* Do initial reset */
+	mov r1, #ESDMISC_MDDR_DL_RST
+	str r1, [r0, #ESDMISC_ROF]
+
+	/* Hold for more than 200ns */
+	wait_timer 0x10000
+
+	/* Activate LPDDR iface */
+	mov r1, #ESDMISC_MDDREN
+	str r1, [r0, #ESDMISC_ROF]
+
+	/* Check The chip version TO1 or TO2 */
+	ldr r1, SOC_SI_ID_REG_W
+	ldr r1, [r1]
+	ands r1, r1, #0xF0000000
+	/* add Latency on CAS only for TO2 */
+	ldreq r1, SDRAM_ESDCFG_T2_W
+	ldrne r1, SDRAM_ESDCFG_T1_W
+	str r1, [r0, #ESDCFG0_ROF]
+
+	/* Run initialization sequence */
+	ldr r1, SDRAM_PRECHARGE_CMD_W
+	str r1, [r0, #ESDCTL0_ROF]
+	ldr r1, [r2, #SDRAM_ALL_VAL]
+
+	ldr r1, SDRAM_AUTOREF_CMD_W
+	str r1, [r0, #ESDCTL0_ROF]
+	ldr r1, [r2, #SDRAM_ALL_VAL]
+	ldr r1, [r2, #SDRAM_ALL_VAL]
+
+	ldr r1, SDRAM_LOADMODE_CMD_W
+	str r1, [r0, #ESDCTL0_ROF]
+	ldrb r1, [r2, #SDRAM_MODE_REGISTER_VAL]
+	add r3, r2, #SDRAM_EXT_MODE_REGISTER_VAL
+	ldrb r1, [r3]
+
+	ldr r1, SDRAM_NORMAL_CMD_W
+	str r1, [r0, #ESDCTL0_ROF]
+
+#if (CONFIG_NR_DRAM_BANKS > 1)
+	/* 2nd sdram */
+	mov r2, #PHYS_SDRAM_2
+
+	/* Check The chip version TO1 or TO2 */
+	ldr r1, SOC_SI_ID_REG_W
+	ldr r1, [r1]
+	ands r1, r1, #0xF0000000
+	/* add Latency on CAS only for TO2 */
+	ldreq r1, SDRAM_ESDCFG_T2_W
+	ldrne r1, SDRAM_ESDCFG_T1_W
+	str r1, [r0, #ESDCFG1_ROF]
+
+	/* Run initialization sequence */
+	ldr r1, SDRAM_PRECHARGE_CMD_W
+	str r1, [r0, #ESDCTL1_ROF]
+	ldr r1, [r2, #SDRAM_ALL_VAL]
+
+	ldr r1, SDRAM_AUTOREF_CMD_W
+	str r1, [r0, #ESDCTL1_ROF]
+	ldr r1, [r2, #SDRAM_ALL_VAL]
+	ldr r1, [r2, #SDRAM_ALL_VAL]
+
+	ldr r1, SDRAM_LOADMODE_CMD_W
+	str r1, [r0, #ESDCTL1_ROF]
+	ldrb r1, [r2, #SDRAM_MODE_REGISTER_VAL]
+	add r3, r2, #SDRAM_EXT_MODE_REGISTER_VAL
+	ldrb r1, [r3]
+
+	ldr r1, SDRAM_NORMAL_CMD_W
+	str r1, [r0, #ESDCTL1_ROF]
+#endif  /* CONFIG_NR_DRAM_BANKS > 1 */
+
+.endm /* sdram_init */
+
+.globl	lowlevel_init
+lowlevel_init:
+
+	mov	r10, lr
+
+	init_aipi
+
+	init_clock
+
+	sdram_init
+
+	mov	pc,r10
diff --git a/include/configs/imx27lite.h b/include/configs/imx27lite.h
new file mode 100644
index 0000000..7822748
--- /dev/null
+++ b/include/configs/imx27lite.h
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2009 Ilya Yanok <yanok@emcraft.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 __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * SoC Configuration
+ */
+#define CONFIG_ARM926EJS			/* arm926ejs CPU core */
+#define CONFIG_MX27
+#define CONFIG_IMX27LITE
+#define CONFIG_MX27_CLK32	32768		/* OSC32K frequency */
+#define CONFIG_SYS_HZ		1000
+
+#define CONFIG_DISPLAY_CPUINFO
+
+#define CONFIG_CMDLINE_TAG		1	/* enable passing of ATAGs */
+#define CONFIG_SETUP_MEMORY_TAGS	1
+#define CONFIG_INITRD_TAG		1
+
+/*
+ * Lowlevel configuration
+ */
+#define SDRAM_ESDCFG_REGISTER_VAL(cas)	\
+		(ESDCFG_TRC(10) |	\
+		ESDCFG_TRCD(3) |	\
+		ESDCFG_TCAS(cas) |	\
+		ESDCFG_TRRD(1) |	\
+		ESDCFG_TRAS(5) |	\
+		ESDCFG_TWR |		\
+		ESDCFG_TMRD(2) |	\
+		ESDCFG_TRP(2) |		\
+		ESDCFG_TXP(3))
+
+#define SDRAM_ESDCTL_REGISTER_VAL	\
+		(ESDCTL_PRCT(0) |	\
+		 ESDCTL_BL |		\
+		 ESDCTL_PWDT(0) |	\
+		 ESDCTL_SREFR(3) |	\
+		 ESDCTL_DSIZ_32 |	\
+		 ESDCTL_COL10 |		\
+		 ESDCTL_ROW13 |		\
+		 ESDCTL_SDE)
+
+#define SDRAM_ALL_VAL		0xf00
+
+#define SDRAM_MODE_REGISTER_VAL	0x33	/* BL: 8, CAS: 3 */
+#define SDRAM_EXT_MODE_REGISTER_VAL	0x1000000
+
+#define MPCTL0_VAL	0x1ef15d5
+
+#define SPCTL0_VAL	0x043a1c09
+
+#define CSCR_VAL	0x33f08107
+
+#define PCDR0_VAL	0x120470c3
+#define PCDR1_VAL	0x03030303
+#define PCCR0_VAL	0xffffffff
+#define PCCR1_VAL	0xfffffffc
+
+#define AIPI1_PSR0_VAL	0x20040304
+#define AIPI1_PSR1_VAL	0xdffbfcfb
+#define AIPI2_PSR0_VAL	0x07ffc200
+#define AIPI2_PSR1_VAL	0xffffffff
+
+/*
+ * Memory Info
+ */
+/* malloc() len */
+#define CONFIG_SYS_MALLOC_LEN		(0x10000 + 256 * 1024)
+/* reserved for initial data */
+#define CONFIG_SYS_GBL_DATA_SIZE	128
+/* memtest start address */
+#define CONFIG_SYS_MEMTEST_START	0xA0000000
+#define CONFIG_SYS_MEMTEST_END		0xA1000000	/* 16MB RAM test */
+#define CONFIG_NR_DRAM_BANKS	1		/* we have 1 bank of DRAM */
+#define CONFIG_STACKSIZE	(256 * 1024)	/* regular stack */
+#define PHYS_SDRAM_1		0xA0000000	/* DDR Start */
+#define PHYS_SDRAM_1_SIZE	0x08000000	/* DDR size 128MB */
+
+/*
+ * Serial Driver info
+ */
+#define CONFIG_MXC_UART
+#define CONFIG_SYS_MX27_UART1
+#define CONFIG_CONS_INDEX	1		/* use UART0 for console */
+#define CONFIG_BAUDRATE		115200		/* Default baud rate */
+#define CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 }
+
+/*
+ * Flash & Environment
+ */
+#define CONFIG_ENV_IS_IN_FLASH
+#define CONFIG_FLASH_CFI_DRIVER
+#define CONFIG_SYS_FLASH_CFI
+/* Use buffered writes (~10x faster) */
+#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE	1
+/* Use hardware sector protection */
+#define CONFIG_SYS_FLASH_PROTECTION		1
+#define CONFIG_SYS_MAX_FLASH_BANKS	1	/* max number of flash banks */
+#define CONFIG_SYS_FLASH_SECT_SZ	0x2000	/* 8KB sect size Intel Flash */
+/* end of flash */
+#define CONFIG_ENV_OFFSET		(PHYS_FLASH_SIZE - 0x20000)
+/* CS2 Base address */
+#define PHYS_FLASH_1			0xc0000000
+/* Flash Base for U-Boot */
+#define CONFIG_SYS_FLASH_BASE		PHYS_FLASH_1
+/* Flash size 2MB */
+#define PHYS_FLASH_SIZE			0x200000
+#define CONFIG_SYS_MAX_FLASH_SECT	(PHYS_FLASH_SIZE / \
+		CONFIG_SYS_FLASH_SECT_SZ)
+#define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_FLASH_BASE
+#define CONFIG_SYS_MONITOR_LEN		0x40000		/* Reserve 256KiB */
+#define CONFIG_ENV_SECT_SIZE		0x10000		/* Env sector Size */
+#define CONFIG_ENV_SIZE		CONFIG_ENV_SECT_SIZE
+/* Address and size of Redundant Environment Sector	*/
+#define CONFIG_ENV_OFFSET_REDUND	(CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE)
+#define CONFIG_ENV_SIZE_REDUND	CONFIG_ENV_SIZE
+
+/*
+ * Ethernet
+ */
+#define CONFIG_FEC_MXC
+#define CONFIG_FEC_MXC_PHYADDR		0x1f
+#define CONFIG_MII
+#define CONFIG_NET_MULTI
+
+/*
+ * MTD
+ */
+#define CONFIG_MTD_DEVICE
+
+/*
+ * NAND
+ */
+#define CONFIG_NAND_MXC
+#define CONFIG_MXC_NAND_REGS_BASE	0xd8000000
+#define CONFIG_SYS_MAX_NAND_DEVICE	1
+#define CONFIG_SYS_NAND_BASE		0xd8000000
+#define CONFIG_JFFS2_NAND
+#define CONFIG_MXC_NAND_HWECC
+
+/*
+ * SD/MMC
+ */
+#define CONFIG_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_MXC_MMC
+#define CONFIG_MXC_MCI_REGS_BASE	0x10014000
+#define CONFIG_DOS_PARTITION
+
+/*
+ * MTD partitions
+ */
+#define CONFIG_CMD_MTDPARTS
+#define MTDIDS_DEFAULT		"nor0=physmap-flash.0,nand0=mxc_nand.0"
+#define MTDPARTS_DEFAULT			\
+	"mtdparts="				\
+		"physmap-flash.0:"		\
+			"256k(U-Boot),"		\
+			"1664k(user),"		\
+			"64k(env1),"		\
+			"64k(env2);"		\
+		"mxc_nand.0:"			\
+			"128k(IPL-SPL),"	\
+			"4m(kernel),"		\
+			"22m(rootfs),"		\
+			"-(userfs)"
+
+/*
+ * U-Boot general configuration
+ */
+#define CONFIG_BOOTFILE		"uImage"	/* Boot file name */
+#define CONFIG_SYS_PROMPT	"=> "	/* Monitor Command Prompt */
+#define CONFIG_SYS_CBSIZE	1024	/* Console I/O Buffer Size  */
+/* Print buffer sz */
+#define CONFIG_SYS_PBSIZE	(CONFIG_SYS_CBSIZE + \
+		sizeof(CONFIG_SYS_PROMPT) + 16)
+#define CONFIG_SYS_MAXARGS	16	/* max number of command args */
+/* Boot Argument Buffer Size */
+#define CONFIG_SYS_BARGSIZE	CONFIG_SYS_CBSIZE
+#define CONFIG_CMDLINE_EDITING
+#define CONFIG_SYS_LONGHELP
+
+/*
+ * U-Boot commands
+ */
+#include <config_cmd_default.h>
+#define CONFIG_CMD_ASKENV
+#define CONFIG_CMD_BDI
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_DIAG
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_JFFS2
+#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_BOOTDELAY	5
+
+#define CONFIG_LOADADDR		0xa0800000	/* loadaddr env var */
+#define CONFIG_SYS_LOAD_ADDR		CONFIG_LOADADDR
+
+#define xstr(s)	str(s)
+#define str(s)	#s
+
+#define	CONFIG_EXTRA_ENV_SETTINGS					\
+	"netdev=eth0\0"							\
+	"nfsargs=setenv bootargs root=/dev/nfs rw "			\
+		"nfsroot=${serverip}:${rootpath}\0"			\
+	"ramargs=setenv bootargs root=/dev/ram rw\0"			\
+	"addip=setenv bootargs ${bootargs} "				\
+		"ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}"	\
+		":${hostname}:${netdev}:off panic=1\0"			\
+	"addtty=setenv bootargs ${bootargs}"				\
+		" console=ttymxc0,${baudrate}\0"			\
+	"addmtd=setenv bootargs ${bootargs} ${mtdparts}\0"		\
+	"addmisc=setenv bootargs ${bootargs}\0"				\
+	"u-boot=imx27/u-boot.bin\0"					\
+	"kernel_addr_r=a0800000\0"					\
+	"hostname=imx27\0"						\
+	"bootfile=imx27/uImage\0"					\
+	"rootpath=/opt/eldk-4.2-arm/arm\0"				\
+	"net_nfs=tftp ${kernel_addr_r} ${bootfile};"			\
+		"run nfsargs addip addtty addmtd addmisc;"		\
+		"bootm\0"						\
+	"bootcmd=run net_nfs\0"					\
+	"load=tftp ${loadaddr} ${u-boot}\0"				\
+	"update=protect off " xstr(CONFIG_SYS_MONITOR_BASE)		\
+		" +${filesize};era " xstr(CONFIG_SYS_MONITOR_BASE)	\
+		" +${filesize};cp.b ${fileaddr} "			\
+		xstr(CONFIG_SYS_MONITOR_BASE) " ${filesize}\0"		\
+	"upd=run load update\0"						\
+
+#endif /* __CONFIG_H */
-- 
1.6.0.6

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

* [U-Boot] [PATCH] mxc_nand: add nand driver for MX2/MX3
  2009-07-28 22:37         ` Scott Wood
  2009-08-03  1:45           ` Ilya Yanok
@ 2009-08-03  2:01           ` Ilya Yanok
  2009-08-03 16:58             ` Scott Wood
  1 sibling, 1 reply; 70+ messages in thread
From: Ilya Yanok @ 2009-08-03  2:01 UTC (permalink / raw)
  To: u-boot

Hi Scott,

thanks for the review.

Scott Wood wrote:
>> +/* OOB placement block for use with hardware ecc generation */
>> +static struct nand_ecclayout nand_hw_eccoob = {
>> +	.eccbytes = 5,
>> +	.eccpos = {6, 7, 8, 9, 10},
>> +	.oobfree = {{0, 5}, {11, 5}, }
>> +};
>> +
>> +#ifndef CONFIG_MXC_NAND_HWECC
>> +static struct nand_ecclayout nand_hw_eccoob_soft = {
>> +	.eccbytes = 6,
>> +	.eccpos = {6, 7, 8, 9, 10, 11},
>> +	.oobfree = {{0, 5}, {12, 4}, }
>> +};
>> +#endif
>>     
>
> Why is one struct #ifndef, but the other isn't #ifdef?
>   

Fixed.

>> +/*
>> + * This function requests the NANDFC to initate the transfer
>> + * of data currently in the NANDFC RAM buffer to the NAND device.
>> + */
>> +static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id,
>> +			int spare_only)
>> +{
>> +	MTDDEBUG(MTD_DEBUG_LEVEL3, "send_prog_page (%d)\n", spare_only);
>> +
>> +	/* NANDFC buffer 0 is used for page read/write */
>> +	writew(buf_id, &host->regs->nfc_buf_addr);
>>     
>
> Comment does not match code.
>   

Comment removed.

>> +	/*
>> +	 * NANDFC buffer 1 is used for device status to prevent
>> +	 * corruption of read/write buffer on status requests.
>> +	 */
>> +	writew(1, &host->regs->nfc_buf_addr);
>>     
>
> From discussion on the previous patch:
>   
>>> But it looks like buffer 1 is used for data with large page flash.
>>>   
>>>       
>> Well, we save first word of the buffer and then recover it.
>>     
>
> So then there's no longer any special reason to use buffer 1 for status,
> and that comment is misleading...
>   

Misleading comment removed.

>> +static u_char mxc_nand_read_byte(struct mtd_info *mtd)
>> +{
>> +	struct nand_chip *nand_chip = mtd->priv;
>> +	struct mxc_nand_host *host = nand_chip->priv;
>> +	uint8_t ret = 0;
>> +	uint16_t col, rd_word;
>> +	uint16_t __iomem *main_buf =
>> +		(uint16_t __iomem *)host->regs->main_area0;
>> +	uint16_t __iomem *spare_buf =
>> +		(uint16_t __iomem *)host->regs->spare_area0;
>> +
>> +	/* Check for status request */
>> +	if (host->status_request)
>> +		return get_dev_status(host) & 0xFF;
>> +
>> +	/* Get column for 16-bit access */
>> +	col = host->col_addr >> 1;
>> +
>> +	/* If we are accessing the spare region */
>> +	if (host->spare_only)
>> +		rd_word = readw(&spare_buf[col]);
>> +	else
>> +		rd_word = readw(&main_buf[col]);
>> +
>> +	/* Pick upper/lower byte of word from RAM buffer */
>> +	if (host->col_addr & 0x1)
>> +		ret = (rd_word >> 8) & 0xFF;
>> +	else
>> +		ret = rd_word & 0xFF;
>>     
>
> Use a union, as in read_buf().  Otherwise, this breaks on big-endian --
> you may not care, but it's better to not have such dependencies lurking
> in the code that could be reused who-knows-where.
>   

Ok. Fixed.

>> +	if (col & 1) {
>> +		rd_word = readw(p);
>> +		ret = (rd_word >> 8) & 0xff;
>> +		rd_word = readw(&p[1]);
>> +		ret |= (rd_word << 8) & 0xff00;
>>     
>
> Again, this is unnecessary, but if you insist, use a union.
>   

I understood that read_byte()/read_word() never mix up in existing code
but the API doesn't completely exclude such possibility so I'd like this
case to be treated correctly. I've updated the code to use union but if
you insist I'll remove this if clause completely.

>> +#ifdef CONFIG_MTD_NAND_MXC_FORCE_CE
>> +	if (chip > 0) {
>> +		MTDDEBUG(MTD_DEBUG_LEVEL0,
>> +		      "ERROR:  Illegal chip select (chip = %d)\n", chip);
>>     
>
> If it's an error, that's not exactly debug (especially since there's no
> way to propagate the error upwards)...
>   

Changed to printf().

>> +		return;
>> +	}
>> +
>> +	if (chip == -1) {
>> +		writew(readw(&host->regs->nfc_config1) & ~NFC_CE,
>> +				&host->regs->nfc_config1);
>> +		return;
>> +	}
>> +
>> +	writew(readw(&host->regs->nfc_config1) | NFC_CE,
>> +			&host->regs->nfc_config1);
>> +#endif
>>     
>
> #else?
>   

For me it just works (I've never defined CONFIG_MTD_NAND_MXC_FORCE_CE).

>> +		if (column >= mtd->writesize) {
>> +			/*
>> +			 * before sending SEQIN command for partial write,
>> +			 * we need read one page out. FSL NFC does not support
>> +			 * partial write. It alway send out 512+ecc+512+ecc ...
>> +			 * for large page nand flash. But for small page nand
>> +			 * flash, it does support SPARE ONLY operation.
>> +			 */
>> +			if (host->pagesize_2k) {
>> +				/* call ourself to read a page */
>> +				mxc_nand_command(mtd, NAND_CMD_READ0, 0,
>> +						page_addr);
>> +			}
>>     
>
> #ifdef CONFIG_MXC_NAND_HWECC?
>   

Uh... I have to admit I don't really have clear understanding of this
problem and I can't find it's description in i.MX27 Reference Manual...
Maybe you can point me in some direction? For now I'm not sure if
putting this under #ifdef won't break something...

>> +	/* 50 us command delay time */
>> +	this->chip_delay = 5;
>>     
>
> 5 or 50?
>   

Comment fixed.

>> +	host->pagesize_2k = 0;
>>     
>
> Make this board-configurable.  Has large page been tested?  If not,
> perhaps it should stay out for now, given how weird it is on this
> controller.
>   

I've never tested it with large page devices... So I'd vote to leave
large-page support disabled.

Regards, Ilya.

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

* [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD
  2009-08-03  1:46             ` Ilya Yanok
@ 2009-08-03  5:32               ` Jean-Christophe PLAGNIOL-VILLARD
  2009-08-03  8:19                 ` Wolfgang Denk
  2009-08-10 22:32                 ` [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD Ilya Yanok
  0 siblings, 2 replies; 70+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2009-08-03  5:32 UTC (permalink / raw)
  To: u-boot

> + * Copyright (C) 2008,2009 Eric Jarrige <jorasse@users.sourceforge.net>
> + * Copyright (C) 2009 Ilya Yanok <yanok@emcraft.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
> + *
> + */
> +
> +#include <common.h>
> +#include <asm/io.h>
> +#include <asm/arch/imx-regs.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#ifdef CONFIG_MXC_UART
> +static void imx27lite_uart_init()
> +{
> +	int i;
> +	unsigned int mode[] = {
> +		PE12_PF_UART1_TXD,
> +		PE13_PF_UART1_RXD,
> +	};
> +
> +	for (i = 0; i < ARRAY_SIZE(mode); i++)
> +		imx_gpio_mode(mode[i]);
> +
> +}
> +#endif /* CONFIGL_MXC_UART */
> +
> +#ifdef CONFIG_FEC_MXC
> +static void imx27lite_fec_init()
> +{
> +	struct gpio_regs *regs = (struct gpio_regs *)IMX_GPIO_BASE;
> +	int i;
> +	unsigned int mode[] = {
> +		PD0_AIN_FEC_TXD0,
> +		PD1_AIN_FEC_TXD1,
> +		PD2_AIN_FEC_TXD2,
> +		PD3_AIN_FEC_TXD3,
> +		PD4_AOUT_FEC_RX_ER,
> +		PD5_AOUT_FEC_RXD1,
> +		PD6_AOUT_FEC_RXD2,
> +		PD7_AOUT_FEC_RXD3,
> +		PD8_AF_FEC_MDIO,
> +		PD9_AIN_FEC_MDC | GPIO_PUEN,
> +		PD10_AOUT_FEC_CRS,
> +		PD11_AOUT_FEC_TX_CLK,
> +		PD12_AOUT_FEC_RXD0,
> +		PD13_AOUT_FEC_RX_DV,
> +		PD14_AOUT_FEC_CLR,
> +		PD15_AOUT_FEC_COL,
> +		PD16_AIN_FEC_TX_ER,
> +		PF23_AIN_FEC_TX_EN,
> +		(GPIO_PORTC | GPIO_OUT | GPIO_PUEN | GPIO_GPIO | 31),
> +	};
> +
> +	for (i = 0; i < ARRAY_SIZE(mode); i++)
> +		imx_gpio_mode(mode[i]);
> +
> +	writel(readl(&regs->port[PORTC].dr) | (1 << 31),
> +				&regs->port[PORTC].dr);
> +}
> +#endif /* CONFIG_FEC_MXC */
> +
> +#ifdef CONFIG_MXC_MMC
> +static void imx27lite_sd_init()
> +{
> +	int i;
> +	unsigned int mode[] = {
> +		PB4_PF_SD2_D0,
> +		PB5_PF_SD2_D1,
> +		PB6_PF_SD2_D2,
> +		PB7_PF_SD2_D3,
> +		PB8_PF_SD2_CMD,
> +		PB9_PF_SD2_CLK,
> +	};
> +
> +	for (i = 0; i < ARRAY_SIZE(mode); i++)
> +		imx_gpio_mode(mode[i]);
> +
> +}
> +#endif /* CONFIG_MXC_MMC */
tks for the udpate
but the init function are not board specific but soc specific please move
the to cpu/arm926ejs/soc/something.c
> +
> +int board_init (void)
> +{
> +	gd->bd->bi_arch_number = MACH_TYPE_IMX27LITE;
> +	gd->bd->bi_boot_params = 0xa0000100;
please BASE + 0x100;
> +
> +#ifdef CONFIG_MXC_UART
> +	imx27lite_uart_init();
> +#endif
> +#ifdef CONFIG_FEC_MXC
> +	imx27lite_fec_init();
> +#endif
> +#ifdef CONFIG_MXC_MMC
> +	imx27lite_sd_init();
> +#endif
> +
> +	return 0;
> +}
> +
> +int dram_init (void)
> +{
> +
> +#if CONFIG_NR_DRAM_BANKS > 0
> +	gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
> +	gd->bd->bi_dram[0].size = get_ram_size((volatile void *)PHYS_SDRAM_1,
> +			PHYS_SDRAM_1_SIZE);
> +#endif
> +#if CONFIG_NR_DRAM_BANKS > 1
> +	gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
> +	gd->bd->bi_dram[1].size = get_ram_size((volatile void *)PHYS_SDRAM_2,
> +			PHYS_SDRAM_2_SIZE);
> +#endif
> +
> +	return 0;
> +}
> +
> +int checkboard(void)
> +{
> +	printf("LogicPD imx27lite\n");
> +	return 0;
> +}
> diff --git a/board/logicpd/imx27lite/lowlevel_init.S b/board/logicpd/imx27lite/lowlevel_init.S
> new file mode 100644
> index 0000000..e2cdecb
> --- /dev/null
<snip>
> +
> +#define SDRAM_MODE_REGISTER_VAL	0x33	/* BL: 8, CAS: 3 */
> +#define SDRAM_EXT_MODE_REGISTER_VAL	0x1000000
> +
> +#define MPCTL0_VAL	0x1ef15d5
> +
> +#define SPCTL0_VAL	0x043a1c09
> +
> +#define CSCR_VAL	0x33f08107
> +
> +#define PCDR0_VAL	0x120470c3
> +#define PCDR1_VAL	0x03030303
> +#define PCCR0_VAL	0xffffffff
> +#define PCCR1_VAL	0xfffffffc
> +
> +#define AIPI1_PSR0_VAL	0x20040304
> +#define AIPI1_PSR1_VAL	0xdffbfcfb
> +#define AIPI2_PSR0_VAL	0x07ffc200
> +#define AIPI2_PSR1_VAL	0xffffffff
> +
> +/*
> + * Memory Info
> + */
> +/* malloc() len */
> +#define CONFIG_SYS_MALLOC_LEN		(0x10000 + 256 * 1024)
please do not mix hexa and decimal
> +/* reserved for initial data */
> +#define CONFIG_SYS_GBL_DATA_SIZE	128
> +/* memtest start address */
> +#define CONFIG_SYS_MEMTEST_START	0xA0000000
> +#define CONFIG_SYS_MEMTEST_END		0xA1000000	/* 16MB RAM test */
> +#define CONFIG_NR_DRAM_BANKS	1		/* we have 1 bank of DRAM */
> +#define CONFIG_STACKSIZE	(256 * 1024)	/* regular stack */
> +#define PHYS_SDRAM_1		0xA0000000	/* DDR Start */
> +#define PHYS_SDRAM_1_SIZE	0x08000000	/* DDR size 128MB */
> +
> +/*
> + * Serial Driver info
> + */
> +#define CONFIG_MXC_UART
> +#define CONFIG_SYS_MX27_UART1
> +#define CONFIG_CONS_INDEX	1		/* use UART0 for console */
> +#define CONFIG_BAUDRATE		115200		/* Default baud rate */
> +#define CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 }
> +
> +/*
> + * Flash & Environment
> + */
> +#define CONFIG_ENV_IS_IN_FLASH
> +#define CONFIG_FLASH_CFI_DRIVER
> +#define CONFIG_SYS_FLASH_CFI
> +/* Use buffered writes (~10x faster) */
> +#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE	1
> +/* Use hardware sector protection */
> +#define CONFIG_SYS_FLASH_PROTECTION		1
> +#define CONFIG_SYS_MAX_FLASH_BANKS	1	/* max number of flash banks */
> +#define CONFIG_SYS_FLASH_SECT_SZ	0x2000	/* 8KB sect size Intel Flash */
> +/* end of flash */
> +#define CONFIG_ENV_OFFSET		(PHYS_FLASH_SIZE - 0x20000)
> +/* CS2 Base address */
> +#define PHYS_FLASH_1			0xc0000000
> +/* Flash Base for U-Boot */
> +#define CONFIG_SYS_FLASH_BASE		PHYS_FLASH_1
> +/* Flash size 2MB */
> +#define PHYS_FLASH_SIZE			0x200000
> +#define CONFIG_SYS_MAX_FLASH_SECT	(PHYS_FLASH_SIZE / \
> +		CONFIG_SYS_FLASH_SECT_SZ)
> +#define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_FLASH_BASE
> +#define CONFIG_SYS_MONITOR_LEN		0x40000		/* Reserve 256KiB */
> +#define CONFIG_ENV_SECT_SIZE		0x10000		/* Env sector Size */
> +#define CONFIG_ENV_SIZE		CONFIG_ENV_SECT_SIZE
> +/* Address and size of Redundant Environment Sector	*/
> +#define CONFIG_ENV_OFFSET_REDUND	(CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE)
> +#define CONFIG_ENV_SIZE_REDUND	CONFIG_ENV_SIZE
> +
> +/*
> + * Ethernet
> + */
> +#define CONFIG_FEC_MXC
> +#define CONFIG_FEC_MXC_PHYADDR		0x1f
> +#define CONFIG_MII
> +#define CONFIG_NET_MULTI
> +
> +/*
> + * MTD
> + */
> +#define CONFIG_MTD_DEVICE
> +
> +/*
> + * NAND
> + */
> +#define CONFIG_NAND_MXC
> +#define CONFIG_MXC_NAND_REGS_BASE	0xd8000000
> +#define CONFIG_SYS_MAX_NAND_DEVICE	1
> +#define CONFIG_SYS_NAND_BASE		0xd8000000
> +#define CONFIG_JFFS2_NAND
> +#define CONFIG_MXC_NAND_HWECC
> +
> +/*
> + * SD/MMC
> + */
> +#define CONFIG_MMC
> +#define CONFIG_GENERIC_MMC
> +#define CONFIG_MXC_MMC
> +#define CONFIG_MXC_MCI_REGS_BASE	0x10014000
> +#define CONFIG_DOS_PARTITION
> +
> +/*
> + * MTD partitions
> + */
> +#define CONFIG_CMD_MTDPARTS
> +#define MTDIDS_DEFAULT		"nor0=physmap-flash.0,nand0=mxc_nand.0"
> +#define MTDPARTS_DEFAULT			\
> +	"mtdparts="				\
> +		"physmap-flash.0:"		\
> +			"256k(U-Boot),"		\
> +			"1664k(user),"		\
> +			"64k(env1),"		\
> +			"64k(env2);"		\
> +		"mxc_nand.0:"			\
> +			"128k(IPL-SPL),"	\
> +			"4m(kernel),"		\
> +			"22m(rootfs),"		\
> +			"-(userfs)"
> +
> +/*
> + * U-Boot general configuration
> + */
> +#define CONFIG_BOOTFILE		"uImage"	/* Boot file name */
> +#define CONFIG_SYS_PROMPT	"=> "	/* Monitor Command Prompt */
> +#define CONFIG_SYS_CBSIZE	1024	/* Console I/O Buffer Size  */
> +/* Print buffer sz */
> +#define CONFIG_SYS_PBSIZE	(CONFIG_SYS_CBSIZE + \
> +		sizeof(CONFIG_SYS_PROMPT) + 16)
> +#define CONFIG_SYS_MAXARGS	16	/* max number of command args */
> +/* Boot Argument Buffer Size */
> +#define CONFIG_SYS_BARGSIZE	CONFIG_SYS_CBSIZE
> +#define CONFIG_CMDLINE_EDITING
> +#define CONFIG_SYS_LONGHELP
> +
> +/*
> + * U-Boot commands
> + */
> +#include <config_cmd_default.h>
> +#define CONFIG_CMD_ASKENV
> +#define CONFIG_CMD_BDI
> +#define CONFIG_CMD_DHCP
> +#define CONFIG_CMD_DIAG
> +#define CONFIG_CMD_FAT
> +#define CONFIG_CMD_JFFS2
> +#define CONFIG_CMD_MII
> +#define CONFIG_CMD_MMC
> +#define CONFIG_CMD_NAND
> +#define CONFIG_CMD_NET
> +#define CONFIG_CMD_NFS
> +#define CONFIG_CMD_PING
you redefine cmd that are defined in the default
> +
> +#define CONFIG_BOOTDELAY	5
> +
> +#define CONFIG_LOADADDR		0xa0800000	/* loadaddr env var */
> +#define CONFIG_SYS_LOAD_ADDR		CONFIG_LOADADDR
why 2?

Best Regards,
J.

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

* [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD
  2009-08-03  5:32               ` Jean-Christophe PLAGNIOL-VILLARD
@ 2009-08-03  8:19                 ` Wolfgang Denk
  2009-08-03 12:17                   ` Jean-Christophe PLAGNIOL-VILLARD
  2009-08-10 22:32                 ` [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD Ilya Yanok
  1 sibling, 1 reply; 70+ messages in thread
From: Wolfgang Denk @ 2009-08-03  8:19 UTC (permalink / raw)
  To: u-boot

Dear Jean-Christophe PLAGNIOL-VILLARD,

In message <20090803053218.GA15665@game.jcrosoft.org> you wrote:
>
...
> > +/* malloc() len */
> > +#define CONFIG_SYS_MALLOC_LEN		(0x10000 + 256 * 1024)
> please do not mix hexa and decimal

Please be reasonable. This is a perfectly valid and easy to read
notation. I see no reason to change this - anything else would
probably be much harder to read.

> > +#define CONFIG_LOADADDR		0xa0800000	/* loadaddr env var */
> > +#define CONFIG_SYS_LOAD_ADDR		CONFIG_LOADADDR
> why 2?

Because they do different things.

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 humor is concerned there are no standards -- no  one  can  say
what is good or bad, although you can be sure that everyone will.
- John Kenneth Galbraith

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

* [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD
  2009-08-03  8:19                 ` Wolfgang Denk
@ 2009-08-03 12:17                   ` Jean-Christophe PLAGNIOL-VILLARD
  2009-08-03 14:35                     ` Wolfgang Denk
  0 siblings, 1 reply; 70+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2009-08-03 12:17 UTC (permalink / raw)
  To: u-boot

On 10:19 Mon 03 Aug     , Wolfgang Denk wrote:
> Dear Jean-Christophe PLAGNIOL-VILLARD,
> 
> In message <20090803053218.GA15665@game.jcrosoft.org> you wrote:
> >
> ...
> > > +/* malloc() len */
> > > +#define CONFIG_SYS_MALLOC_LEN		(0x10000 + 256 * 1024)
> > please do not mix hexa and decimal
I've as there is other think to fix otherwise I'll not have ask
> 
> Please be reasonable. This is a perfectly valid and easy to read
> notation. I see no reason to change this - anything else would
> probably be much harder to read.
> 
> > > +#define CONFIG_LOADADDR		0xa0800000	/* loadaddr env var */
> > > +#define CONFIG_SYS_LOAD_ADDR		CONFIG_LOADADDR
> > why 2?
> 
> Because they do different things.
I've take a look they do nearly the same think it will be better to avoid have
2 configs specialy when there are the same

btw I've found nothing about it in the README

Best Regards,
J.

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

* [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD
  2009-08-03 12:17                   ` Jean-Christophe PLAGNIOL-VILLARD
@ 2009-08-03 14:35                     ` Wolfgang Denk
  2009-08-05 10:09                       ` javier Martin
  0 siblings, 1 reply; 70+ messages in thread
From: Wolfgang Denk @ 2009-08-03 14:35 UTC (permalink / raw)
  To: u-boot

Dear Jean-Christophe PLAGNIOL-VILLARD,

In message <20090803121748.GG15665@game.jcrosoft.org> you wrote:
>
> > > > +#define CONFIG_SYS_MALLOC_LEN		(0x10000 + 256 * 1024)
> > > please do not mix hexa and decimal
> I've as there is other think to fix otherwise I'll not have ask
> > 
> > Please be reasonable. This is a perfectly valid and easy to read
> > notation. I see no reason to change this - anything else would
> > probably be much harder to read.

Please do not insist in changing this. No matter how you wrote it,
"0x10000 + 0x100 * 0x400" or "0x10000 + 0x40000" or "65536 + 256 *
1024" or "65536 + 262144" - all thesde forms are more difficult to
parse and give less insight into what is intended.

I say: there is no reason to change this.

> > > > +#define CONFIG_LOADADDR		0xa0800000	/* loadaddr env var */
> > > > +#define CONFIG_SYS_LOAD_ADDR		CONFIG_LOADADDR
> > > why 2?
> > 
> > Because they do different things.
> I've take a look they do nearly the same think it will be better to avoid have
> 2 configs specialy when there are the same

Please feel free to submit a patch if you do not like the current
design. But this has nothing to do with the current patch in
question, i. e. it is not a reason to reject it or ask for changes.

> btw I've found nothing about it in the README

Indeed, documentation is not exactly perfect.  Please  feel  free  to
submit a patch.

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
Heavier than air flying machines are impossible.
                    -- Lord Kelvin, President, Royal Society, c. 1895

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

* [U-Boot] [PATCH] mxc_nand: add nand driver for MX2/MX3
  2009-08-03  2:01           ` Ilya Yanok
@ 2009-08-03 16:58             ` Scott Wood
  0 siblings, 0 replies; 70+ messages in thread
From: Scott Wood @ 2009-08-03 16:58 UTC (permalink / raw)
  To: u-boot

On Mon, Aug 03, 2009 at 06:01:03AM +0400, Ilya Yanok wrote:
> >> +		return;
> >> +	}
> >> +
> >> +	if (chip == -1) {
> >> +		writew(readw(&host->regs->nfc_config1) & ~NFC_CE,
> >> +				&host->regs->nfc_config1);
> >> +		return;
> >> +	}
> >> +
> >> +	writew(readw(&host->regs->nfc_config1) | NFC_CE,
> >> +			&host->regs->nfc_config1);
> >> +#endif
> >>     
> >
> > #else?
> >   
> 
> For me it just works (I've never defined CONFIG_MTD_NAND_MXC_FORCE_CE).

If you've never defined it, how do you know it "just works"? :-)

Under what circumstances would one define it?  Should we take it out, to be
added later by someone who can test it, and understands it better?

> >> +		if (column >= mtd->writesize) {
> >> +			/*
> >> +			 * before sending SEQIN command for partial write,
> >> +			 * we need read one page out. FSL NFC does not support
> >> +			 * partial write. It alway send out 512+ecc+512+ecc ...
> >> +			 * for large page nand flash. But for small page nand
> >> +			 * flash, it does support SPARE ONLY operation.
> >> +			 */
> >> +			if (host->pagesize_2k) {
> >> +				/* call ourself to read a page */
> >> +				mxc_nand_command(mtd, NAND_CMD_READ0, 0,
> >> +						page_addr);
> >> +			}
> >>     
> >
> > #ifdef CONFIG_MXC_NAND_HWECC?
> >   
> 
> Uh... I have to admit I don't really have clear understanding of this
> problem and I can't find it's description in i.MX27 Reference Manual...
> Maybe you can point me in some direction? For now I'm not sure if
> putting this under #ifdef won't break something...

It was my understanding that the whole reason for using soft ecc on this
controller was to avoid the weird OOB layout.  If you're only testing with
hard ecc, though, then I'd leave it as is -- I don't want to make untested
changes.

-Scott

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

* [U-Boot] [PATCH] mxc_nand: add nand driver for MX2/MX3
  2009-08-03  1:45           ` Ilya Yanok
@ 2009-08-04 23:32             ` Scott Wood
  2009-08-10 22:32               ` Ilya Yanok
  0 siblings, 1 reply; 70+ messages in thread
From: Scott Wood @ 2009-08-04 23:32 UTC (permalink / raw)
  To: u-boot

On Mon, Aug 03, 2009 at 05:45:14AM +0400, Ilya Yanok wrote:
> +	if (this->options & NAND_BUSWIDTH_16) {
> +		void __iomem *main_buf = host->regs->main_area0;
> +		/* compress the ID info */
> +		writeb(readb(main_buf + 2), main_buf + 1);
> +		writeb(readb(main_buf + 4), main_buf + 2);
> +		writeb(readb(main_buf + 6), main_buf + 3);
> +		writeb(readb(main_buf + 8), main_buf + 4);
> +		writeb(readb(main_buf + 10), main_buf + 5);
> +	}

This indicates that read_byte isn't doing what the generic NAND code is
expecting.  It should advance by a word in the buffer for each byte read
-- the implementation of nand_read_byte16 confirms this.

In that case, though, why have separate read_byte and read_word?  Just
to provide an endian-broken alternative, that is only used where
endianness doesn't matter (checking bad block markers)? :-(

> +	if (col & 1) {
> +		union {
> +			uint16_t word;
> +			uint8_t bytes[2];
> +		} nfc_word;
> +
> +		nfc_word.word = readw(p);
> +		ret = nfc_word.bytes[1];
> +		nfc_word.word = readw(&p[1]);
> +		ret |= nfc_word.bytes[0] << 16;

This still has an endian assumption (and shouldn't << 16 be << 8, and
require a cast to avoid shifting beyond the type width?) -- it's moot
given the nature of read_byte and read_word, but if this were necessary
it should be something like:

union {
	...
} nfc_word[3];

nfc_word[0] = readw(p);
nfc_word[1] = readw(p + 1);

nfc_word[2].bytes[0] = nfc_word[0].bytes[1];
nfc_word[2].bytes[1] = nfc_word[1].bytes[0];

ret = nfc_word[2].word;

Alternatively, you could apply le16_to_cpu to the result of something
like your version.

-Scott

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

* [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD
  2009-08-03 14:35                     ` Wolfgang Denk
@ 2009-08-05 10:09                       ` javier Martin
  2009-08-05 12:30                         ` javier Martin
  0 siblings, 1 reply; 70+ messages in thread
From: javier Martin @ 2009-08-05 10:09 UTC (permalink / raw)
  To: u-boot

Hi,
What happened with this patch? Was it applied or did it have any problems?
Is it tested?

Thank you.

-- 
Javier Martin
Vista Silicon S.L.
Universidad de Cantabria
CDTUC - FASE C - Oficina S-345
Avda de los Castros s/n
39005- Santander. Cantabria. Spain
+34 942 25 32 60
www.vista-silicon.com

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

* [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD
  2009-08-05 10:09                       ` javier Martin
@ 2009-08-05 12:30                         ` javier Martin
  2009-08-05 12:45                           ` Wolfgang Denk
  2009-08-06 19:29                           ` [U-Boot] [PATCH] ARM EABI: add new helper functions resp. function names Wolfgang Denk
  0 siblings, 2 replies; 70+ messages in thread
From: javier Martin @ 2009-08-05 12:30 UTC (permalink / raw)
  To: u-boot

2009/8/5 javier Martin <javier.martin@vista-silicon.com>:
> Hi,
> What happened with this patch? Was it applied or did it have any problems?
> Is it tested?

I have applied it but when compiling it gives the following errors:

hdog/libwatchdog.a common/libcommon.a libfdt/libfdt.a api/libapi.a
post/libpost.a board/freescale/mx31ads/libmx31ads.a --end-group -L
/opt/freescale/usr/local/gcc-4.1.2-glibc-2.5-nptl-3/arm-none-linux-gnueabi/lib/gcc/arm-none-linux-gnueabi/4.1.2
-lgcc -Map u-boot.map -o u-boot
arm-none-linux-gnueabi-ld: ERROR: Source object
/opt/freescale/usr/local/gcc-4.1.2-glibc-2.5-nptl-3/arm-none-linux-gnueabi/lib/gcc/arm-none-linux-gnueabi/4.1.2/libgcc.a(_udivsi3.o)
has EABI version 4, but target u-boot has EABI version 0
arm-none-linux-gnueabi-ld: failed to merge target specific data of
file /opt/freescale/usr/local/gcc-4.1.2-glibc-2.5-nptl-3/arm-none-linux-gnueabi/lib/gcc/arm-none-linux-gnueabi/4.1.2/libgcc.a(_udivsi3.o)
arm-none-linux-gnueabi-ld: ERROR: Source object
/opt/freescale/usr/local/gcc-4.1.2-glibc-2.5-nptl-3/arm-none-linux-gnueabi/lib/gcc/arm-none-linux-gnueabi/4.1.2/libgcc.a(_divsi3.o)
has EABI version 4, but target u-boot has EABI version 0
arm-none-linux-gnueabi-ld: failed to merge target specific data of
file /opt/freescale/usr/local/gcc-4.1.2-glibc-2.5-nptl-3/arm-none-linux-gnueabi/lib/gcc/arm-none-linux-gnueabi/4.1.2/libgcc.a(_divsi3.o)
arm-none-linux-gnueabi-ld: ERROR: Source object
/opt/freescale/usr/local/gcc-4.1.2-glibc-2.5-nptl-3/arm-none-linux-gnueabi/lib/gcc/arm-none-linux-gnueabi/4.1.2/libgcc.a(_umodsi3.o)
has EABI version 4, but target u-boot has EABI version 0
arm-none-linux-gnueabi-ld: failed to merge target specific data of
file /opt/freescale/usr/local/gcc-4.1.2-glibc-2.5-nptl-3/arm-none-linux-gnueabi/lib/gcc/arm-none-linux-gnueabi/4.1.2/libgcc.a(_umodsi3.o)
arm-none-linux-gnueabi-ld: ERROR: Source object
/opt/freescale/usr/local/gcc-4.1.2-glibc-2.5-nptl-3/arm-none-linux-gnueabi/lib/gcc/arm-none-linux-gnueabi/4.1.2/libgcc.a(_modsi3.o)
has EABI version 4, but target u-boot has EABI version 0
arm-none-linux-gnueabi-ld: failed to merge target specific data of
file /opt/freescale/usr/local/gcc-4.1.2-glibc-2.5-nptl-3/arm-none-linux-gnueabi/lib/gcc/arm-none-linux-gnueabi/4.1.2/libgcc.a(_modsi3.o)
arm-none-linux-gnueabi-ld: ERROR: Source object
/opt/freescale/usr/local/gcc-4.1.2-glibc-2.5-nptl-3/arm-none-linux-gnueabi/lib/gcc/arm-none-linux-gnueabi/4.1.2/libgcc.a(_dvmd_lnx.o)
has EABI version 4, but target u-boot has EABI version 0
arm-none-linux-gnueabi-ld: failed to merge target specific data of
file /opt/freescale/usr/local/gcc-4.1.2-glibc-2.5-nptl-3/arm-none-linux-gnueabi/lib/gcc/arm-none-linux-gnueabi/4.1.2/libgcc.a(_dvmd_lnx.o)
/opt/freescale/usr/local/gcc-4.1.2-glibc-2.5-nptl-3/arm-none-linux-gnueabi/lib/gcc/arm-none-linux-gnueabi/4.1.2/libgcc.a(_dvmd_lnx.o):
In function `__div0':
/usr/src/redhat/BUILD/cross-mlib/source/gcc-4.1.2/gcc/config/arm/lib1funcs.asm:1000:
undefined reference to `raise'
make: *** [u-boot] Error 1

Any ideas about this problem?

Thank you.

>
> --
> Javier Martin
> Vista Silicon S.L.
> Universidad de Cantabria
> CDTUC - FASE C - Oficina S-345
> Avda de los Castros s/n
> 39005- Santander. Cantabria. Spain
> +34 942 25 32 60
> www.vista-silicon.com
>



-- 
Javier Martin
Vista Silicon S.L.
Universidad de Cantabria
CDTUC - FASE C - Oficina S-345
Avda de los Castros s/n
39005- Santander. Cantabria. Spain
+34 942 25 32 60
www.vista-silicon.com

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

* [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD
  2009-08-05 12:30                         ` javier Martin
@ 2009-08-05 12:45                           ` Wolfgang Denk
  2009-08-05 14:17                             ` javier Martin
  2009-08-06 19:29                           ` [U-Boot] [PATCH] ARM EABI: add new helper functions resp. function names Wolfgang Denk
  1 sibling, 1 reply; 70+ messages in thread
From: Wolfgang Denk @ 2009-08-05 12:45 UTC (permalink / raw)
  To: u-boot

Dear javier Martin,

In message <eedb5540908050530u610d9dfgc235faf9e0a8a587@mail.gmail.com> you wrote:
>
> I have applied it but when compiling it gives the following errors:
...
> arm-none-linux-gnueabi-ld: ERROR: Source object
> /opt/freescale/usr/local/gcc-4.1.2-glibc-2.5-nptl-3/arm-none-linux-gnueabi/lib/gcc/arm-none-linux-gnueabi/4.1.2/libgcc.a(_udivsi3.o)
> has EABI version 4, but target u-boot has EABI version 0
...
> Any ideas about this problem?

You want to read the FAQ:
http://www.denx.de/wiki/view/DULG/SourceObjectHasEABIVersion4ButTargetHasEABIVersion0

Jean-Christophe once had a patch to add the libgcc routines as used by
the Linux kernel, but despite all my asking he did not re-submit this
yet.

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
"What the scientists have in their briefcases is terrifying."
- Nikita Khrushchev

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

* [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD
  2009-08-05 12:45                           ` Wolfgang Denk
@ 2009-08-05 14:17                             ` javier Martin
  2009-08-05 14:21                               ` Wolfgang Denk
  0 siblings, 1 reply; 70+ messages in thread
From: javier Martin @ 2009-08-05 14:17 UTC (permalink / raw)
  To: u-boot

2009/8/5 Wolfgang Denk <wd@denx.de>:
> Dear javier Martin,
>
> In message <eedb5540908050530u610d9dfgc235faf9e0a8a587@mail.gmail.com> you wrote:
>>
>> I have applied it but when compiling it gives the following errors:
> ...
>> arm-none-linux-gnueabi-ld: ERROR: Source object
>> /opt/freescale/usr/local/gcc-4.1.2-glibc-2.5-nptl-3/arm-none-linux-gnueabi/lib/gcc/arm-none-linux-gnueabi/4.1.2/libgcc.a(_udivsi3.o)
>> has EABI version 4, but target u-boot has EABI version 0
> ...
>> Any ideas about this problem?
>
> You want to read the FAQ:
> http://www.denx.de/wiki/view/DULG/SourceObjectHasEABIVersion4ButTargetHasEABIVersion0

What toolchains do you use then?
I have tried with the toolchains provided with ELDK4 but no luck. They
also seem to be EABI version 4.

-- 
Javier Martin
Vista Silicon S.L.
Universidad de Cantabria
CDTUC - FASE C - Oficina S-345
Avda de los Castros s/n
39005- Santander. Cantabria. Spain
+34 942 25 32 60
www.vista-silicon.com

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

* [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD
  2009-08-05 14:17                             ` javier Martin
@ 2009-08-05 14:21                               ` Wolfgang Denk
  2009-08-05 15:01                                 ` javier Martin
  0 siblings, 1 reply; 70+ messages in thread
From: Wolfgang Denk @ 2009-08-05 14:21 UTC (permalink / raw)
  To: u-boot

Dear javier Martin,

In message <eedb5540908050717g5047899ci2de7eac4139ca18e@mail.gmail.com> you wrote:
>
> > http://www.denx.de/wiki/view/DULG/SourceObjectHasEABIVersion4ButTargetHasEABIVersion0
> 
> What toolchains do you use then?
> I have tried with the toolchains provided with ELDK4 but no luck. They
> also seem to be EABI version 4.

I'm waiting for Jean-Christophe's patch. In the meantime I use ELDK
4.1 which uses the old ABI.

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
: ... and it's got weird formatting - Notepad, Write, Works  3  can't
: decipher it, and it's too big to go in DOS Edit. Help!
Install an operating system. :-)                  -- Tom Christiansen

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

* [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD
  2009-08-05 14:21                               ` Wolfgang Denk
@ 2009-08-05 15:01                                 ` javier Martin
  0 siblings, 0 replies; 70+ messages in thread
From: javier Martin @ 2009-08-05 15:01 UTC (permalink / raw)
  To: u-boot

Now, I am using 4.1 version of eldk.

With the previous patch applied I get this problem with
"board_nand_init". I don't know if it's still a problem of my
toolchain of this is a BUG:

drivers/mtd/nand/libnand.a(nand.o): In function `nand_init':
/home/javier/GIT/u-boot/drivers/mtd/nand/nand.c:53: undefined
reference to `board_nand_init'

Regards.

-- 
Javier Martin
Vista Silicon S.L.
Universidad de Cantabria
CDTUC - FASE C - Oficina S-345
Avda de los Castros s/n
39005- Santander. Cantabria. Spain
+34 942 25 32 60
www.vista-silicon.com

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

* [U-Boot] [PATCH] ARM EABI: add new helper functions resp. function names
@ 2009-08-06 19:29                           ` Wolfgang Denk
  2009-08-06 20:10                             ` [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD Wolfgang Denk
                                               ` (2 more replies)
  0 siblings, 3 replies; 70+ messages in thread
From: Wolfgang Denk @ 2009-08-06 19:29 UTC (permalink / raw)
  To: u-boot

The ARM EABI defines new names for GCC helper functions,
and GCC seems to need some new functions as well.

This patch is a minimal-invasive approach to fix problems with EABI
conformant tool chains (to be used with "USE_PRIVATE_LIBGCC=yes").

Signed-off-by: Wolfgang Denk <wd@denx.de>
---
 lib_arm/_ashldi3.S |    2 ++
 lib_arm/_ashrdi3.S |    2 ++
 lib_arm/_divsi3.S  |    2 ++
 lib_arm/_lshrdi3.S |    2 ++
 lib_arm/_udivsi3.S |   34 +++++++++++++++++++++++++---------
 5 files changed, 33 insertions(+), 9 deletions(-)

diff --git a/lib_arm/_ashldi3.S b/lib_arm/_ashldi3.S
index de4403d..834ddc2 100644
--- a/lib_arm/_ashldi3.S
+++ b/lib_arm/_ashldi3.S
@@ -35,7 +35,9 @@ Boston, MA 02110-1301, USA.  */
 #endif
 
 .globl __ashldi3
+.globl	__aeabi_llsl
 __ashldi3:
+__aeabi_llsl:
 
 	subs	r3, r2, #32
 	rsb	ip, r2, #32
diff --git a/lib_arm/_ashrdi3.S b/lib_arm/_ashrdi3.S
index 5edbcb3..671ac87 100644
--- a/lib_arm/_ashrdi3.S
+++ b/lib_arm/_ashrdi3.S
@@ -35,7 +35,9 @@ Boston, MA 02110-1301, USA.  */
 #endif
 
 .globl __ashrdi3
+.globl __aeabi_lasr
 __ashrdi3:
+__aeabi_lasr:
 
 	subs	r3, r2, #32
 	rsb	ip, r2, #32
diff --git a/lib_arm/_divsi3.S b/lib_arm/_divsi3.S
index 9dc15f6..cfbadb2 100644
--- a/lib_arm/_divsi3.S
+++ b/lib_arm/_divsi3.S
@@ -96,7 +96,9 @@
 
 	.align	5
 .globl __divsi3
+.globl __aeabi_idiv
 __divsi3:
+__aeabi_idiv:
 	cmp	r1, #0
 	eor	ip, r0, r1			@ save the sign of the result.
 	beq	Ldiv0
diff --git a/lib_arm/_lshrdi3.S b/lib_arm/_lshrdi3.S
index fabfd9f..e7fa799 100644
--- a/lib_arm/_lshrdi3.S
+++ b/lib_arm/_lshrdi3.S
@@ -35,7 +35,9 @@ Boston, MA 02110-1301, USA.  */
 #endif
 
 .globl __lshrdi3
+.globl __aeabi_llsr
 __lshrdi3:
+__aeabi_llsr:
 
 	subs	r3, r2, #32
 	rsb	ip, r2, #32
diff --git a/lib_arm/_udivsi3.S b/lib_arm/_udivsi3.S
index a3f9b59..1309802 100644
--- a/lib_arm/_udivsi3.S
+++ b/lib_arm/_udivsi3.S
@@ -11,9 +11,12 @@ curbit		.req	r3
 /* pc		.req	r15	*/
 	.text
 	.globl	 __udivsi3
-	.type  __udivsi3       ,function
+	.type	__udivsi3 ,function
+	.globl	__aeabi_uidiv
+	.type	__aeabi_uidiv ,function
 	.align	0
- __udivsi3      :
+ __udivsi3:
+ __aeabi_uidiv:
 	cmp	divisor, #0
 	beq	Ldiv0
 	mov	curbit, #1
@@ -68,10 +71,23 @@ Ldiv0:
 	mov	r0, #0			@ about as wrong as it could be
 	ldmia	sp!, {pc}
 	.size  __udivsi3       , . -  __udivsi3
-/* # 235 "libgcc1.S" */
-/* # 320 "libgcc1.S" */
-/* # 421 "libgcc1.S" */
-/* # 433 "libgcc1.S" */
-/* # 456 "libgcc1.S" */
-/* # 500 "libgcc1.S" */
-/* # 580 "libgcc1.S" */
+
+.globl __aeabi_uidivmod
+__aeabi_uidivmod:
+
+	stmfd	sp!, {r0, r1, ip, lr}
+	bl	__aeabi_uidiv
+	ldmfd	sp!, {r1, r2, ip, lr}
+	mul	r3, r0, r2
+	sub	r1, r1, r3
+	mov	pc, lr
+
+.globl __aeabi_idivmod
+__aeabi_idivmod:
+
+	stmfd	sp!, {r0, r1, ip, lr}
+	bl	__aeabi_idiv
+	ldmfd	sp!, {r1, r2, ip, lr}
+	mul	r3, r0, r2
+	sub	r1, r1, r3
+	mov	pc, lr
-- 
1.6.0.6

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

* [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD
  2009-08-06 19:29                           ` [U-Boot] [PATCH] ARM EABI: add new helper functions resp. function names Wolfgang Denk
@ 2009-08-06 20:10                             ` Wolfgang Denk
  2009-08-07  7:18                               ` javier Martin
  2009-08-08  6:50                             ` [U-Boot] [PATCH] ARM EABI: add new helper functions resp. function names Dirk Behme
  2009-08-09 21:28                             ` Wolfgang Denk
  2 siblings, 1 reply; 70+ messages in thread
From: Wolfgang Denk @ 2009-08-06 20:10 UTC (permalink / raw)
  To: u-boot

Dear Javier,

In message <eedb5540908050530u610d9dfgc235faf9e0a8a587@mail.gmail.com> you wrote:
...
> I have applied it but when compiling it gives the following errors:
...
> arm-none-linux-gnueabi-ld: ERROR: Source object
> /opt/freescale/usr/local/gcc-4.1.2-glibc-2.5-nptl-3/arm-none-linux-gnueabi/lib/gcc/arm-none-linux-gnueabi/4.1.2/libgcc.a(_udivsi3.o)
> has EABI version 4, but target u-boot has EABI version 0


I have just posted a patch:

[PATCH] ARM EABI: add new helper functions resp. function names

(see http://thread.gmane.org/gmane.comp.boot-loaders.u-boot/65473


Combined with commit 52b1bf2c:

	Make linking against libgcc configurable

I can run a "USE_PRIVATE_LIBGCC=yes ./MAKEALL arm" with an EABI
conformant tool chain (ELDK 4.2) without any related issues.

It would be great if you all could test this, so we can get this in as
quickly as possible.

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
"You know, after a woman's raised a family and so on,  she  wants  to
start living her own life."   "Whose life she's _been_ living, then?"
                                  - Terry Pratchett, _Witches Abroad_

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

* [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD
  2009-08-06 20:10                             ` [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD Wolfgang Denk
@ 2009-08-07  7:18                               ` javier Martin
  2009-08-07  9:13                                 ` Wolfgang Denk
  0 siblings, 1 reply; 70+ messages in thread
From: javier Martin @ 2009-08-07  7:18 UTC (permalink / raw)
  To: u-boot

2009/8/6 Wolfgang Denk <wd@denx.de>:
> I have just posted a patch:
>
> [PATCH] ARM EABI: add new helper functions resp. function names
>
> (see http://thread.gmane.org/gmane.comp.boot-loaders.u-boot/65473
>
>
> Combined with commit 52b1bf2c:
>
> ? ? ? ?Make linking against libgcc configurable
>
> I can run a "USE_PRIVATE_LIBGCC=yes ./MAKEALL arm" with an EABI
> conformant tool chain (ELDK 4.2) without any related issues.
>
> It would be great if you all could test this, so we can get this in as
> quickly as possible.

This also works for me using Freescale's toolchain included in LTIB
for i.mx27 ads board.

One thing that confuses me a little about this imx27litekit patch is
that TEXT_ADDRESS is a RAM address but, according to the FAQ u-boot
cannot be run from RAM by another bootloader.

Why is TEXT_ADDRESS in RAM then?

Thanks.

-- 
Javier Martin
Vista Silicon S.L.
Universidad de Cantabria
CDTUC - FASE C - Oficina S-345
Avda de los Castros s/n
39005- Santander. Cantabria. Spain
+34 942 25 32 60
www.vista-silicon.com

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

* [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD
  2009-08-07  7:18                               ` javier Martin
@ 2009-08-07  9:13                                 ` Wolfgang Denk
  0 siblings, 0 replies; 70+ messages in thread
From: Wolfgang Denk @ 2009-08-07  9:13 UTC (permalink / raw)
  To: u-boot

Dear javier Martin,

In message <eedb5540908070018o157def3fleb4b1d04da853376@mail.gmail.com> you wrote:
>
> > It would be great if you all could test this, so we can get this in as
> > quickly as possible.
> 
> This also works for me using Freescale's toolchain included in LTIB
> for i.mx27 ads board.

thanks a lot for the confirmation.

> One thing that confuses me a little about this imx27litekit patch is
> that TEXT_ADDRESS is a RAM address but, according to the FAQ u-boot
> cannot be run from RAM by another bootloader.
> 
> Why is TEXT_ADDRESS in RAM then?

This is "normal" on ARM systems - there TEXT_BASE holds the address of
the image after copying (I hesitate to call it relocating) it to RAM.

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
But it's real. And if it's real it can be affected ... we may not  be
able  to break it, but, I'll bet you credits to Navy Beans we can put
a dent in it.
	-- deSalle, "Catspaw", stardate 3018.2

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

* [U-Boot] [PATCH 5/7] mxc-mmc: sdhc host driver for MX2 and MX3 proccessor
  2009-06-08  0:12 ` [U-Boot] [PATCH 5/7] mxc-mmc: sdhc host driver for MX2 and MX3 proccessor Ilya Yanok
  2009-06-21 11:04   ` Jean-Christophe PLAGNIOL-VILLARD
  2009-06-23 23:02   ` alfred steele
@ 2009-08-07 20:13   ` Jean-Christophe PLAGNIOL-VILLARD
  2 siblings, 0 replies; 70+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2009-08-07 20:13 UTC (permalink / raw)
  To: u-boot

On 04:12 Mon 08 Jun     , Ilya Yanok wrote:
> This is a port of Linux driver for SDHC host controller hardware
> found on Freescale's MX2 and MX3 processors. Uses new generic MMC
> framework (CONFIG_GENERIC_MMC) and it looks like there are some
> problems with a framework (at least on LE cpus). Some of these
> problems are addressed in the following patches.
> 
> Signed-off-by: Ilya Yanok <yanok@emcraft.com>
> ---
>  cpu/arm926ejs/mx27/generic.c       |   16 ++
>  drivers/mmc/Makefile               |    1 +
>  drivers/mmc/mxcmmc.c               |  523 ++++++++++++++++++++++++++++++++++++
>  include/asm-arm/arch-mx27/mxcmmc.h |   25 ++
>  4 files changed, 565 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/mmc/mxcmmc.c
>  create mode 100644 include/asm-arm/arch-mx27/mxcmmc.h
applied to u-boot-arm

Best Regards,
J.

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

* [U-Boot] [PATCH] ARM EABI: add new helper functions resp. function names
  2009-08-06 19:29                           ` [U-Boot] [PATCH] ARM EABI: add new helper functions resp. function names Wolfgang Denk
  2009-08-06 20:10                             ` [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD Wolfgang Denk
@ 2009-08-08  6:50                             ` Dirk Behme
  2009-08-08  7:16                               ` Wolfgang Denk
  2009-08-09 21:28                             ` Wolfgang Denk
  2 siblings, 1 reply; 70+ messages in thread
From: Dirk Behme @ 2009-08-08  6:50 UTC (permalink / raw)
  To: u-boot

Wolfgang Denk wrote:
> The ARM EABI defines new names for GCC helper functions,
> and GCC seems to need some new functions as well.
> 
> This patch is a minimal-invasive approach to fix problems with EABI
> conformant tool chains (to be used with "USE_PRIVATE_LIBGCC=yes").

Using my broken toolchain, which needs USE_PRIVATE_LIBGCC=yes for 
successful linking, I did ./MAKEALL ARM_CORTEX_A8 without and with 
this patch and both compile fine recent git head.

Thanks

Dirk

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

* [U-Boot] [PATCH] ARM EABI: add new helper functions resp. function names
  2009-08-08  6:50                             ` [U-Boot] [PATCH] ARM EABI: add new helper functions resp. function names Dirk Behme
@ 2009-08-08  7:16                               ` Wolfgang Denk
  2009-08-08  7:39                                 ` Dirk Behme
  0 siblings, 1 reply; 70+ messages in thread
From: Wolfgang Denk @ 2009-08-08  7:16 UTC (permalink / raw)
  To: u-boot

Dear Dirk,

In message <4A7D203B.2000803@googlemail.com> you wrote:
>
> Using my broken toolchain, which needs USE_PRIVATE_LIBGCC=yes for 
> successful linking, I did ./MAKEALL ARM_CORTEX_A8 without and with 
> this patch and both compile fine recent git head.

Thanks for testing.

May I interpret this a s "Tested-by:" message?

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
A right is not what someone gives you; it's what no one can take from
you.                                                   - Ramsey Clark

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

* [U-Boot] [PATCH] ARM EABI: add new helper functions resp. function names
  2009-08-08  7:16                               ` Wolfgang Denk
@ 2009-08-08  7:39                                 ` Dirk Behme
  0 siblings, 0 replies; 70+ messages in thread
From: Dirk Behme @ 2009-08-08  7:39 UTC (permalink / raw)
  To: u-boot

Wolfgang Denk wrote:
> Dear Dirk,
> 
> In message <4A7D203B.2000803@googlemail.com> you wrote:
>> Using my broken toolchain, which needs USE_PRIVATE_LIBGCC=yes for 
>> successful linking, I did ./MAKEALL ARM_CORTEX_A8 without and with 
>> this patch and both compile fine recent git head.
> 
> Thanks for testing.
> 
> May I interpret this a s "Tested-by:" message?

After boot test on BeagleBoard:

Tested-by: Dirk Behme <dirk.behme@googlemail.com>

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

* [U-Boot] [PATCH] ARM EABI: add new helper functions resp. function names
  2009-08-06 19:29                           ` [U-Boot] [PATCH] ARM EABI: add new helper functions resp. function names Wolfgang Denk
  2009-08-06 20:10                             ` [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD Wolfgang Denk
  2009-08-08  6:50                             ` [U-Boot] [PATCH] ARM EABI: add new helper functions resp. function names Dirk Behme
@ 2009-08-09 21:28                             ` Wolfgang Denk
  2 siblings, 0 replies; 70+ messages in thread
From: Wolfgang Denk @ 2009-08-09 21:28 UTC (permalink / raw)
  To: u-boot

In message <1249586999-2595-1-git-send-email-wd@denx.de> I wrote:
> The ARM EABI defines new names for GCC helper functions,
> and GCC seems to need some new functions as well.
> 
> This patch is a minimal-invasive approach to fix problems with EABI
> conformant tool chains (to be used with "USE_PRIVATE_LIBGCC=yes").
> 
> Signed-off-by: Wolfgang Denk <wd@denx.de>
> ---
>  lib_arm/_ashldi3.S |    2 ++
>  lib_arm/_ashrdi3.S |    2 ++
>  lib_arm/_divsi3.S  |    2 ++
>  lib_arm/_lshrdi3.S |    2 ++
>  lib_arm/_udivsi3.S |   34 +++++++++++++++++++++++++---------
>  5 files changed, 33 insertions(+), 9 deletions(-)

Applied.


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
Never underestimate the power of human stupidity  when  it  comes  to
using technology they don't understand.

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

* [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD
  2009-08-03  5:32               ` Jean-Christophe PLAGNIOL-VILLARD
  2009-08-03  8:19                 ` Wolfgang Denk
@ 2009-08-10 22:32                 ` Ilya Yanok
  2009-08-11 18:47                   ` Fabio Estevam
                                     ` (2 more replies)
  1 sibling, 3 replies; 70+ messages in thread
From: Ilya Yanok @ 2009-08-10 22:32 UTC (permalink / raw)
  To: u-boot

This patch adds support for i.MX27-LITEKIT development board from
LogicPD. This board uses i.MX27 SoC and has 2MB NOR flash, 64MB NAND
flash, FEC ethernet controller integrated into i.MX27.

Signed-off-by: Ilya Yanok <yanok@emcraft.com>
---
 MAINTAINERS                             |    1 +
 MAKEALL                                 |    1 +
 Makefile                                |    3 +
 board/logicpd/imx27lite/Makefile        |   51 ++++++
 board/logicpd/imx27lite/config.mk       |    1 +
 board/logicpd/imx27lite/imx27lite.c     |   73 +++++++++
 board/logicpd/imx27lite/lowlevel_init.S |  170 +++++++++++++++++++++
 cpu/arm926ejs/mx27/generic.c            |   65 ++++++++
 include/asm-arm/arch-mx27/imx-regs.h    |   12 ++
 include/configs/imx27lite.h             |  252 +++++++++++++++++++++++++++++++
 10 files changed, 629 insertions(+), 0 deletions(-)
 create mode 100644 board/logicpd/imx27lite/Makefile
 create mode 100644 board/logicpd/imx27lite/config.mk
 create mode 100644 board/logicpd/imx27lite/imx27lite.c
 create mode 100644 board/logicpd/imx27lite/lowlevel_init.S
 create mode 100644 include/configs/imx27lite.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 620604c..60185ab 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -539,6 +539,7 @@ George G. Davis <gdavis@mvista.com>
 	gcplus		SA1100
 
 Wolfgang Denk <wd@denx.de>
+	imx27lite	i.MX27
 	qong		i.MX31
 
 Thomas Elste <info@elste.org>
diff --git a/MAKEALL b/MAKEALL
index edebaea..3b0fd56 100755
--- a/MAKEALL
+++ b/MAKEALL
@@ -515,6 +515,7 @@ LIST_ARM9="			\
 	cp926ejs		\
 	cp946es			\
 	cp966			\
+	imx27lite		\
 	lpd7a400		\
 	mv88f6281gtw_ge		\
 	mx1ads			\
diff --git a/Makefile b/Makefile
index 329e0f5..c0f30d1 100644
--- a/Makefile
+++ b/Makefile
@@ -2879,6 +2879,9 @@ davinci_sonata_config :	unconfig
 davinci_dm355evm_config :	unconfig
 	@$(MKCONFIG) $(@:_config=) arm arm926ejs dm355evm davinci davinci
 
+imx27lite_config:	unconfig
+	@$(MKCONFIG) $(@:_config=) arm arm926ejs imx27lite logicpd mx27
+
 lpd7a400_config \
 lpd7a404_config:	unconfig
 	@$(MKCONFIG) $(@:_config=) arm lh7a40x lpd7a40x
diff --git a/board/logicpd/imx27lite/Makefile b/board/logicpd/imx27lite/Makefile
new file mode 100644
index 0000000..c404cef
--- /dev/null
+++ b/board/logicpd/imx27lite/Makefile
@@ -0,0 +1,51 @@
+#
+# (C) Copyright 2000-2004
+# 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).a
+
+COBJS	:= imx27lite.o
+SOBJS	:= lowlevel_init.o
+
+SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+SOBJS	:= $(addprefix $(obj),$(SOBJS))
+
+$(LIB):	$(obj).depend $(OBJS) $(SOBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS)
+
+clean:
+	rm -f $(SOBJS) $(OBJS)
+
+distclean:	clean
+	rm -f $(LIB) core *.bak $(obj).depend
+
+#########################################################################
+
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
+
diff --git a/board/logicpd/imx27lite/config.mk b/board/logicpd/imx27lite/config.mk
new file mode 100644
index 0000000..a2e7768
--- /dev/null
+++ b/board/logicpd/imx27lite/config.mk
@@ -0,0 +1 @@
+TEXT_BASE = 0xA7F00000
diff --git a/board/logicpd/imx27lite/imx27lite.c b/board/logicpd/imx27lite/imx27lite.c
new file mode 100644
index 0000000..63375d5
--- /dev/null
+++ b/board/logicpd/imx27lite/imx27lite.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2007 Sascha Hauer, Pengutronix
+ * Copyright (C) 2008,2009 Eric Jarrige <jorasse@users.sourceforge.net>
+ * Copyright (C) 2009 Ilya Yanok <yanok@emcraft.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
+ *
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int board_init (void)
+{
+	struct gpio_regs *regs = (struct gpio_regs *)IMX_GPIO_BASE;
+
+	gd->bd->bi_arch_number = MACH_TYPE_IMX27LITE;
+	gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
+
+#ifdef CONFIG_MXC_UART
+	mx27_uart_init_pins();
+#endif
+#ifdef CONFIG_FEC_MXC
+	mx27_fec_init_pins();
+	imx_gpio_mode((GPIO_PORTC | GPIO_OUT | GPIO_PUEN | GPIO_GPIO | 31));
+	writel(readl(&regs->port[PORTC].dr) | (1 << 31),
+				&regs->port[PORTC].dr);
+#endif
+#ifdef CONFIG_MXC_MMC
+	mx27_sd2_init_pins();
+#endif
+
+	return 0;
+}
+
+int dram_init (void)
+{
+
+#if CONFIG_NR_DRAM_BANKS > 0
+	gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
+	gd->bd->bi_dram[0].size = get_ram_size((volatile void *)PHYS_SDRAM_1,
+			PHYS_SDRAM_1_SIZE);
+#endif
+#if CONFIG_NR_DRAM_BANKS > 1
+	gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
+	gd->bd->bi_dram[1].size = get_ram_size((volatile void *)PHYS_SDRAM_2,
+			PHYS_SDRAM_2_SIZE);
+#endif
+
+	return 0;
+}
+
+int checkboard(void)
+{
+	printf("LogicPD imx27lite\n");
+	return 0;
+}
diff --git a/board/logicpd/imx27lite/lowlevel_init.S b/board/logicpd/imx27lite/lowlevel_init.S
new file mode 100644
index 0000000..e2cdecb
--- /dev/null
+++ b/board/logicpd/imx27lite/lowlevel_init.S
@@ -0,0 +1,170 @@
+/*
+ * For clock initialization, see chapter 3 of the "MCIMX27 Multimedia
+ * Applications Processor Reference Manual, Rev. 0.2".
+ *
+ * (C) Copyright 2008 Eric Jarrige <eric.jarrige@armadeus.org>
+ * (C) Copyright 2009 Ilya Yanok <yanok@emcraft.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
+ */
+
+
+#include <config.h>
+#include <version.h>
+#include <asm/macro.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/asm-offsets.h>
+
+SOC_ESDCTL_BASE_W:	.word	IMX_ESD_BASE
+SOC_SI_ID_REG_W:	.word	IMX_SYSTEM_CTL_BASE
+SDRAM_ESDCFG_T1_W:	.word	SDRAM_ESDCFG_REGISTER_VAL(0)
+SDRAM_ESDCFG_T2_W:	.word	SDRAM_ESDCFG_REGISTER_VAL(3)
+SDRAM_PRECHARGE_CMD_W:	.word	(ESDCTL_SDE | ESDCTL_SMODE_PRECHARGE | \
+				 ESDCTL_ROW13 | ESDCTL_COL10)
+SDRAM_AUTOREF_CMD_W:	.word	(ESDCTL_SDE | ESDCTL_SMODE_AUTO_REF | \
+				 ESDCTL_ROW13 | ESDCTL_COL10)
+SDRAM_LOADMODE_CMD_W:	.word	(ESDCTL_SDE | ESDCTL_SMODE_LOAD_MODE | \
+				 ESDCTL_ROW13 | ESDCTL_COL10)
+SDRAM_NORMAL_CMD_W:	.word	SDRAM_ESDCTL_REGISTER_VAL
+
+.macro init_aipi
+	/*
+	 * setup AIPI1 and AIPI2
+	 */
+	write32 AIPI1_PSR0, AIPI1_PSR0_VAL
+	write32 AIPI1_PSR1, AIPI1_PSR1_VAL
+	write32 AIPI2_PSR0, AIPI2_PSR0_VAL
+	write32 AIPI2_PSR1, AIPI2_PSR1_VAL
+
+.endm /* init_aipi */
+
+.macro init_clock
+	ldr r0, =CSCR
+	/* disable MPLL/SPLL first */
+	ldr r1, [r0]
+	bic r1, r1, #(CSCR_MPEN|CSCR_SPEN)
+	str r1, [r0]
+
+	write32 MPCTL0, MPCTL0_VAL
+	write32 SPCTL0, SPCTL0_VAL
+
+	write32 CSCR, CSCR_VAL | CSCR_MPLL_RESTART | CSCR_SPLL_RESTART
+
+	/*
+	 * add some delay here
+	 */
+	wait_timer 0x1000
+
+	/* peripheral clock divider */
+	write32 PCDR0, PCDR0_VAL
+	write32 PCDR1, PCDR1_VAL
+
+	/* Configure PCCR0 and PCCR1 */
+	write32 PCCR0, PCCR0_VAL
+	write32 PCCR1, PCCR1_VAL
+
+.endm /* init_clock */
+
+.macro sdram_init
+	ldr r0, SOC_ESDCTL_BASE_W
+	mov r2, #PHYS_SDRAM_1
+
+	/* Do initial reset */
+	mov r1, #ESDMISC_MDDR_DL_RST
+	str r1, [r0, #ESDMISC_ROF]
+
+	/* Hold for more than 200ns */
+	wait_timer 0x10000
+
+	/* Activate LPDDR iface */
+	mov r1, #ESDMISC_MDDREN
+	str r1, [r0, #ESDMISC_ROF]
+
+	/* Check The chip version TO1 or TO2 */
+	ldr r1, SOC_SI_ID_REG_W
+	ldr r1, [r1]
+	ands r1, r1, #0xF0000000
+	/* add Latency on CAS only for TO2 */
+	ldreq r1, SDRAM_ESDCFG_T2_W
+	ldrne r1, SDRAM_ESDCFG_T1_W
+	str r1, [r0, #ESDCFG0_ROF]
+
+	/* Run initialization sequence */
+	ldr r1, SDRAM_PRECHARGE_CMD_W
+	str r1, [r0, #ESDCTL0_ROF]
+	ldr r1, [r2, #SDRAM_ALL_VAL]
+
+	ldr r1, SDRAM_AUTOREF_CMD_W
+	str r1, [r0, #ESDCTL0_ROF]
+	ldr r1, [r2, #SDRAM_ALL_VAL]
+	ldr r1, [r2, #SDRAM_ALL_VAL]
+
+	ldr r1, SDRAM_LOADMODE_CMD_W
+	str r1, [r0, #ESDCTL0_ROF]
+	ldrb r1, [r2, #SDRAM_MODE_REGISTER_VAL]
+	add r3, r2, #SDRAM_EXT_MODE_REGISTER_VAL
+	ldrb r1, [r3]
+
+	ldr r1, SDRAM_NORMAL_CMD_W
+	str r1, [r0, #ESDCTL0_ROF]
+
+#if (CONFIG_NR_DRAM_BANKS > 1)
+	/* 2nd sdram */
+	mov r2, #PHYS_SDRAM_2
+
+	/* Check The chip version TO1 or TO2 */
+	ldr r1, SOC_SI_ID_REG_W
+	ldr r1, [r1]
+	ands r1, r1, #0xF0000000
+	/* add Latency on CAS only for TO2 */
+	ldreq r1, SDRAM_ESDCFG_T2_W
+	ldrne r1, SDRAM_ESDCFG_T1_W
+	str r1, [r0, #ESDCFG1_ROF]
+
+	/* Run initialization sequence */
+	ldr r1, SDRAM_PRECHARGE_CMD_W
+	str r1, [r0, #ESDCTL1_ROF]
+	ldr r1, [r2, #SDRAM_ALL_VAL]
+
+	ldr r1, SDRAM_AUTOREF_CMD_W
+	str r1, [r0, #ESDCTL1_ROF]
+	ldr r1, [r2, #SDRAM_ALL_VAL]
+	ldr r1, [r2, #SDRAM_ALL_VAL]
+
+	ldr r1, SDRAM_LOADMODE_CMD_W
+	str r1, [r0, #ESDCTL1_ROF]
+	ldrb r1, [r2, #SDRAM_MODE_REGISTER_VAL]
+	add r3, r2, #SDRAM_EXT_MODE_REGISTER_VAL
+	ldrb r1, [r3]
+
+	ldr r1, SDRAM_NORMAL_CMD_W
+	str r1, [r0, #ESDCTL1_ROF]
+#endif  /* CONFIG_NR_DRAM_BANKS > 1 */
+
+.endm /* sdram_init */
+
+.globl	lowlevel_init
+lowlevel_init:
+
+	mov	r10, lr
+
+	init_aipi
+
+	init_clock
+
+	sdram_init
+
+	mov	pc,r10
diff --git a/cpu/arm926ejs/mx27/generic.c b/cpu/arm926ejs/mx27/generic.c
index 9b4ff02..808371f 100644
--- a/cpu/arm926ejs/mx27/generic.c
+++ b/cpu/arm926ejs/mx27/generic.c
@@ -264,3 +264,68 @@ void imx_gpio_mode(int gpio_mode)
 				&regs->port[port].iconfb2);
 	}
 }
+
+#ifdef CONFIG_MXC_UART
+void mx27_uart_init_pins(void)
+{
+	int i;
+	unsigned int mode[] = {
+		PE12_PF_UART1_TXD,
+		PE13_PF_UART1_RXD,
+	};
+
+	for (i = 0; i < ARRAY_SIZE(mode); i++)
+		imx_gpio_mode(mode[i]);
+
+}
+#endif /* CONFIG_MXC_UART */
+
+#ifdef CONFIG_FEC_MXC
+void mx27_fec_init_pins(void)
+{
+	int i;
+	unsigned int mode[] = {
+		PD0_AIN_FEC_TXD0,
+		PD1_AIN_FEC_TXD1,
+		PD2_AIN_FEC_TXD2,
+		PD3_AIN_FEC_TXD3,
+		PD4_AOUT_FEC_RX_ER,
+		PD5_AOUT_FEC_RXD1,
+		PD6_AOUT_FEC_RXD2,
+		PD7_AOUT_FEC_RXD3,
+		PD8_AF_FEC_MDIO,
+		PD9_AIN_FEC_MDC | GPIO_PUEN,
+		PD10_AOUT_FEC_CRS,
+		PD11_AOUT_FEC_TX_CLK,
+		PD12_AOUT_FEC_RXD0,
+		PD13_AOUT_FEC_RX_DV,
+		PD14_AOUT_FEC_CLR,
+		PD15_AOUT_FEC_COL,
+		PD16_AIN_FEC_TX_ER,
+		PF23_AIN_FEC_TX_EN,
+	};
+
+	for (i = 0; i < ARRAY_SIZE(mode); i++)
+		imx_gpio_mode(mode[i]);
+}
+#endif /* CONFIG_FEC_MXC */
+
+#ifdef CONFIG_MXC_MMC
+void mx27_sd2_init_pins(void)
+{
+	int i;
+	unsigned int mode[] = {
+		PB4_PF_SD2_D0,
+		PB5_PF_SD2_D1,
+		PB6_PF_SD2_D2,
+		PB7_PF_SD2_D3,
+		PB8_PF_SD2_CMD,
+		PB9_PF_SD2_CLK,
+	};
+
+	for (i = 0; i < ARRAY_SIZE(mode); i++)
+		imx_gpio_mode(mode[i]);
+
+}
+#endif /* CONFIG_MXC_MMC */
+
diff --git a/include/asm-arm/arch-mx27/imx-regs.h b/include/asm-arm/arch-mx27/imx-regs.h
index cff2b0e..d36a6da 100644
--- a/include/asm-arm/arch-mx27/imx-regs.h
+++ b/include/asm-arm/arch-mx27/imx-regs.h
@@ -28,6 +28,18 @@
 
 extern void imx_gpio_mode (int gpio_mode);
 
+#ifdef CONFIG_MXC_UART
+extern void mx27_uart_init_pins(void);
+#endif /* CONFIG_MXC_UART */
+
+#ifdef CONFIG_FEC_MXC
+extern void mx27_fec_init_pins(void);
+#endif /* CONFIG_FEC_MXC */
+
+#ifdef CONFIG_MXC_MMC
+extern void mx27_sd2_init_pins(void);
+#endif /* CONFIG_MXC_MMC */
+
 /* AIPI */
 struct aipi_regs {
 	u32 psr0;
diff --git a/include/configs/imx27lite.h b/include/configs/imx27lite.h
new file mode 100644
index 0000000..8ebb0bb
--- /dev/null
+++ b/include/configs/imx27lite.h
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2009 Ilya Yanok <yanok@emcraft.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 __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * SoC Configuration
+ */
+#define CONFIG_ARM926EJS			/* arm926ejs CPU core */
+#define CONFIG_MX27
+#define CONFIG_IMX27LITE
+#define CONFIG_MX27_CLK32	32768		/* OSC32K frequency */
+#define CONFIG_SYS_HZ		1000
+
+#define CONFIG_DISPLAY_CPUINFO
+
+#define CONFIG_CMDLINE_TAG		1	/* enable passing of ATAGs */
+#define CONFIG_SETUP_MEMORY_TAGS	1
+#define CONFIG_INITRD_TAG		1
+
+/*
+ * Lowlevel configuration
+ */
+#define SDRAM_ESDCFG_REGISTER_VAL(cas)	\
+		(ESDCFG_TRC(10) |	\
+		ESDCFG_TRCD(3) |	\
+		ESDCFG_TCAS(cas) |	\
+		ESDCFG_TRRD(1) |	\
+		ESDCFG_TRAS(5) |	\
+		ESDCFG_TWR |		\
+		ESDCFG_TMRD(2) |	\
+		ESDCFG_TRP(2) |		\
+		ESDCFG_TXP(3))
+
+#define SDRAM_ESDCTL_REGISTER_VAL	\
+		(ESDCTL_PRCT(0) |	\
+		 ESDCTL_BL |		\
+		 ESDCTL_PWDT(0) |	\
+		 ESDCTL_SREFR(3) |	\
+		 ESDCTL_DSIZ_32 |	\
+		 ESDCTL_COL10 |		\
+		 ESDCTL_ROW13 |		\
+		 ESDCTL_SDE)
+
+#define SDRAM_ALL_VAL		0xf00
+
+#define SDRAM_MODE_REGISTER_VAL	0x33	/* BL: 8, CAS: 3 */
+#define SDRAM_EXT_MODE_REGISTER_VAL	0x1000000
+
+#define MPCTL0_VAL	0x1ef15d5
+
+#define SPCTL0_VAL	0x043a1c09
+
+#define CSCR_VAL	0x33f08107
+
+#define PCDR0_VAL	0x120470c3
+#define PCDR1_VAL	0x03030303
+#define PCCR0_VAL	0xffffffff
+#define PCCR1_VAL	0xfffffffc
+
+#define AIPI1_PSR0_VAL	0x20040304
+#define AIPI1_PSR1_VAL	0xdffbfcfb
+#define AIPI2_PSR0_VAL	0x07ffc200
+#define AIPI2_PSR1_VAL	0xffffffff
+
+/*
+ * Memory Info
+ */
+/* malloc() len */
+#define CONFIG_SYS_MALLOC_LEN		(0x10000 + 512 * 1024)
+/* reserved for initial data */
+#define CONFIG_SYS_GBL_DATA_SIZE	128
+/* memtest start address */
+#define CONFIG_SYS_MEMTEST_START	0xA0000000
+#define CONFIG_SYS_MEMTEST_END		0xA1000000	/* 16MB RAM test */
+#define CONFIG_NR_DRAM_BANKS	1		/* we have 1 bank of DRAM */
+#define CONFIG_STACKSIZE	(256 * 1024)	/* regular stack */
+#define PHYS_SDRAM_1		0xA0000000	/* DDR Start */
+#define PHYS_SDRAM_1_SIZE	0x08000000	/* DDR size 128MB */
+
+/*
+ * Serial Driver info
+ */
+#define CONFIG_MXC_UART
+#define CONFIG_SYS_MX27_UART1
+#define CONFIG_CONS_INDEX	1		/* use UART0 for console */
+#define CONFIG_BAUDRATE		115200		/* Default baud rate */
+#define CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 }
+
+/*
+ * Flash & Environment
+ */
+#define CONFIG_ENV_IS_IN_FLASH
+#define CONFIG_FLASH_CFI_DRIVER
+#define CONFIG_SYS_FLASH_CFI
+/* Use buffered writes (~10x faster) */
+#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE	1
+/* Use hardware sector protection */
+#define CONFIG_SYS_FLASH_PROTECTION		1
+#define CONFIG_SYS_MAX_FLASH_BANKS	1	/* max number of flash banks */
+#define CONFIG_SYS_FLASH_SECT_SZ	0x2000	/* 8KB sect size Intel Flash */
+/* end of flash */
+#define CONFIG_ENV_OFFSET		(PHYS_FLASH_SIZE - 0x20000)
+/* CS2 Base address */
+#define PHYS_FLASH_1			0xc0000000
+/* Flash Base for U-Boot */
+#define CONFIG_SYS_FLASH_BASE		PHYS_FLASH_1
+/* Flash size 2MB */
+#define PHYS_FLASH_SIZE			0x200000
+#define CONFIG_SYS_MAX_FLASH_SECT	(PHYS_FLASH_SIZE / \
+		CONFIG_SYS_FLASH_SECT_SZ)
+#define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_FLASH_BASE
+#define CONFIG_SYS_MONITOR_LEN		0x40000		/* Reserve 256KiB */
+#define CONFIG_ENV_SECT_SIZE		0x10000		/* Env sector Size */
+#define CONFIG_ENV_SIZE		CONFIG_ENV_SECT_SIZE
+/* Address and size of Redundant Environment Sector	*/
+#define CONFIG_ENV_OFFSET_REDUND	(CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE)
+#define CONFIG_ENV_SIZE_REDUND	CONFIG_ENV_SIZE
+
+/*
+ * Ethernet
+ */
+#define CONFIG_FEC_MXC
+#define CONFIG_FEC_MXC_PHYADDR		0x1f
+#define CONFIG_MII
+#define CONFIG_NET_MULTI
+
+/*
+ * MTD
+ */
+#define CONFIG_MTD_DEVICE
+
+/*
+ * NAND
+ */
+#define CONFIG_NAND_MXC
+#define CONFIG_MXC_NAND_REGS_BASE	0xd8000000
+#define CONFIG_SYS_MAX_NAND_DEVICE	1
+#define CONFIG_SYS_NAND_BASE		0xd8000000
+#define CONFIG_JFFS2_NAND
+#define CONFIG_MXC_NAND_HWECC
+
+/*
+ * SD/MMC
+ */
+#define CONFIG_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_MXC_MMC
+#define CONFIG_MXC_MCI_REGS_BASE	0x10014000
+#define CONFIG_DOS_PARTITION
+
+/*
+ * MTD partitions
+ */
+#define CONFIG_CMD_MTDPARTS
+#define MTDIDS_DEFAULT		"nor0=physmap-flash.0,nand0=mxc_nand.0"
+#define MTDPARTS_DEFAULT			\
+	"mtdparts="				\
+		"physmap-flash.0:"		\
+			"256k(U-Boot),"		\
+			"1664k(user),"		\
+			"64k(env1),"		\
+			"64k(env2);"		\
+		"mxc_nand.0:"			\
+			"128k(IPL-SPL),"	\
+			"4m(kernel),"		\
+			"22m(rootfs),"		\
+			"-(userfs)"
+
+/*
+ * U-Boot general configuration
+ */
+#define CONFIG_BOOTFILE		"uImage"	/* Boot file name */
+#define CONFIG_SYS_PROMPT	"=> "	/* Monitor Command Prompt */
+#define CONFIG_SYS_CBSIZE	1024	/* Console I/O Buffer Size  */
+/* Print buffer sz */
+#define CONFIG_SYS_PBSIZE	(CONFIG_SYS_CBSIZE + \
+		sizeof(CONFIG_SYS_PROMPT) + 16)
+#define CONFIG_SYS_MAXARGS	16	/* max number of command args */
+/* Boot Argument Buffer Size */
+#define CONFIG_SYS_BARGSIZE	CONFIG_SYS_CBSIZE
+#define CONFIG_CMDLINE_EDITING
+#define CONFIG_SYS_LONGHELP
+
+/*
+ * U-Boot commands
+ */
+#include <config_cmd_default.h>
+#define CONFIG_CMD_ASKENV
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_DIAG
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_JFFS2
+#define CONFIG_CMD_MII
+#define CONFIG_CMD_MMC
+#define CONFIG_CMD_NAND
+#define CONFIG_CMD_PING
+
+#define CONFIG_BOOTDELAY	5
+
+#define CONFIG_LOADADDR		0xa0800000	/* loadaddr env var */
+#define CONFIG_SYS_LOAD_ADDR		CONFIG_LOADADDR
+
+#define xstr(s)	str(s)
+#define str(s)	#s
+
+#define	CONFIG_EXTRA_ENV_SETTINGS					\
+	"netdev=eth0\0"							\
+	"nfsargs=setenv bootargs root=/dev/nfs rw "			\
+		"nfsroot=${serverip}:${rootpath}\0"			\
+	"ramargs=setenv bootargs root=/dev/ram rw\0"			\
+	"addip=setenv bootargs ${bootargs} "				\
+		"ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}"	\
+		":${hostname}:${netdev}:off panic=1\0"			\
+	"addtty=setenv bootargs ${bootargs}"				\
+		" console=ttymxc0,${baudrate}\0"			\
+	"addmtd=setenv bootargs ${bootargs} ${mtdparts}\0"		\
+	"addmisc=setenv bootargs ${bootargs}\0"				\
+	"u-boot=imx27/u-boot.bin\0"					\
+	"kernel_addr_r=a0800000\0"					\
+	"hostname=imx27\0"						\
+	"bootfile=imx27/uImage\0"					\
+	"rootpath=/opt/eldk-4.2-arm/arm\0"				\
+	"net_nfs=tftp ${kernel_addr_r} ${bootfile};"			\
+		"run nfsargs addip addtty addmtd addmisc;"		\
+		"bootm\0"						\
+	"bootcmd=run net_nfs\0"					\
+	"load=tftp ${loadaddr} ${u-boot}\0"				\
+	"update=protect off " xstr(CONFIG_SYS_MONITOR_BASE)		\
+		" +${filesize};era " xstr(CONFIG_SYS_MONITOR_BASE)	\
+		" +${filesize};cp.b ${fileaddr} "			\
+		xstr(CONFIG_SYS_MONITOR_BASE) " ${filesize}\0"		\
+	"upd=run load update\0"						\
+
+#endif /* __CONFIG_H */
-- 
1.6.0.6

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

* [U-Boot] [PATCH] mxc_nand: add nand driver for MX2/MX3
  2009-08-04 23:32             ` Scott Wood
@ 2009-08-10 22:32               ` Ilya Yanok
  2009-08-11 22:53                 ` Scott Wood
  0 siblings, 1 reply; 70+ messages in thread
From: Ilya Yanok @ 2009-08-10 22:32 UTC (permalink / raw)
  To: u-boot

Driver for NFC NAND controller found on Freescale's MX2 and MX3
processors. Ported from Linux. Tested only with i.MX27 but should
works with other MX2 and MX3 processors too.

Signed-off-by: Ilya Yanok <yanok@emcraft.com>
---
 drivers/mtd/nand/Makefile   |    1 +
 drivers/mtd/nand/mxc_nand.c |  880 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 881 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/nand/mxc_nand.c

diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 89ccec2..ea8572f 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -40,6 +40,7 @@ COBJS-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_nand.o
 COBJS-$(CONFIG_NAND_FSL_UPM) += fsl_upm.o
 COBJS-$(CONFIG_NAND_KIRKWOOD) += kirkwood_nand.o
 COBJS-$(CONFIG_NAND_MPC5121_NFC) += mpc5121_nfc.o
+COBJS-$(CONFIG_NAND_MXC) += mxc_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/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
new file mode 100644
index 0000000..647be0b
--- /dev/null
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -0,0 +1,880 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Sascha Hauer, kernel at pengutronix.de
+ * Copyright 2009 Ilya Yanok, <yanok@emcraft.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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <common.h>
+#include <nand.h>
+#include <linux/err.h>
+#include <asm/io.h>
+#ifdef CONFIG_MX27
+#include <asm/arch/imx-regs.h>
+#endif
+
+#define DRIVER_NAME "mxc_nand"
+
+struct nfc_regs {
+/* NFC RAM BUFFER Main area 0 */
+	uint8_t main_area0[0x200];
+	uint8_t main_area1[0x200];
+	uint8_t main_area2[0x200];
+	uint8_t main_area3[0x200];
+/* SPARE BUFFER Spare area 0 */
+	uint8_t spare_area0[0x10];
+	uint8_t spare_area1[0x10];
+	uint8_t spare_area2[0x10];
+	uint8_t spare_area3[0x10];
+	uint8_t pad[0x5c0];
+/* NFC registers */
+	uint16_t nfc_buf_size;
+	uint16_t reserved;
+	uint16_t nfc_buf_addr;
+	uint16_t nfc_flash_addr;
+	uint16_t nfc_flash_cmd;
+	uint16_t nfc_config;
+	uint16_t nfc_ecc_status_result;
+	uint16_t nfc_rsltmain_area;
+	uint16_t nfc_rsltspare_area;
+	uint16_t nfc_wrprot;
+	uint16_t nfc_unlockstart_blkaddr;
+	uint16_t nfc_unlockend_blkaddr;
+	uint16_t nfc_nf_wrprst;
+	uint16_t nfc_config1;
+	uint16_t nfc_config2;
+};
+
+/*
+ * Set INT to 0, FCMD to 1, rest to 0 in NFC_CONFIG2 Register
+ * for Command operation
+ */
+#define NFC_CMD            0x1
+
+/*
+ * Set INT to 0, FADD to 1, rest to 0 in NFC_CONFIG2 Register
+ * for Address operation
+ */
+#define NFC_ADDR           0x2
+
+/*
+ * Set INT to 0, FDI to 1, rest to 0 in NFC_CONFIG2 Register
+ * for Input operation
+ */
+#define NFC_INPUT          0x4
+
+/*
+ * Set INT to 0, FDO to 001, rest to 0 in NFC_CONFIG2 Register
+ * for Data Output operation
+ */
+#define NFC_OUTPUT         0x8
+
+/*
+ * Set INT to 0, FD0 to 010, rest to 0 in NFC_CONFIG2 Register
+ * for Read ID operation
+ */
+#define NFC_ID             0x10
+
+/*
+ * Set INT to 0, FDO to 100, rest to 0 in NFC_CONFIG2 Register
+ * for Read Status operation
+ */
+#define NFC_STATUS         0x20
+
+/*
+ * Set INT to 1, rest to 0 in NFC_CONFIG2 Register for Read
+ * Status operation
+ */
+#define NFC_INT            0x8000
+
+#define NFC_SP_EN           (1 << 2)
+#define NFC_ECC_EN          (1 << 3)
+#define NFC_BIG             (1 << 5)
+#define NFC_RST             (1 << 6)
+#define NFC_CE              (1 << 7)
+#define NFC_ONE_CYCLE       (1 << 8)
+
+typedef enum {false, true} bool;
+
+struct mxc_nand_host {
+	struct mtd_info		mtd;
+	struct nand_chip	*nand;
+
+	struct nfc_regs __iomem	*regs;
+	int			spare_only;
+	int			status_request;
+	int			pagesize_2k;
+	int			clk_act;
+	uint16_t		col_addr;
+};
+
+static struct mxc_nand_host mxc_host;
+static struct mxc_nand_host *host = &mxc_host;
+
+/* Define delays in microsec for NAND device operations */
+#define TROP_US_DELAY   2000
+/* Macros to get byte and bit positions of ECC */
+#define COLPOS(x)  ((x) >> 3)
+#define BITPOS(x) ((x) & 0xf)
+
+/* Define single bit Error positions in Main & Spare area */
+#define MAIN_SINGLEBIT_ERROR 0x4
+#define SPARE_SINGLEBIT_ERROR 0x1
+
+/* OOB placement block for use with hardware ecc generation */
+#ifdef CONFIG_MXC_NAND_HWECC
+static struct nand_ecclayout nand_hw_eccoob = {
+	.eccbytes = 5,
+	.eccpos = {6, 7, 8, 9, 10},
+	.oobfree = {{0, 5}, {11, 5}, }
+};
+#else
+static struct nand_ecclayout nand_soft_eccoob = {
+	.eccbytes = 6,
+	.eccpos = {6, 7, 8, 9, 10, 11},
+	.oobfree = {{0, 5}, {12, 4}, }
+};
+#endif
+
+static uint32_t *mxc_nand_memcpy32(uint32_t *dest, uint32_t *source, size_t size)
+{
+	uint32_t *d = dest;
+
+	size >>= 2;
+	while (size--)
+		__raw_writel(__raw_readl(source++), d++);
+	return dest;
+}
+
+/*
+ * This function polls the NANDFC to wait for the basic operation to
+ * complete by checking the INT bit of config2 register.
+ */
+static void wait_op_done(struct mxc_nand_host *host, int max_retries,
+				uint16_t param)
+{
+	uint32_t tmp;
+
+	while (max_retries-- > 0) {
+		if (readw(&host->regs->nfc_config2) & NFC_INT) {
+			tmp = readw(&host->regs->nfc_config2);
+			tmp  &= ~NFC_INT;
+			writew(tmp, &host->regs->nfc_config2);
+			break;
+		}
+		udelay(1);
+	}
+	if (max_retries < 0) {
+		MTDDEBUG(MTD_DEBUG_LEVEL0, "%s(%d): INT not set\n",
+				__func__, param);
+	}
+}
+
+/*
+ * This function issues the specified command to the NAND device and
+ * waits for completion.
+ */
+static void send_cmd(struct mxc_nand_host *host, uint16_t cmd)
+{
+	MTDDEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x)\n", cmd);
+
+	writew(cmd, &host->regs->nfc_flash_cmd);
+	writew(NFC_CMD, &host->regs->nfc_config2);
+
+	/* Wait for operation to complete */
+	wait_op_done(host, TROP_US_DELAY, cmd);
+}
+
+/*
+ * This function sends an address (or partial address) to the
+ * NAND device. The address is used to select the source/destination for
+ * a NAND command.
+ */
+static void send_addr(struct mxc_nand_host *host, uint16_t addr)
+{
+	MTDDEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x)\n", addr);
+
+	writew(addr, &host->regs->nfc_flash_addr);
+	writew(NFC_ADDR, &host->regs->nfc_config2);
+
+	/* Wait for operation to complete */
+	wait_op_done(host, TROP_US_DELAY, addr);
+}
+
+/*
+ * This function requests the NANDFC to initate the transfer
+ * of data currently in the NANDFC RAM buffer to the NAND device.
+ */
+static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id,
+			int spare_only)
+{
+	MTDDEBUG(MTD_DEBUG_LEVEL3, "send_prog_page (%d)\n", spare_only);
+
+	writew(buf_id, &host->regs->nfc_buf_addr);
+
+	/* Configure spare or page+spare access */
+	if (!host->pagesize_2k) {
+		uint16_t config1 = readw(&host->regs->nfc_config1);
+		if (spare_only)
+			config1 |= NFC_SP_EN;
+		else
+			config1 &= ~(NFC_SP_EN);
+		writew(config1, &host->regs->nfc_config1);
+	}
+
+	writew(NFC_INPUT, &host->regs->nfc_config2);
+
+	/* Wait for operation to complete */
+	wait_op_done(host, TROP_US_DELAY, spare_only);
+}
+
+/*
+ * Requests NANDFC to initated the transfer of data from the
+ * NAND device into in the NANDFC ram buffer.
+ */
+static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id,
+		int spare_only)
+{
+	MTDDEBUG(MTD_DEBUG_LEVEL3, "send_read_page (%d)\n", spare_only);
+
+	writew(buf_id, &host->regs->nfc_buf_addr);
+
+	/* Configure spare or page+spare access */
+	if (!host->pagesize_2k) {
+		uint32_t config1 = readw(&host->regs->nfc_config1);
+		if (spare_only)
+			config1 |= NFC_SP_EN;
+		else
+			config1 &= ~NFC_SP_EN;
+		writew(config1, &host->regs->nfc_config1);
+	}
+
+	writew(NFC_OUTPUT, &host->regs->nfc_config2);
+
+	/* Wait for operation to complete */
+	wait_op_done(host, TROP_US_DELAY, spare_only);
+}
+
+/* Request the NANDFC to perform a read of the NAND device ID. */
+static void send_read_id(struct mxc_nand_host *host)
+{
+	uint16_t tmp;
+
+	/* NANDFC buffer 0 is used for device ID output */
+	writew(0x0, &host->regs->nfc_buf_addr);
+
+	/* Read ID into main buffer */
+	tmp = readw(&host->regs->nfc_config1);
+	tmp &= ~NFC_SP_EN;
+	writew(tmp, &host->regs->nfc_config1);
+
+	writew(NFC_ID, &host->regs->nfc_config2);
+
+	/* Wait for operation to complete */
+	wait_op_done(host, TROP_US_DELAY, 0);
+}
+
+/*
+ * This function requests the NANDFC to perform a read of the
+ * NAND device status and returns the current status.
+ */
+static uint16_t get_dev_status(struct mxc_nand_host *host)
+{
+	void __iomem *main_buf = host->regs->main_area1;
+	uint32_t store;
+	uint16_t ret, tmp;
+	/* Issue status request to NAND device */
+
+	/* store the main area1 first word, later do recovery */
+	store = readl(main_buf);
+	/* NANDFC buffer 1 is used for device status */
+	writew(1, &host->regs->nfc_buf_addr);
+
+	/* Read status into main buffer */
+	tmp = readw(&host->regs->nfc_config1);
+	tmp &= ~NFC_SP_EN;
+	writew(tmp, &host->regs->nfc_config1);
+
+	writew(NFC_STATUS, &host->regs->nfc_config2);
+
+	/* Wait for operation to complete */
+	wait_op_done(host, TROP_US_DELAY, 0);
+
+	/*
+	 *  Status is placed in first word of main buffer
+	 * get status, then recovery area 1 data
+	 */
+	ret = readw(main_buf);
+	writel(store, main_buf);
+
+	return ret;
+}
+
+/* This function is used by upper layer to checks if device is ready */
+static int mxc_nand_dev_ready(struct mtd_info *mtd)
+{
+	/*
+	 * NFC handles R/B internally. Therefore, this function
+	 * always returns status as ready.
+	 */
+	return 1;
+}
+
+#ifdef CONFIG_MXC_NAND_HWECC
+static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
+{
+	/*
+	 * If HW ECC is enabled, we turn it on during init. There is
+	 * no need to enable again here.
+	 */
+}
+
+static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
+				 u_char *read_ecc, u_char *calc_ecc)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+
+	/*
+	 * 1-Bit errors are automatically corrected in HW.  No need for
+	 * additional correction.  2-Bit errors cannot be corrected by
+	 * HW ECC, so we need to return failure
+	 */
+	uint16_t ecc_status = readw(&host->regs->nfc_ecc_status_result);
+
+	if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
+		MTDDEBUG(MTD_DEBUG_LEVEL0,
+		      "MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
+				  u_char *ecc_code)
+{
+	return 0;
+}
+#endif
+
+static u_char mxc_nand_read_byte(struct mtd_info *mtd)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+	uint8_t ret = 0;
+	uint16_t col;
+	uint16_t __iomem *main_buf =
+		(uint16_t __iomem *)host->regs->main_area0;
+	uint16_t __iomem *spare_buf =
+		(uint16_t __iomem *)host->regs->spare_area0;
+	union {
+		uint16_t word;
+		uint8_t bytes[2];
+	} nfc_word;
+
+	/* Check for status request */
+	if (host->status_request)
+		return get_dev_status(host) & 0xFF;
+
+	/* Get column for 16-bit access */
+	col = host->col_addr >> 1;
+
+	/* If we are accessing the spare region */
+	if (host->spare_only)
+		nfc_word.word = readw(&spare_buf[col]);
+	else
+		nfc_word.word = readw(&main_buf[col]);
+
+	/* Pick upper/lower byte of word from RAM buffer */
+	ret = nfc_word.bytes[host->col_addr & 0x1];
+
+	/* Update saved column address */
+	if (nand_chip->options & NAND_BUSWIDTH_16)
+		host->col_addr += 2;
+	else
+		host->col_addr++;
+
+	return ret;
+}
+
+static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+	uint16_t col, ret;
+	uint16_t __iomem *p;
+
+	MTDDEBUG(MTD_DEBUG_LEVEL3,
+	      "mxc_nand_read_word(col = %d)\n", host->col_addr);
+
+	col = host->col_addr;
+	/* Adjust saved column address */
+	if (col < mtd->writesize && host->spare_only)
+		col += mtd->writesize;
+
+	if (col < mtd->writesize) {
+		p = (uint16_t __iomem *)(host->regs->main_area0 + (col >> 1));
+	} else {
+		p = (uint16_t __iomem *)(host->regs->spare_area0 +
+				((col - mtd->writesize) >> 1));
+	}
+
+	if (col & 1) {
+		union {
+			uint16_t word;
+			uint8_t bytes[2];
+		} nfc_word[3];
+
+		nfc_word[0].word = readw(p);
+		nfc_word[1].word = readw(p + 1);
+
+		nfc_word[2].bytes[0] = nfc_word[0].bytes[1];
+		nfc_word[2].bytes[1] = nfc_word[1].bytes[0];
+
+		ret = nfc_word[2].word;
+	} else {
+		ret = readw(p);
+	}
+
+	/* Update saved column address */
+	host->col_addr = col + 2;
+
+	return ret;
+}
+
+/*
+ * Write data of length len to buffer buf. The data to be
+ * written on NAND Flash is first copied to RAMbuffer. After the Data Input
+ * Operation by the NFC, the data is written to NAND Flash
+ */
+static void mxc_nand_write_buf(struct mtd_info *mtd,
+				const u_char *buf, int len)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+	int n, col, i = 0;
+
+	MTDDEBUG(MTD_DEBUG_LEVEL3,
+	      "mxc_nand_write_buf(col = %d, len = %d)\n", host->col_addr,
+	      len);
+
+	col = host->col_addr;
+
+	/* Adjust saved column address */
+	if (col < mtd->writesize && host->spare_only)
+		col += mtd->writesize;
+
+	n = mtd->writesize + mtd->oobsize - col;
+	n = min(len, n);
+
+	MTDDEBUG(MTD_DEBUG_LEVEL3,
+	      "%s:%d: col = %d, n = %d\n", __func__, __LINE__, col, n);
+
+	while (n > 0) {
+		void __iomem *p;
+
+		if (col < mtd->writesize) {
+			p = host->regs->main_area0 + (col & ~3);
+		} else {
+			p = host->regs->spare_area0 -
+						mtd->writesize + (col & ~3);
+		}
+
+		MTDDEBUG(MTD_DEBUG_LEVEL3, "%s:%d: p = %p\n", __func__,
+		      __LINE__, p);
+
+		if (((col | (unsigned long)&buf[i]) & 3) || n < 4) {
+			union {
+				uint32_t word;
+				uint8_t bytes[4];
+			} nfc_word;
+
+			nfc_word.word = readl(p);
+			nfc_word.bytes[col & 3] = buf[i++];
+			n--;
+			col++;
+
+			writel(nfc_word.word, p);
+		} else {
+			int m = mtd->writesize - col;
+
+			if (col >= mtd->writesize)
+				m += mtd->oobsize;
+
+			m = min(n, m) & ~3;
+
+			MTDDEBUG(MTD_DEBUG_LEVEL3,
+			      "%s:%d: n = %d, m = %d, i = %d, col = %d\n",
+			      __func__,  __LINE__, n, m, i, col);
+
+			mxc_nand_memcpy32(p, (uint32_t *)&buf[i], m);
+			col += m;
+			i += m;
+			n -= m;
+		}
+	}
+	/* Update saved column address */
+	host->col_addr = col;
+}
+
+/*
+ * Read the data buffer from the NAND Flash. To read the data from NAND
+ * Flash first the data output cycle is initiated by the NFC, which copies
+ * the data to RAMbuffer. This data of length len is then copied to buffer buf.
+ */
+static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+	int n, col, i = 0;
+
+	MTDDEBUG(MTD_DEBUG_LEVEL3,
+	      "mxc_nand_read_buf(col = %d, len = %d)\n", host->col_addr, len);
+
+	col = host->col_addr;
+
+	/* Adjust saved column address */
+	if (col < mtd->writesize && host->spare_only)
+		col += mtd->writesize;
+
+	n = mtd->writesize + mtd->oobsize - col;
+	n = min(len, n);
+
+	while (n > 0) {
+		void __iomem *p;
+
+		if (col < mtd->writesize) {
+			p = host->regs->main_area0 + (col & ~3);
+		} else {
+			p = host->regs->spare_area0 -
+					mtd->writesize + (col & ~3);
+		}
+
+		if (((col | (int)&buf[i]) & 3) || n < 4) {
+			union {
+				uint32_t word;
+				uint8_t bytes[4];
+			} nfc_word;
+
+			nfc_word.word = readl(p);
+			buf[i++] = nfc_word.bytes[col & 3];
+			n--;
+			col++;
+		} else {
+			int m = mtd->writesize - col;
+
+			if (col >= mtd->writesize)
+				m += mtd->oobsize;
+
+			m = min(n, m) & ~3;
+			mxc_nand_memcpy32((uint32_t *)&buf[i], p, m);
+
+			col += m;
+			i += m;
+			n -= m;
+		}
+	}
+	/* Update saved column address */
+	host->col_addr = col;
+}
+
+/*
+ * Used by the upper layer to verify the data in NAND Flash
+ * with the data in the buf.
+ */
+static int mxc_nand_verify_buf(struct mtd_info *mtd,
+				const u_char *buf, int len)
+{
+	u_char tmp[256];
+	uint bsize;
+
+	while (len) {
+		bsize = min(len, 256);
+		mxc_nand_read_buf(mtd, tmp, bsize);
+
+		if (memcmp(buf, tmp, bsize))
+			return 1;
+
+		buf += bsize;
+		len -= bsize;
+	}
+
+	return 0;
+}
+
+/*
+ * This function is used by upper layer for select and
+ * deselect of the NAND chip
+ */
+static void mxc_nand_select_chip(struct mtd_info *mtd, int chip)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+
+	switch (chip) {
+	case -1:
+		/* TODO: Disable the NFC clock */
+		if (host->clk_act)
+			host->clk_act = 0;
+		break;
+	case 0:
+		/* TODO: Enable the NFC clock */
+		if (!host->clk_act)
+			host->clk_act = 1;
+		break;
+
+	default:
+		break;
+	}
+}
+
+/*
+ * Used by the upper layer to write command to NAND Flash for
+ * different operations to be carried out on NAND Flash
+ */
+static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
+				int column, int page_addr)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+
+	MTDDEBUG(MTD_DEBUG_LEVEL3,
+	      "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
+	      command, column, page_addr);
+
+	/* Reset command state information */
+	host->status_request = false;
+
+	/* Command pre-processing step */
+	switch (command) {
+
+	case NAND_CMD_STATUS:
+		host->col_addr = 0;
+		host->status_request = true;
+		break;
+
+	case NAND_CMD_READ0:
+		host->col_addr = column;
+		host->spare_only = false;
+		break;
+
+	case NAND_CMD_READOOB:
+		host->col_addr = column;
+		host->spare_only = true;
+		if (host->pagesize_2k)
+			command = NAND_CMD_READ0; /* only READ0 is valid */
+		break;
+
+	case NAND_CMD_SEQIN:
+		if (column >= mtd->writesize) {
+			/*
+			 * before sending SEQIN command for partial write,
+			 * we need read one page out. FSL NFC does not support
+			 * partial write. It alway send out 512+ecc+512+ecc ...
+			 * for large page nand flash. But for small page nand
+			 * flash, it does support SPARE ONLY operation.
+			 */
+			if (host->pagesize_2k) {
+				/* call ourself to read a page */
+				mxc_nand_command(mtd, NAND_CMD_READ0, 0,
+						page_addr);
+			}
+
+			host->col_addr = column - mtd->writesize;
+			host->spare_only = true;
+
+			/* Set program pointer to spare region */
+			if (!host->pagesize_2k)
+				send_cmd(host, NAND_CMD_READOOB);
+		} else {
+			host->spare_only = false;
+			host->col_addr = column;
+
+			/* Set program pointer to page start */
+			if (!host->pagesize_2k)
+				send_cmd(host, NAND_CMD_READ0);
+		}
+		break;
+
+	case NAND_CMD_PAGEPROG:
+		send_prog_page(host, 0, host->spare_only);
+
+		if (host->pagesize_2k) {
+			/* data in 4 areas datas */
+			send_prog_page(host, 1, host->spare_only);
+			send_prog_page(host, 2, host->spare_only);
+			send_prog_page(host, 3, host->spare_only);
+		}
+
+		break;
+	}
+
+	/* Write out the command to the device. */
+	send_cmd(host, command);
+
+	/* Write out column address, if necessary */
+	if (column != -1) {
+		/*
+		 * MXC NANDFC can only perform full page+spare or
+		 * spare-only read/write.  When the upper layers
+		 * layers perform a read/write buf operation,
+		 * we will used the saved column adress to index into
+		 * the full page.
+		 */
+		send_addr(host, 0);
+		if (host->pagesize_2k)
+			/* another col addr cycle for 2k page */
+			send_addr(host, 0);
+	}
+
+	/* Write out page address, if necessary */
+	if (page_addr != -1) {
+		/* paddr_0 - p_addr_7 */
+		send_addr(host, (page_addr & 0xff));
+
+		if (host->pagesize_2k) {
+			send_addr(host, (page_addr >> 8) & 0xFF);
+			if (mtd->size >= 0x10000000) {
+				/* paddr_8 - paddr_15 */
+				send_addr(host, (page_addr >> 8) & 0xff);
+				send_addr(host, (page_addr >> 16) & 0xff);
+			} else {
+				/* paddr_8 - paddr_15 */
+				send_addr(host, (page_addr >> 8) & 0xff);
+			}
+		} else {
+			/* One more address cycle for higher density devices */
+			if (mtd->size >= 0x4000000) {
+				/* paddr_8 - paddr_15 */
+				send_addr(host, (page_addr >> 8) & 0xff);
+				send_addr(host, (page_addr >> 16) & 0xff);
+			} else {
+				/* paddr_8 - paddr_15 */
+				send_addr(host, (page_addr >> 8) & 0xff);
+			}
+		}
+	}
+
+	/* Command post-processing step */
+	switch (command) {
+
+	case NAND_CMD_RESET:
+		break;
+
+	case NAND_CMD_READOOB:
+	case NAND_CMD_READ0:
+		if (host->pagesize_2k) {
+			/* send read confirm command */
+			send_cmd(host, NAND_CMD_READSTART);
+			/* read for each AREA */
+			send_read_page(host, 0, host->spare_only);
+			send_read_page(host, 1, host->spare_only);
+			send_read_page(host, 2, host->spare_only);
+			send_read_page(host, 3, host->spare_only);
+		} else {
+			send_read_page(host, 0, host->spare_only);
+		}
+		break;
+
+	case NAND_CMD_READID:
+		host->col_addr = 0;
+		send_read_id(host);
+		break;
+
+	case NAND_CMD_PAGEPROG:
+		break;
+
+	case NAND_CMD_STATUS:
+		break;
+
+	case NAND_CMD_ERASE2:
+		break;
+	}
+}
+
+int board_nand_init(struct nand_chip *this)
+{
+	struct system_control_regs *sc_regs =
+		(struct system_control_regs *)IMX_SYSTEM_CTL_BASE;
+	struct mtd_info *mtd;
+	uint16_t tmp;
+	int err = 0;
+
+	/* structures must be linked */
+	mtd = &host->mtd;
+	mtd->priv = this;
+	host->nand = this;
+
+	/* 5 us command delay time */
+	this->chip_delay = 5;
+
+	this->priv = host;
+	this->dev_ready = mxc_nand_dev_ready;
+	this->cmdfunc = mxc_nand_command;
+	this->select_chip = mxc_nand_select_chip;
+	this->read_byte = mxc_nand_read_byte;
+	this->read_word = mxc_nand_read_word;
+	this->write_buf = mxc_nand_write_buf;
+	this->read_buf = mxc_nand_read_buf;
+	this->verify_buf = mxc_nand_verify_buf;
+
+	host->regs = (struct nfc_regs __iomem *)CONFIG_MXC_NAND_REGS_BASE;
+	host->clk_act = 1;
+
+#ifdef CONFIG_MXC_NAND_HWECC
+	this->ecc.calculate = mxc_nand_calculate_ecc;
+	this->ecc.hwctl = mxc_nand_enable_hwecc;
+	this->ecc.correct = mxc_nand_correct_data;
+	this->ecc.mode = NAND_ECC_HW;
+	this->ecc.size = 512;
+	this->ecc.bytes = 3;
+	this->ecc.layout = &nand_hw_eccoob;
+	tmp = readw(&host->regs->nfc_config1);
+	tmp |= NFC_ECC_EN;
+	writew(tmp, &host->regs->nfc_config1);
+#else
+	this->ecc.layout = &nand_soft_eccoob;
+	this->ecc.mode = NAND_ECC_SOFT;
+	tmp = readw(&host->regs->nfc_config1);
+	tmp &= ~NFC_ECC_EN;
+	writew(tmp, &host->regs->nfc_config1);
+#endif
+
+	/* Reset NAND */
+	this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
+
+	/*
+	 * preset operation
+	 * Unlock the internal RAM Buffer
+	 */
+	writew(0x2, &host->regs->nfc_config);
+
+	/* Blocks to be unlocked */
+	writew(0x0, &host->regs->nfc_unlockstart_blkaddr);
+	writew(0x4000, &host->regs->nfc_unlockend_blkaddr);
+
+	/* Unlock Block Command for given address range */
+	writew(0x4, &host->regs->nfc_wrprot);
+
+	/* NAND bus width determines access funtions used by upper layer */
+	if (readl(&sc_regs->fmcr) & NF_16BIT_SEL)
+		this->options |= NAND_BUSWIDTH_16;
+
+	host->pagesize_2k = 0;
+
+	return err;
+}
-- 
1.6.0.6

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

* [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD
  2009-08-10 22:32                 ` [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD Ilya Yanok
@ 2009-08-11 18:47                   ` Fabio Estevam
  2009-08-11 19:12                     ` Ilya Yanok
  2009-08-14  7:03                   ` Jean-Christophe PLAGNIOL-VILLARD
  2009-09-01 20:10                   ` Jean-Christophe PLAGNIOL-VILLARD
  2 siblings, 1 reply; 70+ messages in thread
From: Fabio Estevam @ 2009-08-11 18:47 UTC (permalink / raw)
  To: u-boot


--- On Mon, 8/10/09, Ilya Yanok <yanok@emcraft.com> wrote:

> From: Ilya Yanok <yanok@emcraft.com>
> Subject: [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD
> To: plagnioj at jcrosoft.com
> Cc: u-boot at lists.denx.de, "Ilya Yanok" <yanok@emcraft.com>
> Date: Monday, August 10, 2009, 7:32 PM
> This patch adds support for
> i.MX27-LITEKIT development board from
> LogicPD. This board uses i.MX27 SoC and has 2MB NOR flash,
> 64MB NAND
> flash, FEC ethernet controller integrated into i.MX27.
> 
> Signed-off-by: Ilya Yanok <yanok@emcraft.com>

...

>  cpu/arm926ejs/mx27/generic.c ? |???65 ++++++++
>  include/asm-arm/arch-mx27/imx-regs.h? ?

Shouldn't these two files be part of a separate patch as they are not specific to the iMX27 Lite board support?

Regards,

Fabio Estevam




      

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

* [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD
  2009-08-11 18:47                   ` Fabio Estevam
@ 2009-08-11 19:12                     ` Ilya Yanok
  0 siblings, 0 replies; 70+ messages in thread
From: Ilya Yanok @ 2009-08-11 19:12 UTC (permalink / raw)
  To: u-boot

Hi Fabio,

Fabio Estevam wrote:
>>  cpu/arm926ejs/mx27/generic.c   |   65 ++++++++
>>  include/asm-arm/arch-mx27/imx-regs.h   
>>     
>
> Shouldn't these two files be part of a separate patch as they are not specific to the iMX27 Lite board support?
>   

Well, I thought about this... Let's wait for a Jean-Christophe opinion.

Regards, Ilya.

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

* [U-Boot] [PATCH] mxc_nand: add nand driver for MX2/MX3
  2009-08-10 22:32               ` Ilya Yanok
@ 2009-08-11 22:53                 ` Scott Wood
  0 siblings, 0 replies; 70+ messages in thread
From: Scott Wood @ 2009-08-11 22:53 UTC (permalink / raw)
  To: u-boot

On Tue, Aug 11, 2009 at 02:32:54AM +0400, Ilya Yanok wrote:
> Driver for NFC NAND controller found on Freescale's MX2 and MX3
> processors. Ported from Linux. Tested only with i.MX27 but should
> works with other MX2 and MX3 processors too.
> 
> Signed-off-by: Ilya Yanok <yanok@emcraft.com>

Applied to u-boot-nand-flash/next.

-Scott

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

* [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD
  2009-08-10 22:32                 ` [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD Ilya Yanok
  2009-08-11 18:47                   ` Fabio Estevam
@ 2009-08-14  7:03                   ` Jean-Christophe PLAGNIOL-VILLARD
  2009-08-26 20:14                     ` Wolfgang Denk
  2009-09-01 20:10                   ` Jean-Christophe PLAGNIOL-VILLARD
  2 siblings, 1 reply; 70+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2009-08-14  7:03 UTC (permalink / raw)
  To: u-boot

On 02:32 Tue 11 Aug     , Ilya Yanok wrote:
> This patch adds support for i.MX27-LITEKIT development board from
> LogicPD. This board uses i.MX27 SoC and has 2MB NOR flash, 64MB NAND
> flash, FEC ethernet controller integrated into i.MX27.
> 
> Signed-off-by: Ilya Yanok <yanok@emcraft.com>
> ---
>  MAINTAINERS                             |    1 +
>  MAKEALL                                 |    1 +
>  Makefile                                |    3 +
>  board/logicpd/imx27lite/Makefile        |   51 ++++++
>  board/logicpd/imx27lite/config.mk       |    1 +
>  board/logicpd/imx27lite/imx27lite.c     |   73 +++++++++
>  board/logicpd/imx27lite/lowlevel_init.S |  170 +++++++++++++++++++++
>  cpu/arm926ejs/mx27/generic.c            |   65 ++++++++
>  include/asm-arm/arch-mx27/imx-regs.h    |   12 ++
>  include/configs/imx27lite.h             |  252 +++++++++++++++++++++++++++++++
>  10 files changed, 629 insertions(+), 0 deletions(-)
>  create mode 100644 board/logicpd/imx27lite/Makefile
>  create mode 100644 board/logicpd/imx27lite/config.mk
>  create mode 100644 board/logicpd/imx27lite/imx27lite.c
>  create mode 100644 board/logicpd/imx27lite/lowlevel_init.S
>  create mode 100644 include/configs/imx27lite.h
Acked-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>

Scott could you applied on your tree as this one need the nand patch that you
handle

Best Regards,
J.

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

* [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD
  2009-08-14  7:03                   ` Jean-Christophe PLAGNIOL-VILLARD
@ 2009-08-26 20:14                     ` Wolfgang Denk
  2009-08-26 20:43                       ` Scott Wood
  0 siblings, 1 reply; 70+ messages in thread
From: Wolfgang Denk @ 2009-08-26 20:14 UTC (permalink / raw)
  To: u-boot

Dear Scott,

In message <20090814070359.GD11003@game.jcrosoft.org> Jean-Christophe PLAGNIOL-VILLARD wrote:
> On 02:32 Tue 11 Aug     , Ilya Yanok wrote:
> > This patch adds support for i.MX27-LITEKIT development board from
> > LogicPD. This board uses i.MX27 SoC and has 2MB NOR flash, 64MB NAND
> > flash, FEC ethernet controller integrated into i.MX27.
> > 
> > Signed-off-by: Ilya Yanok <yanok@emcraft.com>
> > ---
> >  MAINTAINERS                             |    1 +
> >  MAKEALL                                 |    1 +
> >  Makefile                                |    3 +
> >  board/logicpd/imx27lite/Makefile        |   51 ++++++
> >  board/logicpd/imx27lite/config.mk       |    1 +
> >  board/logicpd/imx27lite/imx27lite.c     |   73 +++++++++
> >  board/logicpd/imx27lite/lowlevel_init.S |  170 +++++++++++++++++++++
> >  cpu/arm926ejs/mx27/generic.c            |   65 ++++++++
> >  include/asm-arm/arch-mx27/imx-regs.h    |   12 ++
> >  include/configs/imx27lite.h             |  252 +++++++++++++++++++++++++++++++
> >  10 files changed, 629 insertions(+), 0 deletions(-)
> >  create mode 100644 board/logicpd/imx27lite/Makefile
> >  create mode 100644 board/logicpd/imx27lite/config.mk
> >  create mode 100644 board/logicpd/imx27lite/imx27lite.c
> >  create mode 100644 board/logicpd/imx27lite/lowlevel_init.S
> >  create mode 100644 include/configs/imx27lite.h
> Acked-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> 
> Scott could you applied on your tree as this one need the nand patch that you
> handle

Could you please run this through your "next" branch and send a pullr
equest? TIA.

Acked-by: Wolfgang Denk <wd@denx.de>

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
A father doesn't destroy his children.
	-- Lt. Carolyn Palamas, "Who Mourns for Adonais?",
	   stardate 3468.1.

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

* [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD
  2009-08-26 20:14                     ` Wolfgang Denk
@ 2009-08-26 20:43                       ` Scott Wood
  0 siblings, 0 replies; 70+ messages in thread
From: Scott Wood @ 2009-08-26 20:43 UTC (permalink / raw)
  To: u-boot

Wolfgang Denk wrote:
>> Scott could you applied on your tree as this one need the nand patch that you
>> handle
> 
> Could you please run this through your "next" branch and send a pullr
> equest? TIA.
> 
> Acked-by: Wolfgang Denk <wd@denx.de>

I don't have that patch in my inbox anymore -- but I've sent a pull 
request for what I do have in "next".  You (or JC) should be able to 
apply this after pulling that.

-Scott

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

* [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD
  2009-08-10 22:32                 ` [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD Ilya Yanok
  2009-08-11 18:47                   ` Fabio Estevam
  2009-08-14  7:03                   ` Jean-Christophe PLAGNIOL-VILLARD
@ 2009-09-01 20:10                   ` Jean-Christophe PLAGNIOL-VILLARD
  2 siblings, 0 replies; 70+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2009-09-01 20:10 UTC (permalink / raw)
  To: u-boot

On 02:32 Tue 11 Aug     , Ilya Yanok wrote:
> This patch adds support for i.MX27-LITEKIT development board from
> LogicPD. This board uses i.MX27 SoC and has 2MB NOR flash, 64MB NAND
> flash, FEC ethernet controller integrated into i.MX27.
> 
> Signed-off-by: Ilya Yanok <yanok@emcraft.com>
> ---
>  MAINTAINERS                             |    1 +
>  MAKEALL                                 |    1 +
>  Makefile                                |    3 +
>  board/logicpd/imx27lite/Makefile        |   51 ++++++
>  board/logicpd/imx27lite/config.mk       |    1 +
>  board/logicpd/imx27lite/imx27lite.c     |   73 +++++++++
>  board/logicpd/imx27lite/lowlevel_init.S |  170 +++++++++++++++++++++
>  cpu/arm926ejs/mx27/generic.c            |   65 ++++++++
>  include/asm-arm/arch-mx27/imx-regs.h    |   12 ++
>  include/configs/imx27lite.h             |  252 +++++++++++++++++++++++++++++++
>  10 files changed, 629 insertions(+), 0 deletions(-)
>  create mode 100644 board/logicpd/imx27lite/Makefile
>  create mode 100644 board/logicpd/imx27lite/config.mk
>  create mode 100644 board/logicpd/imx27lite/imx27lite.c
>  create mode 100644 board/logicpd/imx27lite/lowlevel_init.S
>  create mode 100644 include/configs/imx27lite.h
Applie to u-boot-arm

Best Regards,
J.

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

end of thread, other threads:[~2009-09-01 20:10 UTC | newest]

Thread overview: 70+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-06-08  0:12 [U-Boot] [PATCH 0/7][v3] Support for LogicPD i.MX27-LITEKIT development board Ilya Yanok
2009-06-08  0:12 ` [U-Boot] [PATCH 1/7] mx27: basic cpu support Ilya Yanok
2009-06-20 13:13   ` Jean-Christophe PLAGNIOL-VILLARD
2009-06-08  0:12 ` [U-Boot] [PATCH 2/7] serial_mx31: allow it to work with mx27 too and rename to serial_mxc Ilya Yanok
2009-06-20 13:18   ` Jean-Christophe PLAGNIOL-VILLARD
2009-06-08  0:12 ` [U-Boot] [PATCH 3/7] fec_imx27: driver for FEC ethernet controller on i.MX27 Ilya Yanok
2009-07-17 10:57   ` [U-Boot] [PATCH] fec_mxc: " Ilya Yanok
2009-07-17 14:05     ` Ben Warren
2009-07-21 15:32       ` Ilya Yanok
2009-07-22 22:23         ` Jean-Christophe PLAGNIOL-VILLARD
2009-07-22 23:03           ` Ben Warren
2009-07-23  6:28         ` Ben Warren
2009-06-08  0:12 ` [U-Boot] [PATCH 4/7] mxc_nand: add nand driver for MX2/MX3 Ilya Yanok
2009-06-20 13:22   ` Jean-Christophe PLAGNIOL-VILLARD
2009-06-22 23:43   ` Scott Wood
2009-06-23 20:03     ` Magnus Lilja
2009-07-03 19:03       ` Paul Thomas
2009-07-03 19:11         ` Paul Thomas
2009-07-17 10:48     ` Ilya Yanok
2009-07-17 10:53       ` [U-Boot] [PATCH] " Ilya Yanok
2009-07-22 21:33         ` Jean-Christophe PLAGNIOL-VILLARD
2009-07-28 22:37         ` Scott Wood
2009-08-03  1:45           ` Ilya Yanok
2009-08-04 23:32             ` Scott Wood
2009-08-10 22:32               ` Ilya Yanok
2009-08-11 22:53                 ` Scott Wood
2009-08-03  2:01           ` Ilya Yanok
2009-08-03 16:58             ` Scott Wood
2009-07-17 16:00       ` [U-Boot] [PATCH 4/7] " Scott Wood
2009-06-08  0:12 ` [U-Boot] [PATCH 5/7] mxc-mmc: sdhc host driver for MX2 and MX3 proccessor Ilya Yanok
2009-06-21 11:04   ` Jean-Christophe PLAGNIOL-VILLARD
2009-06-23 23:02   ` alfred steele
2009-08-07 20:13   ` Jean-Christophe PLAGNIOL-VILLARD
2009-06-08  0:12 ` [U-Boot] [PATCH 6/7] arm: add support for CONFIG_GENERIC_MMC Ilya Yanok
2009-06-20 13:20   ` Jean-Christophe PLAGNIOL-VILLARD
2009-06-08  0:12 ` [U-Boot] [PATCH 7/7] imx27lite: add support for imx27lite board from LogicPD Ilya Yanok
2009-06-21 11:21   ` Jean-Christophe PLAGNIOL-VILLARD
2009-06-23 16:55     ` Detlev Zundel
2009-07-07 19:24     ` Wolfgang Denk
2009-07-17 11:00     ` [U-Boot] [PATCH] " Ilya Yanok
2009-07-22 21:37       ` Jean-Christophe PLAGNIOL-VILLARD
2009-07-22 22:17         ` Ilya Yanok
2009-07-23 21:37           ` Jean-Christophe PLAGNIOL-VILLARD
2009-08-03  1:46             ` Ilya Yanok
2009-08-03  5:32               ` Jean-Christophe PLAGNIOL-VILLARD
2009-08-03  8:19                 ` Wolfgang Denk
2009-08-03 12:17                   ` Jean-Christophe PLAGNIOL-VILLARD
2009-08-03 14:35                     ` Wolfgang Denk
2009-08-05 10:09                       ` javier Martin
2009-08-05 12:30                         ` javier Martin
2009-08-05 12:45                           ` Wolfgang Denk
2009-08-05 14:17                             ` javier Martin
2009-08-05 14:21                               ` Wolfgang Denk
2009-08-05 15:01                                 ` javier Martin
2009-08-06 19:29                           ` [U-Boot] [PATCH] ARM EABI: add new helper functions resp. function names Wolfgang Denk
2009-08-06 20:10                             ` [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD Wolfgang Denk
2009-08-07  7:18                               ` javier Martin
2009-08-07  9:13                                 ` Wolfgang Denk
2009-08-08  6:50                             ` [U-Boot] [PATCH] ARM EABI: add new helper functions resp. function names Dirk Behme
2009-08-08  7:16                               ` Wolfgang Denk
2009-08-08  7:39                                 ` Dirk Behme
2009-08-09 21:28                             ` Wolfgang Denk
2009-08-10 22:32                 ` [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD Ilya Yanok
2009-08-11 18:47                   ` Fabio Estevam
2009-08-11 19:12                     ` Ilya Yanok
2009-08-14  7:03                   ` Jean-Christophe PLAGNIOL-VILLARD
2009-08-26 20:14                     ` Wolfgang Denk
2009-08-26 20:43                       ` Scott Wood
2009-09-01 20:10                   ` Jean-Christophe PLAGNIOL-VILLARD
2009-06-28  9:52 ` [U-Boot] [PATCH 0/7][v3] Support for LogicPD i.MX27-LITEKIT development board Jean-Christophe PLAGNIOL-VILLARD

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.