[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