Index: u-boot/cpu/arm920t/s3c24x0/nand_read.c
===================================================================
--- /dev/null
+++ u-boot/cpu/arm920t/s3c24x0/nand_read.c
@@ -0,0 +1,98 @@
+/*
+ * nand_read.c: Simple NAND read functions for booting from NAND
+ *
+ * This is used by cpu/arm920/start.S assembler code,
+ * and the board-specific linker script must make sure this
+ * file is linked within the first 4kB of NAND flash.
+ *
+ * Taken from GPLv2 licensed vivi bootloader,
+ * Copyright (C) 2002 MIZI Research, Inc.
+ *
+ * Author: Hwang, Chideok <hwang@mizi.com>
+ * Date  : $Date: 2004/02/04 10:37:37 $
+ *
+ * u-boot integration and bad-block skipping (C) 2006 by OpenMoko, Inc.
+ * Author: Harald Welte <laforge@openmoko.org>
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_S3C2410_NAND_BOOT
+
+#define __REGb(x)	(*(volatile unsigned char *)(x))
+#define __REGi(x)	(*(volatile unsigned int *)(x))
+#define NF_BASE		0x4e000000
+#define NFCONF		__REGi(NF_BASE + 0x0)
+#define NFCMD		__REGb(NF_BASE + 0x4)
+#define NFADDR		__REGb(NF_BASE + 0x8)
+#define NFDATA		__REGb(NF_BASE + 0xc)
+#define NFSTAT		__REGb(NF_BASE + 0x10)
+
+#define BUSY 1
+inline void wait_idle(void)
+{
+	int i;
+
+	while (!(NFSTAT & BUSY))
+		for (i=0; i<10; i++);
+}
+
+#define NAND_SECTOR_SIZE	512
+#define NAND_BLOCK_MASK		(NAND_SECTOR_SIZE - 1)
+#define NAND_PAGE_SIZE		0x4000
+
+/* low level nand read function */
+int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)
+{
+	int i, j;
+
+	if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK))
+		return -1;	/* invalid alignment */
+
+	/* chip Enable */
+	NFCONF &= ~0x800;
+	for (i=0; i<10; i++);
+
+	for (i=start_addr; i < (start_addr + size);) {
+#ifdef CONFIG_S3C2410_NAND_SKIP_BAD
+		if (start_addr % NAND_PAGE_SIZE == 0) {
+			unsigned char data;
+			NFCMD = 0x50;
+			NFADDR = 517&0xf;
+			NFADDR = (i >> 9) & 0xff;
+			NFADDR = (i >> 17) & 0xff;
+			NFADDR = (i >> 25) & 0xff;
+			wait_idle();
+			data = (NFDATA & 0xff);
+			if (data != 0xff) {
+				/* Bad block */
+				i += NAND_PAGE_SIZE;
+				size += NAND_PAGE_SIZE;
+				continue;
+			}
+		}
+#endif
+		/* READ0 */
+		NFCMD = 0;
+
+		/* Write Address */
+		NFADDR = i & 0xff;
+		NFADDR = (i >> 9) & 0xff;
+		NFADDR = (i >> 17) & 0xff;
+		NFADDR = (i >> 25) & 0xff;
+
+		wait_idle();
+
+		for (j=0; j < NAND_SECTOR_SIZE; j++, i++) {
+			*buf = (NFDATA & 0xff);
+			buf++;
+		}
+	}
+
+	/* chip Disable */
+	NFCONF |= 0x800;	/* chip disable */
+
+	return 0;
+}
+
+#endif /* CONFIG_S3C2410_NAND_BOOT */
Index: u-boot/cpu/arm920t/start.S
===================================================================
--- u-boot.orig/cpu/arm920t/start.S
+++ u-boot/cpu/arm920t/start.S
@@ -5,6 +5,10 @@
  *  Copyright (c) 2002	Alex Züpke <azu@sysgo.de>
  *  Copyright (c) 2002	Gary Jennejohn <gj@denx.de>
  *
+ * S3C2410 NAND portions
+ *  Copyright (c) 2001  MIZI Research, Inc.
+ *  Copyright (c) 2006  OpenMoko, Inc. (Harald Welte <laforge@openmmoko.org>
+ *
  * See file CREDITS for list of people who contributed to this
  * project.
  *
@@ -27,6 +31,7 @@
 
 #include <config.h>
 #include <version.h>
+#include <s3c2410.h>
 #include <status_led.h>
 
 /*
@@ -116,8 +121,13 @@
 	orr	r0,r0,#0xd3
 	msr	cpsr,r0
 
+	/* in case we run from the s3c24xx NAND stepping stone, the symbols
+	 * for LED support are in lib_arm/board.o, i.e. outside of the
+	 * steppingstone */
+#ifndef CONFIG_S3C2410_NAND_BOOT
 	bl coloured_LED_init
 	bl red_LED_on
+#endif
 
 #if	defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)
 	/*
@@ -178,9 +188,10 @@
 	bl	cpu_init_crit
 #endif
 
-#ifdef	CONFIG_AT91RM9200
+#if defined(CONFIG_AT91RM9200) || defined(CONFIG_S3C2410)
 
 #ifndef CONFIG_SKIP_RELOCATE_UBOOT
+#ifndef CONFIG_S3C2410_NAND_BOOT
 relocate:				/* relocate U-Boot to RAM	    */
 	adr	r0, _start		/* r0 <- current position of code   */
 	ldr	r1, _TEXT_BASE		/* test if we run from flash or RAM */
@@ -197,6 +208,87 @@
 	stmia	r1!, {r3-r10}		/* copy to   target address [r1]    */
 	cmp	r0, r2			/* until source end addreee [r2]    */
 	ble	copy_loop
+#else /* NAND_BOOT */
+relocate:
+copy_myself:
+	/* mov	r10, lr */
+
+	@ reset NAND
+	mov	r1, #S3C2410_NAND_BASE
+	ldr	r2, =0xf842		@ initial value enable tacls=3,rph0=6,rph1=0
+	str	r2, [r1, #oNFCONF]
+	ldr	r2, [r1, #oNFCONF]
+	bic	r2, r2, #0x800		@ enable chip
+	str	r2, [r1, #oNFCONF]
+	mov	r2, #0xff		@ RESET command
+	strb	r2, [r1, #oNFCMD]
+	mov	r3, #0			@ wait
+1:	add	r3, r3, #0x1
+	cmp	r3, #0xa
+	blt	1b
+2:	ldr	r2, [r1, #oNFSTAT]	@ wait ready
+	tst	r2, #0x1
+	beq	2b
+	ldr	r2, [r1, #oNFCONF]
+	orr	r2, r2, #0x800		@ disable chip
+	str	r2, [r1, #oNFCONF]
+
+	ldr	r0, _TEXT_BASE		/* upper 128 KiB: relocated uboot   */
+	sub	r0, r0, #CFG_MALLOC_LEN	/* malloc area                      */
+	sub	r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */
+#ifdef CONFIG_USE_IRQ
+	sub	r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
+#endif
+	sub	sp, r0, #12		/* leave 3 words for abort-stack    */
+
+	@ copy u-boot to RAM
+	ldr	r0, _TEXT_BASE
+	mov     r1, #0x0
+	mov	r2, #CFG_UBOOT_SIZE
+	bl	nand_read_ll
+
+	tst	r0, #0x0
+	beq	ok_nand_read
+#ifdef CONFIG_DEBUG_LL
+bad_nand_read:
+	ldr	r0, STR_FAIL
+	ldr	r1, SerBase
+	bl	PrintWord
+1:	b	1b		@ infinite loop
+#endif
+
+ok_nand_read:
+#ifdef CONFIG_DEBUG_LL
+	ldr	r0, STR_OK
+	ldr	r1, SerBase
+	bl	PrintWord
+#endif
+
+	@ verify
+	mov	r0, #0
+	@ldr	r1, =0x33f00000
+	ldr	r1, _TEXT_BASE
+	mov	r2, #0x400	@ 4 bytes * 1024 = 4K-bytes
+go_next:
+	ldr	r3, [r0], #4
+	ldr	r4, [r1], #4
+	teq	r3, r4
+	bne	notmatch
+	subs	r2, r2, #4
+	beq	done_nand_read
+	bne	go_next
+notmatch:
+#ifdef CONFIG_DEBUG_LL
+	sub	r0, r0, #4
+	ldr	r1, SerBase
+	bl	PrintHexWord
+	ldr	r0, STR_FAIL
+	ldr	r1, SerBase
+	bl	PrintWord
+#endif
+1:	b	1b
+done_nand_read:
+#endif /* NAND_BOOT */
 #endif	/* CONFIG_SKIP_RELOCATE_UBOOT */
 #endif
 	/* Set up the stack						    */
Index: u-boot/include/s3c2410.h
===================================================================
--- u-boot.orig/include/s3c2410.h
+++ u-boot/include/s3c2410.h
@@ -38,12 +38,6 @@
 #define S3C2410_ECCSIZE		512
 #define S3C2410_ECCBYTES	3
 
-typedef enum {
-	S3C24X0_UART0,
-	S3C24X0_UART1,
-	S3C24X0_UART2
-} S3C24X0_UARTS_NR;
-
 /* S3C2410 device base addresses */
 #define S3C24X0_MEMCTL_BASE		0x48000000
 #define S3C24X0_USB_HOST_BASE		0x49000000
@@ -65,9 +59,23 @@
 #define S3C2410_SDI_BASE		0x5A000000
 
 
+#define oNFCONF			0x00
+#define oNFCMD			0x04
+#define oNFADDR			0x08
+#define oNFDATA			0x0C
+#define oNFSTAT			0x10
+#define oNFECC			0x14
+
+#ifndef __ASSEMBLER__
+
 /* include common stuff */
 #include <s3c24x0.h>
 
+typedef enum {
+	S3C24X0_UART0,
+	S3C24X0_UART1,
+	S3C24X0_UART2
+} S3C24X0_UARTS_NR;
 
 static inline S3C24X0_MEMCTL * S3C24X0_GetBase_MEMCTL(void)
 {
@@ -142,6 +150,7 @@
 	return (S3C2410_SDI * const)S3C2410_SDI_BASE;
 }
 
+#endif
 
 /* ISR */
 #define pISR_RESET		(*(unsigned *)(_ISR_STARTADDRESS+0x0))
Index: u-boot/cpu/arm920t/s3c24x0/Makefile
===================================================================
--- u-boot.orig/cpu/arm920t/s3c24x0/Makefile
+++ u-boot/cpu/arm920t/s3c24x0/Makefile
@@ -26,7 +26,7 @@
 LIB	= $(obj)lib$(SOC).a
 
 COBJS	= i2c.o interrupts.o serial.o speed.o \
-	  usb.o usb_ohci.o nand.o
+	  usb.o usb_ohci.o nand_read.o nand.o
 
 SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
