summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFred Fan <r01011@freescale.com>2009-02-23 13:34:09 +0800
committerFred Fan <r01011@freescale.com>2009-09-09 17:15:27 +0800
commitd409f3fd05bef817c37bade4b6a803da80dc7ad0 (patch)
treed7651f6c09179ff7e72d904dd1b047645840a09b
parent6259800e38b3da575a8436d5616b3920c77f25f5 (diff)
downloadu-boot-imx-d409f3fd05bef817c37bade4b6a803da80dc7ad0.zip
u-boot-imx-d409f3fd05bef817c37bade4b6a803da80dc7ad0.tar.gz
u-boot-imx-d409f3fd05bef817c37bade4b6a803da80dc7ad0.tar.bz2
ENGR00094619 Support i.MX31 3stack board
Support boot from NAND Flash Add driver for i.MX31 NFC Upgate U-Boot to support NAND boot Signed-off-by: Xinyu Chen <xinyu.chen@freescale.com>
-rw-r--r--Makefile3
-rw-r--r--board/freescale/mx31_3stack/Makefile47
-rw-r--r--board/freescale/mx31_3stack/config.mk1
-rw-r--r--board/freescale/mx31_3stack/lowlevel_init.S248
-rw-r--r--board/freescale/mx31_3stack/mx31_3stack.c75
-rw-r--r--board/freescale/mx31_3stack/u-boot.lds72
-rw-r--r--cpu/arm1136/mx31/Makefile4
-rw-r--r--cpu/arm1136/mx31/nand_load.S160
-rw-r--r--cpu/arm1136/start.S113
-rw-r--r--cpu/arm926ejs/mx27/timer.c1
-rw-r--r--drivers/mtd/nand/Makefile1
-rw-r--r--drivers/mtd/nand/mx31_nand.c969
-rw-r--r--include/asm-arm/arch-mx31/mx31-regs.h96
-rw-r--r--include/configs/mx31_3stack.h165
14 files changed, 1925 insertions, 30 deletions
diff --git a/Makefile b/Makefile
index b20d531..413d1f3 100644
--- a/Makefile
+++ b/Makefile
@@ -3229,6 +3229,9 @@ mx31pdk_nand_config : unconfig
fi
@$(MKCONFIG) -a mx31pdk arm arm1136 mx31pdk freescale mx31
+Mx31_3stack_config : unconfig
+ @$(MKCONFIG) $(@:_config=) arm arm1136 mx31_3stack freescale mx31
+
mx35_3stack_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm1136 mx35_3stack freescale mx35
diff --git a/board/freescale/mx31_3stack/Makefile b/board/freescale/mx31_3stack/Makefile
new file mode 100644
index 0000000..836c19c
--- /dev/null
+++ b/board/freescale/mx31_3stack/Makefile
@@ -0,0 +1,47 @@
+#
+# Copyright (C) 2008, Guennadi Liakhovetski <lg@denx.de>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = $(obj)lib$(BOARD).a
+
+COBJS := mx31_3stack.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 .depend
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/freescale/mx31_3stack/config.mk b/board/freescale/mx31_3stack/config.mk
new file mode 100644
index 0000000..d34dc02
--- /dev/null
+++ b/board/freescale/mx31_3stack/config.mk
@@ -0,0 +1 @@
+TEXT_BASE = 0x87f00000
diff --git a/board/freescale/mx31_3stack/lowlevel_init.S b/board/freescale/mx31_3stack/lowlevel_init.S
new file mode 100644
index 0000000..bd0de81
--- /dev/null
+++ b/board/freescale/mx31_3stack/lowlevel_init.S
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2008, Guennadi Liakhovetski <lg@denx.de>
+ * Copyright (C) 2008, Freescale Semiconductor
+ * Modifications for MX31 3Stack board
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <asm/arch/mx31-regs.h>
+
+.macro REG reg, val
+ ldr r2, =\reg
+ ldr r3, =\val
+ str r3, [r2]
+.endm
+
+.macro REG8 reg, val
+ ldr r2, =\reg
+ ldr r3, =\val
+ strb r3, [r2]
+.endm
+
+.macro DELAY loops
+ ldr r2, =\loops
+1:
+ subs r2, r2, #1
+ nop
+ bcs 1b
+.endm
+
+.macro init_aips
+ /*
+ * Set all MPROTx to be non-bufferable, trusted for R/W,
+ * not forced to user-mode.
+ */
+ ldr r0, =0x43F00000
+ ldr r1, =0x77777777
+ str r1, [r0, #0x00]
+ str r1, [r0, #0x04]
+ ldr r0, =0x53F00000
+ str r1, [r0, #0x00]
+ str r1, [r0, #0x04]
+
+ /*
+ * Clear the on and off peripheral modules Supervisor Protect bit
+ * for SDMA to access them. Did not change the AIPS control registers
+ * (offset 0x20) access type
+ */
+ ldr r0, =0x43F00000
+ ldr r1, =0x0
+ str r1, [r0, #0x40]
+ str r1, [r0, #0x44]
+ str r1, [r0, #0x48]
+ str r1, [r0, #0x4C]
+ ldr r1, [r0, #0x50]
+ and r1, r1, #0x00FFFFFF
+ str r1, [r0, #0x50]
+
+ ldr r0, =0x53F00000
+ ldr r1, =0x0
+ str r1, [r0, #0x40]
+ str r1, [r0, #0x44]
+ str r1, [r0, #0x48]
+ str r1, [r0, #0x4C]
+ ldr r1, [r0, #0x50]
+ and r1, r1, #0x00FFFFFF
+ str r1, [r0, #0x50]
+.endm /* init_aips */
+
+.macro init_max
+ ldr r0, =0x43F04000
+ /* MPR - priority is M4 > M2 > M3 > M5 > M0 > M1 */
+ ldr r1, =0x00302154
+ str r1, [r0, #0x000] /* for S0 */
+ str r1, [r0, #0x100] /* for S1 */
+ str r1, [r0, #0x200] /* for S2 */
+ str r1, [r0, #0x300] /* for S3 */
+ str r1, [r0, #0x400] /* for S4 */
+ /* SGPCR - always park on last master */
+ ldr r1, =0x10
+ str r1, [r0, #0x010] /* for S0 */
+ str r1, [r0, #0x110] /* for S1 */
+ str r1, [r0, #0x210] /* for S2 */
+ str r1, [r0, #0x310] /* for S3 */
+ str r1, [r0, #0x410] /* for S4 */
+ /* MGPCR - restore default values */
+ ldr r1, =0x0
+ str r1, [r0, #0x800] /* for M0 */
+ str r1, [r0, #0x900] /* for M1 */
+ str r1, [r0, #0xA00] /* for M2 */
+ str r1, [r0, #0xB00] /* for M3 */
+ str r1, [r0, #0xC00] /* for M4 */
+ str r1, [r0, #0xD00] /* for M5 */
+.endm /* init_max */
+
+.macro init_m3if
+ /* Configure M3IF registers */
+ ldr r1, =0xB8003000
+ /*
+ * M3IF Control Register (M3IFCTL)
+ * MRRP[0] = L2CC0 not on priority list (0 << 0) = 0x00000000
+ * MRRP[1] = L2CC1 not on priority list (0 << 0) = 0x00000000
+ * MRRP[2] = MBX not on priority list (0 << 0) = 0x00000000
+ * MRRP[3] = MAX1 not on priority list (0 << 0) = 0x00000000
+ * MRRP[4] = SDMA not on priority list (0 << 0) = 0x00000000
+ * MRRP[5] = MPEG4 not on priority list (0 << 0) = 0x00000000
+ * MRRP[6] = IPU1 on priority list (1 << 6) = 0x00000040
+ * MRRP[7] = IPU2 not on priority list (0 << 0) = 0x00000000
+ * ------------
+ * 0x00000040
+ */
+ ldr r0, =0x00000040
+ str r0, [r1] /* M3IF control reg */
+.endm /* init_m3if */
+
+.macro init_drive_strength
+ /*
+ * Disable maximum drive strength SDRAM/DDR lines by clearing DSE1 bits
+ * in SW_PAD_CTL registers
+ */
+
+ /* SDCLK */
+ ldr r1, =0x43FAC200
+ ldr r0, [r1, #0x6C]
+ bic r0, r0, #(1 << 12)
+ str r0, [r1, #0x6C]
+
+ /* CAS */
+ ldr r0, [r1, #0x70]
+ bic r0, r0, #(1 << 22)
+ str r0, [r1, #0x70]
+
+ /* RAS */
+ ldr r0, [r1, #0x74]
+ bic r0, r0, #(1 << 2)
+ str r0, [r1, #0x74]
+
+ /* CS2 (CSD0) */
+ ldr r0, [r1, #0x7C]
+ bic r0, r0, #(1 << 22)
+ str r0, [r1, #0x7C]
+
+ /* DQM3 */
+ ldr r0, [r1, #0x84]
+ bic r0, r0, #(1 << 22)
+ str r0, [r1, #0x84]
+
+ /* DQM2, DQM1, DQM0, SD31-SD0, A25-A0, MA10 (0x288..0x2DC) */
+ ldr r2, =22 /* (0x2E0 - 0x288) / 4 = 22 */
+pad_loop:
+ ldr r0, [r1, #0x88]
+ bic r0, r0, #(1 << 22)
+ bic r0, r0, #(1 << 12)
+ bic r0, r0, #(1 << 2)
+ str r0, [r1, #0x88]
+ add r1, r1, #4
+ subs r2, r2, #0x1
+ bne pad_loop
+.endm /* init_drive_strength */
+
+.section ".text.init", "x"
+
+.globl lowlevel_init
+lowlevel_init:
+
+ ldr r0, =0x40000015 /* start from AIPS 2GB region */
+ mcr p15, 0, r0, c15, c2, 4
+
+ init_aips
+
+ init_max
+
+ init_m3if
+
+ init_drive_strength
+
+ /* Image Processing Unit: */
+ /* Too early to switch display on? */
+ REG IPU_CONF, IPU_CONF_DI_EN
+ /* Clock Control Module: */
+ REG CCM_CCMR, 0x074B0BF5 /* Use CKIH, MCU PLL off */
+
+ DELAY 0x40000
+
+ REG CCM_CCMR, 0x074B0BF5 | CCMR_MPE /* MCU PLL on */
+ /* Switch to MCU PLL */
+ REG CCM_CCMR, (0x074B0BF5 | CCMR_MPE) & ~CCMR_MDS
+
+ /* 532-133-66.5 */
+ ldr r0, =CCM_BASE
+ ldr r1, =0xFF871D58
+ /* PDR0 */
+ str r1, [r0, #0x4]
+ ldr r1, MPCTL_PARAM_532
+ /* MPCTL */
+ str r1, [r0, #0x10]
+
+ /* Set UPLL=240MHz, USB=60MHz */
+ ldr r1, =0x49FCFE7F
+ /* PDR1 */
+ str r1, [r0, #0x8]
+ ldr r1, UPCTL_PARAM_240
+ /* UPCTL */
+ str r1, [r0, #0x14]
+ /* default CLKO to 1/8 of the ARM core */
+ mov r1, #0x000002C0
+ add r1, r1, #0x00000006
+ /* COSR */
+ str r1, [r0, #0x1c]
+
+ /* initial CSD0 MDDR */
+ REG 0xB8001004, 0x0075E73A
+ REG 0xB8001010, 0x00000002 /* reset */
+ REG 0xB8001010, 0x00000004
+ DELAY 0x10000
+
+ REG 0xB8001000, 0x92100000
+ REG 0x80000F00, 0x0
+ REG 0xB8001000, 0xA2100000
+ REG 0x80000000, 0x0
+ REG 0xB8001000, 0xB2100000
+ REG8 0x80000033, 0x0
+ REG8 0x81000000, 0xff
+ REG 0xB8001000, 0x82226080
+ REG 0x80000000, 0x0
+ REG 0xB8001010, 0x0000000c
+
+ mov r13, ip
+ /* copy blocks of total uboot to DDR */
+ b mxc_nand_load
+
+MPCTL_PARAM_532:
+ .word (((1-1) << 26) + ((52-1) << 16) + (10 << 10) + (12 << 0))
+UPCTL_PARAM_240:
+ .word (((2-1) << 26) + ((13-1) << 16) + (9 << 10) + (3 << 0))
diff --git a/board/freescale/mx31_3stack/mx31_3stack.c b/board/freescale/mx31_3stack/mx31_3stack.c
new file mode 100644
index 0000000..33adfd3
--- /dev/null
+++ b/board/freescale/mx31_3stack/mx31_3stack.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2008, Guennadi Liakhovetski <lg@denx.de>
+ * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Modifications for MX31 3Stack board
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/mx31.h>
+#include <asm/arch/mx31-regs.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int dram_init(void)
+{
+ gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
+ gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
+
+ return 0;
+}
+
+int board_init(void)
+{
+ /* CS5: Debug board for ethernet */
+ __REG(CSCR_U(5)) = 0x0000D843;
+ __REG(CSCR_L(5)) = 0x22252521;
+ __REG(CSCR_A(5)) = 0x22220A00;
+
+ /* setup pins for UART1 */
+ mx31_gpio_mux(MUX_RXD1__UART1_RXD_MUX);
+ mx31_gpio_mux(MUX_TXD1__UART1_TXD_MUX);
+ mx31_gpio_mux(MUX_RTS1__UART1_RTS_B);
+ mx31_gpio_mux(MUX_RTS1__UART1_CTS_B);
+
+ /* SPI2 */
+ mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_SS2);
+ mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_SCLK);
+ mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_SPI_RDY);
+ mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_MOSI);
+ mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_MISO);
+ mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_SS0);
+ mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_SS1);
+
+ /* start SPI2 clock */
+ __REG(CCM_CGR2) = __REG(CCM_CGR2) | (3 << 4);
+
+ gd->bd->bi_arch_number = MACH_TYPE_MX31_3DS; /* board id for linux */
+ gd->bd->bi_boot_params = 0x80000100; /* adress of boot parameters */
+
+ return 0;
+}
+
+int checkboard(void)
+{
+ printf("Board: MX31 3Stack\n");
+ return 0;
+}
diff --git a/board/freescale/mx31_3stack/u-boot.lds b/board/freescale/mx31_3stack/u-boot.lds
new file mode 100644
index 0000000..8b717ff
--- /dev/null
+++ b/board/freescale/mx31_3stack/u-boot.lds
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@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(reset)
+SECTIONS
+{
+ . = 0x00000000;
+
+ . = ALIGN(4);
+ .text :
+ {
+ /* WARNING - the following is hand-optimized to fit within */
+ /* the sector layout of our flash chips! XXX FIXME XXX */
+
+ * (.text.head) /* arm reset handler */
+ * (.text.init) /* lowlevel initial */
+ * (.text.load) /* nand copy and load */
+ * (.text.setup)
+ board/freescale/mx31_3stack/libmx31_3stack.a (.text)
+ lib_arm/libarm.a (.text)
+ net/libnet.a (.text)
+ drivers/mtd/libmtd.a (.text)
+
+ . = DEFINED(env_offset) ? env_offset : .;
+ common/environment.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/cpu/arm1136/mx31/Makefile b/cpu/arm1136/mx31/Makefile
index c8e18f7..a57465f 100644
--- a/cpu/arm1136/mx31/Makefile
+++ b/cpu/arm1136/mx31/Makefile
@@ -29,6 +29,10 @@ COBJS += generic.o
COBJS += timer.o
COBJS += devices.o
+ifdef CONFIG_NAND_BOOT
+SOBJS = nand_load.o
+endif
+
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
diff --git a/cpu/arm1136/mx31/nand_load.S b/cpu/arm1136/mx31/nand_load.S
new file mode 100644
index 0000000..c0d099a
--- /dev/null
+++ b/cpu/arm1136/mx31/nand_load.S
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2008 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <asm/arch/mx31-regs.h>
+
+.section ".text.load", "x"
+
+.macro wait_op_done
+1: ldrh r3, [r12, #NAND_FLASH_CONFIG2_REG_OFF]
+ ands r3, r3, #NAND_FLASH_CONFIG2_INT_DONE
+ beq 1b
+.endm
+
+data_output:
+ strh r8, [r12, #RAM_BUFFER_ADDRESS_REG_OFF]
+ mov r3, #FDO_PAGE_SPARE_VAL
+ strh r3, [r12, #NAND_FLASH_CONFIG2_REG_OFF]
+ wait_op_done
+ bx lr
+
+send_addr:
+ strh r3, [r12, #NAND_FLASH_ADD_REG_OFF]
+ mov r3, #NAND_FLASH_CONFIG2_FADD_EN
+ strh r3, [r12, #NAND_FLASH_CONFIG2_REG_OFF]
+ wait_op_done
+ bx lr
+
+send_cmd:
+ strh r3, [r12, #NAND_FLASH_CMD_REG_OFF]
+ mov r3, #NAND_FLASH_CONFIG2_FCMD_EN
+ strh r3, [r12, #NAND_FLASH_CONFIG2_REG_OFF]
+ wait_op_done
+ bx lr
+
+
+nand_read_page:
+
+ mov r7, lr
+
+ mov r3, #0x0
+ /* send command */
+ bl send_cmd
+ /* 5 cycles address input */
+ mov r3, #0x0
+ bl send_addr
+ mov r3, #0x0
+ bl send_addr
+ mov r3, r0
+ bl send_addr
+ mov r3, #0x0
+ bl send_addr
+ mov r3, #0x0
+ bl send_addr
+ /* confirm read */
+ mov r3, #0x30
+ bl send_cmd
+ /* data output */
+ mov r8, #0x0
+ mov r4, #0x4
+1:
+ bl data_output
+ add r8, r8, #0x01
+ cmp r8, r4
+ bne 1b
+ ldrh r3, [r12, #ECC_STATUS_RESULT_REG_OFF]
+ tst r3, #0x0a
+ bne .
+ mov pc, r7
+
+.global mxc_nand_load
+mxc_nand_load:
+
+ /* Copy image from flash to SDRAM first */
+ mov r0, #NFC_BASE_ADDR
+ add r12, r0, #0xE00 /* register */
+ add r2, r0, #0x800 /* 2K */
+ ldr r1, __TEXT_BASE
+
+1: ldmia r0!, {r3-r10}
+ stmia r1!, {r3-r10}
+ cmp r0, r2
+ blo 1b
+ /* Jump to SDRAM */
+ ldr r1, =0x0FFF
+ and r0, pc, r1 /* offset of pc */
+ ldr r1, __TEXT_BASE
+ add r1, r1, #0x10
+ add pc, r0, r1
+ nop
+ nop
+ nop
+ nop
+
+nand_copy_block:
+
+ /* wait for boot complete */
+4:
+ ldrh r3, [r12, #NAND_FLASH_CONFIG2_REG_OFF]
+ tst r3, #0x8000
+ beq 4b
+
+ /* unlock buffer and blocks */
+ mov r3, #0x02
+ strh r3, [r12, #NFC_CONFIGURATION_REG_OFF]
+ mov r3, #0x0
+ strh r3, [r12, #UNLOCK_START_BLK_ADD_REG_OFF]
+ mov r3, #0x800
+ strh r3, [r12, #UNLOCK_END_BLK_ADD_REG_OFF]
+ mov r3, #0x04
+ strh r3, [r12, #NF_WR_PROT_REG_OFF]
+ mov r3, #0x10
+ strh r3, [r12, #NAND_FLASH_CONFIG1_REG_OFF]
+
+ /* read 1 block, 256K */
+ mov r0, #0x01 /* page offset */
+ ldr r11, __TEXT_BASE
+ add r11, r11, #0x800
+
+ mov r1, #NFC_BASE_ADDR
+ add r2, r1, #0x800
+2:
+ bl nand_read_page /* r0, r1, r2, r11 has been used */
+ /* copy data from internal buffer */
+3: ldmia r1!, {r3-r10}
+ stmia r11!, {r3-r10}
+ cmp r1, r2
+ blo 3b
+
+ add r0, r0, #0x01
+ cmp r0, #0x80
+ mov r1, #NFC_BASE_ADDR
+ bne 2b
+
+ /* set pc to _set_env */
+ ldr r11, __TEXT_BASE
+ ldr r1, =0x7FF
+ /* correct the lr */
+ and r13, r13, r1
+ add r13, r13, r11
+ mov pc, r13
+
+__TEXT_BASE:
+ .word TEXT_BASE
diff --git a/cpu/arm1136/start.S b/cpu/arm1136/start.S
index 957f438..a957ccc 100644
--- a/cpu/arm1136/start.S
+++ b/cpu/arm1136/start.S
@@ -85,40 +85,15 @@ _end_vect:
*************************************************************************
*/
-_TEXT_BASE:
- .word TEXT_BASE
-
-.globl _armboot_start
-_armboot_start:
- .word _start
-
/*
- * These are defined in the board-specific linker script.
+ * the actual reset code
*/
-.globl _bss_start
-_bss_start:
- .word __bss_start
-
-.globl _bss_end
-_bss_end:
- .word _end
-#ifdef CONFIG_USE_IRQ
-/* IRQ stack memory (calculated at run-time) */
-.globl IRQ_STACK_START
-IRQ_STACK_START:
- .word 0x0badc0de
-
-/* IRQ stack memory (calculated at run-time) */
-.globl FIQ_STACK_START
-FIQ_STACK_START:
- .word 0x0badc0de
+#ifdef CONFIG_NAND_BOOT
+.section ".text.head", "x"
#endif
-/*
- * the actual reset code
- */
-
+.globl reset
reset:
/*
* set the cpu to SVC32 mode
@@ -150,6 +125,86 @@ next:
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif
+ b setup_env
+
+/*
+ *************************************************************************
+ *
+ * CPU_init_critical registers
+ *
+ * setup important registers
+ * setup memory timing
+ *
+ *************************************************************************
+ */
+cpu_init_crit:
+ /*
+ * flush v4 I/D caches
+ */
+ mov r0, #0
+ mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
+ mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
+
+ /*
+ * disable MMU stuff and caches
+ */
+ mrc p15, 0, r0, c1, c0, 0
+ bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
+ bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
+ orr r0, r0, #0x00000002 @ set bit 2 (A) Align
+ orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
+ mcr p15, 0, r0, c1, c0, 0
+
+ /*
+ * Jump to board specific initialization... The Mask ROM will have already initialized
+ * basic memory. Go here to bump up clock rate and handle wake up conditions.
+ */
+ mov ip, lr /* persevere link reg across call */
+ bl lowlevel_init /* go setup pll,mux,memory */
+ mov lr, ip /* restore link */
+ mov pc, lr /* back to my caller */
+
+
+#ifdef CONFIG_NAND_BOOT
+.section ".text.setup"
+#endif
+
+.globl _TEST_BASE
+_TEXT_BASE:
+ .word TEXT_BASE
+
+.globl _armboot_start
+_armboot_start:
+#ifndef CONFIG_NAND_BOOT
+ .word _start
+#else
+ .word reset
+#endif
+
+/*
+ * These are defined in the board-specific linker script.
+ */
+.globl _bss_start
+_bss_start:
+ .word __bss_start
+
+.globl _bss_end
+_bss_end:
+ .word _end
+
+#ifdef CONFIG_USE_IRQ
+/* IRQ stack memory (calculated at run-time) */
+.globl IRQ_STACK_START
+IRQ_STACK_START:
+ .word 0x0badc0de
+
+/* IRQ stack memory (calculated at run-time) */
+.globl FIQ_STACK_START
+FIQ_STACK_START:
+ .word 0x0badc0de
+#endif
+
+setup_env:
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate: /* relocate U-Boot to RAM */
diff --git a/cpu/arm926ejs/mx27/timer.c b/cpu/arm926ejs/mx27/timer.c
index 9011058..1e13627 100644
--- a/cpu/arm926ejs/mx27/timer.c
+++ b/cpu/arm926ejs/mx27/timer.c
@@ -118,7 +118,6 @@ int timer_init(void)
writel(readl(&regs->gpt_tctl) | GPTCR_CLKSOURCE_32 | GPTCR_FRR,
&regs->gpt_tctl);
writel(readl(&regs->gpt_tctl) | GPTCR_TEN, &regs->gpt_tctl);
-
return 0;
}
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 89ccec2..975a1b8 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -46,6 +46,7 @@ COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o
COBJS-$(CONFIG_NAND_S3C64XX) += s3c64xx.o
COBJS-$(CONFIG_NAND_OMAP_GPMC) += omap_gpmc.o
COBJS-$(CONFIG_NAND_PLAT) += nand_plat.o
+COBJS-$(CONFIG_MX31_NAND) += mx31_nand.o
endif
COBJS := $(COBJS-y)
diff --git a/drivers/mtd/nand/mx31_nand.c b/drivers/mtd/nand/mx31_nand.c
new file mode 100644
index 0000000..325e0f0
--- /dev/null
+++ b/drivers/mtd/nand/mx31_nand.c
@@ -0,0 +1,969 @@
+/*
+ * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <common.h>
+#include <nand.h>
+#include <asm-arm/arch/mx31-regs.h>
+
+/*
+ * 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) >> 4)
+#define BITPOS(x) ((x) & 0xf)
+
+/* Define single bit Error positions in Main & Spare area */
+#define MAIN_SINGLEBIT_ERROR 0x4
+#define SPARE_SINGLEBIT_ERROR 0x1
+
+struct nand_info {
+ int oob;
+ int read_status;
+ int largepage;
+ u16 col;
+};
+
+static struct nand_info nandinfo;
+static int ecc_disabled;
+
+/*
+ * OOB placement block for use with hardware ecc generation
+ */
+static struct nand_oobinfo nand_hw_eccoob_8 = {
+ .useecc = MTD_NANDECC_AUTOPL_USR,
+ .eccbytes = 5,
+ .eccpos = {6, 7, 8, 9, 10},
+ .oobfree = {
+ {0, 5},
+ {11, 5}
+ }
+};
+
+static struct nand_oobinfo nand_hw_eccoob_2k = {
+ .useecc = MTD_NANDECC_AUTOPL_USR,
+ .eccbytes = 20,
+ .eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26,
+ 38, 39, 40, 41, 42, 54, 55, 56, 57, 58},
+ .oobfree = {
+ {0, 5},
+ {11, 10},
+ {27, 10},
+ {43, 10},
+ {59, 5}
+ }
+};
+
+/* Define some generic bad / good block scan pattern which are used
+ * while scanning a device for factory marked good / bad blocks. */
+static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
+
+static struct nand_bbt_descr smallpage_memorybased = {
+ .options = NAND_BBT_SCAN2NDPAGE,
+ .offs = 5,
+ .len = 1,
+ .pattern = scan_ff_pattern
+};
+
+static struct nand_bbt_descr largepage_memorybased = {
+ .options = 0,
+ .offs = 0,
+ .len = 2,
+ .pattern = scan_ff_pattern
+};
+
+/* Generic flash bbt decriptors */
+static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
+static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
+
+static struct nand_bbt_descr bbt_main_descr = {
+ .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+ | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+ .offs = 0,
+ .len = 4,
+ .veroffs = 4,
+ .maxblocks = 4,
+ .pattern = bbt_pattern
+};
+
+static struct nand_bbt_descr bbt_mirror_descr = {
+ .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+ | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+ .offs = 0,
+ .len = 4,
+ .veroffs = 4,
+ .maxblocks = 4,
+ .pattern = mirror_pattern
+};
+
+/**
+ * memcpy variant that copies 32 bit words. This is needed since the
+ * NFC only allows 32 bit accesses. Added for U-boot.
+ */
+static void *memcpy_32(void *dest, const void *src, size_t n)
+{
+ u32 *dst_32 = (u32 *) dest;
+ const u32 *src_32 = (u32 *) src;
+
+ while (n > 0) {
+ *dst_32++ = *src_32++;
+ n -= 4;
+ }
+
+ return dest;
+}
+
+/**
+ * This function polls the NANDFC to wait for the basic operation to
+ * complete by checking the INT bit of config2 register.
+ *
+ * @param max_retries number of retry attempts (separated by 1 us)
+ */
+static void wait_op_done(int max_retries)
+{
+ while (max_retries-- > 0) {
+ if (NFC_CONFIG2 & NFC_INT) {
+ NFC_CONFIG2 &= ~NFC_INT;
+ break;
+ }
+ udelay(1);
+ }
+ if (max_retries <= 0)
+ DEBUG(MTD_DEBUG_LEVEL0, "wait: INT not set\n");
+}
+
+/**
+ * This function issues the specified command to the NAND device and
+ * waits for completion.
+ *
+ * @param cmd command for NAND Flash
+ */
+static void send_cmd(u16 cmd)
+{
+ DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(0x%x)\n", cmd);
+
+ NFC_FLASH_CMD = (u16) cmd;
+ NFC_CONFIG2 = NFC_CMD;
+
+ /* Wait for operation to complete */
+ wait_op_done(TROP_US_DELAY);
+}
+
+/**
+ * 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.
+ *
+ * @param addr address to be written to NFC.
+ * @param islast 1 if this is the last address cycle for command
+ */
+static void send_addr(u16 addr)
+{
+ DEBUG(MTD_DEBUG_LEVEL3, "send_addr(0x%x %d)\n", addr);
+
+ NFC_FLASH_ADDR = addr;
+ NFC_CONFIG2 = NFC_ADDR;
+
+ /* Wait for operation to complete */
+ wait_op_done(TROP_US_DELAY);
+}
+
+/**
+ * This function requests the NANDFC to initate the transfer
+ * of data currently in the NANDFC RAM buffer to the NAND device.
+ *
+ * @param buf_id Specify Internal RAM Buffer number (0-3)
+ * @param oob set to 1 if only the spare area is transferred
+ */
+static void send_prog_page(u8 buf_id)
+{
+ DEBUG(MTD_DEBUG_LEVEL3, "send_prog_page (%d)\n", nandinfo.oob);
+
+ /* NANDFC buffer 0 is used for page read/write */
+
+ NFC_BUF_ADDR = buf_id;
+
+ /* Configure spare or page+spare access */
+ if (!nandinfo.largepage) {
+ if (nandinfo.oob)
+ NFC_CONFIG1 |= NFC_SP_EN;
+ else
+ NFC_CONFIG1 &= ~NFC_SP_EN;
+ }
+ NFC_CONFIG2 = NFC_INPUT;
+
+ /* Wait for operation to complete */
+ wait_op_done(TROP_US_DELAY);
+}
+
+/**
+ * This function will correct the single bit ECC error
+ *
+ * @param buf_id Specify Internal RAM Buffer number (0-3)
+ * @param eccpos Ecc byte and bit position
+ * @param oob set to 1 if only spare area needs correction
+ */
+static void mxc_nd_correct_error(u8 buf_id, u16 eccpos, int oob)
+{
+ u16 col;
+ u8 pos;
+ u16 *buf;
+
+ /* Get col & bit position of error
+ these macros works for both 8 & 16 bits */
+ col = COLPOS(eccpos); /* Get half-word position */
+ pos = BITPOS(eccpos); /* Get bit position */
+
+ DEBUG(MTD_DEBUG_LEVEL3,
+ "mxc_nd_correct_error (col=%d pos=%d)\n", col, pos);
+
+ /* Set the pointer for main / spare area */
+ if (!oob)
+ buf = (u16 *)(MAIN_AREA0 + col + (256 * buf_id));
+ else
+ buf = (u16 *)(SPARE_AREA0 + col + (8 * buf_id));
+
+ /* Fix the data */
+ *buf ^= 1 << pos;
+}
+
+/**
+ * This function will maintains state of single bit Error
+ * in Main & spare area
+ *
+ * @param buf_id Specify Internal RAM Buffer number (0-3)
+ * @param spare set to 1 if only spare area needs correction
+ */
+static void mxc_nd_correct_ecc(u8 buf_id, int spare)
+{
+ u16 value, ecc_status;
+
+ /* Read the ECC result */
+ ecc_status = NFC_ECC_STATUS_RESULT;
+ DEBUG(MTD_DEBUG_LEVEL3,
+ "mxc_nd_correct_ecc (Ecc status=%x)\n", ecc_status);
+
+ if (((ecc_status & 0xC) == MAIN_SINGLEBIT_ERROR)
+ || ((ecc_status & 0x3) == SPARE_SINGLEBIT_ERROR)) {
+ if (ecc_disabled) {
+ if ((ecc_status & 0xC) == MAIN_SINGLEBIT_ERROR) {
+ value = NFC_RSLTMAIN_AREA;
+ /* Correct single bit error in Mainarea
+ NFC will not correct the error in
+ current page */
+ mxc_nd_correct_error(buf_id, value, 0);
+ }
+ if ((ecc_status & 0x3) == SPARE_SINGLEBIT_ERROR) {
+ value = NFC_RSLTSPARE_AREA;
+ /* Correct single bit error in Mainarea
+ NFC will not correct the error in
+ current page */
+ mxc_nd_correct_error(buf_id, value, 1);
+ }
+
+ } else {
+ /* Disable ECC */
+ NFC_CONFIG1 &= ~NFC_ECC_EN;
+ ecc_disabled = 1;
+ }
+ } else if (ecc_status == 0) {
+ if (ecc_disabled) {
+ /* Enable ECC */
+ NFC_CONFIG1 |= NFC_ECC_EN;
+ ecc_disabled = 0;
+ }
+ } /* else 2-bit Error. Do nothing */
+}
+
+/**
+ * This function requests the NANDFC to initated the transfer
+ * of data from the NAND device into in the NANDFC ram buffer.
+ *
+ * @param buf_id Specify Internal RAM Buffer number (0-3)
+ * @param oob set 1 if only the spare area is
+ * transferred
+ */
+static void send_read_page(u8 buf_id)
+{
+ DEBUG(MTD_DEBUG_LEVEL3, "send_read_page (%d)\n", nandinfo.oob);
+
+ /* NANDFC buffer 0 is used for page read/write */
+ NFC_BUF_ADDR = buf_id;
+
+ /* Configure spare or page+spare access */
+ if (!nandinfo.largepage) {
+ if (nandinfo.oob)
+ NFC_CONFIG1 |= NFC_SP_EN;
+ else
+ NFC_CONFIG1 &= ~NFC_SP_EN;
+ }
+
+ NFC_CONFIG2 = NFC_OUTPUT;
+
+ /* Wait for operation to complete */
+ wait_op_done(TROP_US_DELAY);
+
+ /* If there are single bit errors in
+ two consecutive page reads then
+ the error is not corrected by the
+ NFC for the second page.
+ Correct single bit error in driver */
+
+ mxc_nd_correct_ecc(buf_id, nandinfo.oob);
+}
+
+/**
+ * This function requests the NANDFC to perform a read of the
+ * NAND device ID.
+ */
+static void send_read_id(void)
+{
+ /* NANDFC buffer 0 is used for device ID output */
+ NFC_BUF_ADDR = 0x0;
+
+ /* Read ID into main buffer */
+ NFC_CONFIG1 &= ~NFC_SP_EN;
+ NFC_CONFIG2 = NFC_ID;
+
+ /* Wait for operation to complete */
+ wait_op_done(TROP_US_DELAY);
+}
+
+/**
+ * This function requests the NANDFC to perform a read of the
+ * NAND device status and returns the current status.
+ *
+ * @return device status
+ */
+static u16 get_dev_status(void)
+{
+ volatile u16 *mainbuf = MAIN_AREA1;
+ u32 store;
+ u16 ret;
+ /* Issue status request to NAND device */
+
+ /* store the main area1 first word, later do recovery */
+ store = *((u32 *) mainbuf);
+ /*
+ * NANDFC buffer 1 is used for device status to prevent
+ * corruption of read/write buffer on status requests.
+ */
+ NFC_BUF_ADDR = 1;
+
+ /* Read status into main buffer */
+ NFC_CONFIG1 &= ~NFC_SP_EN;
+ NFC_CONFIG2 = NFC_STATUS;
+
+ /* Wait for operation to complete */
+ wait_op_done(TROP_US_DELAY);
+
+ /* Status is placed in first word of main buffer */
+ /* get status, then recovery area 1 data */
+ ret = mainbuf[0];
+ *((u32 *) mainbuf) = store;
+
+ return ret;
+}
+
+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, unsigned char *dat,
+ unsigned char *read_ecc, unsigned char *calc_ecc)
+{
+ /*
+ * 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
+ */
+ u16 ecc_status = NFC_ECC_STATUS_RESULT;
+
+ if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
+ DEBUG(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 unsigned char *dat,
+ unsigned char *ecc_code)
+{
+ /*
+ * Just return success. HW ECC does not read/write the NFC spare
+ * buffer. Only the FLASH spare area contains the calcuated ECC.
+ */
+ return 0;
+}
+
+/**
+ * This function reads byte from the NAND Flash
+ *
+ * @param mtd MTD structure for the NAND Flash
+ *
+ * @return data read from the NAND Flash
+ */
+static unsigned char mxc_nand_read_byte(struct mtd_info *mtd)
+{
+ unsigned char ret_val = 0;
+ u16 col, rd_word;
+ volatile u16 *mainbuf = MAIN_AREA0;
+ volatile u16 *sparebuf = SPARE_AREA0;
+
+ /* Check for status request */
+ if (nandinfo.read_status)
+ return get_dev_status() & 0xFF;
+
+ /* Get column for 16-bit access */
+ col = nandinfo.col >> 1;
+
+ /* If we are accessing the spare region */
+ if (nandinfo.oob)
+ rd_word = sparebuf[col];
+ else
+ rd_word = mainbuf[col];
+
+ /* Pick upper/lower byte of word from RAM buffer */
+ if (nandinfo.col & 0x1)
+ ret_val = (rd_word >> 8) & 0xFF;
+ else
+ ret_val = rd_word & 0xFF;
+
+ /* Update saved column address */
+ nandinfo.col++;
+
+ return ret_val;
+}
+
+/**
+ * This function reads word from the NAND Flash
+ *
+ * @param mtd MTD structure for the NAND Flash
+ *
+ * @return data read from the NAND Flash
+ */
+static u16 mxc_nand_read_word(struct mtd_info *mtd)
+{
+ u16 col;
+ u16 rd_word, ret_val;
+ volatile u16 *p;
+
+ DEBUG(MTD_DEBUG_LEVEL3, "mxc_nand_read_word(col = %d)\n", nandinfo.col);
+
+ col = nandinfo.col;
+ /* Adjust saved column address */
+ if (col < mtd->oobblock && nandinfo.oob)
+ col += mtd->oobblock;
+
+ if (col < mtd->oobblock)
+ p = (MAIN_AREA0) + (col >> 1);
+ else
+ p = (SPARE_AREA0) + ((col - mtd->oobblock) >> 1);
+
+ if (col & 1) {
+ rd_word = *p;
+ ret_val = (rd_word >> 8) & 0xff;
+ rd_word = *(p + 1);
+ ret_val |= (rd_word << 8) & 0xff00;
+
+ } else
+ ret_val = *p;
+
+ /* Update saved column address */
+ nandinfo.col = col + 2;
+
+ return ret_val;
+}
+
+/**
+ * This function writes data of length \b len to buffer \b 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.
+ *
+ * @param mtd MTD structure for the NAND Flash
+ * @param buf data to be written to NAND Flash
+ * @param len number of bytes to be written
+ */
+static void mxc_nand_write_buf(struct mtd_info *mtd,
+ const unsigned char *buf, int len)
+{
+ int n;
+ int col;
+ int i = 0;
+
+ DEBUG(MTD_DEBUG_LEVEL3,
+ "mxc_nand_write_buf(col = %d, len = %d)\n", nandinfo.col, len);
+
+ col = nandinfo.col;
+
+ /* Adjust saved column address */
+ if (col < mtd->oobblock && nandinfo.oob)
+ col += mtd->oobblock;
+
+ n = mtd->oobblock + mtd->oobsize - col;
+ if (len > mtd->oobblock + mtd->oobsize - col)
+ DEBUG(MTD_DEBUG_LEVEL1, "Error: too much data.\n");
+
+ n = min(len, n);
+
+ DEBUG(MTD_DEBUG_LEVEL3,
+ "%s:%d: col = %d, n = %d\n", __FUNCTION__, __LINE__, col, n);
+
+ while (n) {
+ volatile u32 *p;
+ if (col < mtd->oobblock)
+ p = (volatile u32 *)((ulong) (MAIN_AREA0) + (col & ~3));
+ else
+ p = (volatile u32 *)((ulong) (SPARE_AREA0) -
+ mtd->oobblock + (col & ~3));
+
+ DEBUG(MTD_DEBUG_LEVEL3, "%s:%d: p = %p\n",
+ __FUNCTION__, __LINE__, p);
+
+ if (((col | (int)&buf[i]) & 3) || n < 16) {
+ u32 data = 0;
+
+ if (col & 3 || n < 4)
+ data = *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++;
+ }
+ }
+
+ *p = data;
+ } else {
+ int m = mtd->oobblock - col;
+
+ if (col >= mtd->oobblock)
+ m += mtd->oobsize;
+
+ m = min(n, m) & ~3;
+
+ DEBUG(MTD_DEBUG_LEVEL3,
+ "%s:%d: n = %d, m = %d, i = %d, col = %d\n",
+ __FUNCTION__, __LINE__, n, m, i, col);
+
+ memcpy_32((void *)(p), &buf[i], m);
+ col += m;
+ i += m;
+ n -= m;
+ }
+ }
+ /* Update saved column address */
+ nandinfo.col = col;
+}
+
+/**
+ * This function id is used to 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 \b len is
+ * then copied to buffer \b buf.
+ *
+ * @param mtd MTD structure for the NAND Flash
+ * @param buf data to be read from NAND Flash
+ * @param len number of bytes to be read
+ */
+static void mxc_nand_read_buf(struct mtd_info *mtd, unsigned char *buf, int len)
+{
+ int n;
+ int col;
+ int i = 0;
+
+ DEBUG(MTD_DEBUG_LEVEL3,
+ "mxc_nand_read_buf(col = %d, len = %d)\n", nandinfo.col, len);
+
+ col = nandinfo.col;
+ /**
+ * Adjust saved column address
+ * for nand_read_oob will pass col within oobsize
+ */
+ if (col < mtd->oobblock && nandinfo.oob)
+ col += mtd->oobblock;
+
+ n = mtd->oobblock + mtd->oobsize - col;
+ n = min(len, n);
+
+ while (n) {
+ volatile u32 *p;
+
+ if (col < mtd->oobblock)
+ p = (volatile u32 *)((ulong) (MAIN_AREA0) + (col & ~3));
+ else
+ p = (volatile u32 *)((ulong) (SPARE_AREA0) -
+ mtd->oobblock + (col & ~3));
+
+ if (((col | (int)&buf[i]) & 3) || n < 16) {
+ u32 data;
+
+ data = *p;
+ switch (col & 3) {
+ case 0:
+ if (n) {
+ buf[i++] = (u8) (data);
+ n--;
+ col++;
+ }
+ case 1:
+ if (n) {
+ buf[i++] = (u8) (data >> 8);
+ n--;
+ col++;
+ }
+ case 2:
+ if (n) {
+ buf[i++] = (u8) (data >> 16);
+ n--;
+ col++;
+ }
+ case 3:
+ if (n) {
+ buf[i++] = (u8) (data >> 24);
+ n--;
+ col++;
+ }
+ }
+ } else {
+ int m = mtd->oobblock - col;
+
+ if (col >= mtd->oobblock)
+ m += mtd->oobsize;
+
+ m = min(n, m) & ~3;
+ memcpy_32(&buf[i], (void *)(p), m);
+ col += m;
+ i += m;
+ n -= m;
+ }
+ }
+ /* Update saved column address */
+ nandinfo.col = col;
+}
+
+/**
+ * This function is used by the upper layer to verify the data in NAND Flash
+ * with the data in the \b buf.
+ *
+ * @param mtd MTD structure for the NAND Flash
+ * @param buf data to be verified
+ * @param len length of the data to be verified
+ *
+ * @return -EFAULT if error else 0
+ */
+static int
+mxc_nand_verify_buf(struct mtd_info *mtd, const unsigned char *buf, int len)
+{
+ return -1; /* Was -EFAULT */
+}
+
+/**
+ * This function is used by upper layer for select and deselect of the NAND
+ * chip.
+ *
+ * @param mtd MTD structure for the NAND Flash
+ * @param chip val indicating select or deselect
+ */
+static void mxc_nand_select_chip(struct mtd_info *mtd, int chip)
+{
+}
+
+/**
+ * This function is used by the upper layer to write command to NAND Flash
+ * for different operations to be carried out on NAND Flash
+ *
+ * @param mtd MTD structure for the NAND Flash
+ * @param command command for NAND Flash
+ * @param column column offset for the page read
+ * @param page_addr page to be read from NAND Flash
+ */
+static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
+ int column, int page_addr)
+{
+ DEBUG(MTD_DEBUG_LEVEL3,
+ "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
+ command, column, page_addr);
+
+ /* Reset command state information */
+ nandinfo.read_status = 0;
+ nandinfo.oob = 0;
+
+ /* Command pre-processing step */
+ switch (command) {
+
+ case NAND_CMD_STATUS:
+ nandinfo.col = 0;
+ nandinfo.read_status = 1;
+ break;
+
+ case NAND_CMD_READ0:
+ nandinfo.col = column;
+ break;
+
+ case NAND_CMD_READOOB:
+ nandinfo.col = column;
+ nandinfo.oob = 1;
+ if (nandinfo.largepage)
+ command = NAND_CMD_READ0;
+ break;
+
+ case NAND_CMD_SEQIN:
+ if (column >= mtd->oobblock) {
+ /* write oob routine caller */
+ if (nandinfo.largepage) {
+ /*
+ * FIXME: before send SEQIN command for
+ * write OOB, we must read one page out.
+ * For 2K nand has no READ1 command to set
+ * current HW pointer to spare area, we must
+ * write the whole page including OOB together.
+ */
+ /* call itself to read a page */
+ mxc_nand_command(mtd, NAND_CMD_READ0, 0,
+ page_addr);
+ }
+ nandinfo.col = column - mtd->oobblock;
+ nandinfo.oob = 1;
+ /* Set program pointer to spare region */
+ if (!nandinfo.largepage)
+ send_cmd(NAND_CMD_READOOB);
+ } else {
+ nandinfo.oob = 0;
+ nandinfo.col = column;
+ /* Set program pointer to page start */
+ if (!nandinfo.largepage)
+ send_cmd(NAND_CMD_READ0);
+ }
+ break;
+
+ case NAND_CMD_PAGEPROG:
+ if (ecc_disabled) {
+ /* Enable Ecc for page writes */
+ NFC_CONFIG1 |= NFC_ECC_EN;
+ }
+ send_prog_page(0);
+
+ if (nandinfo.largepage) {
+ /* data in 4 areas datas */
+ send_prog_page(1);
+ send_prog_page(2);
+ send_prog_page(3);
+ }
+
+ break;
+
+ case NAND_CMD_ERASE1:
+ break;
+ }
+
+ /*
+ * Write out the command to the device.
+ */
+ send_cmd(command);
+
+ /*
+ * Write out column address, if necessary
+ */
+ if (column != -1) {
+ /*
+ * MXC NANDFC can only perform full page+spare or
+ * spare-only read/write. When the upper layers
+ * layers perform a read/write buf operation,
+ * we will used the saved column adress to index into
+ * the full page.
+ */
+ send_addr(0);
+ if (nandinfo.largepage)
+ /* another col addr cycle for 2k page */
+ send_addr(0);
+ }
+
+ /*
+ * Write out page address, if necessary
+ */
+ if (page_addr != -1) {
+ /* paddr_0 - p_addr_7 */
+ send_addr((page_addr & 0xff));
+
+ if (nandinfo.largepage) {
+ /* One more address cycle for higher
+ * density devices */
+
+ if (mtd->size >= 0x10000000) {
+ /* paddr_8 - paddr_15 */
+ send_addr((page_addr >> 8) & 0xff);
+ send_addr((page_addr >> 16) & 0xff);
+ } else
+ /* paddr_8 - paddr_15 */
+ send_addr((page_addr >> 8) & 0xff);
+ } else {
+ /* One more address cycle for higher
+ * density devices */
+
+ if (mtd->size >= 0x4000000) {
+ /* paddr_8 - paddr_15 */
+ send_addr((page_addr >> 8) & 0xff);
+ send_addr((page_addr >> 16) & 0xff);
+ } else
+ /* paddr_8 - paddr_15 */
+ send_addr((page_addr >> 8) & 0xff);
+ }
+ }
+
+ /*
+ * Command post-processing step
+ */
+ switch (command) {
+
+ case NAND_CMD_RESET:
+ break;
+
+ case NAND_CMD_READOOB:
+ case NAND_CMD_READ0:
+ if (nandinfo.largepage) {
+ /* send read confirm command */
+ send_cmd(NAND_CMD_READSTART);
+ /* read for each AREA */
+ send_read_page(0);
+ send_read_page(1);
+ send_read_page(2);
+ send_read_page(3);
+ } else
+ send_read_page(0);
+ break;
+
+ case NAND_CMD_READID:
+ send_read_id();
+ break;
+
+ case NAND_CMD_PAGEPROG:
+ if (ecc_disabled) {
+ /* Disable Ecc after page writes */
+ NFC_CONFIG1 &= ~NFC_ECC_EN;
+ }
+ break;
+
+ case NAND_CMD_ERASE2:
+ break;
+ }
+}
+
+static int mxc_nand_scan_bbt(struct mtd_info *mtd)
+{
+ struct nand_chip *this = mtd->priv;
+
+ /* Config before scanning */
+ /* Do not rely on NFMS_BIT, set/clear NFMS bit based
+ * on mtd->oobblock */
+ if (mtd->oobblock == 2048)
+ NFMS |= 1 << NFMS_BIT;
+ else if ((NFMS >> NFMS_BIT) & 0x1)
+ NFMS &= ~(1 << NFMS_BIT);
+
+ /* use flash based bbt */
+ this->bbt_td = &bbt_main_descr;
+ this->bbt_md = &bbt_mirror_descr;
+
+ /* update flash based bbt */
+ this->options |= NAND_USE_FLASH_BBT;
+
+ if (!this->badblock_pattern) {
+ if (nandinfo.largepage)
+ this->badblock_pattern = &smallpage_memorybased;
+ else
+ this->badblock_pattern = (mtd->oobblock > 512) ?
+ &largepage_memorybased : &smallpage_memorybased;
+ }
+ /* Build bad block table */
+ return nand_scan_bbt(mtd, this->badblock_pattern);
+}
+
+int board_nand_init(struct nand_chip *nand)
+{
+ nand->chip_delay = 0;
+
+ nand->cmdfunc = mxc_nand_command;
+ nand->select_chip = mxc_nand_select_chip;
+ nand->read_byte = mxc_nand_read_byte;
+ nand->read_word = mxc_nand_read_word;
+ nand->write_buf = mxc_nand_write_buf;
+ nand->read_buf = mxc_nand_read_buf;
+ nand->verify_buf = mxc_nand_verify_buf;
+ nand->scan_bbt = mxc_nand_scan_bbt;
+ nand->calculate_ecc = mxc_nand_calculate_ecc;
+ nand->correct_data = mxc_nand_correct_data;
+ nand->enable_hwecc = mxc_nand_enable_hwecc;
+ nand->eccmode = NAND_ECC_HW3_512;
+ nand->eccbytes = 512;
+ nand->eccsize = 3;
+
+ /* Reset NAND */
+ NFC_CONFIG1 |= NFC_INT_MSK | NFC_RST | NFC_ECC_EN;
+
+ /* Unlock the internal RAM buffer */
+ NFC_CONFIG = 0x2;
+
+ /* Block to be unlocked */
+ NFC_UNLOCKSTART_BLKADDR = 0x0;
+ NFC_UNLOCKEND_BLKADDR = 0x4000;
+
+ /* Unlock Block Command for given address range */
+ NFC_WRPROT = 0x4;
+
+ /* Only 8 bit bus support for now */
+ nand->options |= 0;
+
+ if ((NFMS >> NFMS_BIT) & 1) {
+ nandinfo.largepage = 1;
+ nand->autooob = &nand_hw_eccoob_2k;
+ } else {
+ nandinfo.largepage = 0;
+ nand->autooob = &nand_hw_eccoob_8;
+ }
+
+ return 0;
+}
diff --git a/include/asm-arm/arch-mx31/mx31-regs.h b/include/asm-arm/arch-mx31/mx31-regs.h
index 51b02a2..a8b7c10 100644
--- a/include/asm-arm/arch-mx31/mx31-regs.h
+++ b/include/asm-arm/arch-mx31/mx31-regs.h
@@ -255,4 +255,100 @@
*/
#define NFC_BASE_ADDR 0xB8000000
+/*
+ * Addresses for NFC registers
+ */
+#define NFC_BUF_SIZE (*((volatile u16 *)(NFC_BASE_ADDR + 0xE00)))
+#define NFC_BUF_ADDR (*((volatile u16 *)(NFC_BASE_ADDR + 0xE04)))
+#define NFC_FLASH_ADDR (*((volatile u16 *)(NFC_BASE_ADDR + 0xE06)))
+#define NFC_FLASH_CMD (*((volatile u16 *)(NFC_BASE_ADDR + 0xE08)))
+#define NFC_CONFIG (*((volatile u16 *)(NFC_BASE_ADDR + 0xE0A)))
+#define NFC_ECC_STATUS_RESULT (*((volatile u16 *)(NFC_BASE_ADDR + 0xE0C)))
+#define NFC_RSLTMAIN_AREA (*((volatile u16 *)(NFC_BASE_ADDR + 0xE0E)))
+#define NFC_RSLTSPARE_AREA (*((volatile u16 *)(NFC_BASE_ADDR + 0xE10)))
+#define NFC_WRPROT (*((volatile u16 *)(NFC_BASE_ADDR + 0xE12)))
+#define NFC_UNLOCKSTART_BLKADDR (*((volatile u16 *)(NFC_BASE_ADDR + 0xE14)))
+#define NFC_UNLOCKEND_BLKADDR (*((volatile u16 *)(NFC_BASE_ADDR + 0xE16)))
+#define NFC_NF_WRPRST (*((volatile u16 *)(NFC_BASE_ADDR + 0xE18)))
+#define NFC_CONFIG1 (*((volatile u16 *)(NFC_BASE_ADDR + 0xE1A)))
+#define NFC_CONFIG2 (*((volatile u16 *)(NFC_BASE_ADDR + 0xE1C)))
+
+#define NFC_BUFSIZE_REG_OFF (0 + 0x00)
+#define RAM_BUFFER_ADDRESS_REG_OFF (0 + 0x04)
+#define NAND_FLASH_ADD_REG_OFF (0 + 0x06)
+#define NAND_FLASH_CMD_REG_OFF (0 + 0x08)
+#define NFC_CONFIGURATION_REG_OFF (0 + 0x0A)
+#define ECC_STATUS_RESULT_REG_OFF (0 + 0x0C)
+#define ECC_RSLT_MAIN_AREA_REG_OFF (0 + 0x0E)
+#define ECC_RSLT_SPARE_AREA_REG_OFF (0 + 0x10)
+#define NF_WR_PROT_REG_OFF (0 + 0x12)
+#define UNLOCK_START_BLK_ADD_REG_OFF (0 + 0x14)
+#define UNLOCK_END_BLK_ADD_REG_OFF (0 + 0x16)
+#define NAND_FLASH_WR_PR_ST_REG_OFF (0 + 0x18)
+#define NAND_FLASH_CONFIG1_REG_OFF (0 + 0x1A)
+#define NAND_FLASH_CONFIG2_REG_OFF (0 + 0x1C)
+#define RAM_BUFFER_ADDRESS_RBA_3 0x3
+#define NFC_BUFSIZE_1KB 0x0
+#define NFC_BUFSIZE_2KB 0x1
+#define NFC_CONFIGURATION_UNLOCKED 0x2
+#define ECC_STATUS_RESULT_NO_ERR 0x0
+#define ECC_STATUS_RESULT_1BIT_ERR 0x1
+#define ECC_STATUS_RESULT_2BIT_ERR 0x2
+#define NF_WR_PROT_UNLOCK 0x4
+#define NAND_FLASH_CONFIG1_FORCE_CE (1 << 7)
+#define NAND_FLASH_CONFIG1_RST (1 << 6)
+#define NAND_FLASH_CONFIG1_BIG (1 << 5)
+#define NAND_FLASH_CONFIG1_INT_MSK (1 << 4)
+#define NAND_FLASH_CONFIG1_ECC_EN (1 << 3)
+#define NAND_FLASH_CONFIG1_SP_EN (1 << 2)
+#define NAND_FLASH_CONFIG2_INT_DONE (1 << 15)
+#define NAND_FLASH_CONFIG2_FDO_PAGE (0 << 3)
+#define NAND_FLASH_CONFIG2_FDO_ID (2 << 3)
+#define NAND_FLASH_CONFIG2_FDO_STATUS (4 << 3)
+#define NAND_FLASH_CONFIG2_FDI_EN (1 << 2)
+#define NAND_FLASH_CONFIG2_FADD_EN (1 << 1)
+#define NAND_FLASH_CONFIG2_FCMD_EN (1 << 0)
+#define FDO_PAGE_SPARE_VAL 0x8
+#define NAND_FLASH_BOOT 0x10000000
+#define MXCFIS_NAND 0x10000000
+
+/*
+ * Addresses for NFC RAM BUFFER Main area 0
+ */
+#define MAIN_AREA0 (volatile u16 *)(NFC_BASE_ADDR + 0x000)
+#define MAIN_AREA1 (volatile u16 *)(NFC_BASE_ADDR + 0x200)
+#define MAIN_AREA2 (volatile u16 *)(NFC_BASE_ADDR + 0x400)
+#define MAIN_AREA3 (volatile u16 *)(NFC_BASE_ADDR + 0x600)
+
+/*
+ * Addresses for NFC SPARE BUFFER Spare area 0
+ */
+#define SPARE_AREA0 (volatile u16 *)(NFC_BASE_ADDR + 0x800)
+#define SPARE_AREA1 (volatile u16 *)(NFC_BASE_ADDR + 0x810)
+#define SPARE_AREA2 (volatile u16 *)(NFC_BASE_ADDR + 0x820)
+#define SPARE_AREA3 (volatile u16 *)(NFC_BASE_ADDR + 0x830)
+
+#define NFC_CMD 0x1
+#define NFC_ADDR 0x2
+#define NFC_INPUT 0x4
+#define NFC_OUTPUT 0x8
+#define NFC_ID 0x10
+#define NFC_STATUS 0x20
+#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)
+
+/*
+ * NFMS bit in RCSR register for pagesize of nandflash
+ */
+#define NFMS (*((volatile u32 *)CCM_RCSR))
+#define NFMS_BIT 30
+
#endif /* __ASM_ARCH_MX31_REGS_H */
+
diff --git a/include/configs/mx31_3stack.h b/include/configs/mx31_3stack.h
new file mode 100644
index 0000000..7aaef4f
--- /dev/null
+++ b/include/configs/mx31_3stack.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * Configuration settings for the MX31 3Stack Freescale board.
+ *
+ * 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
+
+#include <asm/arch/mx31-regs.h>
+
+ /* High Level Configuration Options */
+#define CONFIG_ARM1136 1 /* This is an arm1136 CPU core */
+#define CONFIG_MX31 1 /* in a mx31 */
+#define CONFIG_MX31_HCLK_FREQ 26000000
+#define CONFIG_MX31_CLK32 32768
+
+#define CONFIG_MX31_NAND
+
+#define CONFIG_DISPLAY_CPUINFO
+#define CONFIG_DISPLAY_BOARDINFO
+
+#define CONFIG_NAND_BOOT
+#define CONFIG_SKIP_RELOCATE_UBOOT
+
+#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */
+#define CONFIG_SETUP_MEMORY_TAGS 1
+#define CONFIG_INITRD_TAG 1
+
+/*
+ * Size of malloc() pool
+ */
+#define CFG_MALLOC_LEN (CFG_ENV_SIZE + 128 * 1024)
+#define CFG_GBL_DATA_SIZE 128
+
+/*
+ * Hardware drivers
+ */
+
+#define CONFIG_MX31_UART 1
+#define CFG_MX31_UART1 1
+
+#define CONFIG_HARD_SPI 1
+#define CONFIG_MXC_SPI 1
+#define CONFIG_MXC_SPI_IFACE 1
+
+#define CONFIG_RTC_MC13783 1
+
+/* allow to overwrite serial and ethaddr */
+#define CONFIG_ENV_OVERWRITE
+#define CONFIG_CONS_INDEX 1
+#define CONFIG_BAUDRATE 115200
+#define CFG_BAUDRATE_TABLE {9600, 19200, 38400, 57600, 115200}
+
+/***********************************************************
+ * Command definition
+ ***********************************************************/
+
+#include <config_cmd_default.h>
+
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_SPI
+#define CONFIG_CMD_DATE
+#define CONFIG_CMD_NAND
+#undef CONFIG_CMD_IMLS
+
+#define CONFIG_BOOTDELAY 3
+
+#define CONFIG_LOADADDR 0x80800000 /* loadaddr env var */
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+ "netdev=eth0\0" \
+ "uboot=u-boot.bin\0" \
+ "kernel=uImage\0" \
+ "loadaddr=0x80010000\0" \
+ "tftp_server=10.192.225.58\0" \
+ "serverip=10.192.225.211\0" \
+ "nfsroot=/tools/rootfs/rootfs-2.6.24\0" \
+ "bootargs_base=setenv bootargs console=ttymxc0,115200\0" \
+ "bootargs_nfs=setenv bootargs ${bootargs} root=/dev/nfs " \
+ "ip=dhcp nfsroot=${serverip}:${nfsroot} rw\0" \
+ "bootcmd=run bootcmd_net\0" \
+ "bootcmd_net=run bootargs_base bootargs_nfs; " \
+ "tftpboot ${loadaddr} ${tftp_server}:${kernel}; bootm\0"
+
+/* configure for smc91xx debug board ethernet */
+#define CONFIG_NET_MULTI 1
+#define CONFIG_DRIVER_SMC911X 1
+#define CONFIG_DRIVER_SMC911X_BASE CS5_BASE
+#define CONFIG_DRIVER_SMC911X_32_BIT 1
+
+#define CONFIG_ARP_TIMEOUT 200UL
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CFG_LONGHELP /* undef to save memory */
+#define CFG_PROMPT "=> "
+#define CFG_CBSIZE 256 /* Console I/O Buffer Size */
+/* Print Buffer Size */
+#define CFG_PBSIZE (CFG_CBSIZE + sizeof(CFG_PROMPT) + 16)
+#define CFG_MAXARGS 16 /* max number of command args */
+#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */
+
+#define CFG_MEMTEST_START 0 /* memtest works on */
+#define CFG_MEMTEST_END 0x10000
+
+#undef CFG_CLKS_IN_HZ /* everything, incl board info, in Hz */
+
+#define CFG_LOAD_ADDR CONFIG_LOADADDR
+
+#define CFG_HZ CONFIG_MX31_CLK32
+
+#define CONFIG_CMDLINE_EDITING 1
+
+/*-----------------------------------------------------------------------
+ * Stack sizes
+ *
+ * The stack sizes are set up in start.S using the settings below
+ */
+#define CONFIG_STACKSIZE (128 * 1024) /* regular stack */
+
+/*-----------------------------------------------------------------------
+ * Physical Memory Map
+ */
+#define CONFIG_NR_DRAM_BANKS 1
+#define PHYS_SDRAM_1 CSD0_BASE
+#define PHYS_SDRAM_1_SIZE (128 * 1024 * 1024)
+
+/*
+ * TODO: NAND Flash configure
+ */
+
+#define CFG_NO_FLASH
+#define NAND_MAX_CHIPS 1
+#define CFG_MAX_NAND_DEVICE 1
+#define CFG_NAND_BASE 0x40000000
+
+#define CFG_ENV_IS_IN_NAND 1
+#define CFG_ENV_OFFSET 0x40000 /* 2nd block */
+#define CFG_ENV_SIZE (128*1024)
+
+/*
+ * JFFS2 partitions TODO:
+ */
+#undef CONFIG_JFFS2_CMDLINE
+#define CONFIG_JFFS2_DEV "nand0"
+
+#endif /* __CONFIG_H */