[PATCH 10/15] fix-nand.patch

Andy Green andy at openmoko.com
Wed Aug 13 01:59:39 CEST 2008


NAND stuff wasn't going to do anything until the controller in
the CPU was reset.  NAND code was cleaned and other minor meddlings

Signed-off-by: Andy Green <andy at openmoko.com>
---

 src/kboot-stage1.lds |    1 
 src/lowlevel_init.S  |    3 +
 src/nand_read.c      |  103 +++++++++++++++++++++++----------
 src/phase2.c         |  154 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/start.S          |   13 ++++
 src/start_kboot.c    |   42 ++++++++------
 6 files changed, 268 insertions(+), 48 deletions(-)
 create mode 100644 src/phase2.c

diff --git a/src/kboot-stage1.lds b/src/kboot-stage1.lds
index 1998807..551d354 100644
--- a/src/kboot-stage1.lds
+++ b/src/kboot-stage1.lds
@@ -35,6 +35,7 @@ SECTIONS
 	  src/start.o	(.text)
 	  src/lowlevel_init.o(.text)
 	  src/start_kboot.o	(.text)
+	  src/start_kboot.o	(.rodata)
 	  *(.text)
 	  *(.rodata)
 	}
diff --git a/src/lowlevel_init.S b/src/lowlevel_init.S
index dcb3adf..4f20d5e 100644
--- a/src/lowlevel_init.S
+++ b/src/lowlevel_init.S
@@ -19,6 +19,9 @@
  * MA 02111-1307 USA
  */
 
+/* NOTE this stuff runs in steppingstone context! */
+
+
 /*
  * #include <config.h>
  * #include <version.h>
diff --git a/src/nand_read.c b/src/nand_read.c
index 8a5778a..8deadb7 100644
--- a/src/nand_read.c
+++ b/src/nand_read.c
@@ -15,7 +15,11 @@
  * Author: Harald Welte <laforge at openmoko.org>
  */
 
+/* NOTE this stuff runs in steppingstone context! */
+
+
 #include "nand_read.h"
+#include "kboot.h"
 
 #define NAND_CMD_READ0 0
 #define NAND_CMD_READSTART 0x30
@@ -67,6 +71,14 @@ static int is_bad_block(unsigned long i)
 	NFCMD = NAND_CMD_READSTART;
 	nand_wait();
 	data = (NFDATA & 0xff);
+#ifdef DEBUG
+	serial_putc(2, '$');
+	serial_putc(2, '0');
+	serial_putc(2, 'x');
+	print32((unsigned int)data);
+	serial_putc(2, ' ');
+#endif
+
 	if (data != 0xff)
 		return 1;
 
@@ -103,38 +115,65 @@ static int nand_read_page_ll(unsigned char *buf, unsigned long addr)
 /* low level nand read function */
 int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)
 {
-  int i, j;
-  int bad_count = 0;
-
-  if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK))
-    return -1;	/* invalid alignment */
-
-  /* chip Enable */
-  nand_select();
-  nand_clear_RnB();
-  for (i=0; i<10; i++);
-
-  for (i=start_addr; i < (start_addr + size);) {
-    if (i % NAND_BLOCK_SIZE == 0) {
-      if (is_bad_block(i) ||
-	  is_bad_block(i + NAND_PAGE_SIZE)) {
-	i += NAND_BLOCK_SIZE;
-	size += NAND_BLOCK_SIZE;
-	if(bad_count++ == 4) {
-	  return -1;
+	int i, j;
+	int bad_count = 0;
+
+	if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK))
+		return -1;	/* invalid alignment */
+
+	/* chip Enable */
+	nand_select();
+	nand_clear_RnB();
+
+	for (i = 0; i < 10; i++)
+		;
+
+	for (i = start_addr; i < (start_addr + size);) {
+#ifdef DEBUG
+		serial_putc(2, 'i');
+		serial_putc(2, '0');
+		serial_putc(2, 'x');
+		print32((unsigned int)i);
+		serial_putc(2, ' ');
+#endif
+		if (i % NAND_BLOCK_SIZE == 0) {
+			if (is_bad_block(i) ||
+					is_bad_block(i + NAND_PAGE_SIZE)) {
+#ifdef DEBUG
+				serial_putc(2, '?');
+#endif
+				i += NAND_BLOCK_SIZE;
+				size += NAND_BLOCK_SIZE;
+				if (bad_count++ == 4) {
+#ifdef DEBUG
+					serial_putc(2, '+');
+					serial_putc(2, '\n');
+#endif
+					return -1;
+				}
+				serial_putc(2, '\n');
+				continue;
+			}
+		}
+
+		j = nand_read_page_ll(buf, i);
+#ifdef DEBUG
+		serial_putc(2, 'j');
+		serial_putc(2, '0');
+		serial_putc(2, 'x');
+		print32((unsigned int)j);
+		serial_putc(2, ' ');
+#endif
+		i += j;
+		buf += j;
+#if DEBUG
+		serial_putc(2, '\n');
+#endif
 	}
-	continue;
-      }
-    }
-
-    j = nand_read_page_ll(buf, i);
-    i += j;
-    /*    buf += j;*/
-  }
-
-  /* chip Disable */
-  nand_deselect();
-  
-  return 0;
+
+	/* chip Disable */
+	nand_deselect();
+
+	return 0;
 }
 
diff --git a/src/phase2.c b/src/phase2.c
new file mode 100644
index 0000000..75ae2fd
--- /dev/null
+++ b/src/phase2.c
@@ -0,0 +1,154 @@
+#include "kboot.h"
+#include <neo_gta02.h>
+#include "blink_led.h"
+#include <string.h>
+#define __ARM__
+#include <image.h>
+#define u32 unsigned int
+#define u16 unsigned short
+#define u8 unsigned char
+typedef unsigned int uint32_t;
+
+#include <setup.h>
+#include "nand_read.h"
+
+/* See also ARM920T    Technical reference Manual */
+#define C1_MMU          (1<<0)          /* mmu off/on */
+#define C1_ALIGN        (1<<1)          /* alignment faults off/on */
+#define C1_DC           (1<<2)          /* dcache off/on */
+
+#define C1_BIG_ENDIAN   (1<<7)          /* big endian off/on */
+#define C1_SYS_PROT     (1<<8)          /* system protection */
+#define C1_ROM_PROT     (1<<9)          /* ROM protection */
+#define C1_IC           (1<<12)         /* icache off/on */
+#define C1_HIGH_VECTORS (1<<13)         /* location of vectors: low/high addresses */
+
+size_t strlen(const char *s)
+{
+	size_t n = 0;
+
+	while (*s++)
+		n++;
+
+	return n;
+}
+
+char *strcpy(char *dest, const char *src)
+{
+	char * dest_orig = dest;
+
+	while (*src)
+		*dest++ = *src++;
+
+	return dest_orig;
+}
+
+unsigned int _ntohl(unsigned int n) {
+	return ((n & 0xff) << 24) | ((n & 0xff00) << 8) |
+			       ((n & 0xff0000) >> 8) | ((n & 0xff000000) >> 24);
+}
+
+void bootloader_second_phase(void)
+{
+	image_header_t	*hdr;
+        unsigned long i = 0;
+	int	machid = 1304; /* GTA02 */
+	void	(*theKernel)(int zero, int arch, uint params);
+	struct tag * params_base = (struct tag *)0x30000100; /* atags need to live here */
+	struct tag *params = params_base;
+	const char * cmdline = "rootfstype=ext2 root=/dev/mmcblk0p1 console=ttySAC2,115200 loglevel=8 init=/sbin/init ro";
+	const char *p = cmdline;
+	void * kernel_nand = (void *)(TEXT_BASE - 4 * 1024 * 1024);
+
+	puts("Checking kernel... ");
+
+	if (nand_read_ll(kernel_nand, 0x80000, 4096) < 0) {
+		puts ("Kernel header read failed\n");
+		goto unhappy;
+	}
+
+	hdr = (image_header_t *)kernel_nand;
+
+	if (_ntohl(hdr->ih_magic) != IH_MAGIC) {
+		puts("Unknown image magic ");
+		print32(hdr->ih_magic);
+		goto unhappy;
+	}
+
+	puts((const char *)hdr->ih_name);
+
+	puts("Fetching kernel...");
+
+	if (nand_read_ll(kernel_nand, 0x80000, ((32 * 1024) +
+						(_ntohl(hdr->ih_size) +
+						sizeof(hdr) + 2048)) &
+					       ~(2048 - 1)) < 0) {
+		puts ("Kernel body read failed\n");
+		goto unhappy;
+	}
+
+	puts(" Done");
+
+	theKernel = (void (*)(int, int, uint))
+				(((char *)hdr) + sizeof(image_header_t));
+
+	/* first tag */
+	params->hdr.tag = ATAG_CORE;
+	params->hdr.size = tag_size (tag_core);
+	params->u.core.flags = 0;
+	params->u.core.pagesize = 0;
+	params->u.core.rootdev = 0;
+	params = tag_next (params);
+
+	/* revision tag */
+	params->hdr.tag = ATAG_REVISION;
+	params->hdr.size = tag_size (tag_revision);
+	params->u.revision.rev = 0x350;
+	params = tag_next (params);
+
+	/* memory tags */
+	params->hdr.tag = ATAG_MEM;
+	params->hdr.size = tag_size (tag_mem32);
+	params->u.mem.start = 0x30000000;
+	params->u.mem.size = 128 * 1024 * 1024;
+	params = tag_next (params);
+
+	/* kernel commandline */
+	/* eat leading white space */
+	for (p = cmdline; *p == ' '; p++);
+
+	if (*p) {
+		params->hdr.tag = ATAG_CMDLINE;
+		params->hdr.size =
+			 (sizeof (struct tag_header) + strlen (p) + 1 + 4) >> 2;
+		strcpy (params->u.cmdline.cmdline, p);
+		params = tag_next (params);
+	}
+
+	/* needs to always be the last tag */
+	params->hdr.tag = ATAG_NONE;
+	params->hdr.size = 0;
+
+	puts ("Running Linux...\n\n");
+
+	/* trash the cache */
+
+        /* turn off I/D-cache */
+        asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
+        i &= ~(C1_DC | C1_IC);
+        asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
+
+        /* flush I/D-cache */
+        i = 0;
+        asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (i));
+
+	/* ooh that's it, we're gonna try boot this image! */
+
+	theKernel(0, machid, (unsigned int)params_base);
+
+	/* that didn't quite pan out */
+
+unhappy:
+	while (1)
+		blue_on(1);
+}
diff --git a/src/start.S b/src/start.S
index 5f956ed..c16a2a0 100644
--- a/src/start.S
+++ b/src/start.S
@@ -140,6 +140,19 @@ start_code:
 	str	r1, [r0, #0x28] */
 
 	bl	cpu_init_crit
+
+/* reset nand controller, or it is dead to us */
+
+        mov     r1, #0x4E000000
+        ldr     r2, =0xfff0             @ initial value tacls=3,rph0=7,rph1=7
+        ldr     r3, [r1, #0]
+        orr     r3, r3, r2
+        str     r3, [r1, #0]
+
+        ldr     r3, [r1, #4]
+        orr     r3, r3, #1              @ enable nand controller
+        str     r3, [r1, #4]
+
 										/* >> CFG_VIDEO_LOGO_MAX_SIZE */
 #define CFG_GBL_DATA_SIZE		128			/* size in bytes reserved for initial data */
 stack_setup:
diff --git a/src/start_kboot.c b/src/start_kboot.c
index 8b46919..b4256d2 100644
--- a/src/start_kboot.c
+++ b/src/start_kboot.c
@@ -19,9 +19,15 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  * MA 02111-1307 USA
  */
+
+/* NOTE this stuff runs in steppingstone context! */
+
+
 #include "blink_led.h"
 #include "nand_read.h"
 #include "kboot.h"
+#include <neo_gta02.h>
+
 /*
 unsigned char buf[]={
 0x0d,0xc0,0xa0,0xe1,0x00,0xd8,0x2d,0xe9,0x04,0xb0,0x4c,0xe2,0x4c,0x20,0x9f,0xe5,
@@ -33,21 +39,20 @@ unsigned char buf[]={
 0x10,0x00,0x00,0x56,0x18,0x00,0x00,0x56,0xff,0xff,0x00,0x00,0x14,0x00,0x00,0x56,
 0x01,0x00,0x50,0xe2,0xfd,0xff,0xff,0x1a,0x0e,0xf0,0xa0,0xe1,0x0a};
 */
-unsigned char buf[2*1024];
-
-#define ADDR  ((volatile unsigned *)&buf) 
 #define stringify(x) #x
 
-static char * hello = "hello";
+extern void bootloader_second_phase(void);
 
-int start_kboot(void)
+void start_kboot(void)
 {
-	static int n = 0;
-	void (*p)(unsigned int) = print32;
+	void (*phase2)(void) = bootloader_second_phase + TEXT_BASE;
 
 	port_init();
 	serial_init(0x11, UART2);
 
+	puts("Openmoko KBOOT BUILD_HOST BUILD_VERSION BUILD_DATE\n");
+
+#if 0
 	while(1) {
 		serial_putc(2, '0');
 		serial_putc(2, 'x');
@@ -63,21 +68,26 @@ int start_kboot(void)
 
 		serial_putc(2, '\n');
 
-
-//		printk("Openmoko KBOOT "stringify(BUILD_HOST)" "stringify(BUILD_VERSION)" "stringify(BUILD_DATE)"\n");
 		blue_on(1);
 		n++;
 	}
 
-	/*2. test nand flash */
-	if(nand_read_ll(buf, 0x000, sizeof(buf))==-1)
+#endif
+
+	/*
+	 * pull the whole U-Boot image into SDRAM
+	 */
+
+	if (nand_read_ll((unsigned char *)TEXT_BASE, 0, 256 * 1024) < 0)
 		while(1)
 			blink_led();
 
-	asm volatile("mov pc, %0\n"
-		:              /* output */
-		:"r"(ADDR)     /* input */
-	);
+		serial_putc(2, '0');
+		serial_putc(2, 'x');
+		print32((unsigned int)bootloader_second_phase);
+		serial_putc(2, ' ');
+		serial_putc(2, '\n');
+
 
-	return 0;
+	(phase2)();
 }





More information about the openmoko-kernel mailing list