All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 00/10] Support for LogicPD i.MX27-LITEKIT development board
@ 2009-05-06 18:30 Ilya Yanok
  2009-05-06 18:30 ` [U-Boot] [PATCH 01/10] mx27: basic cpu support Ilya Yanok
                   ` (10 more replies)
  0 siblings, 11 replies; 49+ messages in thread
From: Ilya Yanok @ 2009-05-06 18:30 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. It also
contains some fixes to generic MMC subsystem.

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

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

* [U-Boot] [PATCH 01/10] mx27: basic cpu support
  2009-05-06 18:30 [U-Boot] [PATCH 00/10] Support for LogicPD i.MX27-LITEKIT development board Ilya Yanok
@ 2009-05-06 18:30 ` Ilya Yanok
  2009-05-06 20:30   ` Magnus Lilja
  2009-05-06 21:16   ` Wolfgang Denk
  2009-05-06 18:30 ` [U-Boot] [PATCH 02/10] serial_mx31: allow it to work with mx27 too Ilya Yanok
                   ` (9 subsequent siblings)
  10 siblings, 2 replies; 49+ messages in thread
From: Ilya Yanok @ 2009-05-06 18:30 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         |  205 ++++++++++++++
 cpu/arm926ejs/mx27/interrupt.c       |  201 ++++++++++++++
 include/asm-arm/arch-mx27/clock.h    |   17 ++
 include/asm-arm/arch-mx27/imx-regs.h |  504 ++++++++++++++++++++++++++++++++++
 5 files changed, 971 insertions(+), 0 deletions(-)
 create mode 100644 cpu/arm926ejs/mx27/Makefile
 create mode 100644 cpu/arm926ejs/mx27/generic.c
 create mode 100644 cpu/arm926ejs/mx27/interrupt.c
 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..c86f3c2
--- /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	= interrupt.o generic.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..fdbc8b7
--- /dev/null
+++ b/cpu/arm926ejs/mx27/generic.c
@@ -0,0 +1,205 @@
+/*
+ *  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/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_MX31_CLK32;
+}
+
+static ulong clk_in_26m(void)
+{
+	if (CSCR & CSCR_OSC26M_DIV1P5) {
+		/* divide by 1.5 */
+		return 26000000 / 1.5;
+	} else {
+		/* divide by 1 */
+		return 26000000;
+	}
+}
+
+ulong imx_get_mpllclk(void)
+{
+	ulong cscr = CSCR;
+	ulong fref;
+
+	if (cscr & CSCR_MCU_SEL)
+		fref = clk_in_26m();
+	else
+		fref = clk_in_32k();
+
+	return imx_decode_pll(MPCTL0, fref);
+}
+
+ulong imx_get_armclk(void)
+{
+	ulong cscr = 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)
+{
+	ulong cscr = CSCR;
+	ulong fref = imx_get_mpllclk();
+	ulong div;
+
+	div = ((cscr >> 8) & 0x3) + 1;
+
+	return lldiv(fref * 2, 3 * div);
+
+}
+
+ulong imx_get_spllclk(void)
+{
+	ulong cscr = CSCR;
+	ulong fref;
+
+	if (cscr & CSCR_SP_SEL)
+		fref = clk_in_26m();
+	else
+		fref = clk_in_32k();
+
+	return imx_decode_pll(SPCTL0, fref);
+}
+
+static ulong imx_decode_perclk(ulong div)
+{
+        return lldiv((imx_get_mpllclk() * 2), (div * 3));
+}
+
+ulong imx_get_perclk1(void)
+{
+	return imx_decode_perclk((PCDR1 & 0x3f) + 1);
+}
+
+ulong imx_get_perclk2(void)
+{
+	return imx_decode_perclk(((PCDR1 >> 8) & 0x3f) + 1);
+}
+
+ulong imx_get_perclk3(void)
+{
+	return imx_decode_perclk(((PCDR1 >> 16) & 0x3f) + 1);
+}
+
+ulong imx_get_perclk4(void)
+{
+	return imx_decode_perclk(((PCDR1 >> 24) & 0x3f) + 1);
+}
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+int print_cpuinfo (void)
+{
+       printf("CPU:   Freescale i.MX27 at %llu MHz\n",
+               lldiv(imx_get_mpllclk(), 1000000));
+       printf("\n");
+       return 0;
+}
+#endif
+
+void imx_gpio_mode(int gpio_mode)
+{
+	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)
+		PUEN(port) |= (1 << pin);
+	else
+		PUEN(port) &= ~(1 << pin);
+
+	/* Data direction */
+	if(gpio_mode & GPIO_OUT)
+		DDIR(port) |= 1 << pin;
+	else
+		DDIR(port) &= ~(1 << pin);
+
+	/* Primary / alternate function */
+	if(gpio_mode & GPIO_AF)
+		GPR(port) |= (1 << pin);
+	else
+		GPR(port) &= ~(1 << pin);
+
+	/* use as gpio? */
+	if(!(gpio_mode & (GPIO_PF | GPIO_AF)))
+		GIUS(port) |= (1 << pin);
+	else
+		GIUS(port) &= ~(1 << pin);
+
+	/* Output / input configuration */
+	if (pin < 16) {
+		tmp = OCR1(port);
+		tmp &= ~(3 << (pin * 2));
+		tmp |= (ocr << (pin * 2));
+		OCR1(port) = tmp;
+
+		ICONFA1(port) &= ~(3 << (pin * 2));
+		ICONFA1(port) |= aout << (pin * 2);
+		ICONFB1(port) &= ~(3 << (pin * 2));
+		ICONFB1(port) |= bout << (pin * 2);
+	} else {
+		pin -= 16;
+
+		tmp = OCR2(port);
+		tmp &= ~(3 << (pin * 2));
+		tmp |= (ocr << (pin * 2));
+		OCR2(port) = tmp;
+
+		ICONFA2(port) &= ~(3 << (pin * 2));
+		ICONFA2(port) |= aout << (pin * 2);
+		ICONFB2(port) &= ~(3 << (pin * 2));
+		ICONFB2(port) |= bout << (pin * 2);
+	}
+
+}
+
diff --git a/cpu/arm926ejs/mx27/interrupt.c b/cpu/arm926ejs/mx27/interrupt.c
new file mode 100644
index 0000000..6138d91
--- /dev/null
+++ b/cpu/arm926ejs/mx27/interrupt.c
@@ -0,0 +1,201 @@
+/*
+ * (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/arch/imx-regs.h>
+
+/* General purpose timers registers */
+#define GPTCR	__REG(IMX_TIM1_BASE)		/* Control register	*/
+#define GPTPR	__REG(IMX_TIM1_BASE + 0x4)	/* Prescaler register	*/
+#define GPTCNT	__REG(IMX_TIM1_BASE + 0x10)	/* Counter register	*/
+#define GPTSR	__REG(IMX_TIM1_BASE + 0x14)	/* Status register	*/
+
+/* 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_MX31_CLK32);
+	return tick;
+}
+
+static inline unsigned long long time_to_tick(unsigned long long time)
+{
+	time *= CONFIG_MX31_CLK32;
+	do_div(time, CONFIG_SYS_HZ);
+	return time;
+}
+
+static inline unsigned long long us_to_tick(unsigned long long us)
+{
+	us = us * CONFIG_MX31_CLK32 + 999999;
+	do_div(us, 1000000);
+	return us;
+}
+#else
+/* ~2% error */
+#define TICK_PER_TIME	((CONFIG_MX31_CLK32 + CONFIG_SYS_HZ / 2) / CONFIG_SYS_HZ)
+#define US_PER_TICK	(1000000 / CONFIG_MX31_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;
+
+	/* setup GP Timer 1 */
+	GPTCR = GPTCR_SWR;
+
+#ifdef CONFIG_IMX27
+	PCCR0 |= PCCR0_GPT1_EN;
+	PCCR1 |= PCCR1_PERCLK1_EN;
+#endif
+
+	for (i = 0; i < 100; i++)
+		GPTCR = 0; /* We have no udelay by now */
+	GPTPR = 0; /* 32Khz */
+	/* Freerun Mode, PERCLK1 input */
+	GPTCR |= GPTCR_CLKSOURCE_32 | GPTCR_FRR;
+	GPTCR |= GPTCR_TEN;
+
+	return 0;
+}
+
+void reset_timer_masked (void)
+{
+	/* reset time */
+	lastinc = GPTCNT; /* capture current incrementer value time */
+	timestamp = 0; /* start "advancing" time stamp from 0 */
+}
+
+void reset_timer(void)
+{
+	reset_timer_masked();
+}
+
+unsigned long long get_ticks (void)
+{
+	ulong now = GPTCNT; /* 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_MX31_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*/;
+}
+
+/*
+ * Reset the cpu by setting up the watchdog timer and let it time out
+ */
+void reset_cpu (ulong ignored)
+{
+	/* Disable watchdog and set Time-Out field to 0 */
+	WCR = 0x00000000;
+
+	/* Write Service Sequence */
+	WSR = 0x00005555;
+	WSR = 0x0000AAAA;
+
+	/* Enable watchdog */
+	WCR = WCR_WDE;
+
+	while (1);
+	/*NOTREACHED*/
+}
diff --git a/include/asm-arm/arch-mx27/clock.h b/include/asm-arm/arch-mx27/clock.h
new file mode 100644
index 0000000..f6615d9
--- /dev/null
+++ b/include/asm-arm/arch-mx27/clock.h
@@ -0,0 +1,17 @@
+
+#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..a856f7e
--- /dev/null
+++ b/include/asm-arm/arch-mx27/imx-regs.h
@@ -0,0 +1,504 @@
+/*
+ *
+ * (c) 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.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
+ */
+
+#ifndef _IMX_REGS_H
+#define _IMX_REGS_H
+
+/* ------------------------------------------------------------------------
+ *  Motorola IMX system registers
+ * ------------------------------------------------------------------------
+ */
+
+# ifndef __ASSEMBLY__
+# define __REG(x)	(*((volatile u32 *)(x)))
+# define __REG16(x)     (*(volatile u16 *)(x))
+# define __REG2(x,y)    (*(volatile u32 *)((u32)&__REG(x) + (y)))
+
+extern void imx_gpio_mode (int gpio_mode);
+
+# else
+#  define __REG(x) (x)
+#  define __REG16(x) (x)
+#  define __REG2(x,y) ((x)+(y))
+#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)
+
+
+/* AIPI */
+#define AIPI1_PSR0	__REG(IMX_AIPI1_BASE + 0x00)
+#define AIPI1_PSR1	__REG(IMX_AIPI1_BASE + 0x04)
+#define AIPI2_PSR0	__REG(IMX_AIPI2_BASE + 0x00)
+#define AIPI2_PSR1	__REG(IMX_AIPI2_BASE + 0x04)
+
+/* System Control */
+#define FMCR	__REG(IMX_SYSTEM_CTL_BASE + 0x14)
+#define GPCR	__REG(IMX_SYSTEM_CTL_BASE + 0x18)
+#define WBCR	__REG(IMX_SYSTEM_CTL_BASE + 0x1C)
+#define DSCR1	__REG(IMX_SYSTEM_CTL_BASE + 0x20)
+#define DSCR2	__REG(IMX_SYSTEM_CTL_BASE + 0x24)
+#define DSCR3	__REG(IMX_SYSTEM_CTL_BASE + 0x28)
+#define DSCR4	__REG(IMX_SYSTEM_CTL_BASE + 0x2C)
+#define DSCR5	__REG(IMX_SYSTEM_CTL_BASE + 0x30)
+#define DSCR6	__REG(IMX_SYSTEM_CTL_BASE + 0x34)
+#define DSCR7	__REG(IMX_SYSTEM_CTL_BASE + 0x38)
+#define DSCR8	__REG(IMX_SYSTEM_CTL_BASE + 0x3C)
+#define DSCR9	__REG(IMX_SYSTEM_CTL_BASE + 0x40)
+#define DSCR10	__REG(IMX_SYSTEM_CTL_BASE + 0x44)
+#define DSCR11	__REG(IMX_SYSTEM_CTL_BASE + 0x48)
+#define DSCR12	__REG(IMX_SYSTEM_CTL_BASE + 0x4C)
+#define DSCR13	__REG(IMX_SYSTEM_CTL_BASE + 0x50)
+#define PSCR	__REG(IMX_SYSTEM_CTL_BASE + 0x54)
+#define PMCR	__REG(IMX_SYSTEM_CTL_BASE + 0x58)
+#define DCVR0	__REG(IMX_SYSTEM_CTL_BASE + 0x60)
+#define DCVR1	__REG(IMX_SYSTEM_CTL_BASE + 0x64)
+#define DCVR2	__REG(IMX_SYSTEM_CTL_BASE + 0x68)
+#define DCVR3	__REG(IMX_SYSTEM_CTL_BASE + 0x6C)
+
+/* 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)
+
+
+/* Chip Select Registers */
+#define CS0U __REG(IMX_WEIM_BASE + 0x00) /* Chip Select 0 Upper Register    */
+#define CS0L __REG(IMX_WEIM_BASE + 0x04) /* Chip Select 0 Lower Register    */
+#define CS0A __REG(IMX_WEIM_BASE + 0x08) /* Chip Select 0 Addition Register */
+#define CS1U __REG(IMX_WEIM_BASE + 0x10) /* Chip Select 1 Upper Register    */
+#define CS1L __REG(IMX_WEIM_BASE + 0x14) /* Chip Select 1 Lower Register    */
+#define CS1A __REG(IMX_WEIM_BASE + 0x18) /* Chip Select 1 Addition Register */
+#define CS2U __REG(IMX_WEIM_BASE + 0x20) /* Chip Select 2 Upper Register    */
+#define CS2L __REG(IMX_WEIM_BASE + 0x24) /* Chip Select 2 Lower Register    */
+#define CS2A __REG(IMX_WEIM_BASE + 0x28) /* Chip Select 2 Addition Register */
+#define CS3U __REG(IMX_WEIM_BASE + 0x30) /* Chip Select 3 Upper Register    */
+#define CS3L __REG(IMX_WEIM_BASE + 0x34) /* Chip Select 3 Lower Register    */
+#define CS3A __REG(IMX_WEIM_BASE + 0x38) /* Chip Select 3 Addition Register */
+#define CS4U __REG(IMX_WEIM_BASE + 0x40) /* Chip Select 4 Upper Register    */
+#define CS4L __REG(IMX_WEIM_BASE + 0x44) /* Chip Select 4 Lower Register    */
+#define CS4A __REG(IMX_WEIM_BASE + 0x48) /* Chip Select 4 Addition Register */
+#define CS5U __REG(IMX_WEIM_BASE + 0x50) /* Chip Select 5 Upper Register    */
+#define CS5L __REG(IMX_WEIM_BASE + 0x54) /* Chip Select 5 Lower Register    */
+#define CS5A __REG(IMX_WEIM_BASE + 0x58) /* Chip Select 5 Addition Register */
+#define EIM  __REG(IMX_WEIM_BASE + 0x60) /* WEIM Configuration Register     */
+
+/* SDRAM Controller registers */
+#define ESDCTL0_ROF	0x00
+#define ESDCFG0_ROF	0x04
+#define ESDCTL1_ROF	0x08
+#define ESDCFG1_ROF	0x0C
+#define ESDMISC_ROF	0x10
+/* Enhanced SDRAM Control Register 0 */
+#define ESDCTL0 __REG(IMX_ESD_BASE + ESDCTL0_ROF)
+/* Enhanced SDRAM Configuration Register 0 */
+#define ESDCFG0 __REG(IMX_ESD_BASE + ESDCFG0_ROF)
+/* Enhanced SDRAM Control Register 1 */
+#define ESDCTL1 __REG(IMX_ESD_BASE + ESDCTL1_ROF)
+/* Enhanced SDRAM Configuration Register 1 */
+#define ESDCFG1 __REG(IMX_ESD_BASE + ESDCFG1_ROF)
+/* Enhanced SDRAM Miscellanious Register */
+#define ESDMISC __REG(IMX_ESD_BASE + ESDMISC_ROF)
+
+/* Watchdog Registers*/
+#define WCR  __REG16(IMX_WDT_BASE + 0x00) /* Watchdog Control Register */
+#define WSR  __REG16(IMX_WDT_BASE + 0x04) /* Watchdog Service Register */
+#define WSTR __REG16(IMX_WDT_BASE + 0x08) /* Watchdog Status Register  */
+
+/* important definition of some bits of WCR */
+#define WCR_WDE 0x04
+
+/* PLL registers */
+#define CSCR		__REG(IMX_PLL_BASE + 0x00) /* Clock Source Control Register       */
+#define MPCTL0		__REG(IMX_PLL_BASE + 0x04) /* MCU PLL Control Register 0          */
+#define MPCTL1		__REG(IMX_PLL_BASE + 0x08) /* MCU PLL Control Register 1          */
+#define SPCTL0		__REG(IMX_PLL_BASE + 0x0c) /* System PLL Control Register 0       */
+#define SPCTL1		__REG(IMX_PLL_BASE + 0x10) /* System PLL Control Register 1       */
+#define OSC26MCTL	__REG(IMX_PLL_BASE + 0x14) /* Oscillator 26M Register             */
+#define PCDR0		__REG(IMX_PLL_BASE + 0x18) /* Peripheral Clock Divider Register 0 */
+#define PCDR1		__REG(IMX_PLL_BASE + 0x1c) /* Peripheral Clock Divider Register 1 */
+#define PCCR0		__REG(IMX_PLL_BASE + 0x20) /* Peripheral Clock Control Register 0 */
+#define PCCR1		__REG(IMX_PLL_BASE + 0x24) /* Peripheral Clock Control Register 1 */
+#define CCSR		__REG(IMX_PLL_BASE + 0x28) /* Clock Control Status Register       */
+
+#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)
+
+/*
+ * Definitions for the clocksource driver
+ */
+/* Part 1: Registers */
+# define GPT_TCTL   0x00
+# define GPT_TPRER  0x04
+# define GPT_TCMP   0x08
+# define GPT_TCR    0x0c
+# define GPT_TCN    0x10
+# define GPT_TSTAT  0x14
+
+/* Part 2: 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 */
+
+/*
+ *  GPIO Module and I/O Multiplexer
+ *  x = 0..3 for reg_A, reg_B, reg_C, reg_D
+ *
+ *  i.MX1 and i.MXL: 0 <= x <= 3
+ *  i.MX27         : 0 <= x <= 5
+ */
+#define PORTA 0
+#define PORTB 1
+#define PORTC 2
+#define PORTD 3
+#define PORTE 4
+#define PORTF 5
+
+#define DDIR(x)    __REG2(IMX_GPIO_BASE + 0x00, ((x) & 7) << 8)
+#define OCR1(x)    __REG2(IMX_GPIO_BASE + 0x04, ((x) & 7) << 8)
+#define OCR2(x)    __REG2(IMX_GPIO_BASE + 0x08, ((x) & 7) << 8)
+#define ICONFA1(x) __REG2(IMX_GPIO_BASE + 0x0c, ((x) & 7) << 8)
+#define ICONFA2(x) __REG2(IMX_GPIO_BASE + 0x10, ((x) & 7) << 8)
+#define ICONFB1(x) __REG2(IMX_GPIO_BASE + 0x14, ((x) & 7) << 8)
+#define ICONFB2(x) __REG2(IMX_GPIO_BASE + 0x18, ((x) & 7) << 8)
+#define DR(x)      __REG2(IMX_GPIO_BASE + 0x1c, ((x) & 7) << 8)
+#define GIUS(x)    __REG2(IMX_GPIO_BASE + 0x20, ((x) & 7) << 8)
+#define SSR(x)     __REG2(IMX_GPIO_BASE + 0x24, ((x) & 7) << 8)
+#define ICR1(x)    __REG2(IMX_GPIO_BASE + 0x28, ((x) & 7) << 8)
+#define ICR2(x)    __REG2(IMX_GPIO_BASE + 0x2c, ((x) & 7) << 8)
+#define IMR(x)     __REG2(IMX_GPIO_BASE + 0x30, ((x) & 7) << 8)
+#define ISR(x)     __REG2(IMX_GPIO_BASE + 0x34, ((x) & 7) << 8)
+#define GPR(x)     __REG2(IMX_GPIO_BASE + 0x38, ((x) & 7) << 8)
+#define SWR(x)     __REG2(IMX_GPIO_BASE + 0x3c, ((x) & 7) << 8)
+#define PUEN(x)    __REG2(IMX_GPIO_BASE + 0x40, ((x) & 7) << 8)
+
+#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)
+
+/* IIM Control Registers */
+#define IIM_STAT	__REG(IMX_IIM_BASE + 0x00)
+#define IIM_STAT_BUSY	(1 << 7)
+#define IIM_STAT_PRGD	(1 << 1)
+#define IIM_STAT_SNSD	(1 << 0)
+#define IIM_STATM	__REG(IMX_IIM_BASE + 0x04)
+#define IIM_ERR		__REG(IMX_IIM_BASE + 0x08)
+#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)
+#define IIM_EMASK	__REG(IMX_IIM_BASE + 0x0C)
+#define IIM_FCTL	__REG(IMX_IIM_BASE + 0x10)
+#define IIM_UA		__REG(IMX_IIM_BASE + 0x14)
+#define IIM_LA		__REG(IMX_IIM_BASE + 0x18)
+#define IIM_SDAT	__REG(IMX_IIM_BASE + 0x1C)
+#define IIM_PREV	__REG(IMX_IIM_BASE + 0x20)
+#define IIM_SREV	__REG(IMX_IIM_BASE + 0x24)
+#define IIM_PROG_P	__REG(IMX_IIM_BASE + 0x28)
+#define IIM_SCS0	__REG(IMX_IIM_BASE + 0x2C)
+#define IIM_SCS1	__REG(IMX_IIM_BASE + 0x30)
+#define IIM_SCS2	__REG(IMX_IIM_BASE + 0x34)
+#define IIM_SCS3	__REG(IMX_IIM_BASE + 0x38)
+#define IIM_BANK_AREA	IMX_IIM_BASE + 0x800
+#define IIM_BANK_REG(x,y) __REG2(IIM_BANK_AREA + 0x400 * x, y<<2)
+/* 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] 49+ messages in thread

* [U-Boot] [PATCH 02/10] serial_mx31: allow it to work with mx27 too
  2009-05-06 18:30 [U-Boot] [PATCH 00/10] Support for LogicPD i.MX27-LITEKIT development board Ilya Yanok
  2009-05-06 18:30 ` [U-Boot] [PATCH 01/10] mx27: basic cpu support Ilya Yanok
@ 2009-05-06 18:30 ` Ilya Yanok
  2009-05-06 21:16   ` Wolfgang Denk
  2009-05-06 18:30 ` [U-Boot] [PATCH 03/10] fec_imx27: driver for FEC ethernet controller on i.MX27 Ilya Yanok
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 49+ messages in thread
From: Ilya Yanok @ 2009-05-06 18:30 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/serial_mx31.c |   21 +++++++++++++++++++++
 1 files changed, 21 insertions(+), 0 deletions(-)

diff --git a/drivers/serial/serial_mx31.c b/drivers/serial/serial_mx31.c
index 7c0682a..acc5b7d 100644
--- a/drivers/serial/serial_mx31.c
+++ b/drivers/serial/serial_mx31.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;
-- 
1.6.0.6

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

* [U-Boot] [PATCH 03/10] fec_imx27: driver for FEC ethernet controller on i.MX27
  2009-05-06 18:30 [U-Boot] [PATCH 00/10] Support for LogicPD i.MX27-LITEKIT development board Ilya Yanok
  2009-05-06 18:30 ` [U-Boot] [PATCH 01/10] mx27: basic cpu support Ilya Yanok
  2009-05-06 18:30 ` [U-Boot] [PATCH 02/10] serial_mx31: allow it to work with mx27 too Ilya Yanok
@ 2009-05-06 18:30 ` Ilya Yanok
  2009-05-06 19:51   ` Ben Warren
  2009-05-06 21:20   ` Wolfgang Denk
  2009-05-06 18:30 ` [U-Boot] [PATCH 04/10] mxc_nand: add nand driver for MX2/MX3 Ilya Yanok
                   ` (7 subsequent siblings)
  10 siblings, 2 replies; 49+ messages in thread
From: Ilya Yanok @ 2009-05-06 18:30 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Ilya Yanok <yanok@emcraft.com>
---
 drivers/net/Makefile       |    1 +
 drivers/net/fec_imx27.c    |  795 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/fec_imx27.h    |  305 +++++++++++++++++
 drivers/net/imx27_miiphy.c |  125 +++++++
 drivers/net/imx27_miiphy.h |  157 +++++++++
 5 files changed, 1383 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/fec_imx27.c
 create mode 100644 drivers/net/fec_imx27.h
 create mode 100644 drivers/net/imx27_miiphy.c
 create mode 100644 drivers/net/imx27_miiphy.h

diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index a360a50..819e609 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -34,6 +34,7 @@ COBJS-$(CONFIG_DRIVER_CS8900) += cs8900.o
 COBJS-$(CONFIG_TULIP) += dc2114x.o
 COBJS-$(CONFIG_DRIVER_DM9000) += dm9000x.o
 COBJS-$(CONFIG_DNET) += dnet.o
+COBJS-$(CONFIG_FEC_IMX27) += fec_imx27.o imx27_miiphy.o
 COBJS-$(CONFIG_E1000) += e1000.o
 COBJS-$(CONFIG_EEPRO100) += eepro100.o
 COBJS-$(CONFIG_ENC28J60) += enc28j60.o
diff --git a/drivers/net/fec_imx27.c b/drivers/net/fec_imx27.c
new file mode 100644
index 0000000..25299b9
--- /dev/null
+++ b/drivers/net/fec_imx27.c
@@ -0,0 +1,795 @@
+/*
+ * (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
+ */
+
+/************************** TODO eth_register + cleanup gfec !! *****/
+
+
+#include <common.h>
+#include <malloc.h>
+#include <net.h>
+#include "imx27_miiphy.h"
+#include "fec_imx27.h"
+
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/io.h>
+
+#define CONFIG_PHY_ADDR	0
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if !(defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
+#error "CONFIG_MII has to be defined!"
+#endif
+
+//#define CONFIG_FEC_IMX27_DEBUG
+#ifdef CONFIG_FEC_IMX27_DEBUG
+#define	PRINTF(fmt,args...)	printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+static int fec_miiphy_read(struct miiphy_device *mdev, uint8_t phyAddr,
+	uint8_t regAddr, uint16_t * retVal);
+static int fec_miiphy_write(struct miiphy_device *mdev, uint8_t phyAddr,
+	uint8_t regAddr, uint16_t data);
+
+typedef struct {
+	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) */
+} NBUF;
+
+fec_priv gfec=
+{
+	.eth       = (ethernet_regs *)IMX_FEC_BASE,
+	.xcv_type  = MII100,
+	.rbd_base  = NULL,
+	.rbd_index = 0,
+	.tbd_base  = NULL,
+	.tbd_index = 0,
+	.miiphy =
+		{
+			CONFIG_PHY_ADDR,
+			fec_miiphy_read,
+			fec_miiphy_write,
+			0,
+			NULL
+		},
+	.bd        = NULL,
+};
+
+/*
+ * MII-interface related functions
+ */
+static int fec_miiphy_read(struct miiphy_device *mdev, uint8_t phyAddr,
+	uint8_t regAddr, uint16_t * retVal)
+{
+	struct eth_device *edev = mdev->edev;
+	fec_priv *fec = (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(); /* get_time_ns(); */
+	while (!(readl(&fec->eth->ievent) & FEC_IEVENT_MII)) {
+		if (get_timer (start) > (CONFIG_SYS_HZ /1000)  /* is_timeout(start, MSECOND)*/) {
+			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);
+	PRINTF("fec_miiphy_read: phy: %02x reg:%02x val:%#x\n", phyAddr, regAddr, *retVal);
+	return 0;
+}
+
+static int fec_miiphy_write(struct miiphy_device *mdev, uint8_t phyAddr,
+	uint8_t regAddr, uint16_t data)
+{
+	struct eth_device *edev = mdev->edev;
+	fec_priv *fec = (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(); /* get_time_ns(); */
+	while (!(readl(&fec->eth->ievent) & FEC_IEVENT_MII)) {
+		if (get_timer (start) > (CONFIG_SYS_HZ /1000)  /* is_timeout(start, MSECOND)*/) {
+			printf("Write MDIO failed...\n");
+			return -1;
+		}
+	}
+
+	/*
+	 * clear MII interrupt bit
+	 */
+	writel(FEC_IEVENT_MII, &fec->eth->ievent);
+	PRINTF("fec_miiphy_write: phy: %02x reg:%02x val:%#x\n", phyAddr, regAddr, data);
+
+	return 0;
+}
+
+static int fec_rx_task_enable(fec_priv *fec)
+{
+	writel(1 << 24, &fec->eth->r_des_active);
+	return 0;
+}
+
+static int fec_rx_task_disable(fec_priv *fec)
+{
+	return 0;
+}
+
+static int fec_tx_task_enable(fec_priv *fec)
+{
+	writel(1 << 24, &fec->eth->x_des_active);
+	return 0;
+}
+
+static int fec_tx_task_disable(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(fec_priv *fec, int count, int size, int once)
+{
+	int ix;
+	uint32_t p=0;
+
+	if (!once) {
+		/* reserve data memory and consider alignment */
+		p = (uint32_t)malloc(size * count + DB_DATA_ALIGNMENT);
+		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++) {
+		if (!once) {
+			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(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, 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)
+{
+	int i;
+	int uninitialized = 0;
+
+	for (i=0;i<6;i++) {
+		mac[6-1-i] = readl(&IIM_BANK_REG(0,(IIM0_MAC+i)));
+	}
+
+	/* uninitialized if all 00 */
+	if ((mac[0] == 0) && (mac[1] == 0) && (mac[2] == 0) &&
+            (mac[3] == 0) && (mac[4] == 0) && (mac[5] == 0))
+                uninitialized = 1;
+
+	/* uninitialized if all FF (could be safe) */
+        if ((mac[0] == 0xff) && (mac[1] == 0xff) && (mac[2] == 0xff) &&
+	    (mac[3] == 0xff) && (mac[4] == 0xff) && (mac[5] == 0xff))
+	        uninitialized = 1;
+
+	return uninitialized;
+}
+
+static int fec_set_hwaddr(struct eth_device *dev, unsigned char *mac)
+{
+	fec_priv *fec = (fec_priv *)dev->priv;
+//#define WTF_IS_THIS
+#ifdef WTF_IS_THIS
+	uint32_t crc = 0xffffffff;	/* initial value */
+	uint8_t currByte;			/* byte for which to compute the CRC */
+	int byte;			/* loop - counter */
+	int bit;			/* loop - counter */
+
+	/*
+	 * The algorithm used is the following:
+	 * we loop on each of the six bytes of the provided address,
+	 * and we compute the CRC by left-shifting the previous
+	 * value by one position, so that each bit in the current
+	 * byte of the address may contribute the calculation. If
+	 * the latter and the MSB in the CRC are different, then
+	 * the CRC value so computed is also ex-ored with the
+	 * "polynomium generator". The current byte of the address
+	 * is also shifted right by one bit at each iteration.
+	 * This is because the CRC generatore in hardware is implemented
+	 * as a shift-register with as many ex-ores as the radixes
+	 * in the polynomium. This suggests that we represent the
+	 * polynomiumm itself as a 32-bit constant.
+	 */
+	for (byte = 0; byte < 6; byte++) {
+		currByte = mac[byte];
+		for (bit = 0; bit < 8; bit++) {
+			if ((currByte & 0x01) ^ (crc & 0x01)) {
+				crc >>= 1;
+				crc = crc ^ 0xedb88320;
+			} else {
+				crc >>= 1;
+			}
+			currByte >>= 1;
+		}
+	}
+
+	crc = crc >> 26;
+
+	/*
+	 * Set individual hash table register
+	 */
+	if (crc >= 32) {
+		fec->eth->iaddr1 = (1 << (crc - 32));
+		fec->eth->iaddr2 = 0;
+	} else {
+		fec->eth->iaddr1 = 0;
+		fec->eth->iaddr2 = (1 << crc);
+	}
+#else
+	writel(0, &fec->eth->iaddr1);
+	writel(0, &fec->eth->iaddr2);
+	writel(0, &fec->eth->gaddr1);
+	writel(0, &fec->eth->gaddr2);
+#endif
+	/*
+	 * 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)
+{
+	fec_priv *fec = (fec_priv *)edev->priv;
+
+	PRINTF("fec_open: fec_open(dev)\n");
+	writel(1 << 2, &fec->eth->x_cntrl);	/* full-duplex, heartbeat disabled */
+	fec->rbd_index = 0;
+
+	/*
+	 * Enable FEC-Lite controller
+	 */
+	writel(FEC_ECNTRL_ETHER_EN, &fec->eth->ecntrl);
+
+	if (fec->xcv_type != SEVENWIRE) {
+		miiphy_wait_aneg(&fec->miiphy);
+		miiphy_print_status(&fec->miiphy);
+	}
+
+	/*
+	 * Enable SmartDMA receive task
+	 */
+	fec_rx_task_enable(fec);
+
+	udelay(100000);
+	return 0;
+}
+
+static int fec_init(struct eth_device *dev, bd_t* bd)
+{
+	static int once = 0;
+	uint32_t base;
+	fec_priv *fec = (fec_priv *)dev->priv;
+
+	if( !once )
+	{
+		/*
+		 * reserve memory for both buffer descriptor chains at once
+		 * Datasheet forces the startaddress of each chain is 16 byte aligned
+		 */
+		base = (uint32_t)malloc( (2 + FEC_RBD_NUM) * sizeof(FEC_BD) + DB_ALIGNMENT );
+		memset((void *)base, 0, (2 + FEC_RBD_NUM) * sizeof(FEC_BD) + DB_ALIGNMENT);
+		base += (DB_ALIGNMENT-1);
+		base &= ~(DB_ALIGNMENT-1);
+
+		fec->rbd_base = (FEC_BD*)base;
+
+		base += FEC_RBD_NUM * sizeof(FEC_BD);
+
+		fec->tbd_base = (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);	/* No MII for 7-wire mode */
+		PRINTF("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
+	 */
+	fec_rbd_init(fec, FEC_RBD_NUM, FEC_MAX_PKT_SIZE, once);
+	fec_tbd_init(fec);
+
+
+	if (fec->xcv_type != SEVENWIRE)
+		miiphy_restart_aneg(&fec->miiphy);
+
+	once = 1;	/* malloc done now (and once) */
+
+	fec_open(dev);
+	return 0;
+}
+
+/**
+ * Halt the FEC engine
+ * @param[in] dev Our device to handle
+ */
+static void fec_halt(struct eth_device *dev)
+{
+	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);
+
+	PRINTF("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;
+	PRINTF("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.
+	 */
+	fec_priv *fec = (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 transmitt buffer
+	 * Note: We are always using the first buffer for transmission,
+	 * the second will be empty and only used to stop the DMA engine
+	 */
+/*	{
+		int i;
+		PRINTF("fec_send %d bytes:", length);
+			for (i=0;i<length;i++)
+				PRINTF(" %02x", ((char*)packet)[i]);
+			PRINTF("\n");
+	}
+*/	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 */
+	}
+	PRINTF("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)
+{
+	fec_priv *fec = (fec_priv *)dev->priv;
+	FEC_BD *rbd = &fec->rbd_base[fec->rbd_index];
+	unsigned long ievent;
+	int frame_length, len = 0;
+	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);
+	PRINTF("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);
+	PRINTF("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 = (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);
+/*			PRINTF("fec_recv %d bytes:", frame_length);
+			for (len=0;len<frame_length;len++)
+				PRINTF(" %02x", buff[len]);
+			PRINTF("\n");
+*/			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;
+	}
+	PRINTF("fec_recv: stop\n");
+
+	return len;
+}
+
+static int fec_probe(bd_t * bd)
+{
+	/*struct fec_platform_data *pdata = (struct fec_platform_data *)dev->platform_data;*/
+	struct eth_device *edev;
+	fec_priv *fec = &gfec;
+	unsigned char ethaddr_str[20];
+	unsigned char ethaddr[6];
+	char *tmp = getenv ("ethaddr");
+	char *end;
+
+	/* enable FEC clock */
+	PCCR1 |= PCCR1_HCLK_FEC;
+	PCCR0 |= PCCR0_FEC_EN;
+
+	/*create and fill edev struct*/
+	edev = (struct eth_device *)malloc(sizeof(struct eth_device));
+	edev->priv = fec;
+	edev->init = fec_init;
+	edev->send = fec_send;
+	edev->recv = fec_recv;
+	edev->halt = fec_halt;
+
+	fec->eth = (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; /*pdata->xcv_type;*/
+
+	sprintf(edev->name, "FEC ETHERNET");
+
+	if (fec->xcv_type != SEVENWIRE) {
+		fec->miiphy.read = fec_miiphy_read;
+		fec->miiphy.write = fec_miiphy_write;
+		fec->miiphy.address = CONFIG_PHY_ADDR;
+		fec->miiphy.flags = fec->xcv_type == MII10 ? MIIPHY_FORCE_10 : 0;
+		fec->miiphy.edev = edev;
+
+		/* if multiple PHY have to be supported */
+		/*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) {
+		sprintf ((char*)ethaddr_str, "%02X:%02X:%02X:%02X:%02X:%02X",
+			ethaddr[0], ethaddr[1], ethaddr[2], ethaddr[3],
+			ethaddr[4], ethaddr[5]);
+		printf("got MAC address from EEPROM: %s\n",ethaddr_str);
+		setenv ("ethaddr", (char*)ethaddr_str);
+	}
+	memcpy(edev->enetaddr, ethaddr, 6);
+	fec_set_hwaddr(edev, ethaddr);
+
+	return 0;
+}
+
+static int once = 0;
+
+int eth_init(bd_t * bd)
+{
+
+	if (!once)
+	{
+		PRINTF("eth_init: fec_probe(bd)\n");
+		fec_probe(bd);
+		once = 1;
+	}
+	PRINTF("eth_init: fec_init(gfec.miiphy.edev, bd)\n");
+	return fec_init(gfec.miiphy.edev, bd);
+};
+
+int fec_eth_initialize(bd_t *bd)
+{
+int lout=1;
+
+	if (!once)
+	{
+		PRINTF("eth_init: fec_probe(bd)\n");
+		lout = fec_probe(bd);
+		once = 1;
+	}
+	return lout;
+}
+
+int eth_send(volatile void *packet, int length)
+{
+	PRINTF("eth_send: fec_send(gfec.miiphy.edev, packet 0x%08lx, length)\n", packet);
+	return fec_send(gfec.miiphy.edev, packet, length);
+};
+
+int eth_rx(void){
+	PRINTF("eth_rcv: fec_rcv(gfec.miiphy.edev)\n");
+	return fec_recv(gfec.miiphy.edev);
+};
+
+
+void eth_halt(void)
+{
+	PRINTF("eth_halt: fec_halt(gfec)\n");
+	fec_halt(NULL);
+	return;
+};
+
+/**
+ * @file
+ * @brief Network driver for FreeScale's FEC implementation.
+ * This type of hardware can be found on i.MX27 CPUs
+ */
+
diff --git a/drivers/net/fec_imx27.h b/drivers/net/fec_imx27.h
new file mode 100644
index 0000000..e47a708
--- /dev/null
+++ b/drivers/net/fec_imx27.h
@@ -0,0 +1,305 @@
+/*
+ * (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
+ */
+typedef struct ethernet_register_set {
+
+/* [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 */
+} ethernet_regs;
+
+#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)
+ */
+typedef struct buffer_descriptor {
+	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 */
+} FEC_BD;
+
+/**
+ * Supported phy types on this platform
+ */
+typedef enum {
+	SEVENWIRE,	/**< 7-wire       */
+	MII10,		/**< MII 10Mbps   */
+	MII100		/**< MII 100Mbps  */
+} xceiver_type;
+
+/**
+ * @brief i.MX27-FEC private structure
+ */
+typedef struct {
+	ethernet_regs *eth;		/**< pointer to register'S base */
+	xceiver_type xcv_type;		/**< transceiver type */
+	FEC_BD *rbd_base;		/**< RBD ring */
+	int rbd_index;			/**< next receive BD to read */
+	FEC_BD *tbd_base;		/**< TBD ring */
+	int tbd_index;			/**< next transmit BD to write */
+	struct miiphy_device miiphy;
+	bd_t * bd;
+} fec_priv;
+
+/**
+ * @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 */
+#define FEC_RBD_LAST		0x0800	/**< Receive BD status: Buffer is last in frame (useless here!) */
+#define FEC_RBD_MISS		0x0100	/**< Receive BD status: Miss bit for prom mode */
+#define FEC_RBD_BC		0x0080	/**< Receive BD status: The received frame is broadcast frame */
+#define FEC_RBD_MC		0x0040	/**< Receive BD status: The received frame is multicast frame */
+#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 */
+
+/**
+ * @file
+ * @brief Definitions for the FEC driver (i.MX27)
+ */
+
diff --git a/drivers/net/imx27_miiphy.c b/drivers/net/imx27_miiphy.c
new file mode 100644
index 0000000..11cf7af
--- /dev/null
+++ b/drivers/net/imx27_miiphy.c
@@ -0,0 +1,125 @@
+/*
+ * miiphy.c - generic phy abstraction
+ *
+ * (C) Copyright 2008 Eric Jarrige <eric.jarrige@armadeus.org>
+ * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * 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 version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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 "imx27_miiphy.h"
+
+int miiphy_restart_aneg(struct miiphy_device *mdev)
+{
+	uint16_t status;
+	int timeout;
+
+	/*
+	 * Wake up from sleep if necessary
+	 * Reset PHY, then delay 300ns
+	 */
+	mdev->write(mdev, mdev->address, MII_SPECIAL, 0x00FF);
+	mdev->write(mdev, mdev->address, MII_BMCR, BMCR_RESET);
+	udelay(1000);
+
+	if (mdev->flags & MIIPHY_FORCE_10) {
+		printf("Forcing 10 Mbps ethernet link... ");
+		mdev->read(mdev, mdev->address, MII_BMSR, &status);
+		mdev->write(mdev, mdev->address, MII_BMCR, BMCR_FULLDPLX | BMCR_CTST);
+
+		timeout = 20;
+		do {	/* wait for link status to go down */
+			udelay(10000);
+			if ((timeout--) == 0) {
+#if (DEBUG & 0x2)
+				printf("hmmm, should not have waited...");
+#endif
+				break;
+			}
+			mdev->read(mdev, mdev->address, MII_BMSR, &status);
+		} while (status & BMSR_LSTATUS);
+
+	} else {	/* MII100 */
+		/*
+		 * Set the auto-negotiation advertisement register bits
+		 */
+		mdev->write(mdev, mdev->address, MII_ADVERTISE, ADVERTISE_ALL);
+		mdev->write(mdev, mdev->address, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART);
+	}
+
+	return 0;
+}
+
+int miiphy_wait_aneg(struct miiphy_device *mdev)
+{
+	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", mdev->edev->name);
+			return -1;
+		}
+
+		if (mdev->read(mdev, mdev->address, MII_BMSR, &status)) {
+			printf("%s: Autonegotiation failed. status: 0x%04x\n", mdev->edev->name, status);
+			return -1;
+		}
+	} while (!(status & BMSR_LSTATUS));
+
+	return 0;
+}
+
+int miiphy_print_status(struct miiphy_device *mdev)
+{
+	uint16_t bmsr, bmcr, lpa;
+	char *duplex;
+	int speed;
+
+	if (mdev->read(mdev, mdev->address, MII_BMSR, &bmsr) != 0)
+		goto err_out;
+	if (mdev->read(mdev, mdev->address, MII_BMCR, &bmcr) != 0)
+		goto err_out;
+	if (mdev->read(mdev, mdev->address, MII_LPA, &lpa) != 0)
+		goto err_out;
+
+	printf("%s: Link is %s", mdev->edev->name,
+			bmsr & BMSR_LSTATUS ? "up" : "down");
+
+	if (bmcr & BMCR_ANENABLE) {
+		duplex = lpa & LPA_DUPLEX ? "Full" : "Half";
+		speed = lpa & LPA_100 ? 100 : 10;
+	} else {
+		duplex = bmcr & BMCR_FULLDPLX ? "Full" : "Half";
+		speed = bmcr & BMCR_SPEED100 ? 100 : 10;
+	}
+
+	printf(" - %d/%s\n", speed, duplex);
+
+	return 0;
+err_out:
+	printf("%s: failed to read\n", mdev->edev->name);
+	return -1;
+}
+
+
+
diff --git a/drivers/net/imx27_miiphy.h b/drivers/net/imx27_miiphy.h
new file mode 100644
index 0000000..b381ea4
--- /dev/null
+++ b/drivers/net/imx27_miiphy.h
@@ -0,0 +1,157 @@
+/*
+ * linux/mii.h: definitions for MII-compatible transceivers
+ * Originally drivers/net/sunhme.h.
+ *
+ * (C) Copyright 2008 Eric Jarrige <eric.jarrige@armadeus.org>
+ * Copyright (C) 1996, 1999, 2001 David S. Miller (davem at redhat.com)
+ */
+
+#ifndef _IMX27_MII_PHY_H_
+#define _IMX27_MII_PHY_H_
+
+#include <net.h>
+
+#define MIIPHY_FORCE_10	1
+
+#define MII_BMCR            0x00        /* Basic mode control register */
+#define MII_BMSR            0x01        /* Basic mode status register  */
+#define MII_PHYSID1         0x02        /* PHYS ID 1                   */
+#define MII_PHYSID2         0x03        /* PHYS ID 2                   */
+#define MII_ADVERTISE       0x04        /* Advertisement control reg   */
+#define MII_LPA             0x05        /* Link partner ability reg    */
+#define MII_EXPANSION       0x06        /* Expansion register          */
+#define MII_CTRL1000        0x09        /* 1000BASE-T control          */
+#define MII_STAT1000        0x0a        /* 1000BASE-T status           */
+#define MII_ESTATUS	    0x0f	/* Extended Status	       */
+#define MII_SPECIAL         0x12        /* Disconnect counter          */
+#define MII_FCSCOUNTER      0x13        /* False carrier counter       */
+#define MII_NWAYTEST        0x14        /* N-way auto-neg test reg     */
+#define MII_RERRCOUNTER     0x15        /* Receive error counter       */
+#define MII_SREVISION       0x16        /* Silicon revision            */
+#define MII_RESV1           0x17        /* Reserved...                 */
+#define MII_LBRERROR        0x18        /* Lpback, rx, bypass error    */
+#define MII_PHYADDR         0x19        /* PHY address                 */
+#define MII_RESV2           0x1a        /* Reserved...                 */
+#define MII_TPISTATUS       0x1b        /* TPI status for 10mbps       */
+#define MII_NCONFIG         0x1c        /* Network interface config    */
+
+/* Basic mode control register. */
+#define BMCR_RESV               0x003f  /* Unused...                   */
+#define BMCR_SPEED1000		0x0040  /* MSB of Speed (1000)         */
+#define BMCR_CTST               0x0080  /* Collision test              */
+#define BMCR_FULLDPLX           0x0100  /* Full duplex                 */
+#define BMCR_ANRESTART          0x0200  /* Auto negotiation restart    */
+#define BMCR_ISOLATE            0x0400  /* Disconnect DP83840 from MII */
+#define BMCR_PDOWN              0x0800  /* Powerdown the DP83840       */
+#define BMCR_ANENABLE           0x1000  /* Enable auto negotiation     */
+#define BMCR_SPEED100           0x2000  /* Select 100Mbps              */
+#define BMCR_LOOPBACK           0x4000  /* TXD loopback bits           */
+#define BMCR_RESET              0x8000  /* Reset the DP83840           */
+
+/* Basic mode status register. */
+#define BMSR_ERCAP              0x0001  /* Ext-reg capability          */
+#define BMSR_JCD                0x0002  /* Jabber detected             */
+#define BMSR_LSTATUS            0x0004  /* Link status                 */
+#define BMSR_ANEGCAPABLE        0x0008  /* Able to do auto-negotiation */
+#define BMSR_RFAULT             0x0010  /* Remote fault detected       */
+#define BMSR_ANEGCOMPLETE       0x0020  /* Auto-negotiation complete   */
+#define BMSR_RESV               0x00c0  /* Unused...                   */
+#define BMSR_ESTATEN		0x0100	/* Extended Status in R15 */
+#define BMSR_100HALF2           0x0200  /* Can do 100BASE-T2 HDX */
+#define BMSR_100FULL2           0x0400  /* Can do 100BASE-T2 FDX */
+#define BMSR_10HALF             0x0800  /* Can do 10mbps, half-duplex  */
+#define BMSR_10FULL             0x1000  /* Can do 10mbps, full-duplex  */
+#define BMSR_100HALF            0x2000  /* Can do 100mbps, half-duplex */
+#define BMSR_100FULL            0x4000  /* Can do 100mbps, full-duplex */
+#define BMSR_100BASE4           0x8000  /* Can do 100mbps, 4k packets  */
+
+/* Advertisement control register. */
+#define ADVERTISE_SLCT          0x001f  /* Selector bits               */
+#define ADVERTISE_CSMA          0x0001  /* Only selector supported     */
+#define ADVERTISE_10HALF        0x0020  /* Try for 10mbps half-duplex  */
+#define ADVERTISE_1000XFULL     0x0020  /* Try for 1000BASE-X full-duplex */
+#define ADVERTISE_10FULL        0x0040  /* Try for 10mbps full-duplex  */
+#define ADVERTISE_1000XHALF     0x0040  /* Try for 1000BASE-X half-duplex */
+#define ADVERTISE_100HALF       0x0080  /* Try for 100mbps half-duplex */
+#define ADVERTISE_1000XPAUSE    0x0080  /* Try for 1000BASE-X pause    */
+#define ADVERTISE_100FULL       0x0100  /* Try for 100mbps full-duplex */
+#define ADVERTISE_1000XPSE_ASYM 0x0100  /* Try for 1000BASE-X asym pause */
+#define ADVERTISE_100BASE4      0x0200  /* Try for 100mbps 4k packets  */
+#define ADVERTISE_PAUSE_CAP     0x0400  /* Try for pause               */
+#define ADVERTISE_PAUSE_ASYM    0x0800  /* Try for asymetric pause     */
+#define ADVERTISE_RESV          0x1000  /* Unused...                   */
+#define ADVERTISE_RFAULT        0x2000  /* Say we can detect faults    */
+#define ADVERTISE_LPACK         0x4000  /* Ack link partners response  */
+#define ADVERTISE_NPAGE         0x8000  /* Next page bit               */
+
+#define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \
+			ADVERTISE_CSMA)
+#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \
+                       ADVERTISE_100HALF | ADVERTISE_100FULL)
+
+/* Link partner ability register. */
+#define LPA_SLCT                0x001f  /* Same as advertise selector  */
+#define LPA_10HALF              0x0020  /* Can do 10mbps half-duplex   */
+#define LPA_1000XFULL           0x0020  /* Can do 1000BASE-X full-duplex */
+#define LPA_10FULL              0x0040  /* Can do 10mbps full-duplex   */
+#define LPA_1000XHALF           0x0040  /* Can do 1000BASE-X half-duplex */
+#define LPA_100HALF             0x0080  /* Can do 100mbps half-duplex  */
+#define LPA_1000XPAUSE          0x0080  /* Can do 1000BASE-X pause     */
+#define LPA_100FULL             0x0100  /* Can do 100mbps full-duplex  */
+#define LPA_1000XPAUSE_ASYM     0x0100  /* Can do 1000BASE-X pause asym*/
+#define LPA_100BASE4            0x0200  /* Can do 100mbps 4k packets   */
+#define LPA_PAUSE_CAP           0x0400  /* Can pause                   */
+#define LPA_PAUSE_ASYM          0x0800  /* Can pause asymetrically     */
+#define LPA_RESV                0x1000  /* Unused...                   */
+#define LPA_RFAULT              0x2000  /* Link partner faulted        */
+#define LPA_LPACK               0x4000  /* Link partner acked us       */
+#define LPA_NPAGE               0x8000  /* Next page bit               */
+
+#define LPA_DUPLEX		(LPA_10FULL | LPA_100FULL)
+#define LPA_100			(LPA_100FULL | LPA_100HALF | LPA_100BASE4)
+
+/* Expansion register for auto-negotiation. */
+#define EXPANSION_NWAY          0x0001  /* Can do N-way auto-nego      */
+#define EXPANSION_LCWP          0x0002  /* Got new RX page code word   */
+#define EXPANSION_ENABLENPAGE   0x0004  /* This enables npage words    */
+#define EXPANSION_NPCAPABLE     0x0008  /* Link partner supports npage */
+#define EXPANSION_MFAULTS       0x0010  /* Multiple faults detected    */
+#define EXPANSION_RESV          0xffe0  /* Unused...                   */
+
+#define ESTATUS_1000_TFULL	0x2000	/* Can do 1000BT Full */
+#define ESTATUS_1000_THALF	0x1000	/* Can do 1000BT Half */
+
+/* N-way test register. */
+#define NWAYTEST_RESV1          0x00ff  /* Unused...                   */
+#define NWAYTEST_LOOPBACK       0x0100  /* Enable loopback for N-way   */
+#define NWAYTEST_RESV2          0xfe00  /* Unused...                   */
+
+/* 1000BASE-T Control register */
+#define ADVERTISE_1000FULL      0x0200  /* Advertise 1000BASE-T full duplex */
+#define ADVERTISE_1000HALF      0x0100  /* Advertise 1000BASE-T half duplex */
+
+/* 1000BASE-T Status register */
+#define LPA_1000LOCALRXOK       0x2000  /* Link partner local receiver status */
+#define LPA_1000REMRXOK         0x1000  /* Link partner remote receiver status */
+#define LPA_1000FULL            0x0800  /* Link partner 1000BASE-T full duplex */
+#define LPA_1000HALF            0x0400  /* Link partner 1000BASE-T half duplex */
+
+struct miiphy_device {
+	/*struct device_d dev;*/
+
+	int address;	/* The address the phy has on the bus */
+	int (*read)(struct miiphy_device *mdev, uint8_t phy_addr, uint8_t reg_addr, uint16_t *value);
+	int (*write)(struct miiphy_device *mdev, uint8_t phy_addr, uint8_t reg_addr, uint16_t data);
+
+	int flags;
+
+	struct eth_device *edev;
+};
+
+int miiphy_register(struct miiphy_device *mdev);
+int miiphy_restart_aneg(struct miiphy_device *mdev);
+int miiphy_wait_aneg(struct miiphy_device *mdev);
+int miiphy_print_status(struct miiphy_device *mdev);
+
+#endif
+
-- 
1.6.0.6

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

* [U-Boot] [PATCH 04/10] mxc_nand: add nand driver for MX2/MX3
  2009-05-06 18:30 [U-Boot] [PATCH 00/10] Support for LogicPD i.MX27-LITEKIT development board Ilya Yanok
                   ` (2 preceding siblings ...)
  2009-05-06 18:30 ` [U-Boot] [PATCH 03/10] fec_imx27: driver for FEC ethernet controller on i.MX27 Ilya Yanok
@ 2009-05-06 18:30 ` Ilya Yanok
  2009-05-06 20:31   ` Magnus Lilja
                     ` (2 more replies)
  2009-05-06 18:30 ` [U-Boot] [PATCH 05/10] mxc-mmc: sdhc host driver for MX2 and MX3 proccessor Ilya Yanok
                   ` (6 subsequent siblings)
  10 siblings, 3 replies; 49+ messages in thread
From: Ilya Yanok @ 2009-05-06 18:30 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 |  891 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 892 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..48a6b7b
--- /dev/null
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -0,0 +1,891 @@
+/*
+ * 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"
+
+/* Addresses for NFC registers */
+#define NFC_BUF_SIZE		0xE00
+#define NFC_BUF_ADDR		0xE04
+#define NFC_FLASH_ADDR		0xE06
+#define NFC_FLASH_CMD		0xE08
+#define NFC_CONFIG		0xE0A
+#define NFC_ECC_STATUS_RESULT	0xE0C
+#define NFC_RSLTMAIN_AREA	0xE0E
+#define NFC_RSLTSPARE_AREA	0xE10
+#define NFC_WRPROT		0xE12
+#define NFC_UNLOCKSTART_BLKADDR	0xE14
+#define NFC_UNLOCKEND_BLKADDR	0xE16
+#define NFC_NF_WRPRST		0xE18
+#define NFC_CONFIG1		0xE1A
+#define NFC_CONFIG2		0xE1C
+
+/* Addresses for NFC RAM BUFFER Main area 0 */
+#define MAIN_AREA0		0x000
+#define MAIN_AREA1		0x200
+#define MAIN_AREA2		0x400
+#define MAIN_AREA3		0x600
+
+/* Addresses for NFC SPARE BUFFER Spare area 0 */
+#define SPARE_AREA0		0x800
+#define SPARE_AREA1		0x810
+#define SPARE_AREA2		0x820
+#define SPARE_AREA3		0x830
+
+/* 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_INT_MSK         (1 << 4)
+#define NFC_BIG             (1 << 5)
+#define NFC_RST             (1 << 6)
+#define NFC_CE              (1 << 7)
+#define NFC_ONE_CYCLE       (1 << 8)
+
+typedef enum _bool{false,true} bool;
+
+struct mxc_nand_host {
+	struct mtd_info		mtd;
+	struct nand_chip	*nand;
+
+	void __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_memcpy(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, int useirq)
+{
+	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, int useirq)
+{
+	MTDDEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x, %d)\n", cmd, useirq);
+
+	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, useirq);
+}
+
+/* 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, int islast)
+{
+	MTDDEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x %d)\n", addr, islast);
+
+	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, islast);
+}
+
+/* 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, true);
+}
+
+/* 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, true);
+}
+
+/* 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, true);
+
+	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, true);
+
+	/* 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 = host->regs + MAIN_AREA0;
+	uint16_t __iomem *spare_buf = 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 = (host->regs + MAIN_AREA0) + (col >> 1);
+	else
+		p = (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_memcpy(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_memcpy(&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;
+	int useirq = false;
+
+	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;
+		useirq = false;
+		break;
+
+	case NAND_CMD_READOOB:
+		host->col_addr = column;
+		host->spare_only = true;
+		useirq = false;
+		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, false);
+		} 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, false);
+		}
+		useirq = false;
+		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;
+
+	case NAND_CMD_ERASE1:
+		useirq = false;
+		break;
+	}
+
+	/* Write out the command to the device. */
+	send_cmd(host, command, useirq);
+
+	/* 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, page_addr == -1);
+		if (host->pagesize_2k)
+			/* another col addr cycle for 2k page */
+			send_addr(host, 0, false);
+	}
+
+	/* Write out page address, if necessary */
+	if (page_addr != -1) {
+		/* paddr_0 - p_addr_7 */
+		send_addr(host, (page_addr & 0xff), false);
+
+		if (host->pagesize_2k) {
+			send_addr(host, (page_addr >> 8) & 0xFF, false);
+			if (mtd->size >= 0x40000000)
+				send_addr(host, (page_addr >> 16) & 0xff, true);
+		} else {
+			/* One more address cycle for higher density devices */
+			if (mtd->size >= 0x4000000) {
+				/* paddr_8 - paddr_15 */
+				send_addr(host, (page_addr >> 8) & 0xff, false);
+				send_addr(host, (page_addr >> 16) & 0xff, true);
+			} else
+				/* paddr_8 - paddr_15 */
+				send_addr(host, (page_addr >> 8) & 0xff, true);
+		}
+	}
+
+	/* 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, true);
+			/* 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:
+		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 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 = (void __iomem *)CONFIG_MXC_NAND_REGS_BASE;
+	host->clk_act = 1;
+
+	tmp = readw(host->regs + NFC_CONFIG1);
+	tmp |= NFC_INT_MSK;
+	writew(tmp, host->regs + NFC_CONFIG1);
+
+#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 (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] 49+ messages in thread

* [U-Boot] [PATCH 05/10] mxc-mmc: sdhc host driver for MX2 and MX3 proccessor
  2009-05-06 18:30 [U-Boot] [PATCH 00/10] Support for LogicPD i.MX27-LITEKIT development board Ilya Yanok
                   ` (3 preceding siblings ...)
  2009-05-06 18:30 ` [U-Boot] [PATCH 04/10] mxc_nand: add nand driver for MX2/MX3 Ilya Yanok
@ 2009-05-06 18:30 ` Ilya Yanok
  2009-05-08  0:26   ` alfred steele
  2009-05-13 21:50   ` alfred steele
  2009-05-06 18:30 ` [U-Boot] [PATCH 06/10] arm: add support for CONFIG_GENERIC_MMC Ilya Yanok
                   ` (5 subsequent siblings)
  10 siblings, 2 replies; 49+ messages in thread
From: Ilya Yanok @ 2009-05-06 18:30 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               |  520 ++++++++++++++++++++++++++++++++++++
 include/asm-arm/arch-mx27/mxcmmc.h |   25 ++
 4 files changed, 562 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 fdbc8b7..a0be35b 100644
--- a/cpu/arm926ejs/mx27/generic.c
+++ b/cpu/arm926ejs/mx27/generic.c
@@ -21,6 +21,9 @@
 #include <common.h>
 #include <div64.h>
 #include <asm/arch/imx-regs.h>
+#ifdef CONFIG_MXC_MMC
+#include <asm/arch/mxcmmc.h>
+#endif
 /*
  *  get the system pll clock in Hz
  *
@@ -143,6 +146,19 @@ int print_cpuinfo (void)
 }
 #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)
 {
 	unsigned int pin = gpio_mode & GPIO_PIN_MASK;
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..9635d6e
--- /dev/null
+++ b/drivers/mmc/mxcmmc.c
@@ -0,0 +1,520 @@
+/*
+ *  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"
+
+#define MMC_REG_STR_STP_CLK		0x00
+#define MMC_REG_STATUS			0x04
+#define MMC_REG_CLK_RATE		0x08
+#define MMC_REG_CMD_DAT_CONT		0x0C
+#define MMC_REG_RES_TO			0x10
+#define MMC_REG_READ_TO			0x14
+#define MMC_REG_BLK_LEN			0x18
+#define MMC_REG_NOB			0x1C
+#define MMC_REG_REV_NO			0x20
+#define MMC_REG_INT_CNTR		0x24
+#define MMC_REG_CMD			0x28
+#define MMC_REG_ARG			0x2C
+#define MMC_REG_RES_FIFO		0x34
+#define MMC_REG_BUFFER_ACCESS		0x38
+
+#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;
+	void 			*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 + MMC_REG_STR_STP_CLK);
+	writew(STR_STP_CLK_RESET | STR_STP_CLK_START_CLK,
+			host->base + MMC_REG_STR_STP_CLK);
+
+	for (i = 0; i < 8; i++)
+		writew(STR_STP_CLK_START_CLK, host->base + MMC_REG_STR_STP_CLK);
+
+	writew(0xff, host->base + MMC_REG_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 + MMC_REG_NOB);
+	writew(blksz, host->base + MMC_REG_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 + MMC_REG_CMD);
+	writel(cmd->cmdarg, host->base + MMC_REG_ARG);
+	writew(cmdat, host->base + MMC_REG_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 + MMC_REG_RES_FIFO);
+				b = readw(host->base + MMC_REG_RES_FIFO);
+				resp[i] = a << 16 | b;
+			}
+		} else {
+			a = readw(host->base + MMC_REG_RES_FIFO);
+			b = readw(host->base + MMC_REG_RES_FIFO);
+			c = readw(host->base + MMC_REG_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 + MMC_REG_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 + MMC_REG_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 + MMC_REG_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 + MMC_REG_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 + MMC_REG_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 + MMC_REG_STATUS);
+		writel(stat, host->base + MMC_REG_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 + MMC_REG_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 + MMC_REG_STR_STP_CLK);
+	} else {
+		writew(STR_STP_CLK_STOP_CLK, host->base + MMC_REG_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 + MMC_REG_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 + MMC_REG_READ_TO);
+
+	writel(0, host->base + MMC_REG_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 = (void *)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] 49+ messages in thread

* [U-Boot] [PATCH 06/10] arm: add support for CONFIG_GENERIC_MMC
  2009-05-06 18:30 [U-Boot] [PATCH 00/10] Support for LogicPD i.MX27-LITEKIT development board Ilya Yanok
                   ` (4 preceding siblings ...)
  2009-05-06 18:30 ` [U-Boot] [PATCH 05/10] mxc-mmc: sdhc host driver for MX2 and MX3 proccessor Ilya Yanok
@ 2009-05-06 18:30 ` Ilya Yanok
  2009-05-06 18:30 ` [U-Boot] [PATCH 07/10] mmc: use lldiv() for 64-bit division Ilya Yanok
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 49+ messages in thread
From: Ilya Yanok @ 2009-05-06 18:30 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..86635bd 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] 49+ messages in thread

* [U-Boot] [PATCH 07/10] mmc: use lldiv() for 64-bit division
  2009-05-06 18:30 [U-Boot] [PATCH 00/10] Support for LogicPD i.MX27-LITEKIT development board Ilya Yanok
                   ` (5 preceding siblings ...)
  2009-05-06 18:30 ` [U-Boot] [PATCH 06/10] arm: add support for CONFIG_GENERIC_MMC Ilya Yanok
@ 2009-05-06 18:30 ` Ilya Yanok
  2009-05-06 20:32   ` Magnus Lilja
  2009-05-08 22:42   ` Andy Fleming
  2009-05-06 18:30 ` [U-Boot] [PATCH 08/10] mmc: some endianess fixes for generic mmc subsystem Ilya Yanok
                   ` (3 subsequent siblings)
  10 siblings, 2 replies; 49+ messages in thread
From: Ilya Yanok @ 2009-05-06 18:30 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Ilya Yanok <yanok@emcraft.com>
---
 drivers/mmc/mmc.c |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 7791c38..77a9aea 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -31,6 +31,7 @@
 #include <malloc.h>
 #include <linux/list.h>
 #include <mmc.h>
+#include <div64.h>
 
 static struct list_head mmc_devices;
 static int cur_dev_num = -1;
@@ -155,8 +156,8 @@ int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size)
 	char *buffer;
 	int i;
 	int blklen = mmc->read_bl_len;
-	int startblock = src / blklen;
-	int endblock = (src + size - 1) / blklen;
+	int startblock = lldiv(src, blklen);
+	int endblock = lldiv((src + size - 1), blklen);
 	int err = 0;
 
 	/* Make a buffer big enough to hold all the blocks we might read */
@@ -789,7 +790,7 @@ int mmc_startup(struct mmc *mmc)
 	mmc->block_dev.lun = 0;
 	mmc->block_dev.type = 0;
 	mmc->block_dev.blksz = mmc->read_bl_len;
-	mmc->block_dev.lba = mmc->capacity/mmc->read_bl_len;
+	mmc->block_dev.lba = lldiv(mmc->capacity,mmc->read_bl_len);
 	sprintf(mmc->block_dev.vendor,"Man %02x%02x%02x Snr %02x%02x%02x%02x",
 			mmc->cid[0], mmc->cid[1], mmc->cid[2],
 			mmc->cid[9], mmc->cid[10], mmc->cid[11], mmc->cid[12]);
-- 
1.6.0.6

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

* [U-Boot] [PATCH 08/10] mmc: some endianess fixes for generic mmc subsystem
  2009-05-06 18:30 [U-Boot] [PATCH 00/10] Support for LogicPD i.MX27-LITEKIT development board Ilya Yanok
                   ` (6 preceding siblings ...)
  2009-05-06 18:30 ` [U-Boot] [PATCH 07/10] mmc: use lldiv() for 64-bit division Ilya Yanok
@ 2009-05-06 18:30 ` Ilya Yanok
  2009-05-08 22:43   ` Andy Fleming
  2009-05-06 18:30 ` [U-Boot] [PATCH 09/10] mmc: fix mmcinfo command Ilya Yanok
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 49+ messages in thread
From: Ilya Yanok @ 2009-05-06 18:30 UTC (permalink / raw)
  To: u-boot

We save response in the cpu order so we need to parse it in the
cpu order too. Things fixed by this patch:
1. OCR_BUSY should be the highest bit in 32-bit response.
2. Proper "tran speed" calculation on LE systems (tran_exp and
   tran_mant should be in 96..98 and 99..102 bits of 128-bit
   response respectively).
3. Proper MMC version detection.

Signed-off-by: Ilya Yanok <yanok@emcraft.com>
---
 drivers/mmc/mmc.c |   10 +++++-----
 include/mmc.h     |    2 +-
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 77a9aea..f7a989b 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -284,7 +284,7 @@ sd_send_op_cond(struct mmc *mmc)
 			return err;
 
 		udelay(1000);
-	} while ((!(cmd.response[0] & OCR_BUSY)) && timeout--);
+	} while ((!(((uint *)cmd.response)[0] & OCR_BUSY)) && timeout--);
 
 	if (timeout <= 0)
 		return UNUSABLE_ERR;
@@ -321,7 +321,7 @@ int mmc_send_op_cond(struct mmc *mmc)
 			return err;
 
 		udelay(1000);
-	} while (!(cmd.response[0] & OCR_BUSY) && timeout--);
+	} while (!(((uint *)cmd.response)[0] & OCR_BUSY) && timeout--);
 
 	if (timeout <= 0)
 		return UNUSABLE_ERR;
@@ -651,7 +651,7 @@ int mmc_startup(struct mmc *mmc)
 	mmc->csd[3] = ((uint *)(cmd.response))[3];
 
 	if (mmc->version == MMC_VERSION_UNKNOWN) {
-		int version = (cmd.response[0] >> 2) & 0xf;
+		int version = (mmc->csd[0] >> 26) & 0xf;
 
 		switch (version) {
 			case 0:
@@ -676,8 +676,8 @@ int mmc_startup(struct mmc *mmc)
 	}
 
 	/* divide frequency by 10, since the mults are 10x bigger */
-	freq = fbase[(cmd.response[3] & 0x7)];
-	mult = multipliers[((cmd.response[3] >> 3) & 0xf)];
+	freq = fbase[(mmc->csd[0] & 0x7)];
+	mult = multipliers[((mmc->csd[0] >> 3) & 0xf)];
 
 	mmc->tran_speed = freq * mult;
 
diff --git a/include/mmc.h b/include/mmc.h
index b9b27ba..64764cb 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -91,7 +91,7 @@
 #define MMC_HS_TIMING		0x00000100
 #define MMC_HS_52MHZ		0x2
 
-#define OCR_BUSY	0x80
+#define OCR_BUSY	0x80000000
 #define OCR_HCS		0x40000000
 
 #define MMC_VDD_165_195		0x00000080	/* VDD voltage 1.65 - 1.95 */
-- 
1.6.0.6

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

* [U-Boot] [PATCH 09/10] mmc: fix mmcinfo command
  2009-05-06 18:30 [U-Boot] [PATCH 00/10] Support for LogicPD i.MX27-LITEKIT development board Ilya Yanok
                   ` (7 preceding siblings ...)
  2009-05-06 18:30 ` [U-Boot] [PATCH 08/10] mmc: some endianess fixes for generic mmc subsystem Ilya Yanok
@ 2009-05-06 18:30 ` Ilya Yanok
  2009-05-08 22:43   ` Andy Fleming
  2009-05-06 18:30 ` [U-Boot] [PATCH 10/10] imx27lite: add support for imx27lite board from LogicPD Ilya Yanok
  2009-05-06 21:26 ` [U-Boot] [PATCH 00/10] Support for LogicPD i.MX27-LITEKIT development board Wolfgang Denk
  10 siblings, 1 reply; 49+ messages in thread
From: Ilya Yanok @ 2009-05-06 18:30 UTC (permalink / raw)
  To: u-boot

cid field of stuct mmc stucture is char*, not u32*. so we need to
convert the pointer for mmcinfo code to work correctly.

Signed-off-by: Ilya Yanok <yanok@emcraft.com>
---
 common/cmd_mmc.c |   11 ++++++-----
 1 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c
index f1fa32f..21b7004 100644
--- a/common/cmd_mmc.c
+++ b/common/cmd_mmc.c
@@ -95,12 +95,13 @@ U_BOOT_CMD(
 
 static void print_mmcinfo(struct mmc *mmc)
 {
+	u32 *cid = mmc->cid;
 	printf("Device: %s\n", mmc->name);
-	printf("Manufacturer ID: %x\n", mmc->cid[0] >> 24);
-	printf("OEM: %x\n", (mmc->cid[0] >> 8) & 0xffff);
-	printf("Name: %c%c%c%c%c \n", mmc->cid[0] & 0xff,
-			(mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff,
-			(mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff);
+	printf("Manufacturer ID: %x\n", cid[0] >> 24);
+	printf("OEM: %x\n", (cid[0] >> 8) & 0xffff);
+	printf("Name: %c%c%c%c%c \n", cid[0] & 0xff,
+			(cid[1] >> 24), (cid[1] >> 16) & 0xff,
+			(cid[1] >> 8) & 0xff, cid[1] & 0xff);
 
 	printf("Tran Speed: %d\n", mmc->tran_speed);
 	printf("Rd Block Len: %d\n", mmc->read_bl_len);
-- 
1.6.0.6

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

* [U-Boot] [PATCH 10/10] imx27lite: add support for imx27lite board from LogicPD
  2009-05-06 18:30 [U-Boot] [PATCH 00/10] Support for LogicPD i.MX27-LITEKIT development board Ilya Yanok
                   ` (8 preceding siblings ...)
  2009-05-06 18:30 ` [U-Boot] [PATCH 09/10] mmc: fix mmcinfo command Ilya Yanok
@ 2009-05-06 18:30 ` Ilya Yanok
  2009-05-06 20:34   ` Magnus Lilja
                     ` (2 more replies)
  2009-05-06 21:26 ` [U-Boot] [PATCH 00/10] Support for LogicPD i.MX27-LITEKIT development board Wolfgang Denk
  10 siblings, 3 replies; 49+ messages in thread
From: Ilya Yanok @ 2009-05-06 18:30 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>
---
 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 |  225 +++++++++++++++++++++++++++++++
 board/logicpd/imx27lite/u-boot.lds      |   56 ++++++++
 include/configs/imx27lite.h             |  188 ++++++++++++++++++++++++++
 8 files changed, 622 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/MAKEALL b/MAKEALL
index f13c81a..4806512 100755
--- a/MAKEALL
+++ b/MAKEALL
@@ -504,6 +504,7 @@ LIST_ARM9="			\
 	cp946es			\
 	cp966			\
 	lpd7a400		\
+	imx27lite		\
 	mx1ads			\
 	mx1fs2			\
 	netstar			\
diff --git a/Makefile b/Makefile
index 137c88f..0c52bfa 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..48c7fe6
--- /dev/null
+++ b/board/logicpd/imx27lite/lowlevel_init.S
@@ -0,0 +1,225 @@
+/*
+ * 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>
+
+#define CFG_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 CFG_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 CFG_SDRAM_ALL_VAL		0xf00
+
+#define CFG_SDRAM_MODE_REGISTER_VAL	0x33	/* BL: 8, CAS: 3 */
+#define CFG_SDRAM_EXT_MODE_REGISTER_VAL	0x1000000
+
+#define CFG_MPCTL0_VAL	0x1ef15d5
+
+#define CFG_SPCTL0_VAL	0x043a1c09
+
+#define CFG_CSCR_VAL	0x33f08107
+
+#define CFG_PCDR0_VAL	0x120470c3
+#define CFG_PCDR1_VAL	0x03030303
+#define CFG_PCCR0_VAL	0xffffffff
+#define CFG_PCCR1_VAL	0xfffffffc
+
+#define CFG_AIPI1_PSR0_VAL	0x20040304
+#define CFG_AIPI1_PSR1_VAL	0xdffbfcfb
+#define CFG_AIPI2_PSR0_VAL	0x07ffc200
+#define CFG_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	CFG_SDRAM_ESDCFG_REGISTER_VAL(0)
+SDRAM_ESDCFG_T2_W:	.word	CFG_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	CFG_SDRAM_ESDCTL_REGISTER_VAL
+
+	.macro init_aipi
+	/*
+	 * setup AIPI1 and AIPI2
+	 */
+	writel(AIPI1_PSR0, CFG_AIPI1_PSR0_VAL)
+	writel(AIPI1_PSR1, CFG_AIPI1_PSR1_VAL)
+	writel(AIPI2_PSR0, CFG_AIPI2_PSR0_VAL)
+	writel(AIPI2_PSR1, CFG_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]
+
+	/*
+	 * pll clock initialization predefined in apf27.h
+	 */
+	writel(MPCTL0, CFG_MPCTL0_VAL)
+	writel(SPCTL0, CFG_SPCTL0_VAL)
+
+	writel(CSCR, CFG_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, CFG_PCDR0_VAL)
+	writel(PCDR1, CFG_PCDR1_VAL)
+
+	/* Configure PCCR0 and PCCR1 */
+	writel(PCCR0, CFG_PCCR0_VAL)
+	writel(PCCR1, CFG_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, #CFG_SDRAM_ALL_VAL]
+
+	ldr r1, SDRAM_AUTOREF_CMD_W
+	str r1, [r0, #ESDCTL0_ROF]
+	ldr r1, [r2, #CFG_SDRAM_ALL_VAL]
+	ldr r1, [r2, #CFG_SDRAM_ALL_VAL]
+
+	ldr r1, SDRAM_LOADMODE_CMD_W
+	str r1, [r0, #ESDCTL0_ROF]
+	ldrb r1, [r2, #CFG_SDRAM_MODE_REGISTER_VAL]
+	add r3, r2, #CFG_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, #CFG_SDRAM_ALL_VAL]
+
+	ldr r1, SDRAM_AUTOREF_CMD_W
+	str r1, [r0, #ESDCTL1_ROF]
+	ldr r1, [r2, #CFG_SDRAM_ALL_VAL]
+	ldr r1, [r2, #CFG_SDRAM_ALL_VAL]
+
+	ldr r1, SDRAM_LOADMODE_CMD_W
+	str r1, [r0, #ESDCTL1_ROF]
+	ldrb r1, [r2, #CFG_SDRAM_MODE_REGISTER_VAL]
+	add r3, r2, #CFG_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..80fb291
--- /dev/null
+++ b/include/configs/imx27lite.h
@@ -0,0 +1,188 @@
+/*
+ * 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_MX31_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 */
+/*=============*/
+#define CONFIG_SYS_MALLOC_LEN		(0x10000 + 128*1024)	/* malloc() len */
+#define CONFIG_SYS_GBL_DATA_SIZE	128		/* reserved for initial data */
+#define CONFIG_SYS_MEMTEST_START	0xA0000000	/* memtest start address */
+#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_MX31_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 */
+#define CONFIG_ENV_OFFSET		(PHYS_FLASH_SIZE - 0x20000)	/* end of flash */
+#define PHYS_FLASH_1			0xc0000000	/* CS2 Base address	 */
+#define CONFIG_SYS_FLASH_BASE		PHYS_FLASH_1	/* Flash Base for U-Boot */
+#define PHYS_FLASH_SIZE			0x200000	/* Flash size 2MB	 */
+#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
+/*
+ * 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
+/*
+ * SD/MMC
+ */
+#define CONFIG_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_MXC_MMC
+#define CONFIG_MXC_MCI_REGS_BASE	0x10014000
+#define CONFIG_DOS_PARTITION
+/*
+ * JFFS2 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:-(nand)"
+
+/*==============================*/
+/* 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 */
+#define CONFIG_SYS_BARGSIZE	CONFIG_SYS_CBSIZE	/* Boot Argument Buffer Size */
+#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_NET
+#undef CONFIG_CMD_NFS
+#define CONFIG_CMD_MII
+#define CONFIG_CMD_PING
+#undef CONFIG_CMD_BDI
+#undef CONFIG_CMD_FPGA
+#undef CONFIG_CMD_SETGETDCR
+#define CONFIG_CMD_NAND
+#define CONFIG_CMD_JFFS2
+#define CONFIG_CMD_MMC
+#define CONFIG_CMD_FAT
+
+/*
+ * You can compile in a MAC address and your custom net settings by using
+ * the following syntax.
+ *
+ * #define CONFIG_ETHADDR		xx:xx:xx:xx:xx:xx
+ * #define CONFIG_SERVERIP		<server ip>
+ * #define CONFIG_IPADDR		<board ip>
+ * #define CONFIG_GATEWAYIP		<gateway ip>
+ * #define CONFIG_NETMASK		<your netmask>
+ */
+
+#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] 49+ messages in thread

* [U-Boot] [PATCH 03/10] fec_imx27: driver for FEC ethernet controller on i.MX27
  2009-05-06 18:30 ` [U-Boot] [PATCH 03/10] fec_imx27: driver for FEC ethernet controller on i.MX27 Ilya Yanok
@ 2009-05-06 19:51   ` Ben Warren
  2009-05-06 21:20   ` Wolfgang Denk
  1 sibling, 0 replies; 49+ messages in thread
From: Ben Warren @ 2009-05-06 19:51 UTC (permalink / raw)
  To: u-boot

Hi Ilya,

Ilya Yanok wrote:
> Signed-off-by: Ilya Yanok <yanok@emcraft.com>
> ---
>  drivers/net/Makefile       |    1 +
>  drivers/net/fec_imx27.c    |  795 ++++++++++++++++++++++++++++++++++++++++++++
>  drivers/net/fec_imx27.h    |  305 +++++++++++++++++
>  drivers/net/imx27_miiphy.c |  125 +++++++
>  drivers/net/imx27_miiphy.h |  157 +++++++++
>  5 files changed, 1383 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/net/fec_imx27.c
>  create mode 100644 drivers/net/fec_imx27.h
>  create mode 100644 drivers/net/imx27_miiphy.c
>  create mode 100644 drivers/net/imx27_miiphy.h
>
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index a360a50..819e609 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -34,6 +34,7 @@ COBJS-$(CONFIG_DRIVER_CS8900) += cs8900.o
>  COBJS-$(CONFIG_TULIP) += dc2114x.o
>  COBJS-$(CONFIG_DRIVER_DM9000) += dm9000x.o
>  COBJS-$(CONFIG_DNET) += dnet.o
> +COBJS-$(CONFIG_FEC_IMX27) += fec_imx27.o imx27_miiphy.o
>  COBJS-$(CONFIG_E1000) += e1000.o
>  COBJS-$(CONFIG_EEPRO100) += eepro100.o
>  COBJS-$(CONFIG_ENC28J60) += enc28j60.o
> diff --git a/drivers/net/fec_imx27.c b/drivers/net/fec_imx27.c
> new file mode 100644
> index 0000000..25299b9
> --- /dev/null
> +++ b/drivers/net/fec_imx27.c
> @@ -0,0 +1,795 @@
> +/*
> + * (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
> + */
> +
> +/************************** TODO eth_register + cleanup gfec !! *****/
>   
Huh?
> +
> +
> +#include <common.h>
> +#include <malloc.h>
> +#include <net.h>
> +#include "imx27_miiphy.h"
> +#include "fec_imx27.h"
> +
> +#include <asm/arch/clock.h>
> +#include <asm/arch/imx-regs.h>
> +#include <asm/io.h>
> +
> +#define CONFIG_PHY_ADDR	0
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#if !(defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
> +#error "CONFIG_MII has to be defined!"
> +#endif
> +
> +//#define CONFIG_FEC_IMX27_DEBUG
>   
Please use #undef instead ( no  C++ -style comments).  Can you use 
debug() instead of this?
> +#ifdef CONFIG_FEC_IMX27_DEBUG
> +#define	PRINTF(fmt,args...)	printf (fmt ,##args)
> +#else
> +#define PRINTF(fmt,args...)
> +#endif
> +
> +static int fec_miiphy_read(struct miiphy_device *mdev, uint8_t phyAddr,
> +	uint8_t regAddr, uint16_t * retVal);
> +static int fec_miiphy_write(struct miiphy_device *mdev, uint8_t phyAddr,
> +	uint8_t regAddr, uint16_t data);
> +
> +typedef struct {
> +	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) */
> +} NBUF;
> +
> +fec_priv gfec=
> +{
> +	.eth       = (ethernet_regs *)IMX_FEC_BASE,
> +	.xcv_type  = MII100,
> +	.rbd_base  = NULL,
> +	.rbd_index = 0,
> +	.tbd_base  = NULL,
> +	.tbd_index = 0,
> +	.miiphy =
> +		{
> +			CONFIG_PHY_ADDR,
> +			fec_miiphy_read,
> +			fec_miiphy_write,
> +			0,
> +			NULL
> +		},
> +	.bd        = NULL,
> +};
> +
> +/*
> + * MII-interface related functions
> + */
> +static int fec_miiphy_read(struct miiphy_device *mdev, uint8_t phyAddr,
> +	uint8_t regAddr, uint16_t * retVal)
> +{
> +	struct eth_device *edev = mdev->edev;
> +	fec_priv *fec = (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);
>   
Line's too long
> +
> +	/*
> +	 * wait for the related interrupt
> +	 */
> +	start = get_timer_masked(); /* get_time_ns(); */
> +	while (!(readl(&fec->eth->ievent) & FEC_IEVENT_MII)) {
> +		if (get_timer (start) > (CONFIG_SYS_HZ /1000)  /* is_timeout(start, MSECOND)*/) {
>   
More long lines, please clean up globally.
> +			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);
> +	PRINTF("fec_miiphy_read: phy: %02x reg:%02x val:%#x\n", phyAddr, regAddr, *retVal);
> +	return 0;
> +}
> +
> +static int fec_miiphy_write(struct miiphy_device *mdev, uint8_t phyAddr,
> +	uint8_t regAddr, uint16_t data)
> +{
> +	struct eth_device *edev = mdev->edev;
> +	fec_priv *fec = (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(); /* get_time_ns(); */
> +	while (!(readl(&fec->eth->ievent) & FEC_IEVENT_MII)) {
> +		if (get_timer (start) > (CONFIG_SYS_HZ /1000)  /* is_timeout(start, MSECOND)*/) {
> +			printf("Write MDIO failed...\n");
> +			return -1;
> +		}
> +	}
> +
> +	/*
> +	 * clear MII interrupt bit
> +	 */
> +	writel(FEC_IEVENT_MII, &fec->eth->ievent);
> +	PRINTF("fec_miiphy_write: phy: %02x reg:%02x val:%#x\n", phyAddr, regAddr, data);
> +
> +	return 0;
> +}
> +
> +static int fec_rx_task_enable(fec_priv *fec)
> +{
> +	writel(1 << 24, &fec->eth->r_des_active);
> +	return 0;
> +}
> +
> +static int fec_rx_task_disable(fec_priv *fec)
> +{
> +	return 0;
> +}
> +
> +static int fec_tx_task_enable(fec_priv *fec)
> +{
> +	writel(1 << 24, &fec->eth->x_des_active);
> +	return 0;
> +}
> +
> +static int fec_tx_task_disable(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(fec_priv *fec, int count, int size, int once)
> +{
> +	int ix;
> +	uint32_t p=0;
> +
> +	if (!once) {
> +		/* reserve data memory and consider alignment */
> +		p = (uint32_t)malloc(size * count + DB_DATA_ALIGNMENT);
> +		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++) {
> +		if (!once) {
> +			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(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, 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)
> +{
> +	int i;
> +	int uninitialized = 0;
> +
> +	for (i=0;i<6;i++) {
> +		mac[6-1-i] = readl(&IIM_BANK_REG(0,(IIM0_MAC+i)));
> +	}
> +
> +	/* uninitialized if all 00 */
> +	if ((mac[0] == 0) && (mac[1] == 0) && (mac[2] == 0) &&
> +            (mac[3] == 0) && (mac[4] == 0) && (mac[5] == 0))
> +                uninitialized = 1;
> +
> +	/* uninitialized if all FF (could be safe) */
> +        if ((mac[0] == 0xff) && (mac[1] == 0xff) && (mac[2] == 0xff) &&
> +	    (mac[3] == 0xff) && (mac[4] == 0xff) && (mac[5] == 0xff))
> +	        uninitialized = 1;
> +
>   
Please use 'is_valid_ether_addr()' instead.  It's in "include/net.h"
> +	return uninitialized;
> +}
> +
> +static int fec_set_hwaddr(struct eth_device *dev, unsigned char *mac)
> +{
> +	fec_priv *fec = (fec_priv *)dev->priv;
> +//#define WTF_IS_THIS
> +#ifdef WTF_IS_THIS
>   
Please figure out WTF this is, and use it always or delete it.
> +	uint32_t crc = 0xffffffff;	/* initial value */
> +	uint8_t currByte;			/* byte for which to compute the CRC */
> +	int byte;			/* loop - counter */
> +	int bit;			/* loop - counter */
> +
> +	/*
> +	 * The algorithm used is the following:
> +	 * we loop on each of the six bytes of the provided address,
> +	 * and we compute the CRC by left-shifting the previous
> +	 * value by one position, so that each bit in the current
> +	 * byte of the address may contribute the calculation. If
> +	 * the latter and the MSB in the CRC are different, then
> +	 * the CRC value so computed is also ex-ored with the
> +	 * "polynomium generator". The current byte of the address
> +	 * is also shifted right by one bit at each iteration.
> +	 * This is because the CRC generatore in hardware is implemented
> +	 * as a shift-register with as many ex-ores as the radixes
> +	 * in the polynomium. This suggests that we represent the
> +	 * polynomiumm itself as a 32-bit constant.
> +	 */
> +	for (byte = 0; byte < 6; byte++) {
> +		currByte = mac[byte];
> +		for (bit = 0; bit < 8; bit++) {
> +			if ((currByte & 0x01) ^ (crc & 0x01)) {
> +				crc >>= 1;
> +				crc = crc ^ 0xedb88320;
> +			} else {
> +				crc >>= 1;
> +			}
> +			currByte >>= 1;
> +		}
> +	}
> +
> +	crc = crc >> 26;
> +
> +	/*
> +	 * Set individual hash table register
> +	 */
> +	if (crc >= 32) {
> +		fec->eth->iaddr1 = (1 << (crc - 32));
> +		fec->eth->iaddr2 = 0;
> +	} else {
> +		fec->eth->iaddr1 = 0;
> +		fec->eth->iaddr2 = (1 << crc);
> +	}
> +#else
> +	writel(0, &fec->eth->iaddr1);
> +	writel(0, &fec->eth->iaddr2);
> +	writel(0, &fec->eth->gaddr1);
> +	writel(0, &fec->eth->gaddr2);
> +#endif
> +	/*
> +	 * 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)
> +{
> +	fec_priv *fec = (fec_priv *)edev->priv;
> +
> +	PRINTF("fec_open: fec_open(dev)\n");
> +	writel(1 << 2, &fec->eth->x_cntrl);	/* full-duplex, heartbeat disabled */
> +	fec->rbd_index = 0;
> +
> +	/*
> +	 * Enable FEC-Lite controller
> +	 */
> +	writel(FEC_ECNTRL_ETHER_EN, &fec->eth->ecntrl);
> +
> +	if (fec->xcv_type != SEVENWIRE) {
> +		miiphy_wait_aneg(&fec->miiphy);
> +		miiphy_print_status(&fec->miiphy);
> +	}
> +
> +	/*
> +	 * Enable SmartDMA receive task
> +	 */
> +	fec_rx_task_enable(fec);
> +
> +	udelay(100000);
> +	return 0;
> +}
> +
> +static int fec_init(struct eth_device *dev, bd_t* bd)
> +{
> +	static int once = 0;
> +	uint32_t base;
> +	fec_priv *fec = (fec_priv *)dev->priv;
> +
> +	if( !once )
> +	{
> +		/*
> +		 * reserve memory for both buffer descriptor chains at once
> +		 * Datasheet forces the startaddress of each chain is 16 byte aligned
> +		 */
> +		base = (uint32_t)malloc( (2 + FEC_RBD_NUM) * sizeof(FEC_BD) + DB_ALIGNMENT );
> +		memset((void *)base, 0, (2 + FEC_RBD_NUM) * sizeof(FEC_BD) + DB_ALIGNMENT);
> +		base += (DB_ALIGNMENT-1);
> +		base &= ~(DB_ALIGNMENT-1);
> +
> +		fec->rbd_base = (FEC_BD*)base;
> +
> +		base += FEC_RBD_NUM * sizeof(FEC_BD);
> +
> +		fec->tbd_base = (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);	/* No MII for 7-wire mode */
> +		PRINTF("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
> +	 */
> +	fec_rbd_init(fec, FEC_RBD_NUM, FEC_MAX_PKT_SIZE, once);
> +	fec_tbd_init(fec);
> +
> +
> +	if (fec->xcv_type != SEVENWIRE)
> +		miiphy_restart_aneg(&fec->miiphy);
> +
> +	once = 1;	/* malloc done now (and once) */
> +
> +	fec_open(dev);
> +	return 0;
> +}
> +
> +/**
> + * Halt the FEC engine
> + * @param[in] dev Our device to handle
> + */
> +static void fec_halt(struct eth_device *dev)
> +{
> +	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);
> +
> +	PRINTF("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;
> +	PRINTF("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.
> +	 */
> +	fec_priv *fec = (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 transmitt buffer
>   
s/transmitt/transmit/
> +	 * Note: We are always using the first buffer for transmission,
> +	 * the second will be empty and only used to stop the DMA engine
> +	 */
> +/*	{
> +		int i;
> +		PRINTF("fec_send %d bytes:", length);
> +			for (i=0;i<length;i++)
> +				PRINTF(" %02x", ((char*)packet)[i]);
> +			PRINTF("\n");
> +	}
> +*/	writew(length, &fec->tbd_base[fec->tbd_index].data_length);
>   
No dead code please
> +	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 */
> +	}
> +	PRINTF("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)
> +{
> +	fec_priv *fec = (fec_priv *)dev->priv;
> +	FEC_BD *rbd = &fec->rbd_base[fec->rbd_index];
> +	unsigned long ievent;
> +	int frame_length, len = 0;
> +	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);
> +	PRINTF("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);
> +	PRINTF("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 = (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);
> +/*			PRINTF("fec_recv %d bytes:", frame_length);
> +			for (len=0;len<frame_length;len++)
> +				PRINTF(" %02x", buff[len]);
> +			PRINTF("\n");
> +*/			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;
> +	}
> +	PRINTF("fec_recv: stop\n");
> +
> +	return len;
> +}
> +
> +static int fec_probe(bd_t * bd)
> +{
> +	/*struct fec_platform_data *pdata = (struct fec_platform_data *)dev->platform_data;*/
> +	struct eth_device *edev;
> +	fec_priv *fec = &gfec;
> +	unsigned char ethaddr_str[20];
> +	unsigned char ethaddr[6];
> +	char *tmp = getenv ("ethaddr");
> +	char *end;
> +
> +	/* enable FEC clock */
> +	PCCR1 |= PCCR1_HCLK_FEC;
> +	PCCR0 |= PCCR0_FEC_EN;
> +
> +	/*create and fill edev struct*/
> +	edev = (struct eth_device *)malloc(sizeof(struct eth_device));
> +	edev->priv = fec;
> +	edev->init = fec_init;
> +	edev->send = fec_send;
> +	edev->recv = fec_recv;
> +	edev->halt = fec_halt;
> +
> +	fec->eth = (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; /*pdata->xcv_type;*/
> +
> +	sprintf(edev->name, "FEC ETHERNET");
> +
> +	if (fec->xcv_type != SEVENWIRE) {
> +		fec->miiphy.read = fec_miiphy_read;
> +		fec->miiphy.write = fec_miiphy_write;
> +		fec->miiphy.address = CONFIG_PHY_ADDR;
> +		fec->miiphy.flags = fec->xcv_type == MII10 ? MIIPHY_FORCE_10 : 0;
> +		fec->miiphy.edev = edev;
> +
> +		/* if multiple PHY have to be supported */
> +		/*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) {
> +		sprintf ((char*)ethaddr_str, "%02X:%02X:%02X:%02X:%02X:%02X",
> +			ethaddr[0], ethaddr[1], ethaddr[2], ethaddr[3],
> +			ethaddr[4], ethaddr[5]);
> +		printf("got MAC address from EEPROM: %s\n",ethaddr_str);
> +		setenv ("ethaddr", (char*)ethaddr_str);
> +	}
> +	memcpy(edev->enetaddr, ethaddr, 6);
> +	fec_set_hwaddr(edev, ethaddr);
> +
> +	return 0;
> +}
> +
> +static int once = 0;
>   
Please give this function scope instead of file scope.
> +
> +int eth_init(bd_t * bd)
> +{
> +
> +	if (!once)
> +	{
> +		PRINTF("eth_init: fec_probe(bd)\n");
> +		fec_probe(bd);
> +		once = 1;
> +	}
> +	PRINTF("eth_init: fec_init(gfec.miiphy.edev, bd)\n");
> +	return fec_init(gfec.miiphy.edev, bd);
> +};
> +
>   
This old-style API is deprecated.  Please remove it.
> +int fec_eth_initialize(bd_t *bd)
> +{
> +int lout=1;
> +
> +	if (!once)
> +	{
> +		PRINTF("eth_init: fec_probe(bd)\n");
> +		lout = fec_probe(bd);
> +		once = 1;
> +	}
> +	return lout;
> +}
>   
Is this really necessary?
> +
> +int eth_send(volatile void *packet, int length)
> +{
> +	PRINTF("eth_send: fec_send(gfec.miiphy.edev, packet 0x%08lx, length)\n", packet);
> +	return fec_send(gfec.miiphy.edev, packet, length);
> +};
> +
> +int eth_rx(void){
> +	PRINTF("eth_rcv: fec_rcv(gfec.miiphy.edev)\n");
> +	return fec_recv(gfec.miiphy.edev);
> +};
> +
> +
> +void eth_halt(void)
> +{
> +	PRINTF("eth_halt: fec_halt(gfec)\n");
> +	fec_halt(NULL);
> +	return;
> +};
>   
Again, the eth_init(), eth_send(), eth_rx() and eth_halt() functions 
need to go.
> +
> +/**
> + * @file
> + * @brief Network driver for FreeScale's FEC implementation.
> + * This type of hardware can be found on i.MX27 CPUs
> + */
> +
>   
What's this all about?
> diff --git a/drivers/net/fec_imx27.h b/drivers/net/fec_imx27.h
> new file mode 100644
> index 0000000..e47a708
> --- /dev/null
> +++ b/drivers/net/fec_imx27.h
> @@ -0,0 +1,305 @@
> +/*
> + * (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
> + */
> +typedef struct ethernet_register_set {
> +
> +/* [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 */
> +} ethernet_regs;
> +
> +#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)
> + */
> +typedef struct buffer_descriptor {
> +	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 */
> +} FEC_BD;
> +
> +/**
> + * Supported phy types on this platform
> + */
> +typedef enum {
> +	SEVENWIRE,	/**< 7-wire       */
> +	MII10,		/**< MII 10Mbps   */
> +	MII100		/**< MII 100Mbps  */
> +} xceiver_type;
> +
> +/**
> + * @brief i.MX27-FEC private structure
> + */
> +typedef struct {
> +	ethernet_regs *eth;		/**< pointer to register'S base */
> +	xceiver_type xcv_type;		/**< transceiver type */
> +	FEC_BD *rbd_base;		/**< RBD ring */
> +	int rbd_index;			/**< next receive BD to read */
> +	FEC_BD *tbd_base;		/**< TBD ring */
> +	int tbd_index;			/**< next transmit BD to write */
> +	struct miiphy_device miiphy;
> +	bd_t * bd;
> +} fec_priv;
> +
> +/**
> + * @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 */
> +#define FEC_RBD_LAST		0x0800	/**< Receive BD status: Buffer is last in frame (useless here!) */
> +#define FEC_RBD_MISS		0x0100	/**< Receive BD status: Miss bit for prom mode */
> +#define FEC_RBD_BC		0x0080	/**< Receive BD status: The received frame is broadcast frame */
> +#define FEC_RBD_MC		0x0040	/**< Receive BD status: The received frame is multicast frame */
> +#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 */
> +
> +/**
> + * @file
> + * @brief Definitions for the FEC driver (i.MX27)
> + */
> +
> diff --git a/drivers/net/imx27_miiphy.c b/drivers/net/imx27_miiphy.c
> new file mode 100644
> index 0000000..11cf7af
> --- /dev/null
> +++ b/drivers/net/imx27_miiphy.c
> @@ -0,0 +1,125 @@
> +/*
> + * miiphy.c - generic phy abstraction
> + *
> + * (C) Copyright 2008 Eric Jarrige <eric.jarrige@armadeus.org>
> + * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
> + *
> + * 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 version 2
> + * as published by the Free Software Foundation.
> + *
> + * 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 "imx27_miiphy.h"
> +
> +int miiphy_restart_aneg(struct miiphy_device *mdev)
> +{
> +	uint16_t status;
> +	int timeout;
> +
> +	/*
> +	 * Wake up from sleep if necessary
> +	 * Reset PHY, then delay 300ns
> +	 */
> +	mdev->write(mdev, mdev->address, MII_SPECIAL, 0x00FF);
> +	mdev->write(mdev, mdev->address, MII_BMCR, BMCR_RESET);
> +	udelay(1000);
> +
> +	if (mdev->flags & MIIPHY_FORCE_10) {
> +		printf("Forcing 10 Mbps ethernet link... ");
> +		mdev->read(mdev, mdev->address, MII_BMSR, &status);
> +		mdev->write(mdev, mdev->address, MII_BMCR, BMCR_FULLDPLX | BMCR_CTST);
> +
> +		timeout = 20;
> +		do {	/* wait for link status to go down */
> +			udelay(10000);
> +			if ((timeout--) == 0) {
> +#if (DEBUG & 0x2)
> +				printf("hmmm, should not have waited...");
> +#endif
> +				break;
> +			}
> +			mdev->read(mdev, mdev->address, MII_BMSR, &status);
> +		} while (status & BMSR_LSTATUS);
> +
> +	} else {	/* MII100 */
> +		/*
> +		 * Set the auto-negotiation advertisement register bits
> +		 */
> +		mdev->write(mdev, mdev->address, MII_ADVERTISE, ADVERTISE_ALL);
> +		mdev->write(mdev, mdev->address, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART);
> +	}
> +
> +	return 0;
> +}
> +
> +int miiphy_wait_aneg(struct miiphy_device *mdev)
> +{
> +	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", mdev->edev->name);
> +			return -1;
> +		}
> +
> +		if (mdev->read(mdev, mdev->address, MII_BMSR, &status)) {
> +			printf("%s: Autonegotiation failed. status: 0x%04x\n", mdev->edev->name, status);
> +			return -1;
> +		}
> +	} while (!(status & BMSR_LSTATUS));
> +
> +	return 0;
> +}
> +
> +int miiphy_print_status(struct miiphy_device *mdev)
> +{
> +	uint16_t bmsr, bmcr, lpa;
> +	char *duplex;
> +	int speed;
> +
> +	if (mdev->read(mdev, mdev->address, MII_BMSR, &bmsr) != 0)
> +		goto err_out;
> +	if (mdev->read(mdev, mdev->address, MII_BMCR, &bmcr) != 0)
> +		goto err_out;
> +	if (mdev->read(mdev, mdev->address, MII_LPA, &lpa) != 0)
> +		goto err_out;
> +
> +	printf("%s: Link is %s", mdev->edev->name,
> +			bmsr & BMSR_LSTATUS ? "up" : "down");
> +
> +	if (bmcr & BMCR_ANENABLE) {
> +		duplex = lpa & LPA_DUPLEX ? "Full" : "Half";
> +		speed = lpa & LPA_100 ? 100 : 10;
> +	} else {
> +		duplex = bmcr & BMCR_FULLDPLX ? "Full" : "Half";
> +		speed = bmcr & BMCR_SPEED100 ? 100 : 10;
> +	}
> +
> +	printf(" - %d/%s\n", speed, duplex);
> +
> +	return 0;
> +err_out:
> +	printf("%s: failed to read\n", mdev->edev->name);
> +	return -1;
> +}
> +
> +
> +
> diff --git a/drivers/net/imx27_miiphy.h b/drivers/net/imx27_miiphy.h
> new file mode 100644
> index 0000000..b381ea4
> --- /dev/null
> +++ b/drivers/net/imx27_miiphy.h
> @@ -0,0 +1,157 @@
> +/*
> + * linux/mii.h: definitions for MII-compatible transceivers
> + * Originally drivers/net/sunhme.h.
> + *
> + * (C) Copyright 2008 Eric Jarrige <eric.jarrige@armadeus.org>
> + * Copyright (C) 1996, 1999, 2001 David S. Miller (davem at redhat.com)
> + */
> +
> +#ifndef _IMX27_MII_PHY_H_
> +#define _IMX27_MII_PHY_H_
> +
> +#include <net.h>
> +
> +#define MIIPHY_FORCE_10	1
> +
> +#define MII_BMCR            0x00        /* Basic mode control register */
> +#define MII_BMSR            0x01        /* Basic mode status register  */
> +#define MII_PHYSID1         0x02        /* PHYS ID 1                   */
> +#define MII_PHYSID2         0x03        /* PHYS ID 2                   */
> +#define MII_ADVERTISE       0x04        /* Advertisement control reg   */
> +#define MII_LPA             0x05        /* Link partner ability reg    */
> +#define MII_EXPANSION       0x06        /* Expansion register          */
> +#define MII_CTRL1000        0x09        /* 1000BASE-T control          */
> +#define MII_STAT1000        0x0a        /* 1000BASE-T status           */
> +#define MII_ESTATUS	    0x0f	/* Extended Status	       */
> +#define MII_SPECIAL         0x12        /* Disconnect counter          */
> +#define MII_FCSCOUNTER      0x13        /* False carrier counter       */
> +#define MII_NWAYTEST        0x14        /* N-way auto-neg test reg     */
> +#define MII_RERRCOUNTER     0x15        /* Receive error counter       */
> +#define MII_SREVISION       0x16        /* Silicon revision            */
> +#define MII_RESV1           0x17        /* Reserved...                 */
> +#define MII_LBRERROR        0x18        /* Lpback, rx, bypass error    */
> +#define MII_PHYADDR         0x19        /* PHY address                 */
> +#define MII_RESV2           0x1a        /* Reserved...                 */
> +#define MII_TPISTATUS       0x1b        /* TPI status for 10mbps       */
> +#define MII_NCONFIG         0x1c        /* Network interface config    */
> +
> +/* Basic mode control register. */
> +#define BMCR_RESV               0x003f  /* Unused...                   */
> +#define BMCR_SPEED1000		0x0040  /* MSB of Speed (1000)         */
> +#define BMCR_CTST               0x0080  /* Collision test              */
> +#define BMCR_FULLDPLX           0x0100  /* Full duplex                 */
> +#define BMCR_ANRESTART          0x0200  /* Auto negotiation restart    */
> +#define BMCR_ISOLATE            0x0400  /* Disconnect DP83840 from MII */
> +#define BMCR_PDOWN              0x0800  /* Powerdown the DP83840       */
> +#define BMCR_ANENABLE           0x1000  /* Enable auto negotiation     */
> +#define BMCR_SPEED100           0x2000  /* Select 100Mbps              */
> +#define BMCR_LOOPBACK           0x4000  /* TXD loopback bits           */
> +#define BMCR_RESET              0x8000  /* Reset the DP83840           */
> +
> +/* Basic mode status register. */
> +#define BMSR_ERCAP              0x0001  /* Ext-reg capability          */
> +#define BMSR_JCD                0x0002  /* Jabber detected             */
> +#define BMSR_LSTATUS            0x0004  /* Link status                 */
> +#define BMSR_ANEGCAPABLE        0x0008  /* Able to do auto-negotiation */
> +#define BMSR_RFAULT             0x0010  /* Remote fault detected       */
> +#define BMSR_ANEGCOMPLETE       0x0020  /* Auto-negotiation complete   */
> +#define BMSR_RESV               0x00c0  /* Unused...                   */
> +#define BMSR_ESTATEN		0x0100	/* Extended Status in R15 */
> +#define BMSR_100HALF2           0x0200  /* Can do 100BASE-T2 HDX */
> +#define BMSR_100FULL2           0x0400  /* Can do 100BASE-T2 FDX */
> +#define BMSR_10HALF             0x0800  /* Can do 10mbps, half-duplex  */
> +#define BMSR_10FULL             0x1000  /* Can do 10mbps, full-duplex  */
> +#define BMSR_100HALF            0x2000  /* Can do 100mbps, half-duplex */
> +#define BMSR_100FULL            0x4000  /* Can do 100mbps, full-duplex */
> +#define BMSR_100BASE4           0x8000  /* Can do 100mbps, 4k packets  */
> +
> +/* Advertisement control register. */
> +#define ADVERTISE_SLCT          0x001f  /* Selector bits               */
> +#define ADVERTISE_CSMA          0x0001  /* Only selector supported     */
> +#define ADVERTISE_10HALF        0x0020  /* Try for 10mbps half-duplex  */
> +#define ADVERTISE_1000XFULL     0x0020  /* Try for 1000BASE-X full-duplex */
> +#define ADVERTISE_10FULL        0x0040  /* Try for 10mbps full-duplex  */
> +#define ADVERTISE_1000XHALF     0x0040  /* Try for 1000BASE-X half-duplex */
> +#define ADVERTISE_100HALF       0x0080  /* Try for 100mbps half-duplex */
> +#define ADVERTISE_1000XPAUSE    0x0080  /* Try for 1000BASE-X pause    */
> +#define ADVERTISE_100FULL       0x0100  /* Try for 100mbps full-duplex */
> +#define ADVERTISE_1000XPSE_ASYM 0x0100  /* Try for 1000BASE-X asym pause */
> +#define ADVERTISE_100BASE4      0x0200  /* Try for 100mbps 4k packets  */
> +#define ADVERTISE_PAUSE_CAP     0x0400  /* Try for pause               */
> +#define ADVERTISE_PAUSE_ASYM    0x0800  /* Try for asymetric pause     */
> +#define ADVERTISE_RESV          0x1000  /* Unused...                   */
> +#define ADVERTISE_RFAULT        0x2000  /* Say we can detect faults    */
> +#define ADVERTISE_LPACK         0x4000  /* Ack link partners response  */
> +#define ADVERTISE_NPAGE         0x8000  /* Next page bit               */
> +
> +#define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \
> +			ADVERTISE_CSMA)
> +#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \
> +                       ADVERTISE_100HALF | ADVERTISE_100FULL)
> +
> +/* Link partner ability register. */
> +#define LPA_SLCT                0x001f  /* Same as advertise selector  */
> +#define LPA_10HALF              0x0020  /* Can do 10mbps half-duplex   */
> +#define LPA_1000XFULL           0x0020  /* Can do 1000BASE-X full-duplex */
> +#define LPA_10FULL              0x0040  /* Can do 10mbps full-duplex   */
> +#define LPA_1000XHALF           0x0040  /* Can do 1000BASE-X half-duplex */
> +#define LPA_100HALF             0x0080  /* Can do 100mbps half-duplex  */
> +#define LPA_1000XPAUSE          0x0080  /* Can do 1000BASE-X pause     */
> +#define LPA_100FULL             0x0100  /* Can do 100mbps full-duplex  */
> +#define LPA_1000XPAUSE_ASYM     0x0100  /* Can do 1000BASE-X pause asym*/
> +#define LPA_100BASE4            0x0200  /* Can do 100mbps 4k packets   */
> +#define LPA_PAUSE_CAP           0x0400  /* Can pause                   */
> +#define LPA_PAUSE_ASYM          0x0800  /* Can pause asymetrically     */
> +#define LPA_RESV                0x1000  /* Unused...                   */
> +#define LPA_RFAULT              0x2000  /* Link partner faulted        */
> +#define LPA_LPACK               0x4000  /* Link partner acked us       */
> +#define LPA_NPAGE               0x8000  /* Next page bit               */
> +
> +#define LPA_DUPLEX		(LPA_10FULL | LPA_100FULL)
> +#define LPA_100			(LPA_100FULL | LPA_100HALF | LPA_100BASE4)
> +
> +/* Expansion register for auto-negotiation. */
> +#define EXPANSION_NWAY          0x0001  /* Can do N-way auto-nego      */
> +#define EXPANSION_LCWP          0x0002  /* Got new RX page code word   */
> +#define EXPANSION_ENABLENPAGE   0x0004  /* This enables npage words    */
> +#define EXPANSION_NPCAPABLE     0x0008  /* Link partner supports npage */
> +#define EXPANSION_MFAULTS       0x0010  /* Multiple faults detected    */
> +#define EXPANSION_RESV          0xffe0  /* Unused...                   */
> +
> +#define ESTATUS_1000_TFULL	0x2000	/* Can do 1000BT Full */
> +#define ESTATUS_1000_THALF	0x1000	/* Can do 1000BT Half */
> +
> +/* N-way test register. */
> +#define NWAYTEST_RESV1          0x00ff  /* Unused...                   */
> +#define NWAYTEST_LOOPBACK       0x0100  /* Enable loopback for N-way   */
> +#define NWAYTEST_RESV2          0xfe00  /* Unused...                   */
> +
> +/* 1000BASE-T Control register */
> +#define ADVERTISE_1000FULL      0x0200  /* Advertise 1000BASE-T full duplex */
> +#define ADVERTISE_1000HALF      0x0100  /* Advertise 1000BASE-T half duplex */
> +
> +/* 1000BASE-T Status register */
> +#define LPA_1000LOCALRXOK       0x2000  /* Link partner local receiver status */
> +#define LPA_1000REMRXOK         0x1000  /* Link partner remote receiver status */
> +#define LPA_1000FULL            0x0800  /* Link partner 1000BASE-T full duplex */
> +#define LPA_1000HALF            0x0400  /* Link partner 1000BASE-T half duplex */
> +
>   
This stuff's all standard (or at least most of it).  Please use what's 
in "include/miiphy.h" intead of redefining.
> +struct miiphy_device {
> +	/*struct device_d dev;*/
> +
> +	int address;	/* The address the phy has on the bus */
> +	int (*read)(struct miiphy_device *mdev, uint8_t phy_addr, uint8_t reg_addr, uint16_t *value);
> +	int (*write)(struct miiphy_device *mdev, uint8_t phy_addr, uint8_t reg_addr, uint16_t data);
> +
> +	int flags;
> +
> +	struct eth_device *edev;
> +};
> +
> +int miiphy_register(struct miiphy_device *mdev);
> +int miiphy_restart_aneg(struct miiphy_device *mdev);
> +int miiphy_wait_aneg(struct miiphy_device *mdev);
> +int miiphy_print_status(struct miiphy_device *mdev);
> +
> +#endif
> +
>   
Can't you use the miiphy framework that's already in place?

regards,
Ben

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

* [U-Boot] [PATCH 01/10] mx27: basic cpu support
  2009-05-06 18:30 ` [U-Boot] [PATCH 01/10] mx27: basic cpu support Ilya Yanok
@ 2009-05-06 20:30   ` Magnus Lilja
  2009-05-06 21:16   ` Wolfgang Denk
  1 sibling, 0 replies; 49+ messages in thread
From: Magnus Lilja @ 2009-05-06 20:30 UTC (permalink / raw)
  To: u-boot

Hi

2009/5/6 Ilya Yanok <yanok@emcraft.com>:
> 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 ? ? ? ? | ?205 ++++++++++++++
> ?cpu/arm926ejs/mx27/interrupt.c ? ? ? | ?201 ++++++++++++++
> ?include/asm-arm/arch-mx27/clock.h ? ?| ? 17 ++
> ?include/asm-arm/arch-mx27/imx-regs.h | ?504 ++++++++++++++++++++++++++++++++++
> ?5 files changed, 971 insertions(+), 0 deletions(-)
> ?create mode 100644 cpu/arm926ejs/mx27/Makefile
> ?create mode 100644 cpu/arm926ejs/mx27/generic.c
> ?create mode 100644 cpu/arm926ejs/mx27/interrupt.c
> ?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..c86f3c2
> --- /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 ?= interrupt.o generic.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..fdbc8b7
> --- /dev/null
> +++ b/cpu/arm926ejs/mx27/generic.c
> @@ -0,0 +1,205 @@
> +/*
> + * ?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/arch/imx-regs.h>

An empty line after the last #include statement improves readability, IMO.

> +/*
> + * ?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)));

Add space before and after * and +

> +}
> +
> +static ulong clk_in_32k(void)
> +{
> + ? ? ? return 1024 * CONFIG_MX31_CLK32;
> +}
> +
> +static ulong clk_in_26m(void)
> +{
> + ? ? ? if (CSCR & CSCR_OSC26M_DIV1P5) {
> + ? ? ? ? ? ? ? /* divide by 1.5 */
> + ? ? ? ? ? ? ? return 26000000 / 1.5;
> + ? ? ? } else {
> + ? ? ? ? ? ? ? /* divide by 1 */
> + ? ? ? ? ? ? ? return 26000000;
> + ? ? ? }
> +}
> +
> +ulong imx_get_mpllclk(void)
> +{
> + ? ? ? ulong cscr = CSCR;
> + ? ? ? ulong fref;
> +
> + ? ? ? if (cscr & CSCR_MCU_SEL)
> + ? ? ? ? ? ? ? fref = clk_in_26m();
> + ? ? ? else
> + ? ? ? ? ? ? ? fref = clk_in_32k();
> +
> + ? ? ? return imx_decode_pll(MPCTL0, fref);
> +}
> +
> +ulong imx_get_armclk(void)
> +{
> + ? ? ? ulong cscr = 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)
> +{
> + ? ? ? ulong cscr = CSCR;
> + ? ? ? ulong fref = imx_get_mpllclk();
> + ? ? ? ulong div;
> +
> + ? ? ? div = ((cscr >> 8) & 0x3) + 1;
> +
> + ? ? ? return lldiv(fref * 2, 3 * div);
> +

Remove empty line.

> +}
> +
> +ulong imx_get_spllclk(void)
> +{
> + ? ? ? ulong cscr = CSCR;
> + ? ? ? ulong fref;
> +
> + ? ? ? if (cscr & CSCR_SP_SEL)
> + ? ? ? ? ? ? ? fref = clk_in_26m();
> + ? ? ? else
> + ? ? ? ? ? ? ? fref = clk_in_32k();
> +
> + ? ? ? return imx_decode_pll(SPCTL0, fref);
> +}
> +
> +static ulong imx_decode_perclk(ulong div)
> +{
> + ? ? ? ?return lldiv((imx_get_mpllclk() * 2), (div * 3));

Use tab instead of space for indent.

> +}
> +
> +ulong imx_get_perclk1(void)
> +{
> + ? ? ? return imx_decode_perclk((PCDR1 & 0x3f) + 1);
> +}
> +
> +ulong imx_get_perclk2(void)
> +{
> + ? ? ? return imx_decode_perclk(((PCDR1 >> 8) & 0x3f) + 1);
> +}
> +
> +ulong imx_get_perclk3(void)
> +{
> + ? ? ? return imx_decode_perclk(((PCDR1 >> 16) & 0x3f) + 1);
> +}
> +
> +ulong imx_get_perclk4(void)
> +{
> + ? ? ? return imx_decode_perclk(((PCDR1 >> 24) & 0x3f) + 1);
> +}
> +
> +#if defined(CONFIG_DISPLAY_CPUINFO)
> +int print_cpuinfo (void)
> +{
> + ? ? ? printf("CPU: ? Freescale i.MX27 at %llu MHz\n",
> + ? ? ? ? ? ? ? lldiv(imx_get_mpllclk(), 1000000));
> + ? ? ? printf("\n");
> + ? ? ? return 0;
> +}
> +#endif
> +
> +void imx_gpio_mode(int gpio_mode)
> +{
> + ? ? ? 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)

Add space after if.

> + ? ? ? ? ? ? ? PUEN(port) |= (1 << pin);
> + ? ? ? else
> + ? ? ? ? ? ? ? PUEN(port) &= ~(1 << pin);
> +
> + ? ? ? /* Data direction */
> + ? ? ? if(gpio_mode & GPIO_OUT)

Add space after if.

> + ? ? ? ? ? ? ? DDIR(port) |= 1 << pin;
> + ? ? ? else
> + ? ? ? ? ? ? ? DDIR(port) &= ~(1 << pin);
> +
> + ? ? ? /* Primary / alternate function */
> + ? ? ? if(gpio_mode & GPIO_AF)

Add space after if.

> + ? ? ? ? ? ? ? GPR(port) |= (1 << pin);
> + ? ? ? else
> + ? ? ? ? ? ? ? GPR(port) &= ~(1 << pin);
> +
> + ? ? ? /* use as gpio? */
> + ? ? ? if(!(gpio_mode & (GPIO_PF | GPIO_AF)))

Add space after if.

> + ? ? ? ? ? ? ? GIUS(port) |= (1 << pin);
> + ? ? ? else
> + ? ? ? ? ? ? ? GIUS(port) &= ~(1 << pin);
> +
> + ? ? ? /* Output / input configuration */
> + ? ? ? if (pin < 16) {
> + ? ? ? ? ? ? ? tmp = OCR1(port);
> + ? ? ? ? ? ? ? tmp &= ~(3 << (pin * 2));
> + ? ? ? ? ? ? ? tmp |= (ocr << (pin * 2));
> + ? ? ? ? ? ? ? OCR1(port) = tmp;
> +
> + ? ? ? ? ? ? ? ICONFA1(port) &= ~(3 << (pin * 2));
> + ? ? ? ? ? ? ? ICONFA1(port) |= aout << (pin * 2);
> + ? ? ? ? ? ? ? ICONFB1(port) &= ~(3 << (pin * 2));
> + ? ? ? ? ? ? ? ICONFB1(port) |= bout << (pin * 2);
> + ? ? ? } else {
> + ? ? ? ? ? ? ? pin -= 16;
> +
> + ? ? ? ? ? ? ? tmp = OCR2(port);
> + ? ? ? ? ? ? ? tmp &= ~(3 << (pin * 2));
> + ? ? ? ? ? ? ? tmp |= (ocr << (pin * 2));
> + ? ? ? ? ? ? ? OCR2(port) = tmp;
> +
> + ? ? ? ? ? ? ? ICONFA2(port) &= ~(3 << (pin * 2));
> + ? ? ? ? ? ? ? ICONFA2(port) |= aout << (pin * 2);
> + ? ? ? ? ? ? ? ICONFB2(port) &= ~(3 << (pin * 2));
> + ? ? ? ? ? ? ? ICONFB2(port) |= bout << (pin * 2);
> + ? ? ? }
> +

Remove empty line.

> +}
> +
> diff --git a/cpu/arm926ejs/mx27/interrupt.c b/cpu/arm926ejs/mx27/interrupt.c
> new file mode 100644
> index 0000000..6138d91
> --- /dev/null
> +++ b/cpu/arm926ejs/mx27/interrupt.c
<..>
> +unsigned long long get_ticks (void)
> +{
> + ? ? ? ulong now = GPTCNT; /* current tick value */
> +
> + ? ? ? if (now >= lastinc) ? ? /* normal mode (non roll) */
> + ? ? ? ? ? ? ? /* move stamp forward with absolut diff ticks */
> + ? ? ? ? ? ? ? timestamp += (now - lastinc);

Add {} for multiline branches?

> + ? ? ? else ? ? ? ? ? ? ? ? ? ?/* we have rollover of incrementer */
> + ? ? ? ? ? ? ? timestamp += (0xFFFFFFFF - lastinc) + now;
> + ? ? ? lastinc = now;
> + ? ? ? return timestamp;
> +}
<..>
> diff --git a/include/asm-arm/arch-mx27/clock.h b/include/asm-arm/arch-mx27/clock.h
> new file mode 100644
> index 0000000..f6615d9
> --- /dev/null
> +++ b/include/asm-arm/arch-mx27/clock.h
> @@ -0,0 +1,17 @@
> +
> +#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..a856f7e
> --- /dev/null
> +++ b/include/asm-arm/arch-mx27/imx-regs.h
> @@ -0,0 +1,504 @@
> +/*
> + *
> + * (c) 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.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
> + */
> +
> +#ifndef _IMX_REGS_H
> +#define _IMX_REGS_H
> +
> +/* ------------------------------------------------------------------------
> + * ?Motorola IMX system registers
> + * ------------------------------------------------------------------------
> + */
> +
> +# ifndef __ASSEMBLY__

Why the space after # here?

> +# define __REG(x) ? ? ?(*((volatile u32 *)(x)))
> +# define __REG16(x) ? ? (*(volatile u16 *)(x))
> +# define __REG2(x,y) ? ?(*(volatile u32 *)((u32)&__REG(x) + (y)))

Add space after comma.

> +
> +extern void imx_gpio_mode (int gpio_mode);
> +
> +# else

Why the space after # here?

> +# ?define __REG(x) (x)
> +# ?define __REG16(x) (x)
> +# ?define __REG2(x,y) ((x)+(y))

Add space after comma.

> +#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)

Use tabs to indent the above values.

> +
> +
<...>
> +#define IIM_BANK_AREA ?IMX_IIM_BASE + 0x800

Add () around the definition.


Regards, Magnus

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

* [U-Boot] [PATCH 04/10] mxc_nand: add nand driver for MX2/MX3
  2009-05-06 18:30 ` [U-Boot] [PATCH 04/10] mxc_nand: add nand driver for MX2/MX3 Ilya Yanok
@ 2009-05-06 20:31   ` Magnus Lilja
  2009-05-06 21:25   ` Wolfgang Denk
  2009-05-08  8:39   ` Ivo Clarysse
  2 siblings, 0 replies; 49+ messages in thread
From: Magnus Lilja @ 2009-05-06 20:31 UTC (permalink / raw)
  To: u-boot

Hi

2009/5/6 Ilya Yanok <yanok@emcraft.com>:
> 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 | ?891 +++++++++++++++++++++++++++++++++++++++++++
> ?2 files changed, 892 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..48a6b7b
> --- /dev/null
> +++ b/drivers/mtd/nand/mxc_nand.c
> @@ -0,0 +1,891 @@
<...>
> +#define NFC_SP_EN ? ? ? ? ? (1 << 2)
> +#define NFC_ECC_EN ? ? ? ? ?(1 << 3)
> +#define NFC_INT_MSK ? ? ? ? (1 << 4)
> +#define NFC_BIG ? ? ? ? ? ? (1 << 5)
> +#define NFC_RST ? ? ? ? ? ? (1 << 6)
> +#define NFC_CE ? ? ? ? ? ? ?(1 << 7)
> +#define NFC_ONE_CYCLE ? ? ? (1 << 8)
> +
> +typedef enum _bool{false,true} bool;

Isn't there some include-file we can use instead of typdefing this locally?

> +

Regards, Magnus

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

* [U-Boot] [PATCH 07/10] mmc: use lldiv() for 64-bit division
  2009-05-06 18:30 ` [U-Boot] [PATCH 07/10] mmc: use lldiv() for 64-bit division Ilya Yanok
@ 2009-05-06 20:32   ` Magnus Lilja
  2009-05-08 22:42   ` Andy Fleming
  1 sibling, 0 replies; 49+ messages in thread
From: Magnus Lilja @ 2009-05-06 20:32 UTC (permalink / raw)
  To: u-boot

Hi

2009/5/6 Ilya Yanok <yanok@emcraft.com>:
> Signed-off-by: Ilya Yanok <yanok@emcraft.com>
> ---
> ?drivers/mmc/mmc.c | ? ?7 ++++---
> ?1 files changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index 7791c38..77a9aea 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -31,6 +31,7 @@
> ?#include <malloc.h>
> ?#include <linux/list.h>
> ?#include <mmc.h>
> +#include <div64.h>
>
> ?static struct list_head mmc_devices;
> ?static int cur_dev_num = -1;
> @@ -155,8 +156,8 @@ int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size)
> ? ? ? ?char *buffer;
> ? ? ? ?int i;
> ? ? ? ?int blklen = mmc->read_bl_len;
> - ? ? ? int startblock = src / blklen;
> - ? ? ? int endblock = (src + size - 1) / blklen;
> + ? ? ? int startblock = lldiv(src, blklen);
> + ? ? ? int endblock = lldiv((src + size - 1), blklen);
> ? ? ? ?int err = 0;
>
> ? ? ? ?/* Make a buffer big enough to hold all the blocks we might read */
> @@ -789,7 +790,7 @@ int mmc_startup(struct mmc *mmc)
> ? ? ? ?mmc->block_dev.lun = 0;
> ? ? ? ?mmc->block_dev.type = 0;
> ? ? ? ?mmc->block_dev.blksz = mmc->read_bl_len;
> - ? ? ? mmc->block_dev.lba = mmc->capacity/mmc->read_bl_len;
> + ? ? ? mmc->block_dev.lba = lldiv(mmc->capacity,mmc->read_bl_len);

Add space after comma.

Regards, Magnus

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

* [U-Boot] [PATCH 10/10] imx27lite: add support for imx27lite board from LogicPD
  2009-05-06 18:30 ` [U-Boot] [PATCH 10/10] imx27lite: add support for imx27lite board from LogicPD Ilya Yanok
@ 2009-05-06 20:34   ` Magnus Lilja
  2009-05-08 18:19     ` Magnus Lilja
  2009-05-06 21:29   ` Wolfgang Denk
  2009-05-19 16:17   ` Paul Thomas
  2 siblings, 1 reply; 49+ messages in thread
From: Magnus Lilja @ 2009-05-06 20:34 UTC (permalink / raw)
  To: u-boot

Hi

2009/5/6 Ilya Yanok <yanok@emcraft.com>:
> 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>
> ---
> ?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 | ?225 +++++++++++++++++++++++++++++++
> ?board/logicpd/imx27lite/u-boot.lds ? ? ?| ? 56 ++++++++
> ?include/configs/imx27lite.h ? ? ? ? ? ? | ?188 ++++++++++++++++++++++++++
> ?8 files changed, 622 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/MAKEALL b/MAKEALL
> index f13c81a..4806512 100755
> --- a/MAKEALL
> +++ b/MAKEALL
> @@ -504,6 +504,7 @@ LIST_ARM9=" ? ? ? ? ? ? ? ? \
> ? ? ? ?cp946es ? ? ? ? ? ? ? ? \
> ? ? ? ?cp966 ? ? ? ? ? ? ? ? ? \
> ? ? ? ?lpd7a400 ? ? ? ? ? ? ? ?\
> + ? ? ? imx27lite ? ? ? ? ? ? ? \

I think the list should be sorted alphabetically, so move it up one step.

> ? ? ? ?mx1ads ? ? ? ? ? ? ? ? ?\
> ? ? ? ?mx1fs2 ? ? ? ? ? ? ? ? ?\
> ? ? ? ?netstar ? ? ? ? ? ? ? ? \
<...>
> diff --git a/board/logicpd/imx27lite/lowlevel_init.S b/board/logicpd/imx27lite/lowlevel_init.S
> new file mode 100644
> index 0000000..48c7fe6
> --- /dev/null
> +++ b/board/logicpd/imx27lite/lowlevel_init.S
> @@ -0,0 +1,225 @@
> +/*
> + * 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>
> +
> +#define CFG_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 CFG_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 CFG_SDRAM_ALL_VAL ? ? ? ? ? ? ?0xf00
> +
> +#define CFG_SDRAM_MODE_REGISTER_VAL ? ?0x33 ? ?/* BL: 8, CAS: 3 */
> +#define CFG_SDRAM_EXT_MODE_REGISTER_VAL ? ? ? ?0x1000000
> +
> +#define CFG_MPCTL0_VAL 0x1ef15d5
> +
> +#define CFG_SPCTL0_VAL 0x043a1c09
> +
> +#define CFG_CSCR_VAL ? 0x33f08107
> +
> +#define CFG_PCDR0_VAL ?0x120470c3
> +#define CFG_PCDR1_VAL ?0x03030303
> +#define CFG_PCCR0_VAL ?0xffffffff
> +#define CFG_PCCR1_VAL ?0xfffffffc
> +
> +#define CFG_AIPI1_PSR0_VAL ? ? 0x20040304
> +#define CFG_AIPI1_PSR1_VAL ? ? 0xdffbfcfb
> +#define CFG_AIPI2_PSR0_VAL ? ? 0x07ffc200
> +#define CFG_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 ? CFG_SDRAM_ESDCFG_REGISTER_VAL(0)
> +SDRAM_ESDCFG_T2_W: ? ? .word ? CFG_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 ? CFG_SDRAM_ESDCTL_REGISTER_VAL
> +
> + ? ? ? .macro init_aipi
> + ? ? ? /*
> + ? ? ? ?* setup AIPI1 and AIPI2
> + ? ? ? ?*/
> + ? ? ? writel(AIPI1_PSR0, CFG_AIPI1_PSR0_VAL)
> + ? ? ? writel(AIPI1_PSR1, CFG_AIPI1_PSR1_VAL)
> + ? ? ? writel(AIPI2_PSR0, CFG_AIPI2_PSR0_VAL)
> + ? ? ? writel(AIPI2_PSR1, CFG_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]
> +
> + ? ? ? /*
> + ? ? ? ?* pll clock initialization predefined in apf27.h
> + ? ? ? ?*/
> + ? ? ? writel(MPCTL0, CFG_MPCTL0_VAL)
> + ? ? ? writel(SPCTL0, CFG_SPCTL0_VAL)
> +
> + ? ? ? writel(CSCR, CFG_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, CFG_PCDR0_VAL)
> + ? ? ? writel(PCDR1, CFG_PCDR1_VAL)
> +
> + ? ? ? /* Configure PCCR0 and PCCR1 */
> + ? ? ? writel(PCCR0, CFG_PCCR0_VAL)
> + ? ? ? writel(PCCR1, CFG_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, #CFG_SDRAM_ALL_VAL]
> +
> + ? ? ? ldr r1, SDRAM_AUTOREF_CMD_W
> + ? ? ? str r1, [r0, #ESDCTL0_ROF]
> + ? ? ? ldr r1, [r2, #CFG_SDRAM_ALL_VAL]
> + ? ? ? ldr r1, [r2, #CFG_SDRAM_ALL_VAL]
> +
> + ? ? ? ldr r1, SDRAM_LOADMODE_CMD_W
> + ? ? ? str r1, [r0, #ESDCTL0_ROF]
> + ? ? ? ldrb r1, [r2, #CFG_SDRAM_MODE_REGISTER_VAL]
> + ? ? ? add r3, r2, #CFG_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, #CFG_SDRAM_ALL_VAL]
> +
> + ? ? ? ldr r1, SDRAM_AUTOREF_CMD_W
> + ? ? ? str r1, [r0, #ESDCTL1_ROF]
> + ? ? ? ldr r1, [r2, #CFG_SDRAM_ALL_VAL]
> + ? ? ? ldr r1, [r2, #CFG_SDRAM_ALL_VAL]
> +
> + ? ? ? ldr r1, SDRAM_LOADMODE_CMD_W
> + ? ? ? str r1, [r0, #ESDCTL1_ROF]
> + ? ? ? ldrb r1, [r2, #CFG_SDRAM_MODE_REGISTER_VAL]
> + ? ? ? add r3, r2, #CFG_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

A general comment on lowlevel_init.S:
A lot of the contents is probably the same for many i.MX27 boards.
Could the definitions, macros be moved to a generic file (perhaps
header file)? We should probably do something like that in i.MX31 in
order to avoid all the duplication that takes place there for the
different boards.

<...>
> diff --git a/include/configs/imx27lite.h b/include/configs/imx27lite.h
> new file mode 100644
> index 0000000..80fb291
> --- /dev/null
> +++ b/include/configs/imx27lite.h
> @@ -0,0 +1,188 @@
> +/*
> + * 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_MX31_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 */
> +/*=============*/
> +#define CONFIG_SYS_MALLOC_LEN ? ? ? ? ?(0x10000 + 128*1024) ? ?/* malloc() len */
> +#define CONFIG_SYS_GBL_DATA_SIZE ? ? ? 128 ? ? ? ? ? ? /* reserved for initial data */
> +#define CONFIG_SYS_MEMTEST_START ? ? ? 0xA0000000 ? ? ?/* memtest start address */
> +#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 */

Add empty line for readability?

> +/*====================*/
> +/* Serial Driver info */
> +/*====================*/
> +#define CONFIG_MX31_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 }

Add empty line for readability?

> +/*=====================*/
> +/* 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 */
> +#define CONFIG_ENV_OFFSET ? ? ? ? ? ? ?(PHYS_FLASH_SIZE - 0x20000) ? ? /* end of flash */
> +#define PHYS_FLASH_1 ? ? ? ? ? ? ? ? ? 0xc0000000 ? ? ?/* CS2 Base address ? ? ?*/
> +#define CONFIG_SYS_FLASH_BASE ? ? ? ? ?PHYS_FLASH_1 ? ?/* Flash Base for U-Boot */
> +#define PHYS_FLASH_SIZE ? ? ? ? ? ? ? ? ? ? ? ?0x200000 ? ? ? ?/* Flash size 2MB ? ? ? ?*/
> +#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

Add empty line for readability?

> +/*
> + * Ethernet
> + */
> +#define CONFIG_FEC_IMX27
> +#define CONFIG_MII

Add empty line for readability?

> +/*
> + * 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

Add empty line for readability?

> +/*
> + * SD/MMC
> + */
> +#define CONFIG_MMC
> +#define CONFIG_GENERIC_MMC
> +#define CONFIG_MXC_MMC
> +#define CONFIG_MXC_MCI_REGS_BASE ? ? ? 0x10014000
> +#define CONFIG_DOS_PARTITION

Add empty line for readability?

> +/*
> + * JFFS2 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:-(nand)"
> +
> +/*==============================*/
> +/* 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 */
> +#define CONFIG_SYS_BARGSIZE ? ?CONFIG_SYS_CBSIZE ? ? ? /* Boot Argument Buffer Size */
> +#define CONFIG_CMDLINE_EDITING
> +#define CONFIG_SYS_LONGHELP

Add empty line for readability?

> +/*=================*/
> +/* U-Boot commands */
> +/*=================*/

Regards, Magnus

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

* [U-Boot] [PATCH 02/10] serial_mx31: allow it to work with mx27 too
  2009-05-06 18:30 ` [U-Boot] [PATCH 02/10] serial_mx31: allow it to work with mx27 too Ilya Yanok
@ 2009-05-06 21:16   ` Wolfgang Denk
  0 siblings, 0 replies; 49+ messages in thread
From: Wolfgang Denk @ 2009-05-06 21:16 UTC (permalink / raw)
  To: u-boot

Dear Ilya Yanok,

In message <1241634633-13917-3-git-send-email-yanok@emcraft.com> you 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.
> 
> Signed-off-by: Ilya Yanok <yanok@emcraft.com>
> ---
>  drivers/serial/serial_mx31.c |   21 +++++++++++++++++++++
>  1 files changed, 21 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/serial/serial_mx31.c b/drivers/serial/serial_mx31.c
> index 7c0682a..acc5b7d 100644
> --- a/drivers/serial/serial_mx31.c
> +++ b/drivers/serial/serial_mx31.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

Should that file be renamed? serial_mx31.c does not seem correct any
more...

And - what are these constants? I smell addresses? Unse I/O accessors
instead?

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
Overdrawn?  But I still have checks left!

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

* [U-Boot] [PATCH 01/10] mx27: basic cpu support
  2009-05-06 18:30 ` [U-Boot] [PATCH 01/10] mx27: basic cpu support Ilya Yanok
  2009-05-06 20:30   ` Magnus Lilja
@ 2009-05-06 21:16   ` Wolfgang Denk
  2009-05-13 22:54     ` Ilya Yanok
  1 sibling, 1 reply; 49+ messages in thread
From: Wolfgang Denk @ 2009-05-06 21:16 UTC (permalink / raw)
  To: u-boot

Dear Ilya,

in message <1241634633-13917-2-git-send-email-yanok@emcraft.com> you wrote:
> This patch adds generic code to support Freescale's i.MX27 SoCs.
...

> +static ulong clk_in_26m(void)
> +{
> +	if (CSCR & CSCR_OSC26M_DIV1P5) {
> +		/* divide by 1.5 */
> +		return 26000000 / 1.5;

We definitely do not allow any FP use in U-Boot.

> +	} else {
> +		/* divide by 1 */
> +		return 26000000;

divide by 1 ???


> +#if defined(CONFIG_DISPLAY_CPUINFO)
> +int print_cpuinfo (void)
> +{
> +       printf("CPU:   Freescale i.MX27 at %llu MHz\n",
> +               lldiv(imx_get_mpllclk(), 1000000));

Please use strmhz() to print frequencies.

> +       printf("\n");

No need to waste another function call - just add this to the previous
format element.

> +void imx_gpio_mode(int gpio_mode)
> +{
> +	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)
> +		PUEN(port) |= (1 << pin);
> +	else
> +		PUEN(port) &= ~(1 << pin);

This smells as if these were pointer accesses using register offsets
instead of I/O accessor calls using C structs?

You probably want to use the respective clrbits*() / setbits*() macros
here?

...
> +void reset_cpu (ulong ignored)
> +{
> +	/* Disable watchdog and set Time-Out field to 0 */
> +	WCR = 0x00000000;
> +
> +	/* Write Service Sequence */
> +	WSR = 0x00005555;
> +	WSR = 0x0000AAAA;

Again: please use I/O accessor calls; also for the rest of the file
and the other patches.

...
> 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..a856f7e
...
> +# ifndef __ASSEMBLY__
> +# define __REG(x)	(*((volatile u32 *)(x)))
> +# define __REG16(x)     (*(volatile u16 *)(x))
> +# define __REG2(x,y)    (*(volatile u32 *)((u32)&__REG(x) + (y)))
> +
> +extern void imx_gpio_mode (int gpio_mode);
> +
> +# else
> +#  define __REG(x) (x)
> +#  define __REG16(x) (x)
> +#  define __REG2(x,y) ((x)+(y))
> +#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)

NAK. We do not accept device I/O through pointers; please use C
structs to describe the hardware and use I/O accessor calls.

> +/* AIPI */
> +#define AIPI1_PSR0	__REG(IMX_AIPI1_BASE + 0x00)
> +#define AIPI1_PSR1	__REG(IMX_AIPI1_BASE + 0x04)
> +#define AIPI2_PSR0	__REG(IMX_AIPI2_BASE + 0x00)
> +#define AIPI2_PSR1	__REG(IMX_AIPI2_BASE + 0x04)
> +
> +/* System Control */
> +#define FMCR	__REG(IMX_SYSTEM_CTL_BASE + 0x14)
> +#define GPCR	__REG(IMX_SYSTEM_CTL_BASE + 0x18)
> +#define WBCR	__REG(IMX_SYSTEM_CTL_BASE + 0x1C)

NAK, for this and all similar code.


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
It is better to marry than to burn.
                                - Bible ``I Corinthians'' ch. 7, v. 9

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

* [U-Boot] [PATCH 03/10] fec_imx27: driver for FEC ethernet controller on i.MX27
  2009-05-06 18:30 ` [U-Boot] [PATCH 03/10] fec_imx27: driver for FEC ethernet controller on i.MX27 Ilya Yanok
  2009-05-06 19:51   ` Ben Warren
@ 2009-05-06 21:20   ` Wolfgang Denk
  1 sibling, 0 replies; 49+ messages in thread
From: Wolfgang Denk @ 2009-05-06 21:20 UTC (permalink / raw)
  To: u-boot

Dear Ilya,

In message <1241634633-13917-4-git-send-email-yanok@emcraft.com> you wrote:
> 
> --- /dev/null
> +++ b/drivers/net/fec_imx27.c
> +#include <asm/arch/clock.h>
> +#include <asm/arch/imx-regs.h>
> +#include <asm/io.h>
> +
> +#define CONFIG_PHY_ADDR	0

Ummm... "CONFIG_*" variables are by definition user changable, so they
get defined in board config files, but never in common C code.

[Lots of problematic code skipped as others already pointed out the
issues.]

> +int eth_init(bd_t * bd)
> +{
> +
> +	if (!once)
> +	{
> +		PRINTF("eth_init: fec_probe(bd)\n");
> +		fec_probe(bd);
> +		once = 1;
> +	}
> +	PRINTF("eth_init: fec_init(gfec.miiphy.edev, bd)\n");
> +	return fec_init(gfec.miiphy.edev, bd);
> +};

Incorrect brace style, also elsewhere.


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're dead, Jim.
	-- McCoy, "The Tholian Web", stardate unknown

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

* [U-Boot] [PATCH 04/10] mxc_nand: add nand driver for MX2/MX3
  2009-05-06 18:30 ` [U-Boot] [PATCH 04/10] mxc_nand: add nand driver for MX2/MX3 Ilya Yanok
  2009-05-06 20:31   ` Magnus Lilja
@ 2009-05-06 21:25   ` Wolfgang Denk
  2009-05-08  8:39   ` Ivo Clarysse
  2 siblings, 0 replies; 49+ messages in thread
From: Wolfgang Denk @ 2009-05-06 21:25 UTC (permalink / raw)
  To: u-boot

Dear Ilya,

In message <1241634633-13917-5-git-send-email-yanok@emcraft.com> you 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.
...
> +/* Set INT to 0, FCMD to 1, rest to 0 in NFC_CONFIG2 Register
> + * for Command operation */

Incorrect multiline comment style. Here and elsewhere.

...
> +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);

Use setbits*() / clrbits*() ? Here and elsewhere.


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
Q:  Do you know what the death rate around here is?
A:  One per person.

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

* [U-Boot] [PATCH 00/10] Support for LogicPD i.MX27-LITEKIT development board
  2009-05-06 18:30 [U-Boot] [PATCH 00/10] Support for LogicPD i.MX27-LITEKIT development board Ilya Yanok
                   ` (9 preceding siblings ...)
  2009-05-06 18:30 ` [U-Boot] [PATCH 10/10] imx27lite: add support for imx27lite board from LogicPD Ilya Yanok
@ 2009-05-06 21:26 ` Wolfgang Denk
  10 siblings, 0 replies; 49+ messages in thread
From: Wolfgang Denk @ 2009-05-06 21:26 UTC (permalink / raw)
  To: u-boot

Dear Ilya,

In message <1241634633-13917-1-git-send-email-yanok@emcraft.com> you 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. It also
> contains some fixes to generic MMC subsystem.
> 
> Signed-off-by: Ilya Yanok <yanok@emcraft.com>

General comments in addition to what the other posters already
remarked:

The whole patch set needs clean up regarding coding style: line
length, indentation and vertical alignment by TABs, brace style, no
C++ comments, incorrect multiline comment style, etc.

Also, large parts of the code are based on accessing device registers
through pointers, usualy hiddewn in some macros  using  base  address
and  offset. We don't accept such code any more. Please use C structs
and I/O accessor calls.


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 the fully armed nuclear warheads, are, of  course,  merely  a
courtesy detail."

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

* [U-Boot] [PATCH 10/10] imx27lite: add support for imx27lite board from LogicPD
  2009-05-06 18:30 ` [U-Boot] [PATCH 10/10] imx27lite: add support for imx27lite board from LogicPD Ilya Yanok
  2009-05-06 20:34   ` Magnus Lilja
@ 2009-05-06 21:29   ` Wolfgang Denk
  2009-05-19 16:17   ` Paul Thomas
  2 siblings, 0 replies; 49+ messages in thread
From: Wolfgang Denk @ 2009-05-06 21:29 UTC (permalink / raw)
  To: u-boot

Dear Ilya,

In message <1241634633-13917-11-git-send-email-yanok@emcraft.com> you 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.
...
> +/*=================*/
> +/* U-Boot commands */
> +/*=================*/
> +#include <config_cmd_default.h>
> +#define CONFIG_CMD_ASKENV
> +#define CONFIG_CMD_DHCP
> +#define CONFIG_CMD_DIAG
> +#define CONFIG_CMD_NET
> +#undef CONFIG_CMD_NFS

Please enable.

> +#define CONFIG_CMD_MII
> +#define CONFIG_CMD_PING
> +#undef CONFIG_CMD_BDI

Please enable.

> +#undef CONFIG_CMD_FPGA

?

> +#undef CONFIG_CMD_SETGETDCR

?

> +#define CONFIG_CMD_NAND
> +#define CONFIG_CMD_JFFS2
> +#define CONFIG_CMD_MMC
> +#define CONFIG_CMD_FAT

Please keep the list sorted.

> +/*
> + * You can compile in a MAC address and your custom net settings by using
> + * the following syntax.
> + *
> + * #define CONFIG_ETHADDR		xx:xx:xx:xx:xx:xx
> + * #define CONFIG_SERVERIP		<server ip>
> + * #define CONFIG_IPADDR		<board ip>
> + * #define CONFIG_GATEWAYIP		<gateway ip>
> + * #define CONFIG_NETMASK		<your netmask>
> + */

Please remove this part.

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
panic: kernel trap (ignored)

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

* [U-Boot] [PATCH 05/10] mxc-mmc: sdhc host driver for MX2 and MX3 proccessor
  2009-05-06 18:30 ` [U-Boot] [PATCH 05/10] mxc-mmc: sdhc host driver for MX2 and MX3 proccessor Ilya Yanok
@ 2009-05-08  0:26   ` alfred steele
  2009-05-13 21:50   ` alfred steele
  1 sibling, 0 replies; 49+ messages in thread
From: alfred steele @ 2009-05-08  0:26 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.

Would your patch  work for the MX31 pdk. Or it will not work as-is is
because the IOMUX setup might be different between MX27  and 31.
Al though i have verified that the register set for the HController is
the same. Can this be used as a base though?

Thanks.
Alfred

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

* [U-Boot] [PATCH 04/10] mxc_nand: add nand driver for MX2/MX3
  2009-05-06 18:30 ` [U-Boot] [PATCH 04/10] mxc_nand: add nand driver for MX2/MX3 Ilya Yanok
  2009-05-06 20:31   ` Magnus Lilja
  2009-05-06 21:25   ` Wolfgang Denk
@ 2009-05-08  8:39   ` Ivo Clarysse
  2009-05-08  8:58     ` Magnus Lilja
  2 siblings, 1 reply; 49+ messages in thread
From: Ivo Clarysse @ 2009-05-08  8:39 UTC (permalink / raw)
  To: u-boot

Ilya,

On Wed, May 6, 2009 at 8:30 PM, Ilya Yanok <yanok@emcraft.com> 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.
[..]
> --- /dev/null
> +++ b/drivers/mtd/nand/mxc_nand.c
> @@ -0,0 +1,891 @@
[...]
> +/* 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, int useirq)
> +{
> + ? ? ? 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);
> +}

As you don't have an interrupt handler (as opposed to the Linux
driver), why keep the 'useirq' parameter ?

[...]
> +static void send_cmd(struct mxc_nand_host *host, uint16_t cmd, int useirq)

Same comment (also renders all 'islast' parameters obsolete).

[...]
> +int board_nand_init(struct nand_chip *this)
> +{
[...]
> +
> + ? ? ? tmp = readw(host->regs + NFC_CONFIG1);
> + ? ? ? tmp |= NFC_INT_MSK;
> + ? ? ? writew(tmp, host->regs + NFC_CONFIG1);

I don't think this is needed on i.MX27, since you don't have an
interrupt handler.
Setting NFC_INT_MSK on i.MX21 will cause NFC_INT in NFC_CONFIG2 to
never get set (and wait_op_done() to always time out)

You might want to have a look at u-boot-v2's MXC nand driver, that one
works on both i.MX21 and i.MX27, without setting NFC_INT_MSK:

      http://git.denx.de/?p=u-boot/u-boot-v2.git;a=blob;f=drivers/nand/nand_imx.c;hb=HEAD

Also, see my post on linux-arm-kernel, "[RFC][PATCH] MXC NAND i.MX21 support":

      http://www.spinics.net/lists/arm-kernel/msg64970.html



Best regards,

Ivo.

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

* [U-Boot] [PATCH 04/10] mxc_nand: add nand driver for MX2/MX3
  2009-05-08  8:39   ` Ivo Clarysse
@ 2009-05-08  8:58     ` Magnus Lilja
  0 siblings, 0 replies; 49+ messages in thread
From: Magnus Lilja @ 2009-05-08  8:58 UTC (permalink / raw)
  To: u-boot

Hi

2009/5/8 Ivo Clarysse <ivo.clarysse@gmail.com>:
> Ilya,
>
> On Wed, May 6, 2009 at 8:30 PM, Ilya Yanok <yanok@emcraft.com> 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.
> [..]
>> --- /dev/null
>> +++ b/drivers/mtd/nand/mxc_nand.c
>> @@ -0,0 +1,891 @@
> [...]
>> +/* 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, int useirq)
>> +{
>> + ? ? ? 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);
>> +}
>
> As you don't have an interrupt handler (as opposed to the Linux
> driver), why keep the 'useirq' parameter ?
>
> [...]
>> +static void send_cmd(struct mxc_nand_host *host, uint16_t cmd, int useirq)
>
> Same comment (also renders all 'islast' parameters obsolete).

I think it's a good idea to keep the code as close as possible to the
original linux driver. That way it's easy to make a diff and update
the U-boot driver with whatever changes are done in Linux.

Regards, Magnus

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

* [U-Boot] [PATCH 10/10] imx27lite: add support for imx27lite board from LogicPD
  2009-05-06 20:34   ` Magnus Lilja
@ 2009-05-08 18:19     ` Magnus Lilja
  0 siblings, 0 replies; 49+ messages in thread
From: Magnus Lilja @ 2009-05-08 18:19 UTC (permalink / raw)
  To: u-boot

Hi

I have now used the mxc_nand.c driver from patch 4 on a i.MX31 Litekit
board and have some add some more input, see below.

2009/5/6 Magnus Lilja <lilja.magnus@gmail.com>:
>> +/*
>> + * NAND
>> + */
>> +#define CONFIG_NAND_MXC
>> +#define CONFIG_MXC_NAND_REGS_BASE ? ? ?0xd8000000

It would be nice to have the REGS_BASE automatically set to whatever
is appropriate for the SoC the code that is selected. I.e. it should
be enough to specify CONFIG_MX31 in the board config file and then the
NFC register base is handled automatically (and the equivalent for
i.MX27).

Other than that, the only change to make it work on i.MX31 Litekit was
to disable the NAND bus width checking since that's currently i.MX27
specific code in mxc_nand.c so that would need some minor update for
i.MX31.


Regards, Magnus Lilja

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

* [U-Boot] [PATCH 07/10] mmc: use lldiv() for 64-bit division
  2009-05-06 18:30 ` [U-Boot] [PATCH 07/10] mmc: use lldiv() for 64-bit division Ilya Yanok
  2009-05-06 20:32   ` Magnus Lilja
@ 2009-05-08 22:42   ` Andy Fleming
  1 sibling, 0 replies; 49+ messages in thread
From: Andy Fleming @ 2009-05-08 22:42 UTC (permalink / raw)
  To: u-boot

On Wed, May 6, 2009 at 1:30 PM, Ilya Yanok <yanok@emcraft.com> wrote:
> Signed-off-by: Ilya Yanok <yanok@emcraft.com>

This is actually already in my tree.  So I'll just take this
opportunity to shake my head at ARM ABI designers, who thought 64-bit
division was too hard to do in the compiler...

Andy

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

* [U-Boot] [PATCH 08/10] mmc: some endianess fixes for generic mmc subsystem
  2009-05-06 18:30 ` [U-Boot] [PATCH 08/10] mmc: some endianess fixes for generic mmc subsystem Ilya Yanok
@ 2009-05-08 22:43   ` Andy Fleming
  0 siblings, 0 replies; 49+ messages in thread
From: Andy Fleming @ 2009-05-08 22:43 UTC (permalink / raw)
  To: u-boot

On Wed, May 6, 2009 at 1:30 PM, Ilya Yanok <yanok@emcraft.com> wrote:
> We save response in the cpu order so we need to parse it in the
> cpu order too. Things fixed by this patch:
> 1. OCR_BUSY should be the highest bit in 32-bit response.
> 2. Proper "tran speed" calculation on LE systems (tran_exp and
> ? tran_mant should be in 96..98 and 99..102 bits of 128-bit
> ? response respectively).
> 3. Proper MMC version detection.

I believe all of these changes are in my tree, as well.

Andy

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

* [U-Boot] [PATCH 09/10] mmc: fix mmcinfo command
  2009-05-06 18:30 ` [U-Boot] [PATCH 09/10] mmc: fix mmcinfo command Ilya Yanok
@ 2009-05-08 22:43   ` Andy Fleming
  0 siblings, 0 replies; 49+ messages in thread
From: Andy Fleming @ 2009-05-08 22:43 UTC (permalink / raw)
  To: u-boot

On Wed, May 6, 2009 at 1:30 PM, Ilya Yanok <yanok@emcraft.com> wrote:
> cid field of stuct mmc stucture is char*, not u32*. so we need to
> convert the pointer for mmcinfo code to work correctly.

Yup, this one, too.  Already in my tree.

Andy

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

* [U-Boot] [PATCH 05/10] mxc-mmc: sdhc host driver for MX2 and MX3 proccessor
  2009-05-06 18:30 ` [U-Boot] [PATCH 05/10] mxc-mmc: sdhc host driver for MX2 and MX3 proccessor Ilya Yanok
  2009-05-08  0:26   ` alfred steele
@ 2009-05-13 21:50   ` alfred steele
  1 sibling, 0 replies; 49+ messages in thread
From: alfred steele @ 2009-05-13 21:50 UTC (permalink / raw)
  To: u-boot

On Wed, May 6, 2009 at 1:30 PM, Ilya Yanok <yanok@emcraft.com> wrote:
> This is a port of Linux driver for SDHC host controller hardware
> found on Freescale's MX2 and MX3 processors.
Would this work asis on the MX31 uboot.
I tried making the code work on the MX31 with minor mods ( on some
registers).  Would it work on MX31? I am trying to understand the
hardware better. I had some confusion on the internally generated
clock. This code seems to borrow heavily from the linux api's. So it i
s using the imx_get_perclk2() function as a source of the divder
frequency. Will it work on the imx31. U-boot already has the
mx31_get_ipg_clk() for extracting the clock. Which one should i use
for the SD_MMC_CLOCK? From the data sheet, it seems ipgperclk3() has
to be used for the divider. I am not sure though at this point .

I am not getting a response from the SD card for the OCR  for voltage
validation as a part of the card identification cycle.
Any help will be appreciated.

Thanks,
Alfred,

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

* [U-Boot] [PATCH 01/10] mx27: basic cpu support
  2009-05-06 21:16   ` Wolfgang Denk
@ 2009-05-13 22:54     ` Ilya Yanok
  2009-05-14  8:10       ` Wolfgang Denk
  0 siblings, 1 reply; 49+ messages in thread
From: Ilya Yanok @ 2009-05-13 22:54 UTC (permalink / raw)
  To: u-boot

Hi Wolfgang,

Wolfgang Denk wrote:
>> +static ulong clk_in_26m(void)
>> +{
>> +	if (CSCR & CSCR_OSC26M_DIV1P5) {
>> +		/* divide by 1.5 */
>> +		return 26000000 / 1.5;
>>     
>
> We definitely do not allow any FP use in U-Boot.
>   

This will be actually converted to an integer at the compile time.

>> +void imx_gpio_mode(int gpio_mode)
>> +{
>> +	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)
>> +		PUEN(port) |= (1 << pin);
>> +	else
>> +		PUEN(port) &= ~(1 << pin);
>>     
>
> This smells as if these were pointer accesses using register offsets
> instead of I/O accessor calls using C structs?
>   

Ok, I really like using accessor calls instead of pointer accesses but I
don't really understand the reason for using C structs here... I
remember I've already asked you about that and you told me that it's for
type safety... But we loose this type-safety when we are using I/O
accessor functions! All pointers are just silently converted to the
needed type... On the other hand Linux uses offsets for registers
definitions so converting them to C structs makes porting and
maintaining ported drivers harder...

> You probably want to use the respective clrbits*() / setbits*() macros
> here?
>   

I can see these macros defined only for ppc arch... And I really prefer
generic writel(readl() | something) here... The reason is the same: to
preserve as much code as it possible in drivers ported from Linux.

>> +#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)
>>     
>
> NAK. We do not accept device I/O through pointers; please use C
> structs to describe the hardware and use I/O accessor calls.
>   

These are actually base addresses. I don't think we can make use of C
structs here.

Regards, Ilya.

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

* [U-Boot] [PATCH 01/10] mx27: basic cpu support
  2009-05-13 22:54     ` Ilya Yanok
@ 2009-05-14  8:10       ` Wolfgang Denk
  2009-05-14  9:23         ` Ilya Yanok
  2009-05-14 13:40         ` Sascha Hauer
  0 siblings, 2 replies; 49+ messages in thread
From: Wolfgang Denk @ 2009-05-14  8:10 UTC (permalink / raw)
  To: u-boot

Dear Ilya Yanok,

In message <4A0B4F9A.8030503@emcraft.com> you wrote:
> 
> >> +		return 26000000 / 1.5;
> >
> > We definitely do not allow any FP use in U-Boot.
> 
> This will be actually converted to an integer at the compile time.

Maybe. But it's also trivial not to use any FP calculations at all.

> >> +void imx_gpio_mode(int gpio_mode)
> >> +{
> >> +	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)
> >> +		PUEN(port) |= (1 << pin);
> >> +	else
> >> +		PUEN(port) &= ~(1 << pin);
> >>     
> >
> > This smells as if these were pointer accesses using register offsets
> > instead of I/O accessor calls using C structs?
> >   
> 
> Ok, I really like using accessor calls instead of pointer accesses but I
> don't really understand the reason for using C structs here... I
> remember I've already asked you about that and you told me that it's for
> type safety... But we loose this type-safety when we are using I/O
> accessor functions! All pointers are just silently converted to the
> needed type... 

They are not _silently_ converted. They raise compiler warnings. If,
for example, I try to access a 32 bit register using a 16 bit I/O
accessor function as simulated by this (bogus) change:

-       out_be32(&fec->eth->r_des_active, 0x01000000);
+       out_be16(&fec->eth->r_des_active, 0x01000000);

then the compiler will complain:

mpc512x_fec.c: In function 'mpc512x_fec_rbd_clean':
mpc512x_fec.c:125: warning: passing argument 1 of 'out_be16' from incompatible pointer type

I never understood why you claim such type checking would not
happen...

>            ... On the other hand Linux uses offsets for registers
> definitions so converting them to C structs makes porting and
> maintaining ported drivers harder...

It is incorrect to state that "Linux uses offsets for registers". The
Linux code for ARM may do this, and I consider this one of the major
deficiencies of the ARM code in Linux. Other architectures (like
PowerPC) deprecated this long ago.

And in U-Boot we also don't accept this any more.

> > You probably want to use the respective clrbits*() / setbits*() macros
> > here?
> 
> I can see these macros defined only for ppc arch... And I really prefer
> generic writel(readl() | something) here... The reason is the same: to
> preserve as much code as it possible in drivers ported from Linux.

Yes, I am aware of this. This is another area where cleanup is needed.

Note that I'm not sure if readl() can be considered "generic" across
architectures. If my understanding is correct, then in Linux the
ioread() / iowrite() are considered portable and should be used, i. e.
ioread16(), ioread16be(), ioread32(), ioread32be() etc., with the
plain ioread*() [i. e. without the "be" part] being little-endian on
all architectures.

> >> +#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)
> >>     
> >
> > NAK. We do not accept device I/O through pointers; please use C
> > structs to describe the hardware and use I/O accessor calls.
> >   
> 
> These are actually base addresses. I don't think we can make use of C
> structs here.

Well, each of these addresses points to some device registers that
shoud be described by a C struct. Of course it is possible to sum
these structs up into a big struct like it is done with the IMMR
structs for PowerPC. It has been discussed if this makes sense,
especially when there should be huge gaps in such a stuct, but this is
obviously not the case here. So what prevents you from doung something
like

	struct imx_io {
		struct ... imx_aipi1;
		struct ... imx_wdt;
		struct ... imx_tim[3];
		struct ... imx_uart[4];
		struct ... imx_i2c1;
		...
	};
?

Then just a single base address (IMX_IO_BASE) is left [and I wonder if
you cannot read this from some register.]

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
In theory, there is no difference between  theory  and  practice.  In
practice, however, there is.

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

* [U-Boot] [PATCH 01/10] mx27: basic cpu support
  2009-05-14  8:10       ` Wolfgang Denk
@ 2009-05-14  9:23         ` Ilya Yanok
  2009-05-14  9:42           ` Wolfgang Denk
  2009-05-14 13:40         ` Sascha Hauer
  1 sibling, 1 reply; 49+ messages in thread
From: Ilya Yanok @ 2009-05-14  9:23 UTC (permalink / raw)
  To: u-boot

Hi Wolfgang,

Wolfgang Denk wrote:
>> Ok, I really like using accessor calls instead of pointer accesses but I
>> don't really understand the reason for using C structs here... I
>> remember I've already asked you about that and you told me that it's for
>> type safety... But we loose this type-safety when we are using I/O
>> accessor functions! All pointers are just silently converted to the
>> needed type... 
>>     
>
> They are not _silently_ converted. They raise compiler warnings. If,
> for example, I try to access a 32 bit register using a 16 bit I/O
> accessor function as simulated by this (bogus) change:
>
> -       out_be32(&fec->eth->r_des_active, 0x01000000);
> +       out_be16(&fec->eth->r_des_active, 0x01000000);
>
> then the compiler will complain:
>
> mpc512x_fec.c: In function 'mpc512x_fec_rbd_clean':
> mpc512x_fec.c:125: warning: passing argument 1 of 'out_be16' from incompatible pointer type
>
> I never understood why you claim such type checking would not
> happen...
>   

Well, out_be32() and friends don't convert pointer, you are right. But
these functions are not really generic, they can be found only on couple
of archs. And writel() and friends (which are generic accessor functions
for MMIO) do silent pointer conversion...

>>            ... On the other hand Linux uses offsets for registers
>> definitions so converting them to C structs makes porting and
>> maintaining ported drivers harder...
>>     
>
> It is incorrect to state that "Linux uses offsets for registers". The
> Linux code for ARM may do this, and I consider this one of the major
> deficiencies of the ARM code in Linux. Other architectures (like
> PowerPC) deprecated this long ago.
>
> And in U-Boot we also don't accept this any more.
>   

I see. PowerPC in Linux uses C structs too. But there are still a lot of
code that uses registers offsets in Linux, so my arguments are the same:
requirement to convert offsets to C struct brings additional
difficulties to porting (and maintaining already ported) drivers from Linux.

>> These are actually base addresses. I don't think we can make use of C
>> structs here.
>>     
>
> Well, each of these addresses points to some device registers that
> shoud be described by a C struct. Of course it is possible to sum
> these structs up into a big struct like it is done with the IMMR
> structs for PowerPC. It has been discussed if this makes sense,
> especially when there should be huge gaps in such a stuct, but this is
> obviously not the case here. So what prevents you from doung something
> like
>
> 	struct imx_io {
> 		struct ... imx_aipi1;
> 		struct ... imx_wdt;
> 		struct ... imx_tim[3];
> 		struct ... imx_uart[4];
> 		struct ... imx_i2c1;
> 		...
> 	};
> ?
>
> Then just a single base address (IMX_IO_BASE) is left [and I wonder if
> you cannot read this from some register.]
>   

Ok, we can do that. But for what reason? I don't think this improves
readability...

Regards, Ilya.

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

* [U-Boot] [PATCH 01/10] mx27: basic cpu support
  2009-05-14  9:23         ` Ilya Yanok
@ 2009-05-14  9:42           ` Wolfgang Denk
  2009-05-14 10:26             ` Ilya Yanok
  2009-05-18 16:59             ` Magnus Lilja
  0 siblings, 2 replies; 49+ messages in thread
From: Wolfgang Denk @ 2009-05-14  9:42 UTC (permalink / raw)
  To: u-boot

Dear Ilya,

in message <4A0BE30F.9070902@emcraft.com> you wrote:
>
> Well, out_be32() and friends don't convert pointer, you are right. But
> these functions are not really generic, they can be found only on couple
> of archs. And writel() and friends (which are generic accessor functions
> for MMIO) do silent pointer conversion...

That's a serious deficiency of the (current) ARM implementation then.
Also please keep in mind that, at least in Linux, readl() / writel()
and friend are primarily intended to perform PCI memory accesses via
an ioremap region, and that they perform little endian accesses.

I agree that the current definition:

	#define __arch_getl(a)		(*(volatile unsigned int *)(a))
	...
	#define readl(a)		__arch_getl(a)

is indeed horrible and does not perform any of the  type  checking  I
supposedit was doing.   [Hm.. sometimes I wish I had better knowledge
of the ARM code in U-Boot and Linux, but at  times  like  this  I  am
pretty sure that I should be happy that I don't :-( ]

> I see. PowerPC in Linux uses C structs too. But there are still a lot of
> code that uses registers offsets in Linux, so my arguments are the same:
> requirement to convert offsets to C struct brings additional
> difficulties to porting (and maintaining already ported) drivers from Linux.

I understand your argument, but the decision has been made. We want to
get rid of this pointer stuff in U-Boot, and do not accept any new
code like this any more.

> Ok, we can do that. But for what reason? I don't think this improves
> readability...

Well, I don't think long lists of address offsets improve readability.

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
In the beginning, there was nothing, which exploded.
                                - Terry Pratchett, _Lords and Ladies_

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

* [U-Boot] [PATCH 01/10] mx27: basic cpu support
  2009-05-14  9:42           ` Wolfgang Denk
@ 2009-05-14 10:26             ` Ilya Yanok
  2009-05-14 12:33               ` Wolfgang Denk
  2009-05-18 16:59             ` Magnus Lilja
  1 sibling, 1 reply; 49+ messages in thread
From: Ilya Yanok @ 2009-05-14 10:26 UTC (permalink / raw)
  To: u-boot

Dear Wolfgang,

Wolfgang Denk wrote:
>> I see. PowerPC in Linux uses C structs too. But there are still a lot of
>> code that uses registers offsets in Linux, so my arguments are the same:
>> requirement to convert offsets to C struct brings additional
>> difficulties to porting (and maintaining already ported) drivers from Linux.
>>     
>
> I understand your argument, but the decision has been made. We want to
> get rid of this pointer stuff in U-Boot, and do not accept any new
> code like this any more.
>   

Another issue I've just faced: how we are going to access IO registers
from assembler code? I don't think we have that asm-offsets stuff in
U-Boot...

Regards, Ilya.

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

* [U-Boot] [PATCH 01/10] mx27: basic cpu support
  2009-05-14 10:26             ` Ilya Yanok
@ 2009-05-14 12:33               ` Wolfgang Denk
  0 siblings, 0 replies; 49+ messages in thread
From: Wolfgang Denk @ 2009-05-14 12:33 UTC (permalink / raw)
  To: u-boot

Dear Ilya,

In message <4A0BF1CF.9030907@emcraft.com> you wrote:
> 
> Another issue I've just faced: how we are going to access IO registers
> from assembler code? I don't think we have that asm-offsets stuff in
> U-Boot...

I faced the same problem with the recent  MPC512x  patches;  I  think
it's  time  to  introduce  asm-offsets  (or rather generalize - BF is
already using this, though not really extendable) for U-Boot, too.

For the MPC512x I created a new file cpu/mpc512x/asm-offsets.h which
contains the needed definitions, with the intention to add
auto-generation for this file as soon as possible.

I recommend you do the same.

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
There's another way to survive.  Mutual trust -- and help.
	-- Kirk, "Day of the Dove", stardate unknown

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

* [U-Boot] [PATCH 01/10] mx27: basic cpu support
  2009-05-14  8:10       ` Wolfgang Denk
  2009-05-14  9:23         ` Ilya Yanok
@ 2009-05-14 13:40         ` Sascha Hauer
  2009-05-14 13:56           ` Wolfgang Denk
  1 sibling, 1 reply; 49+ messages in thread
From: Sascha Hauer @ 2009-05-14 13:40 UTC (permalink / raw)
  To: u-boot

On Thu, May 14, 2009 at 10:10:07AM +0200, Wolfgang Denk wrote:
> Dear Ilya Yanok,
> 
> In message <4A0B4F9A.8030503@emcraft.com> you wrote:
> > 
> > >> +		return 26000000 / 1.5;
> > >
> > > We definitely do not allow any FP use in U-Boot.
> > 
> > This will be actually converted to an integer at the compile time.
> 
> Maybe. But it's also trivial not to use any FP calculations at all.
> 
> > >> +void imx_gpio_mode(int gpio_mode)
> > >> +{
> > >> +	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)
> > >> +		PUEN(port) |= (1 << pin);
> > >> +	else
> > >> +		PUEN(port) &= ~(1 << pin);
> > >>     
> > >
> > > This smells as if these were pointer accesses using register offsets
> > > instead of I/O accessor calls using C structs?
> > >   
> > 
> > Ok, I really like using accessor calls instead of pointer accesses but I
> > don't really understand the reason for using C structs here... I
> > remember I've already asked you about that and you told me that it's for
> > type safety... But we loose this type-safety when we are using I/O
> > accessor functions! All pointers are just silently converted to the
> > needed type... 
> 
> They are not _silently_ converted. They raise compiler warnings. If,
> for example, I try to access a 32 bit register using a 16 bit I/O
> accessor function as simulated by this (bogus) change:
> 
> -       out_be32(&fec->eth->r_des_active, 0x01000000);
> +       out_be16(&fec->eth->r_des_active, 0x01000000);
> 
> then the compiler will complain:
> 
> mpc512x_fec.c: In function 'mpc512x_fec_rbd_clean':
> mpc512x_fec.c:125: warning: passing argument 1 of 'out_be16' from incompatible pointer type
> 
> I never understood why you claim such type checking would not
> happen...
> 
> >            ... On the other hand Linux uses offsets for registers
> > definitions so converting them to C structs makes porting and
> > maintaining ported drivers harder...
> 
> It is incorrect to state that "Linux uses offsets for registers". The
> Linux code for ARM may do this, and I consider this one of the major
> deficiencies of the ARM code in Linux. Other architectures (like
> PowerPC) deprecated this long ago.

Can you provide some pointers to a discussion? I sometimes google for
this topic, but I never found something relevant.

> 
> And in U-Boot we also don't accept this any more.
> 
> > > You probably want to use the respective clrbits*() / setbits*() macros
> > > here?
> > 
> > I can see these macros defined only for ppc arch... And I really prefer
> > generic writel(readl() | something) here... The reason is the same: to
> > preserve as much code as it possible in drivers ported from Linux.
> 
> Yes, I am aware of this. This is another area where cleanup is needed.

The good thing about writel(readl() | something) is that this makes it
clear that this operation is not atomic.

> 
> Note that I'm not sure if readl() can be considered "generic" across
> architectures. If my understanding is correct, then in Linux the
> ioread() / iowrite() are considered portable and should be used, i. e.
> ioread16(), ioread16be(), ioread32(), ioread32be() etc., with the
> plain ioread*() [i. e. without the "be" part] being little-endian on
> all architectures.
> 
> > >> +#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)
> > >>     
> > >
> > > NAK. We do not accept device I/O through pointers; please use C
> > > structs to describe the hardware and use I/O accessor calls.
> > >   
> > 
> > These are actually base addresses. I don't think we can make use of C
> > structs here.
> 
> Well, each of these addresses points to some device registers that
> shoud be described by a C struct. Of course it is possible to sum
> these structs up into a big struct like it is done with the IMMR
> structs for PowerPC. It has been discussed if this makes sense,
> especially when there should be huge gaps in such a stuct, but this is
> obviously not the case here. So what prevents you from doung something
> like
> 
> 	struct imx_io {
> 		struct ... imx_aipi1;
> 		struct ... imx_wdt;
> 		struct ... imx_tim[3];
> 		struct ... imx_uart[4];
> 		struct ... imx_i2c1;
> 		...
> 	};
> ?

Sorry, but IMO structs over registers simply suck. I never found
typechecking an issue when searching for bugs, but what I found an issue
several times is to check which register is accessed, especially when
the names in structs differ from those in the datasheet. I have often
enough counted the members in a struct to determine the offset of a
register.

I wouldn't enforce people using structs over hardware registers. This
really hurts portability between U-Boot and the Kernel.

> 
> Then just a single base address (IMX_IO_BASE) is left [and I wonder if
> you cannot read this from some register.]

Arm processors usually have their registers on a fixed address. You
can't map them to another place.

Sascha

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

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

* [U-Boot] [PATCH 01/10] mx27: basic cpu support
  2009-05-14 13:40         ` Sascha Hauer
@ 2009-05-14 13:56           ` Wolfgang Denk
  0 siblings, 0 replies; 49+ messages in thread
From: Wolfgang Denk @ 2009-05-14 13:56 UTC (permalink / raw)
  To: u-boot

Dear Sascha,

in message <20090514134055.GA29278@pengutronix.de> you wrote:
>
> > It is incorrect to state that "Linux uses offsets for registers". The
> > Linux code for ARM may do this, and I consider this one of the major
> > deficiencies of the ARM code in Linux. Other architectures (like
> > PowerPC) deprecated this long ago.
> 
> Can you provide some pointers to a discussion? I sometimes google for
> this topic, but I never found something relevant.

Sorry, I don't have any specific links.


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
If you think the problem is bad now, just wait until we've solved it.
                                                        Epstein's Law

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

* [U-Boot] [PATCH 01/10] mx27: basic cpu support
  2009-05-14  9:42           ` Wolfgang Denk
  2009-05-14 10:26             ` Ilya Yanok
@ 2009-05-18 16:59             ` Magnus Lilja
  2009-05-18 17:34               ` Scott Wood
  2009-05-18 18:42               ` Wolfgang Denk
  1 sibling, 2 replies; 49+ messages in thread
From: Magnus Lilja @ 2009-05-18 16:59 UTC (permalink / raw)
  To: u-boot

Dear Wolfgang,

2009/5/14 Wolfgang Denk <wd@denx.de>:
>> I see. PowerPC in Linux uses C structs too. But there are still a lot of
>> code that uses registers offsets in Linux, so my arguments are the same:
>> requirement to convert offsets to C struct brings additional
>> difficulties to porting (and maintaining already ported) drivers from Linux.
>
> I understand your argument, but the decision has been made. We want to
> get rid of this pointer stuff in U-Boot, and do not accept any new
> code like this any more.

After having browsed some powerpc code I can find two different ways
the struct-thing is used:
Variant A, all members declared volatile:
struct controller_reg {
  volatile uint32_t reg1;
  volatile uint32_t reg2;
}

struct controller_reg *controller = 0xCAFE0000;

Or variant B:
struct controller_reg {
  uint32_t reg1;
  uint32_t reg2;
}

volatile struct controller_reg *controller = 0xCAFE0000;

Also, is it OK to access the registers using reg = controller->reg1 or
should we use reg = readl(&controller->reg1)?

I ask this since I don't want to iterate the patches on the mailing
list too many times...

Regards, Magnus

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

* [U-Boot] [PATCH 01/10] mx27: basic cpu support
  2009-05-18 16:59             ` Magnus Lilja
@ 2009-05-18 17:34               ` Scott Wood
  2009-05-18 18:42               ` Wolfgang Denk
  1 sibling, 0 replies; 49+ messages in thread
From: Scott Wood @ 2009-05-18 17:34 UTC (permalink / raw)
  To: u-boot

On Mon, May 18, 2009 at 06:59:18PM +0200, Magnus Lilja wrote:
> After having browsed some powerpc code I can find two different ways
> the struct-thing is used:
> Variant A, all members declared volatile:
> struct controller_reg {
>   volatile uint32_t reg1;
>   volatile uint32_t reg2;
> }
> 
> struct controller_reg *controller = 0xCAFE0000;
> 
> Or variant B:
> struct controller_reg {
>   uint32_t reg1;
>   uint32_t reg2;
> }
> 
> volatile struct controller_reg *controller = 0xCAFE0000;

Those are both deprecated.  There should be no volatile, and you should
use I/O accessors instead.

> Also, is it OK to access the registers using reg = controller->reg1 or
> should we use reg = readl(&controller->reg1)?

The latter.  Note that readl is supposed to be little-endian regardless
of host endianness, though ARM's io.h looks a bit weird (there are
multiple definitions of readl protected by ifdefs, and the normal one
does no swapping -- and __mem_pci looks like it would result in a name
conflict).  On powerpc we have accessors with explicit endianness.

-Scott

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

* [U-Boot] [PATCH 01/10] mx27: basic cpu support
  2009-05-18 16:59             ` Magnus Lilja
  2009-05-18 17:34               ` Scott Wood
@ 2009-05-18 18:42               ` Wolfgang Denk
  1 sibling, 0 replies; 49+ messages in thread
From: Wolfgang Denk @ 2009-05-18 18:42 UTC (permalink / raw)
  To: u-boot

Dear Magnus,

In message <59b21cf20905180959p4e736d52g566b0e826e17c07a@mail.gmail.com> you wrote:
> 
> After having browsed some powerpc code I can find two different ways
> the struct-thing is used:
> Variant A, all members declared volatile:
> struct controller_reg {
>   volatile uint32_t reg1;
>   volatile uint32_t reg2;
> }

This is probably older code.

> struct controller_reg *controller = 0xCAFE0000;
> 
> Or variant B:
> struct controller_reg {
>   uint32_t reg1;
>   uint32_t reg2;
> }

This is OK.

> volatile struct controller_reg *controller = 0xCAFE0000;
> 
> Also, is it OK to access the registers using reg = controller->reg1 or

No.

> should we use reg = readl(&controller->reg1)?

Yes. All device acesses should use proper I/O accessor calls.

Note though that readl() is not considered to be portable; at least
not across architectures. In Linux the ioread() / iowrite() are
considered portable and should be used, i. e. ioread16(),
ioread16be(), ioread32(), ioread32be() etc. - the plain ioread*()
[i. e. without the "be" part] being little-endian on all
architectures.


I am aware that we don't have appropriate support for all of this in
the standard header files yet (actually I don't think Linu xhas this
yet, either).

But that's the theory. Or at least the intersection of what I've been
told, what I understood and what I still remember ;-)

> I ask this since I don't want to iterate the patches on the mailing
> list too many times...

Good luck!

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
In the beginning, there was nothing, which exploded.
                                - Terry Pratchett, _Lords and Ladies_

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

* [U-Boot] [PATCH 10/10] imx27lite: add support for imx27lite board from LogicPD
  2009-05-06 18:30 ` [U-Boot] [PATCH 10/10] imx27lite: add support for imx27lite board from LogicPD Ilya Yanok
  2009-05-06 20:34   ` Magnus Lilja
  2009-05-06 21:29   ` Wolfgang Denk
@ 2009-05-19 16:17   ` Paul Thomas
  2009-05-20 18:49     ` Ilya Yanok
  2 siblings, 1 reply; 49+ messages in thread
From: Paul Thomas @ 2009-05-19 16:17 UTC (permalink / raw)
  To: u-boot

On Wed, May 6, 2009 at 11:30 AM, Ilya Yanok <yanok@emcraft.com> 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>
> ---
>  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 |  225
> +++++++++++++++++++++++++++++++
>  board/logicpd/imx27lite/u-boot.lds      |   56 ++++++++
>  include/configs/imx27lite.h             |  188 ++++++++++++++++++++++++++
>  8 files changed, 622 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/MAKEALL b/MAKEALL
> index f13c81a..4806512 100755
> --- a/MAKEALL
> +++ b/MAKEALL
> @@ -504,6 +504,7 @@ LIST_ARM9="                 \
>        cp946es                 \
>        cp966                   \
>        lpd7a400                \
> +       imx27lite               \
>        mx1ads                  \
>        mx1fs2                  \
>        netstar                 \
> diff --git a/Makefile b/Makefile
> index 137c88f..0c52bfa 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..48c7fe6
> --- /dev/null
> +++ b/board/logicpd/imx27lite/lowlevel_init.S
> @@ -0,0 +1,225 @@
> +/*
> + * 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>
> +
> +#define CFG_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 CFG_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 CFG_SDRAM_ALL_VAL              0xf00
> +
> +#define CFG_SDRAM_MODE_REGISTER_VAL    0x33    /* BL: 8, CAS: 3 */
> +#define CFG_SDRAM_EXT_MODE_REGISTER_VAL        0x1000000
> +
> +#define CFG_MPCTL0_VAL 0x1ef15d5
> +
> +#define CFG_SPCTL0_VAL 0x043a1c09
> +
> +#define CFG_CSCR_VAL   0x33f08107
> +
> +#define CFG_PCDR0_VAL  0x120470c3
> +#define CFG_PCDR1_VAL  0x03030303
> +#define CFG_PCCR0_VAL  0xffffffff
> +#define CFG_PCCR1_VAL  0xfffffffc
> +
> +#define CFG_AIPI1_PSR0_VAL     0x20040304
> +#define CFG_AIPI1_PSR1_VAL     0xdffbfcfb
> +#define CFG_AIPI2_PSR0_VAL     0x07ffc200
> +#define CFG_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   CFG_SDRAM_ESDCFG_REGISTER_VAL(0)
> +SDRAM_ESDCFG_T2_W:     .word   CFG_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   CFG_SDRAM_ESDCTL_REGISTER_VAL
> +
> +       .macro init_aipi
> +       /*
> +        * setup AIPI1 and AIPI2
> +        */
> +       writel(AIPI1_PSR0, CFG_AIPI1_PSR0_VAL)
> +       writel(AIPI1_PSR1, CFG_AIPI1_PSR1_VAL)
> +       writel(AIPI2_PSR0, CFG_AIPI2_PSR0_VAL)
> +       writel(AIPI2_PSR1, CFG_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]
> +
> +       /*
> +        * pll clock initialization predefined in apf27.h
> +        */
> +       writel(MPCTL0, CFG_MPCTL0_VAL)
> +       writel(SPCTL0, CFG_SPCTL0_VAL)
> +
> +       writel(CSCR, CFG_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, CFG_PCDR0_VAL)
> +       writel(PCDR1, CFG_PCDR1_VAL)
> +
> +       /* Configure PCCR0 and PCCR1 */
> +       writel(PCCR0, CFG_PCCR0_VAL)
> +       writel(PCCR1, CFG_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, #CFG_SDRAM_ALL_VAL]
> +
> +       ldr r1, SDRAM_AUTOREF_CMD_W
> +       str r1, [r0, #ESDCTL0_ROF]
> +       ldr r1, [r2, #CFG_SDRAM_ALL_VAL]
> +       ldr r1, [r2, #CFG_SDRAM_ALL_VAL]
> +
> +       ldr r1, SDRAM_LOADMODE_CMD_W
> +       str r1, [r0, #ESDCTL0_ROF]
> +       ldrb r1, [r2, #CFG_SDRAM_MODE_REGISTER_VAL]
> +       add r3, r2, #CFG_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, #CFG_SDRAM_ALL_VAL]
> +
> +       ldr r1, SDRAM_AUTOREF_CMD_W
> +       str r1, [r0, #ESDCTL1_ROF]
> +       ldr r1, [r2, #CFG_SDRAM_ALL_VAL]
> +       ldr r1, [r2, #CFG_SDRAM_ALL_VAL]
> +
> +       ldr r1, SDRAM_LOADMODE_CMD_W
> +       str r1, [r0, #ESDCTL1_ROF]
> +       ldrb r1, [r2, #CFG_SDRAM_MODE_REGISTER_VAL]
> +       add r3, r2, #CFG_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..80fb291
> --- /dev/null
> +++ b/include/configs/imx27lite.h
> @@ -0,0 +1,188 @@
> +/*
> + * 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_MX31_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 */
> +/*=============*/
> +#define CONFIG_SYS_MALLOC_LEN          (0x10000 + 128*1024)    /* malloc()
> len */
> +#define CONFIG_SYS_GBL_DATA_SIZE       128             /* reserved for
> initial data */
> +#define CONFIG_SYS_MEMTEST_START       0xA0000000      /* memtest start
> address */
> +#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_MX31_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 */
> +#define CONFIG_ENV_OFFSET              (PHYS_FLASH_SIZE - 0x20000)     /*
> end of flash */
> +#define PHYS_FLASH_1                   0xc0000000      /* CS2 Base address
>      */
> +#define CONFIG_SYS_FLASH_BASE          PHYS_FLASH_1    /* Flash Base for
> U-Boot */
> +#define PHYS_FLASH_SIZE                        0x200000        /* Flash
> size 2MB        */
> +#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
> +/*
> + * 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
> +/*
> + * SD/MMC
> + */
> +#define CONFIG_MMC
> +#define CONFIG_GENERIC_MMC
> +#define CONFIG_MXC_MMC
> +#define CONFIG_MXC_MCI_REGS_BASE       0x10014000
> +#define CONFIG_DOS_PARTITION
> +/*
> + * JFFS2 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:-(nand)"
> +
> +/*==============================*/
> +/* 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 */
> +#define CONFIG_SYS_BARGSIZE    CONFIG_SYS_CBSIZE       /* Boot Argument
> Buffer Size */
> +#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_NET
> +#undef CONFIG_CMD_NFS
> +#define CONFIG_CMD_MII
> +#define CONFIG_CMD_PING
> +#undef CONFIG_CMD_BDI
> +#undef CONFIG_CMD_FPGA
> +#undef CONFIG_CMD_SETGETDCR
> +#define CONFIG_CMD_NAND
> +#define CONFIG_CMD_JFFS2
> +#define CONFIG_CMD_MMC
> +#define CONFIG_CMD_FAT
> +
> +/*
> + * You can compile in a MAC address and your custom net settings by using
> + * the following syntax.
> + *
> + * #define CONFIG_ETHADDR              xx:xx:xx:xx:xx:xx
> + * #define CONFIG_SERVERIP             <server ip>
> + * #define CONFIG_IPADDR               <board ip>
> + * #define CONFIG_GATEWAYIP            <gateway ip>
> + * #define CONFIG_NETMASK              <your netmask>
> + */
> +
> +#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
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot
>

Hello,

I was trying to test out this patch, and I'm having some trouble. I did a
git pull on the u-boot tree, and then I saved this patch to a text file. I
was able to apply the patch just fine. The first thing that happend was make
didn't like the Makefile, but I think it was just a space problem because
after I edited the Makefile to match the entries around imx27lite_config it
worked OK. Now when I run make it gives the error:

make[1]: Leaving directory `/home/raid5/imx27env/u-boot/cpu/arm926ejs'
make -C cpu/arm926ejs/mx27/
make: *** cpu/arm926ejs/mx27/: No such file or directory.  Stop.
make: *** [cpu/arm926ejs/mx27/libmx27.a] Error 2

How do I know what git version to use the patch against? If I were using
git-am instead of just saving it to a file would that be different? Is there
another patch I need?

thanks,
Paul

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

* [U-Boot] [PATCH 10/10] imx27lite: add support for imx27lite board from LogicPD
  2009-05-19 16:17   ` Paul Thomas
@ 2009-05-20 18:49     ` Ilya Yanok
  2009-05-20 19:49       ` Paul Thomas
  2009-05-28 19:46       ` Paul Thomas
  0 siblings, 2 replies; 49+ messages in thread
From: Ilya Yanok @ 2009-05-20 18:49 UTC (permalink / raw)
  To: u-boot

Hello Paul,

> I was trying to test out this patch, and I'm having some trouble. I
> did a git pull on the u-boot tree, and then I saved this patch to a
> text file. I was able to apply the patch just fine. The first thing
> that happend was make didn't like the Makefile, but I think it was
> just a space problem because after I edited the Makefile to match the
> entries around imx27lite_config it worked OK. Now when I run make it
> gives the error:
>
> make[1]: Leaving directory `/home/raid5/imx27env/u-boot/cpu/arm926ejs'
> make -C cpu/arm926ejs/mx27/
> make: *** cpu/arm926ejs/mx27/: No such file or directory.  Stop.
> make: *** [cpu/arm926ejs/mx27/libmx27.a] Error 2
>
> How do I know what git version to use the patch against? If I were
> using git-am instead of just saving it to a file would that be
> different? Is there another patch I need?

You need to apply other patches too (at least generic imx27 support and
patch for serial console driver).

Regards, Ilya.

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

* [U-Boot] [PATCH 10/10] imx27lite: add support for imx27lite board from LogicPD
  2009-05-20 18:49     ` Ilya Yanok
@ 2009-05-20 19:49       ` Paul Thomas
  2009-05-28 19:46       ` Paul Thomas
  1 sibling, 0 replies; 49+ messages in thread
From: Paul Thomas @ 2009-05-20 19:49 UTC (permalink / raw)
  To: u-boot

On Wed, May 20, 2009 at 11:49 AM, Ilya Yanok <yanok@emcraft.com> wrote:

> Hello Paul,
>
> > I was trying to test out this patch, and I'm having some trouble. I
> > did a git pull on the u-boot tree, and then I saved this patch to a
> > text file. I was able to apply the patch just fine. The first thing
> > that happend was make didn't like the Makefile, but I think it was
> > just a space problem because after I edited the Makefile to match the
> > entries around imx27lite_config it worked OK. Now when I run make it
> > gives the error:
> >
> > make[1]: Leaving directory `/home/raid5/imx27env/u-boot/cpu/arm926ejs'
> > make -C cpu/arm926ejs/mx27/
> > make: *** cpu/arm926ejs/mx27/: No such file or directory.  Stop.
> > make: *** [cpu/arm926ejs/mx27/libmx27.a] Error 2
> >
> > How do I know what git version to use the patch against? If I were
> > using git-am instead of just saving it to a file would that be
> > different? Is there another patch I need?
>
> You need to apply other patches too (at least generic imx27 support and
> patch for serial console driver).
>
> Regards, Ilya.
>
>
Thanks, I saw your most recent patch set. I'm wondering how soot that will
be available in the normal git tree?

-Paul

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

* [U-Boot] [PATCH 10/10] imx27lite: add support for imx27lite board from LogicPD
  2009-05-20 18:49     ` Ilya Yanok
  2009-05-20 19:49       ` Paul Thomas
@ 2009-05-28 19:46       ` Paul Thomas
  2009-05-28 21:45         ` Wolfgang Denk
  1 sibling, 1 reply; 49+ messages in thread
From: Paul Thomas @ 2009-05-28 19:46 UTC (permalink / raw)
  To: u-boot

On Wed, May 20, 2009 at 11:49 AM, Ilya Yanok <yanok@emcraft.com> wrote:

> Hello Paul,
>
> > I was trying to test out this patch, and I'm having some trouble. I
> > did a git pull on the u-boot tree, and then I saved this patch to a
> > text file. I was able to apply the patch just fine. The first thing
> > that happend was make didn't like the Makefile, but I think it was
> > just a space problem because after I edited the Makefile to match the
> > entries around imx27lite_config it worked OK. Now when I run make it
> > gives the error:
> >
> > make[1]: Leaving directory `/home/raid5/imx27env/u-boot/cpu/arm926ejs'
> > make -C cpu/arm926ejs/mx27/
> > make: *** cpu/arm926ejs/mx27/: No such file or directory.  Stop.
> > make: *** [cpu/arm926ejs/mx27/libmx27.a] Error 2
> >
> > How do I know what git version to use the patch against? If I were
> > using git-am instead of just saving it to a file would that be
> > different? Is there another patch I need?
>
> You need to apply other patches too (at least generic imx27 support and
> patch for serial console driver).
>
> Regards, Ilya.
>
>
Where do I find these patches? Does anyone have an ETA when the imx27 stuff
will show up in git?

thanks,
paul

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

* [U-Boot] [PATCH 10/10] imx27lite: add support for imx27lite board from LogicPD
  2009-05-28 19:46       ` Paul Thomas
@ 2009-05-28 21:45         ` Wolfgang Denk
  2009-05-28 21:51           ` Paul Thomas
  2009-06-11 22:38           ` Paul Thomas
  0 siblings, 2 replies; 49+ messages in thread
From: Wolfgang Denk @ 2009-05-28 21:45 UTC (permalink / raw)
  To: u-boot

Dear Paul,

in message <c785bba30905281246y62fa3556y4a2f8e6a9a04469b@mail.gmail.com> you wrote:
>
> Where do I find these patches? Does anyone have an ETA when the imx27 stuff
> will show up in git?

The patches have been posted here on this mailing list.

It's primarily up to Jean-Cristophe when he will apply these patches
to the ARM repository, from where I can pull them.

Note that the old version of that code is available in the "imx27lite"
branch of the u-boot-testing repository; see
http://git.denx.de/?p=u-boot/u-boot-testing.git;a=shortlog;h=refs/heads/imx27lite

I will try to push the new stuff into a "imx27lite_v2" branch ASAP.
Stay tuned.

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
Brain off-line, please wait.

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

* [U-Boot] [PATCH 10/10] imx27lite: add support for imx27lite board from LogicPD
  2009-05-28 21:45         ` Wolfgang Denk
@ 2009-05-28 21:51           ` Paul Thomas
  2009-06-11 22:38           ` Paul Thomas
  1 sibling, 0 replies; 49+ messages in thread
From: Paul Thomas @ 2009-05-28 21:51 UTC (permalink / raw)
  To: u-boot

On Thu, May 28, 2009 at 2:45 PM, Wolfgang Denk <wd@denx.de> wrote:

> Dear Paul,
>
> in message <c785bba30905281246y62fa3556y4a2f8e6a9a04469b@mail.gmail.com>
> you wrote:
> >
> > Where do I find these patches? Does anyone have an ETA when the imx27
> stuff
> > will show up in git?
>
> The patches have been posted here on this mailing list.
>
> It's primarily up to Jean-Cristophe when he will apply these patches
> to the ARM repository, from where I can pull them.
>
> Note that the old version of that code is available in the "imx27lite"
> branch of the u-boot-testing repository; see
>
> http://git.denx.de/?p=u-boot/u-boot-testing.git;a=shortlog;h=refs/heads/imx27lite
>
> I will try to push the new stuff into a "imx27lite_v2" branch ASAP.
> Stay tuned.
>
> 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
> Brain off-line, please wait.


Wolfgang,

Thanks for the info. I'm pulling u-boot-testing now. You might stick a link
to u-boot-testing on the projects root page (http://git.denx.de/). I looked
there before and only saw the u-boot repository.

thanks,
Paul

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

* [U-Boot] [PATCH 10/10] imx27lite: add support for imx27lite board from LogicPD
  2009-05-28 21:45         ` Wolfgang Denk
  2009-05-28 21:51           ` Paul Thomas
@ 2009-06-11 22:38           ` Paul Thomas
  2009-06-13 23:04             ` Paul Thomas
  1 sibling, 1 reply; 49+ messages in thread
From: Paul Thomas @ 2009-06-11 22:38 UTC (permalink / raw)
  To: u-boot

> Note that the old version of that code is available in the "imx27lite"
> branch of the u-boot-testing repository; see
>
> http://git.denx.de/?p=u-boot/u-boot-testing.git;a=shortlog;h=refs/heads/imx27lite


Is this still the best branch for imx27lite? I'm not getting anything on the
serial port when I run this? I'm using a crosstool NG cross-compiler
"arm-unknown-linux-gnu-gcc (crosstool-NG-svn_trunk at 1300) 4.3.2". Will that
work OK? It builds fine. If I load the redboot image then I do get output on
the serial port, and both images seem to be located at 0xa7f00000 which
should be fine.

thanks,
Paul

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

* [U-Boot] [PATCH 10/10] imx27lite: add support for imx27lite board from LogicPD
  2009-06-11 22:38           ` Paul Thomas
@ 2009-06-13 23:04             ` Paul Thomas
  0 siblings, 0 replies; 49+ messages in thread
From: Paul Thomas @ 2009-06-13 23:04 UTC (permalink / raw)
  To: u-boot

On Thu, Jun 11, 2009 at 3:38 PM, Paul Thomas <pthomas8589@gmail.com> wrote:

>
> Note that the old version of that code is available in the "imx27lite"
>> branch of the u-boot-testing repository; see
>>
>> http://git.denx.de/?p=u-boot/u-boot-testing.git;a=shortlog;h=refs/heads/imx27lite
>
>
> Is this still the best branch for imx27lite? I'm not getting anything on
> the serial port when I run this? I'm using a crosstool NG cross-compiler
> "arm-unknown-linux-gnu-gcc (crosstool-NG-svn_trunk at 1300) 4.3.2". Will that
> work OK? It builds fine. If I load the redboot image then I do get output on
> the serial port, and both images seem to be located at 0xa7f00000 which
> should be fine.
>
> thanks,
> Paul
>

I did pull this tarball:
http://git.denx.de/?p=u-boot/u-boot-testing.git;a=shortlog;h=refs/heads/imx27lite-v2

But it's still not working. So to figure this out I started single stepping
through u-boot with gdb. I get to line 186 in lowlevel_init.S. The line is
"str r1, [r0, #ESDCFG1_ROF]". This looks like a simple simple store
instruction. Any thoughts as to why it stops there?

thanks,
Paul

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

end of thread, other threads:[~2009-06-13 23:04 UTC | newest]

Thread overview: 49+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-05-06 18:30 [U-Boot] [PATCH 00/10] Support for LogicPD i.MX27-LITEKIT development board Ilya Yanok
2009-05-06 18:30 ` [U-Boot] [PATCH 01/10] mx27: basic cpu support Ilya Yanok
2009-05-06 20:30   ` Magnus Lilja
2009-05-06 21:16   ` Wolfgang Denk
2009-05-13 22:54     ` Ilya Yanok
2009-05-14  8:10       ` Wolfgang Denk
2009-05-14  9:23         ` Ilya Yanok
2009-05-14  9:42           ` Wolfgang Denk
2009-05-14 10:26             ` Ilya Yanok
2009-05-14 12:33               ` Wolfgang Denk
2009-05-18 16:59             ` Magnus Lilja
2009-05-18 17:34               ` Scott Wood
2009-05-18 18:42               ` Wolfgang Denk
2009-05-14 13:40         ` Sascha Hauer
2009-05-14 13:56           ` Wolfgang Denk
2009-05-06 18:30 ` [U-Boot] [PATCH 02/10] serial_mx31: allow it to work with mx27 too Ilya Yanok
2009-05-06 21:16   ` Wolfgang Denk
2009-05-06 18:30 ` [U-Boot] [PATCH 03/10] fec_imx27: driver for FEC ethernet controller on i.MX27 Ilya Yanok
2009-05-06 19:51   ` Ben Warren
2009-05-06 21:20   ` Wolfgang Denk
2009-05-06 18:30 ` [U-Boot] [PATCH 04/10] mxc_nand: add nand driver for MX2/MX3 Ilya Yanok
2009-05-06 20:31   ` Magnus Lilja
2009-05-06 21:25   ` Wolfgang Denk
2009-05-08  8:39   ` Ivo Clarysse
2009-05-08  8:58     ` Magnus Lilja
2009-05-06 18:30 ` [U-Boot] [PATCH 05/10] mxc-mmc: sdhc host driver for MX2 and MX3 proccessor Ilya Yanok
2009-05-08  0:26   ` alfred steele
2009-05-13 21:50   ` alfred steele
2009-05-06 18:30 ` [U-Boot] [PATCH 06/10] arm: add support for CONFIG_GENERIC_MMC Ilya Yanok
2009-05-06 18:30 ` [U-Boot] [PATCH 07/10] mmc: use lldiv() for 64-bit division Ilya Yanok
2009-05-06 20:32   ` Magnus Lilja
2009-05-08 22:42   ` Andy Fleming
2009-05-06 18:30 ` [U-Boot] [PATCH 08/10] mmc: some endianess fixes for generic mmc subsystem Ilya Yanok
2009-05-08 22:43   ` Andy Fleming
2009-05-06 18:30 ` [U-Boot] [PATCH 09/10] mmc: fix mmcinfo command Ilya Yanok
2009-05-08 22:43   ` Andy Fleming
2009-05-06 18:30 ` [U-Boot] [PATCH 10/10] imx27lite: add support for imx27lite board from LogicPD Ilya Yanok
2009-05-06 20:34   ` Magnus Lilja
2009-05-08 18:19     ` Magnus Lilja
2009-05-06 21:29   ` Wolfgang Denk
2009-05-19 16:17   ` Paul Thomas
2009-05-20 18:49     ` Ilya Yanok
2009-05-20 19:49       ` Paul Thomas
2009-05-28 19:46       ` Paul Thomas
2009-05-28 21:45         ` Wolfgang Denk
2009-05-28 21:51           ` Paul Thomas
2009-06-11 22:38           ` Paul Thomas
2009-06-13 23:04             ` Paul Thomas
2009-05-06 21:26 ` [U-Boot] [PATCH 00/10] Support for LogicPD i.MX27-LITEKIT development board Wolfgang Denk

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.