[PATCH 4/7] add-per-board-init-change-qi.patch

Andy Green andy at openmoko.com
Mon Aug 18 00:24:19 CEST 2008


Giant patch:

 - renames everything from kboot to qi

 - changes filenames accordingly in several places

 - fixes the linker script so stuff that does not execute
   from steppingstone context has real linked addresses
   in the relocated region, it means all code and pointers
   work now outside first 4KBytes

 - adds src/gta02/gta02.c to contain board-specific init and
   other functions

 - adds sophisticated structs to define most features in the
   board-specific files, including board type detection,
   board revision detection, and multiple kernel source
   definition (NAND, SD FAT, SD ext2, etc), including auto
   sequencing of trying the kernel sources in order (filesystems
   and partition support not done yet)

 - GTA02 detects itself by NOR presence and reports A5 / A6

 - commandlines for kernel also come from board-specific
   kernel source definitions so correct kernel commandlines
   are provided depending on boot device -- on GTA02 now
   boots NAND kernel into NAND jffs2 filesystem

 - CRC32 is checked on loaded kernel image to make sure we
   know about corruption in bootloader

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

 Makefile                       |   22 ++--
 dfu-kboot                      |    7 -
 dfu-qi                         |    7 +
 include/device_configuration.h |   32 -----
 include/neo_gta02.h            |    4 +
 include/qi-serial.h            |    5 -
 include/qi.h                   |   47 ++++++++
 src/gta02/gta02.c              |  236 +++++++++++++++++++++++++++++++++++++++
 src/kboot-stage1.lds           |   64 -----------
 src/lowlevel_init.S            |   17 +--
 src/mmc.c                      |    2 
 src/nand_read.c                |    6 +
 src/phase2.c                   |  239 ++++++++++++++++++++++++----------------
 src/qi.lds                     |   59 ++++++++++
 src/serial.c                   |   89 +++++++--------
 src/start.S                    |   43 ++++++-
 src/start_kboot.c              |  186 -------------------------------
 src/start_qi.c                 |  108 ++++++++++++++++++
 src/utils.c                    |  104 ++++++++++++++++-
 19 files changed, 801 insertions(+), 476 deletions(-)
 delete mode 100755 dfu-kboot
 create mode 100755 dfu-qi
 delete mode 100644 include/device_configuration.h
 create mode 100644 src/gta02/gta02.c
 delete mode 100644 src/kboot-stage1.lds
 create mode 100644 src/qi.lds
 delete mode 100644 src/start_kboot.c
 create mode 100644 src/start_qi.c

diff --git a/Makefile b/Makefile
index 22851f2..794748c 100644
--- a/Makefile
+++ b/Makefile
@@ -22,10 +22,10 @@ BUILD_BRANCH := $(shell git branch | grep ^\* | cut -d' ' -f2)
 BUILD_HEAD := $(shell git show --pretty=oneline | head -n1 | cut -d' ' -f1 | cut -b1-16)
 BUILD_VERSION := ${BUILD_BRANCH}_${BUILD_HEAD}
 
-LDS	= src/kboot-stage1.lds
+LDS	= src/qi.lds
 INCLUDE	= include
 IMAGE_DIR	= image
-CFLAGS	= -Wall -Werror -I $(INCLUDE) -g -c -O2 -fno-strict-aliasing \
+CFLAGS	= -Wall -Werror -I $(INCLUDE) -g -c -Os -fno-strict-aliasing -mlong-calls \
 	  -fno-common -ffixed-r8 -msoft-float -fno-builtin -ffreestanding \
 	  -march=armv4t -mno-thumb-interwork -Wstrict-prototypes \
 	  -DBUILD_HOST="${BUILD_HOST}" -DBUILD_VERSION="${BUILD_VERSION}" \
@@ -34,7 +34,7 @@ LDFLAGS =
 #START	= start.o lowlevel_init.o
 S_SRCS	= src/start.S src/lowlevel_init.S
 S_OBJS	= $(patsubst %.S,%.o, $(S_SRCS))
-C_SRCS	= $(wildcard src/*.c)
+C_SRCS	= $(wildcard src/*.c) $(wildcard src/gt*/*.c)
 C_OBJS	= $(patsubst %.c,%.o, $(C_SRCS))
 
 #SRCS	:= $(START: .o=.S) $(COBJS: .o=.c)
@@ -47,9 +47,9 @@ UDFU_VID = 0x1d50
 UDFU_PID = 0x5119
 UDFU_REV = 0x350
 
-TARGET	= src/start_kboot_all
-IMAGE = $(IMAGE_DIR)/kboot
-UDFU_IMAGE = $(IMAGE_DIR)/kboot.udfu
+TARGET	= image/start_qi_all
+IMAGE = $(IMAGE_DIR)/qi
+UDFU_IMAGE = $(IMAGE_DIR)/qi.udfu
 
 %.o: %.S
 	@$(CC) $(CFLAGS) -o $@ $<
@@ -62,11 +62,11 @@ all:${UDFU_IMAGE}
 ${OBJS}:${SRCS}
 
 ${UDFU_IMAGE}:${OBJS}
-	$(LD) ${LDFLAGS} -T$(LDS) -g $(OBJS) -o ${TARGET} ${LIBS}
-	$(OBJCOPY) -O binary -S ${TARGET} ${IMAGE}
-	$(OBJDUMP) -D ${TARGET} >${IMAGE}.dis
-	$(MKUDFU) -v ${UDFU_VID} -p ${UDFU_PID} -r ${UDFU_REV} \
+	@$(LD) ${LDFLAGS} -T$(LDS) -g $(OBJS) -o ${TARGET} ${LIBS}
+	@$(OBJCOPY) -O binary -S ${TARGET} ${IMAGE}
+	@$(MKUDFU) -v ${UDFU_VID} -p ${UDFU_PID} -r ${UDFU_REV} \
 						-d ${IMAGE} ${UDFU_IMAGE}
+	@$(OBJDUMP) -d ${TARGET} >${IMAGE}.dis
 
 blink_led:src/led_on.S
 	$(CC) $(CFLAGS) led_on.o led_on.S
@@ -74,4 +74,4 @@ blink_led:src/led_on.S
 	$(OBJCOPY) -O binary -S led_on_temp.o $(IMAGE)/led_on 
 
 clean:
-	rm -f src/*.o  src/*~ include/*~ ${IMAGE}* ${TARGET} ${UDFU_IMAGE}
+	@rm -f src/*.o  src/*~ include/*~ ${IMAGE}* ${TARGET} ${UDFU_IMAGE}
diff --git a/dfu-kboot b/dfu-kboot
deleted file mode 100755
index eb54a75..0000000
--- a/dfu-kboot
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/bash
-../dfu-util/src/dfu-util -a 1 -d 0x1d50:0x5119 -D image/kboot.udfu
-if [ $? -eq 1 ] ; then
-../dfu-util/src/dfu-util -a 1 -d 0x1d50:0x5120 -D image/kboot.udfu
-../dfu-util/src/dfu-util -a 1 -d 0x1d50:0x5119 -D image/kboot.udfu
-fi
-
diff --git a/dfu-qi b/dfu-qi
new file mode 100755
index 0000000..1a4e497
--- /dev/null
+++ b/dfu-qi
@@ -0,0 +1,7 @@
+#!/bin/bash
+../dfu-util/src/dfu-util -a 1 -d 0x1d50:0x5119 -D image/qi.udfu
+if [ $? -eq 1 ] ; then
+../dfu-util/src/dfu-util -a 1 -d 0x1d50:0x5120 -D image/qi.udfu
+../dfu-util/src/dfu-util -a 1 -d 0x1d50:0x5119 -D image/qi.udfu
+fi
+
diff --git a/include/device_configuration.h b/include/device_configuration.h
deleted file mode 100644
index deb7072..0000000
--- a/include/device_configuration.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* define the easily changed settings for the device here */
-
-#define CFG_LINUX_MACHINE_ID 1304
-#define CFG_LINUX_ATAG_ADDRESS 0x30000100
-#define CFG_NAND_OFFSET_FOR_KERNEL_PARTITION 0x80000
-/*
- * we follow GTA02 layout actually to make life easier allowing NOR DFU during
- * our initial development on GTA02
- */
-#define CFG_LINUX_CMDLINE_BACKUP "mtdparts=neo1973-nand:" \
-					"0x00040000(kboot)," \
-					"0x00040000(cmdline)," \
-					"0x00800000(backupkernel)," \
-					"0x000a0000(extra)," \
-					"0x00040000(identity)," \
-					"0x0f6a0000(backuprootfs) " \
-				"rootfstype=jffs2 " \
-				"root=/dev/mtdblock5 " \
-				"console=ttySAC2,115200 " \
-				"loglevel=4 " \
-				"init=/sbin/init ro"
-
-#define CFG_LINUX_CMDLINE 	"rootfstype=ext2 " \
-				"root=/dev/mmcblk0p1 " \
-				"console=ttySAC2,115200 " \
-				"loglevel=8 " \
-				"init=/sbin/init ro"
-#define CFG_LINUX_BIGGEST_KERNEL (4 * 1024 * 1024)
-#define CFG_MACHINE_REVISION 0x350
-#define CFG_MEMORY_REGION_START 0x30000000
-#define CFG_MEMORY_REGION_SIZE (128 * 1024 * 1024)
-
diff --git a/include/neo_gta02.h b/include/neo_gta02.h
index c126adb..7492630 100644
--- a/include/neo_gta02.h
+++ b/include/neo_gta02.h
@@ -22,6 +22,10 @@
 
 #ifndef __CONFIG_H
 #define __CONFIG_H
+#ifndef __ASM_MODE__
+#include <qi.h>
+extern const struct board_api board_api_gta02;
+#endif
 
 #define TEXT_BASE 0x33000000
 
diff --git a/include/qi-serial.h b/include/qi-serial.h
index 732fe67..d674178 100644
--- a/include/qi-serial.h
+++ b/include/qi-serial.h
@@ -103,9 +103,8 @@
 #define rGPJDAT   			(*(volatile unsigned *)0x560000d4)	//Port J data
 #define rGPJUP			(*(volatile unsigned *)0x560000d8)	//Port J data
 
-void port_init(void);
-void serial_init (const int ubrdiv_val,const int uart);
-void serial_putc (const int uart,const char c);
+void serial_init(const int uart, const int ubrdiv_val);
+void serial_putc(const int uart, const char c);
 int printk(const char *fmt, ...);
 int puts(const char *string);
 
diff --git a/include/qi.h b/include/qi.h
index 92d92ca..cc27c0c 100644
--- a/include/qi.h
+++ b/include/qi.h
@@ -30,6 +30,51 @@
 #define u8 unsigned char
 typedef unsigned int uint32_t;
 
+enum filesystem {
+	FS_RAW,
+	FS_FAT,
+	FS_EXT2
+};
+
+/* describes a source for getting kernel image */
+
+struct kernel_source {
+	const char *name; /* NULL name means invalid */
+	int (*block_init)(void);
+	int (*block_read)(unsigned char * buf, unsigned long byte_start,
+							       int count_bytes);
+	int partition_index; /* -1 means no partition table */
+	int offset_if_no_partition; /* used if partition_index is -1 */
+	enum filesystem filesystem;
+	const char * commandline;
+};
+
+/* describes a board variant, eg, PCB revision */
+
+struct board_variant {
+	const char * name;
+	int machine_revision; /* passed in revision tag to linux */
+};
+
+/* describes a "board", ie, a device like GTA02 including revisions */
+
+struct board_api {
+	const char * name;
+	int debug_serial_port;
+	int linux_machine_id;
+	unsigned long linux_mem_start;
+	unsigned long linux_mem_size;
+	unsigned long linux_tag_placement;
+	const struct board_variant const * (*get_board_variant)(void);
+	int (*is_this_board)(void);
+	void (*port_init)(void);
+	struct kernel_source kernel_source[8];
+};
+
+/* this is the board we are running on */
+
+extern struct board_api const * this_board;
+
 int printk(const char *fmt, ...);
 int vsprintf(char *buf, const char *fmt, va_list args);
 int puts(const char *string);
@@ -37,6 +82,8 @@ void printhex(unsigned char v);
 void print32(unsigned int u);
 void hexdump(unsigned char *start, int len);
 unsigned int _ntohl(unsigned int n);
+unsigned long crc32(unsigned long crc, const unsigned char *buf,
+							      unsigned int len);
 
 #endif
 
diff --git a/src/gta02/gta02.c b/src/gta02/gta02.c
new file mode 100644
index 0000000..066ed23
--- /dev/null
+++ b/src/gta02/gta02.c
@@ -0,0 +1,236 @@
+#include <qi.h>
+#include <neo_gta02.h>
+#include "nand_read.h"
+
+static const struct board_variant board_variants[] = {
+	[0] = {
+		.name = "A5 PCB",
+		.machine_revision = 0x350,
+	},
+	[1] = {
+		.name = "A6 PCB",
+		.machine_revision = 0x360,
+	}
+};
+
+void port_init_gta02(void)
+{
+    //CAUTION:Follow the configuration order for setting the ports.
+    // 1) setting value(GPnDAT)
+    // 2) setting control register  (GPnCON)
+    // 3) configure pull-up resistor(GPnUP)
+
+    /* 32bit data bus configuration   */
+	/*
+	 * === PORT A GROUP
+	 *     Ports  : GPA22 GPA21  GPA20 GPA19 GPA18 GPA17 GPA16 GPA15 GPA14 GPA13 GPA12
+	 *     Signal : nFCE nRSTOUT nFRE   nFWE  ALE   CLE  nGCS5 nGCS4 nGCS3 nGCS2 nGCS1
+	 *     Binary :  1     1      1  , 1   1   1    1   ,  1     1     1     1
+	 *     Ports  : GPA11   GPA10  GPA9   GPA8   GPA7   GPA6   GPA5   GPA4   GPA3   GPA2   GPA1  GPA0
+	 *     Signal : ADDR26 ADDR25 ADDR24 ADDR23 ADDR22 ADDR21 ADDR20 ADDR19 ADDR18 ADDR17 ADDR16 ADDR0
+	 *     Binary :  1       1      1      1   , 1       1      1      1   ,  1       1     1      1
+	 */
+	rGPACON = 0x007E5FFF;
+	rGPADAT |= (1 << 16);      /* Set GPA16 to high (nNAND_WP) */
+	/*
+	 * ===* PORT B GROUP
+	 *      Ports  : GPB10    GPB9    GPB8    GPB7    GPB6     GPB5    GPB4   GPB3   GPB2     GPB1      GPB0
+	 *      Signal : nXDREQ0 nXDACK0 nXDREQ1 nXDACK1 nSS_KBD nDIS_OFF L3CLOCK L3DATA L3MODE nIrDATXDEN Keyboard
+	 *      Setting: INPUT  OUTPUT   INPUT  OUTPUT   INPUT   OUTPUT   OUTPUT OUTPUT OUTPUT   OUTPUT    OUTPUT
+	 *      Binary :   00  ,  01       00  ,   01      00   ,  01       01  ,   01     01   ,  01        01
+	 */
+	rGPBCON = 0x00155555;
+	rGPBUP = 0x000007FF;
+	/*
+	 * === PORT C GROUP
+	 *     Ports  : GPC15 GPC14 GPC13 GPC12 GPC11 GPC10 GPC9 GPC8  GPC7   GPC6   GPC5 GPC4 GPC3  GPC2  GPC1 GPC0
+	 *     Signal : VD7   VD6   VD5   VD4   VD3   VD2   VD1  VD0 LCDVF2 LCDVF1 LCDVF0 VM VFRAME VLINE VCLK LEND
+	 *     Binary :  10   10  , 10    10  , 10    10  , 10   10  , 10     10  ,  10   10 , 10     10 , 10   10
+	 */
+	rGPCCON = 0x55555155;
+	rGPCUP = 0x0000FFFF & ~(1 << 5);
+	rGPCDAT |= (1 << 13) | (1 << 15); /* index detect -> hi */
+	/*
+	 * === PORT D GROUP
+	 *     Ports  : GPD15 GPD14 GPD13 GPD12 GPD11 GPD10 GPD9 GPD8 GPD7 GPD6 GPD5 GPD4 GPD3 GPD2 GPD1 GPD0
+	 *     Signal : VD23  VD22  VD21  VD20  VD19  VD18  VD17 VD16 VD15 VD14 VD13 VD12 VD11 VD10 VD9  VD8
+	 *     Binary : 10    10  , 10    10  , 10    10  , 10   10 , 10   10 , 10   10 , 10   10 ,10   10
+	 */
+	rGPDCON = 0x55555555;
+	rGPDUP = 0x0000FFFF;
+	rGPDDAT |= (1 << 0) | (1 << 3) | (1 << 4); /* index detect -> hi */
+	/*
+	 * === PORT E GROUP
+	 *     Ports  : GPE15  GPE14 GPE13   GPE12   GPE11   GPE10   GPE9    GPE8     GPE7  GPE6  GPE5   GPE4
+	 *     Signal : IICSDA IICSCL SPICLK SPIMOSI SPIMISO SDDATA3 SDDATA2 SDDATA1 SDDATA0 SDCMD SDCLK I2SSDO
+	 *     Binary :  10     10  ,  10      10  ,  10      10   ,  10      10   ,   10    10  , 10     10  ,
+	 *     -------------------------------------------------------------------------------------------------------
+	 *     Ports  :  GPE3   GPE2  GPE1    GPE0
+	 *     Signal : I2SSDI CDCLK I2SSCLK I2SLRCK
+	 *     Binary :  10     10  ,  10      10
+	 */
+	rGPECON = 0xAAAAAAAA;
+	rGPEUP = 0x0000FFFF & ~(1 << 11);
+	/*
+	 * === PORT F GROUP
+	 *     Ports  : GPF7   GPF6   GPF5   GPF4      GPF3     GPF2  GPF1   GPF0
+	 *     Signal : nLED_8 nLED_4 nLED_2 nLED_1 nIRQ_PCMCIA EINT2 KBDINT EINT0
+	 *     Setting: Output Output Output Output    EINT3    EINT2 EINT1  EINT0
+	 *     Binary :  01      01 ,  01     01  ,     10       10  , 10     10
+	 */
+	/* pulldown on GPF03: TP-4705+debug - debug conn will float */
+	rGPFCON = 0x0000AAAA;
+	rGPFUP = 0x000000FF & ~(1 << 3);
+
+
+	/*
+	 * === PORT G GROUP
+	 *     Ports  : GPG15 GPG14 GPG13 GPG12 GPG11    GPG10    GPG9     GPG8     GPG7      GPG6
+	 *     Signal : nYPON  YMON nXPON XMON  EINT19 DMAMODE1 DMAMODE0 DMASTART KBDSPICLK KBDSPIMOSI
+	 *     Setting: nYPON  YMON nXPON XMON  EINT19  Output   Output   Output   SPICLK1    SPIMOSI1
+	 *     Binary :   11    11 , 11    11  , 10      01    ,   01       01   ,    11         11
+	 *     -----------------------------------------------------------------------------------------
+	 *     Ports  :    GPG5       GPG4    GPG3    GPG2    GPG1    GPG0
+	 *     Signal : KBDSPIMISO LCD_PWREN EINT11 nSS_SPI IRQ_LAN IRQ_PCMCIA
+	 *     Setting:  SPIMISO1  LCD_PWRDN EINT11   nSS0   EINT9    EINT8
+	 *     Binary :     11         11   ,  10      11  ,  10        10
+	 */
+	rGPGCON = 0x01AAFE79;
+	rGPGUP = 0x0000FFFF;
+	/*
+	 * === PORT H GROUP
+	 *     Ports  :  GPH10    GPH9  GPH8 GPH7  GPH6  GPH5 GPH4 GPH3 GPH2 GPH1  GPH0
+	 *     Signal : CLKOUT1 CLKOUT0 UCLK RXD2 TXD2 RXD1 TXD1 RXD0 TXD0 nRTS0 nCTS0
+	 *     Binary :   10   ,  10     10 , 11    11  , 10   10 , 10   10 , 10    10
+	 */
+	/* pulldown on GPH08: UEXTCLK, just floats!
+	 * pulldown GPH0 -- nCTS0 / RTS_MODEM -- floats when GSM off
+	 * pulldown GPH3 -- RXD[0] / TX_MODEM -- floats when GSM off
+	 */
+	rGPHCON = 0x001AAAAA;
+	rGPHUP = 0x000007FF & ~(1 << 8) & ~(1 << 0) & ~(1 << 3);
+
+	/* pulldown on GPJ00: input, just floats! */
+	/* pulldown on GPJ07: WLAN module WLAN_GPIO0, no ext pull */
+	rGPJCON = 0x1551544;
+	rGPJUP = 0x1ffff & ~(1 << 0) & ~(1 << 7);
+	rGPJDAT |= (1 << 4) | (1 << 6);
+					/* Set GPJ4 to high (nGSM_EN) */
+					/* Set GPJ6 to high (nDL_GSM) */
+	rGPJDAT &= ~(1 << 5);	/* Set GPJ5 to low 3D RST */
+
+	/* leaving Glamo forced to Reset# active here killed
+	 * U-Boot when you touched the memory region
+	 */
+
+	rGPJDAT |= (1 << 5);	/* Set GPJ5 to high 3D RST */
+
+	serial_init(UART2, 0x11);
+}
+
+/**
+ * returns PCB revision information in b9,b8 and b2,b1,b0
+ * Pre-GTA02 A6 returns 0x000
+ *     GTA02 A6 returns 0x001
+ */
+
+int gta02_get_pcb_revision(void)
+{
+	int n;
+	u32 u;
+
+	/* make C13 and C15 pulled-down inputs */
+	rGPCCON &= ~0xcc000000;
+	rGPCUP  &= ~((1 << 13) | (1 << 15));
+	/* D0, D3 and D4 pulled-down inputs */
+	rGPDCON &= ~0x000003c3;
+	rGPDUP  &= ~((1 << 0) | (1 << 3) | (1 << 4));
+
+	/* delay after changing pulldowns */
+	u = rGPCDAT;
+	u = rGPDDAT;
+
+	/* read the version info */
+	u = rGPCDAT;
+	n =  (u >> (13 - 0)) & 0x001;
+	n |= (u >> (15 - 1)) & 0x002;
+	u = rGPDDAT;
+	n |= (u << (0 + 2))  & 0x004;
+
+	n |= (u << (8 - 3))  & 0x100;
+	n |= (u << (9 - 4))  & 0x200;
+
+	/*
+	 * when not being interrogated, all of the revision GPIO
+	 * are set to output HIGH without pulldown so no current flows
+	 * if they are NC or pulled up.
+	 */
+	/* make C13 and C15 high ouputs with no pulldowns */
+	rGPCCON |= 0x44000000;
+	rGPCUP  |= (1 << 13) | (1 << 15);
+	rGPCDAT |= (1 << 13) | (1 << 15);
+	/* D0, D3 and D4 high ouputs with no pulldowns */
+	rGPDCON |= 0x00000141;
+	rGPDUP  |= (1 << 0) | (1 << 3) | (1 << 4);
+	rGPDDAT |= (1 << 0) | (1 << 3) | (1 << 4);
+
+	return n;
+}
+
+
+
+/* return nonzero if we believe we run on GTA02 */
+
+int is_this_board_gta02(void)
+{
+	/* look for GTA02 NOR */
+
+	*(volatile unsigned short *)(0x18000000) = 0x98;
+
+	return !!(*(volatile unsigned short *)(0x18000000) == 0x0020);
+}
+
+const struct board_variant const * get_board_variant_gta02(void)
+{
+	return &board_variants[gta02_get_pcb_revision()];
+}
+
+/*
+ * our API for bootloader on this machine
+ */
+
+const struct board_api board_api_gta02 = {
+	.name = "Freerunner / GTA02",
+	.debug_serial_port = 2,
+	.linux_machine_id = 1304,
+	.linux_mem_start = 0x30000000,
+	.linux_mem_size = (128 * 1024 * 1024),
+	.linux_tag_placement = 0x30000000 + 0x100,
+	.get_board_variant = get_board_variant_gta02,
+	.is_this_board = is_this_board_gta02,
+	.port_init = port_init_gta02,
+	/* these are the ways we could boot GTA02 in order to try */
+	.kernel_source = {
+		[0] = {
+			.name = "NAND Kernel",
+			.block_read = nand_read_ll,
+			.partition_index = -1,
+			.offset_if_no_partition = 0x80000,
+			.filesystem = FS_RAW,
+			.commandline = "mtdparts=physmap-flash:-(nor);" \
+					"neo1973-nand:" \
+					 "0x00040000(qi)," \
+					 "0x00040000(cmdline)," \
+					 "0x00800000(backupkernel)," \
+					 "0x000a0000(extra)," \
+					 "0x00040000(identity)," \
+					 "0x0f6a0000(backuprootfs) " \
+				       "rootfstype=jffs2 " \
+				       "root=/dev/mtdblock6 " \
+				       "console=ttySAC2,115200 " \
+				       "loglevel=4 " \
+				       "init=/sbin/init "\
+				       "ro"
+		},
+	},
+};
diff --git a/src/kboot-stage1.lds b/src/kboot-stage1.lds
deleted file mode 100644
index 5c8d50c..0000000
--- a/src/kboot-stage1.lds
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * (C) Copyright 2002
- * Gary Jennejohn, DENX Software Engineering, <gj 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_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
-OUTPUT_ARCH(arm)
-ENTRY(_start)
-SECTIONS
-{
-	. = 0x00000000;
-
-	/* this is intended to take the first 4KBytes of stuff initially.
-	 * We have to make sure we have .rodata* in there for everything
-	 * because we do not compile PIC.
-	 */
-
-	. = ALIGN(4);
-	.text      :
-	{
-	  src/start.o	(.text .rodata* .data)
-	  src/lowlevel_init.o(.text .rodata* .data)
-	  src/start_kboot.o	(.text .rodata* .data)
-	  src/serial.o	(.text .rodata* .data)
-	  src/blink_led.o	(.text .rodata* .data)
-	  * (.rodata* .data)
-	}
-
-	. = ALIGN(4);
-	.everything_else : { *(.text) }
-
-	. = ALIGN(4);
-	.got : 
-    { 
-        *(.got) 
-    }
-
-	. = 0x32000000 ;
-	__bss_start = .;
-	.bss (NOLOAD) : 
-    { 
-        *(.bss) 
-    }
-	_end = .;
-}
diff --git a/src/lowlevel_init.S b/src/lowlevel_init.S
index 4f20d5e..2a1654c 100644
--- a/src/lowlevel_init.S
+++ b/src/lowlevel_init.S
@@ -26,6 +26,7 @@
  * #include <config.h>
  * #include <version.h>
  */
+#define __ASM_MODE__
 #include <neo_gta02.h>
 
 /*
@@ -125,10 +126,8 @@
 
 .globl lowlevel_init
 lowlevel_init:
-	/* memory control configuration */
-	/* make r0 relative the current location so that it */
-	/* reads SMRDATA out of FLASH rather than memory ! */
-	adr	r0, SMRDATA
+
+	ldr	r0, =SMRDATA
 	ldr	r1, =BWSCON	/* Bus Width Status Controller */
 	add     r2, r0, #13*4
 0:
@@ -142,21 +141,11 @@ lowlevel_init:
 	orr	r1, r1, #0xc0000000
 	mcr	p15, 0, r1, c1, c0, 0
 
-	/* enable KEEPACT(GPJ8) to make sure PMU keeps us alive */
-	ldr	r0, =0x56000000	/* GPJ base */
-	ldr	r1, [r0, #0xd0]	/* GPJCON */
-	orr	r1, r1, #(1 << 16)
-	str	r1, [r0, #0xd0]
-
-	ldr	r1, [r0, #0xd4]	/* GPJDAT */
-	orr	r1, r1, #(1 << 8)
-	str	r1, [r0, #0xd4]
 	/* everything is fine now */
 	mov	pc, lr
 
 	.ltorg
 /* the literal pools origin */
-
 SMRDATA:
     .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
     .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
diff --git a/src/mmc.c b/src/mmc.c
index 39f1720..b982657 100644
--- a/src/mmc.c
+++ b/src/mmc.c
@@ -1,3 +1,4 @@
+#if 0
 /*
  * u-boot S3C2410 MMC/SD card driver
  * (C) Copyright 2006 by OpenMoko, Inc.
@@ -536,3 +537,4 @@ mmc2info(ulong addr)
 }
 
 #endif	/* defined(CONFIG_MMC) && defined(CONFIG_MMC_S3C) */
+#endif
diff --git a/src/nand_read.c b/src/nand_read.c
index bdd1b6a..6351173 100644
--- a/src/nand_read.c
+++ b/src/nand_read.c
@@ -89,8 +89,10 @@ static int nand_read_page_ll(unsigned char *buf, unsigned long addr)
 {
 	unsigned short *ptr16 = (unsigned short *)buf;
 	unsigned int i, page_num;
+#if 0
 	unsigned char ecc[64];
 	unsigned short *p16 = (unsigned short *)ecc;
+#endif
 
 	nand_clear_RnB();
 
@@ -108,11 +110,11 @@ static int nand_read_page_ll(unsigned char *buf, unsigned long addr)
 
 	for (i = 0; i < NAND_PAGE_SIZE/2; i++)
 		*ptr16++ = NFDATA16;
-
+#if 0
 	for (i = 0; i < 64 / 2; i++) {
 		*p16++ = NFDATA16;
 	}
-
+#endif
 	return NAND_PAGE_SIZE;
 }
 
diff --git a/src/phase2.c b/src/phase2.c
index 59a18f0..826e90e 100644
--- a/src/phase2.c
+++ b/src/phase2.c
@@ -31,111 +31,156 @@
 #include <setup.h>
 #include "nand_read.h"
 
-#include <device_configuration.h>
-
-#define C1_DC           (1<<2)          /* dcache off/on */
-#define C1_IC           (1<<12)         /* icache off/on */
 
 void bootloader_second_phase(void)
 {
-	image_header_t	*hdr;
-        unsigned long i = 0;
 	void	(*the_kernel)(int zero, int arch, uint params);
-	struct tag * params_base = (struct tag *)CFG_LINUX_ATAG_ADDRESS;
-	struct tag *params = params_base;
-	const char * cmdline = CFG_LINUX_CMDLINE;
-	const char *p = cmdline;
-	void * kernel_nand = (void *)(TEXT_BASE - CFG_LINUX_BIGGEST_KERNEL);
-
-	puts("Checking kernel... ");
-
-	if (nand_read_ll(kernel_nand, CFG_NAND_OFFSET_FOR_KERNEL_PARTITION,
-								    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, CFG_NAND_OFFSET_FOR_KERNEL_PARTITION,
-		((32 * 1024) + (_ntohl(hdr->ih_size) + sizeof(hdr) + 2048)) &
+	int kernel = 0;
+	const struct board_variant * board_variant =
+					      (this_board->get_board_variant)();
+
+	/* we try the possible kernels for this board in order */
+
+	while (this_board->kernel_source[kernel].name) {
+		const char * cmdline = this_board->kernel_source[kernel].commandline;
+		const char *p = cmdline;
+		struct tag *params = (struct tag *)this_board->linux_tag_placement;
+		void * kernel_dram = (void *)(TEXT_BASE - (8 * 1024 * 1024));
+		unsigned long crc;
+		image_header_t	*hdr;
+
+		/* eat leading white space */
+		for (p = cmdline; *p == ' '; p++);
+
+		puts("\nTrying kernel: ");
+		puts(this_board->kernel_source[kernel].name);
+		puts("\n");
+
+		/* if this device needs initializing, try to init it */
+		if (this_board->kernel_source[kernel].block_init)
+			if ((this_board->kernel_source[kernel].block_init)()) {
+				puts("block device init failed\n");
+				kernel++;
+				continue;
+			}
+
+		/* if there's a partition table implied, parse it, otherwise
+		 * just use a fixed offset
+		 */
+		if (this_board->kernel_source[kernel].partition_index != -1) {
+
+			puts("partitions not supported yet\n");
+			kernel++;
+			continue;
+
+		} else {
+			if (this_board->kernel_source[kernel].block_read(
+				kernel_dram, this_board->kernel_source[kernel].
+					    offset_if_no_partition, 4096) < 0) {
+				puts ("Bad kernel header\n");
+				kernel++;
+				continue;
+			}
+
+			hdr = (image_header_t *)kernel_dram;
+
+			if (_ntohl(hdr->ih_magic) != IH_MAGIC) {
+				puts("bad magic ");
+				print32(hdr->ih_magic);
+				kernel++;
+				continue;
+			}
+
+			puts("        Found: ");
+			puts((const char *)hdr->ih_name);
+			puts("\n         Size: 0x");
+			print32(_ntohl(hdr->ih_size));
+
+			if (nand_read_ll(kernel_dram,
+				this_board->kernel_source[kernel].
+				offset_if_no_partition, (_ntohl(hdr->ih_size) +
+						sizeof(image_header_t) + 2048) &
 							     ~(2048 - 1)) < 0) {
-		puts ("Kernel body read failed\n");
-		goto unhappy;
+				puts ("Bad kernel read\n");
+				kernel++;
+				continue;
+			}
+		}
+
+		puts("\n      Cmdline: ");
+		puts(p);
+		puts("\n");
+
+		/*
+		 * It's good for now to know that our kernel is intact from
+		 * the storage before we jump into it and maybe crash silently
+		 * even though it costs us some time
+		 */
+		crc = crc32(0, kernel_dram + sizeof(image_header_t),
+							_ntohl(hdr->ih_size));
+		if (crc != _ntohl(hdr->ih_dcrc)) {
+			puts("\nKernel CRC ERROR: read 0x");
+			print32(crc);
+			puts(" vs hdr CRC 0x");
+			print32(_ntohl(hdr->ih_dcrc));
+			puts("\n");
+			kernel++;
+			continue;
+		}
+
+		the_kernel = (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 = board_variant->machine_revision;
+		params = tag_next(params);
+
+		/* memory tags */
+		params->hdr.tag = ATAG_MEM;
+		params->hdr.size = tag_size (tag_mem32);
+		params->u.mem.start = this_board->linux_mem_start;
+		params->u.mem.size = this_board->linux_mem_size;
+		params = tag_next(params);
+
+		/* kernel commandline */
+
+		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 ("Starting --->\n\n");
+
+		/*
+		* ooh that's it, we're gonna try boot this image!
+		* never mind the cache, Linux will take care of it
+		*/
+		the_kernel(0, this_board->linux_machine_id,
+						this_board->linux_tag_placement);
+
+		/* we won't come back here no matter what */
 	}
 
-	puts(" Done");
-
-	the_kernel = (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 = CFG_MACHINE_REVISION;
-	params = tag_next (params);
-
-	/* memory tags */
-	params->hdr.tag = ATAG_MEM;
-	params->hdr.size = tag_size (tag_mem32);
-	params->u.mem.start = CFG_MEMORY_REGION_START;
-	params->u.mem.size = CFG_MEMORY_REGION_SIZE;
-	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! */
-
-	the_kernel(0, CFG_LINUX_MACHINE_ID, (unsigned int)params_base);
-
-	/* that didn't quite pan out */
+	/* none of the kernels worked out */
 
-unhappy:
+	puts("No usable kernel image found, we've had it  :-(\n");
 	while (1)
 		blue_on(1);
 }
diff --git a/src/qi.lds b/src/qi.lds
new file mode 100644
index 0000000..29ec63f
--- /dev/null
+++ b/src/qi.lds
@@ -0,0 +1,59 @@
+/*
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj 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_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+	. = 0x00000000;
+
+	/* this is intended to take the first 4KBytes of stuff initially.
+	 * We have to make sure we have .rodata* in there for everything
+	 * because we do not compile PIC.
+	 */
+
+	. = ALIGN(4);
+	.text      :
+	{
+	  src/start.o		(.text .rodata* .data)
+	  src/lowlevel_init.o	(.text .rodata* .data)
+	  src/start_qi.o	(.text .rodata* .data)
+	  src/blink_led.o	(.text .rodata* .data)
+	  src/nand_read.o	(.text .rodata* .data)
+	  src/serial.o		(.text .rodata* .data)
+	}
+
+	. = ALIGN(4);
+	.everything_else  ADDR (.text) + SIZEOF (.text) + 0x33000000 :
+		AT ( ADDR (.text) + SIZEOF (.text) ) { *(.text .rodata* .data) }
+
+	. = 0x33800000 ;
+	__bss_start = .;
+	.bss (NOLOAD) : 
+    { 
+        *(.bss) 
+    }
+	_end = .;
+}
diff --git a/src/serial.c b/src/serial.c
index 19fb850..61b4762 100644
--- a/src/serial.c
+++ b/src/serial.c
@@ -23,55 +23,54 @@
 #include <qi.h>
 #include "blink_led.h"
 
-void serial_init (const int uart)
+void serial_init (const int uart, const int ubrdiv_val)
 {
-    int ubrdiv_val = 0x11;
-  switch(uart)
-    {
-    case UART0:
-      rULCON0 = 0x3;
-      rUCON0 = 0x245;
-      rUFCON0 = 0x0;
-      rUMCON0 = 0x0;
-      rUBRDIV0 = ubrdiv_val;
-      break;
-    case UART1:
-      rULCON1 = 0x3;
-      rUCON1 = 0x245;
-      rUFCON1 = 0x0;
-      rUMCON1 = 0x0;
-      rUBRDIV1 = ubrdiv_val;
-      break;
-    case UART2:
-      rULCON2 = 0x3;
-      rUCON2 = 0x245;
-      rUFCON2 = 0x1;
-      rUBRDIV2 = ubrdiv_val;
-      break;
-    default:
-      break;
-    }
+	switch(uart)
+	{
+	case UART0:
+		rULCON0 = 0x3;
+		rUCON0 = 0x245;
+		rUFCON0 = 0x0;
+		rUMCON0 = 0x0;
+		rUBRDIV0 = ubrdiv_val;
+		break;
+	case UART1:
+		rULCON1 = 0x3;
+		rUCON1 = 0x245;
+		rUFCON1 = 0x0;
+		rUMCON1 = 0x0;
+		rUBRDIV1 = ubrdiv_val;
+		break;
+	case UART2:
+		rULCON2 = 0x3;
+		rUCON2 = 0x245;
+		rUFCON2 = 0x1;
+		rUBRDIV2 = ubrdiv_val;
+		break;
+	default:
+		break;
+	}
 }
 /*
  * Output a single byte to the serial port.
  */
-void serial_putc (const int uart,const char c)
+void serial_putc (const int uart, const char c)
 {
-  switch(uart)
-    {
-    case UART0:
-      while ( !( rUTRSTAT0 & 0x2 ) );
-      WrUTXH0(c);
-      break;
-    case UART1:
-      while ( !( rUTRSTAT1 & 0x2 ) );
-      WrUTXH1(c);
-      break;
-    case UART2:
-      while ( !( rUTRSTAT2 & 0x2 ) );
-      WrUTXH2(c);
-      break;
-    default:
-      break;
-    }
+	switch(uart)
+	{
+	case UART0:
+		while ( !( rUTRSTAT0 & 0x2 ) );
+		WrUTXH0(c);
+		break;
+	case UART1:
+		while ( !( rUTRSTAT1 & 0x2 ) );
+		WrUTXH1(c);
+		break;
+	case UART2:
+		while ( !( rUTRSTAT2 & 0x2 ) );
+		WrUTXH2(c);
+		break;
+	default:
+		break;
+	}
 }
diff --git a/src/start.S b/src/start.S
index 1d2ee92..3a98bef 100644
--- a/src/start.S
+++ b/src/start.S
@@ -18,6 +18,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  * MA 02111-1307 USA
  */
+
+#define __ASM_MODE__
 #include <neo_gta02.h>
 
 .globl _start
@@ -119,10 +121,38 @@ start_code:
 	ldr	r1, =0x7fff0		/* all clocks on */
 	str	r1, [r0]
 
-	/* gpio UART0 init */
+	/* gpio UART2 init, H port */
 	ldr	r0, =0x56000070
-	ldr	r1, =0x2afaaa
+	ldr	r1, =0x001AAAAA
+	str	r1, [r0]
+
+	/* enable KEEPACT(GPJ8) to make sure PMU keeps us alive */
+	ldr	r0, =0x56000000	/* GPJ base */
+	ldr	r1, [r0, #0xd0]	/* GPJCON */
+	orr	r1, r1, #(1 << 16)
+	str	r1, [r0, #0xd0]
+
+	ldr	r1, [r0, #0xd4]	/* GPJDAT */
+	orr	r1, r1, #(1 << 8)
+	str	r1, [r0, #0xd4]
+
+
+	/* init uart2 */
+	ldr	r0, =0x50008000
+	mov	r1, #0x03
 	str	r1, [r0]
+	ldr	r1, =0x245
+	str	r1, [r0, #0x04]
+	mov	r1, #0x00
+	str	r1, [r0, #0x08]
+	mov	r1, #0x00
+	str	r1, [r0, #0x0c] 
+	mov	r1, #0x11
+	str	r1, [r0, #0x28]
+
+	ldr	r0, =0x50008000
+	ldr	r1, =0x54
+	str	r1, [r0, #0x20]
 
 	bl	cpu_init_crit
 
@@ -140,11 +170,12 @@ start_code:
 
 								/* >> CFG_VIDEO_LOGO_MAX_SIZE */
 #define CFG_GBL_DATA_SIZE		128			/* size in bytes reserved for initial data */
+
 stack_setup:
 	ldr	r0, _TEXT_BASE		/* upper 128 KiB: relocated uboot   */
 	sub	r0, r0, #CFG_GBL_DATA_SIZE 	/* bdinfo                        */
 	sub	sp, r0, #12		/* leave 3 words for abort-stack    */
-
+#if 0
 clear_bss:
 	ldr	r0, _bss_start		/* find start of bss segment        */
 	ldr	r1, _bss_end		/* stop here                        */
@@ -155,13 +186,14 @@ clbss_l:
 	add	r0, r0, #4
 	cmp	r0, r1
 	ble	clbss_l
+#endif
 
 /* we are going to jump into the C part of the init now */
-
+spin:
 	ldr	pc, _start_armboot
 
 _start_armboot:	
-	.word 	start_kboot
+	.word 	start_qi
 
 /*
  *************************************************************************
@@ -175,6 +207,7 @@ _start_armboot:
  */
 
 cpu_init_crit:
+
 	/*
 	 * flush v4 I/D caches
 	 */
diff --git a/src/start_kboot.c b/src/start_kboot.c
deleted file mode 100644
index 8b5078c..0000000
--- a/src/start_kboot.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * (C) Copyright 2007 OpenMoko, Inc.
- * Author: xiangfu liu <xiangfu at openmoko.org>
- *         Andy Green <andy at openmoko.com>
- *
- * Configuation settings for the OPENMOKO Neo GTA02 Linux GSM phone
- *
- * 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
- */
-
-/* NOTE this stuff runs in steppingstone context! */
-
-
-#include <qi.h>
-#include "blink_led.h"
-#include "nand_read.h"
-#include <neo_gta02.h>
-
-#define stringify2(s) stringify1(s)
-#define stringify1(s) #s
-
-extern void bootloader_second_phase(void);
-
-void port_init(void)
-{
-    //CAUTION:Follow the configuration order for setting the ports.
-    // 1) setting value(GPnDAT)
-    // 2) setting control register  (GPnCON)
-    // 3) configure pull-up resistor(GPnUP)
-
-    /* 32bit data bus configuration   */
-	/*
-	 * === PORT A GROUP
-	 *     Ports  : GPA22 GPA21  GPA20 GPA19 GPA18 GPA17 GPA16 GPA15 GPA14 GPA13 GPA12
-	 *     Signal : nFCE nRSTOUT nFRE   nFWE  ALE   CLE  nGCS5 nGCS4 nGCS3 nGCS2 nGCS1
-	 *     Binary :  1     1      1  , 1   1   1    1   ,  1     1     1     1
-	 *     Ports  : GPA11   GPA10  GPA9   GPA8   GPA7   GPA6   GPA5   GPA4   GPA3   GPA2   GPA1  GPA0
-	 *     Signal : ADDR26 ADDR25 ADDR24 ADDR23 ADDR22 ADDR21 ADDR20 ADDR19 ADDR18 ADDR17 ADDR16 ADDR0
-	 *     Binary :  1       1      1      1   , 1       1      1      1   ,  1       1     1      1
-	 */
-	rGPACON = 0x007E5FFF;
-	rGPADAT |= (1 << 16);      /* Set GPA16 to high (nNAND_WP) */
-	/*
-	 * ===* PORT B GROUP
-	 *      Ports  : GPB10    GPB9    GPB8    GPB7    GPB6     GPB5    GPB4   GPB3   GPB2     GPB1      GPB0
-	 *      Signal : nXDREQ0 nXDACK0 nXDREQ1 nXDACK1 nSS_KBD nDIS_OFF L3CLOCK L3DATA L3MODE nIrDATXDEN Keyboard
-	 *      Setting: INPUT  OUTPUT   INPUT  OUTPUT   INPUT   OUTPUT   OUTPUT OUTPUT OUTPUT   OUTPUT    OUTPUT
-	 *      Binary :   00  ,  01       00  ,   01      00   ,  01       01  ,   01     01   ,  01        01
-	 */
-	rGPBCON = 0x00155555;
-	rGPBUP = 0x000007FF;
-	/*
-	 * === PORT C GROUP
-	 *     Ports  : GPC15 GPC14 GPC13 GPC12 GPC11 GPC10 GPC9 GPC8  GPC7   GPC6   GPC5 GPC4 GPC3  GPC2  GPC1 GPC0
-	 *     Signal : VD7   VD6   VD5   VD4   VD3   VD2   VD1  VD0 LCDVF2 LCDVF1 LCDVF0 VM VFRAME VLINE VCLK LEND
-	 *     Binary :  10   10  , 10    10  , 10    10  , 10   10  , 10     10  ,  10   10 , 10     10 , 10   10
-	 */
-	rGPCCON = 0x55555155;
-	rGPCUP = 0x0000FFFF & ~(1 << 5);
-	rGPCDAT |= (1 << 13) | (1 << 15); /* index detect -> hi */
-	/*
-	 * === PORT D GROUP
-	 *     Ports  : GPD15 GPD14 GPD13 GPD12 GPD11 GPD10 GPD9 GPD8 GPD7 GPD6 GPD5 GPD4 GPD3 GPD2 GPD1 GPD0
-	 *     Signal : VD23  VD22  VD21  VD20  VD19  VD18  VD17 VD16 VD15 VD14 VD13 VD12 VD11 VD10 VD9  VD8
-	 *     Binary : 10    10  , 10    10  , 10    10  , 10   10 , 10   10 , 10   10 , 10   10 ,10   10
-	 */
-	rGPDCON = 0x55555555;
-	rGPDUP = 0x0000FFFF;
-	rGPDDAT |= (1 << 0) | (1 << 3) | (1 << 4); /* index detect -> hi */
-	/*
-	 * === PORT E GROUP
-	 *     Ports  : GPE15  GPE14 GPE13   GPE12   GPE11   GPE10   GPE9    GPE8     GPE7  GPE6  GPE5   GPE4
-	 *     Signal : IICSDA IICSCL SPICLK SPIMOSI SPIMISO SDDATA3 SDDATA2 SDDATA1 SDDATA0 SDCMD SDCLK I2SSDO
-	 *     Binary :  10     10  ,  10      10  ,  10      10   ,  10      10   ,   10    10  , 10     10  ,
-	 *     -------------------------------------------------------------------------------------------------------
-	 *     Ports  :  GPE3   GPE2  GPE1    GPE0
-	 *     Signal : I2SSDI CDCLK I2SSCLK I2SLRCK
-	 *     Binary :  10     10  ,  10      10
-	 */
-	rGPECON = 0xAAAAAAAA;
-	rGPEUP = 0x0000FFFF & ~(1 << 11);
-	/*
-	 * === PORT F GROUP
-	 *     Ports  : GPF7   GPF6   GPF5   GPF4      GPF3     GPF2  GPF1   GPF0
-	 *     Signal : nLED_8 nLED_4 nLED_2 nLED_1 nIRQ_PCMCIA EINT2 KBDINT EINT0
-	 *     Setting: Output Output Output Output    EINT3    EINT2 EINT1  EINT0
-	 *     Binary :  01      01 ,  01     01  ,     10       10  , 10     10
-	 */
-	/* pulldown on GPF03: TP-4705+debug - debug conn will float */
-	rGPFCON = 0x0000AAAA;
-	rGPFUP = 0x000000FF & ~(1 << 3);
-
-
-	/*
-	 * === PORT G GROUP
-	 *     Ports  : GPG15 GPG14 GPG13 GPG12 GPG11    GPG10    GPG9     GPG8     GPG7      GPG6
-	 *     Signal : nYPON  YMON nXPON XMON  EINT19 DMAMODE1 DMAMODE0 DMASTART KBDSPICLK KBDSPIMOSI
-	 *     Setting: nYPON  YMON nXPON XMON  EINT19  Output   Output   Output   SPICLK1    SPIMOSI1
-	 *     Binary :   11    11 , 11    11  , 10      01    ,   01       01   ,    11         11
-	 *     -----------------------------------------------------------------------------------------
-	 *     Ports  :    GPG5       GPG4    GPG3    GPG2    GPG1    GPG0
-	 *     Signal : KBDSPIMISO LCD_PWREN EINT11 nSS_SPI IRQ_LAN IRQ_PCMCIA
-	 *     Setting:  SPIMISO1  LCD_PWRDN EINT11   nSS0   EINT9    EINT8
-	 *     Binary :     11         11   ,  10      11  ,  10        10
-	 */
-	rGPGCON = 0x01AAFE79;
-	rGPGUP = 0x0000FFFF;
-	/*
-	 * === PORT H GROUP
-	 *     Ports  :  GPH10    GPH9  GPH8 GPH7  GPH6  GPH5 GPH4 GPH3 GPH2 GPH1  GPH0
-	 *     Signal : CLKOUT1 CLKOUT0 UCLK nCTS1 nRTS1 RXD1 TXD1 RXD0 TXD0 nRTS0 nCTS0
-	 *     Binary :   10   ,  10     10 , 11    11  , 10   10 , 10   10 , 10    10
-	 */
-	/* pulldown on GPH08: UEXTCLK, just floats!
-	 * pulldown GPH0 -- nCTS0 / RTS_MODEM -- floats when GSM off
-	 * pulldown GPH3 -- RXD[0] / TX_MODEM -- floats when GSM off
-	 */
-	rGPHCON = 0x001AAAAA;
-	rGPHUP = 0x000007FF & ~(1 << 8) & ~(1 << 0) & ~(1 << 3);
-
-	/* pulldown on GPJ00: input, just floats! */
-	/* pulldown on GPJ07: WLAN module WLAN_GPIO0, no ext pull */
-	rGPJCON = 0x1551544;
-	rGPJUP = 0x1ffff & ~(1 << 0) & ~(1 << 7);
-	rGPJDAT |= (1 << 4) | (1 << 6);
-					/* Set GPJ4 to high (nGSM_EN) */
-					/* Set GPJ6 to high (nDL_GSM) */
-	rGPJDAT &= ~(1 << 5);	/* Set GPJ5 to low 3D RST */
-
-	/* leaving Glamo forced to Reset# active here killed
-	 * U-Boot when you touched the memory region
-	 */
-
-	rGPJDAT |= (1 << 5);	/* Set GPJ5 to high 3D RST */
-}
-
-
-
-void start_kboot(void)
-{
-	void (*phase2)(void) = (void (*)(void))((int)bootloader_second_phase +
-								     TEXT_BASE);
-
-	port_init();
-	serial_init(UART2);
-
-	puts("Qi Bootloader  "stringify2(BUILD_HOST)" "
-			      stringify2(BUILD_VERSION)" "
-			      stringify2(BUILD_DATE));
-	puts("Copyright (C) 2008 Openmoko, Inc.");
-	puts("This is free software; see the source for copying conditions.\n"
-	     "There is NO warranty; not even for MERCHANTABILITY or\n"
-	     "FITNESS FOR A PARTICULAR PURPOSE.\n");
-
-	/*
-	 * We got the first 4KBytes of the bootloader pulled into the
-	 * steppingstone SRAM for free.  Now we pull the whole bootloader
-	 * image into SDRAM.
-	 *
-	 * So this doesn't trash position-dependent code, we took care in the
-	 * linker script to arrange all rodata* segment content to be in the
-	 * first 4K region.
-	 */
-
-	/* We randomly pull 24KBytes of bootloader */
-	if (nand_read_ll((unsigned char *)TEXT_BASE, 0, 24 * 1024) < 0)
-		while(1)
-			blink_led();
-	/*
-	 * jump to bootloader_second_phase() running from DRAM copy
-	 */
-	(phase2)();
-}
diff --git a/src/start_qi.c b/src/start_qi.c
new file mode 100644
index 0000000..f0cdeaf
--- /dev/null
+++ b/src/start_qi.c
@@ -0,0 +1,108 @@
+/*
+ * (C) Copyright 2007 OpenMoko, Inc.
+ * Author: xiangfu liu <xiangfu at openmoko.org>
+ *         Andy Green <andy at openmoko.com>
+ *
+ * Configuation settings for the OPENMOKO Neo GTA02 Linux GSM phone
+ *
+ * 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
+ */
+
+/* NOTE this stuff runs in steppingstone context! */
+
+
+#include <qi.h>
+#include "blink_led.h"
+#include "nand_read.h"
+#include <neo_gta02.h>
+
+#define stringify2(s) stringify1(s)
+#define stringify1(s) #s
+
+extern void bootloader_second_phase(void);
+
+const struct board_api * boards[] = {
+	&board_api_gta02
+};
+
+struct board_api const * this_board;
+
+void start_qi(void)
+{
+	int n = 0;
+	int board = 0;
+	const struct board_variant * board_variant;
+	/*
+	 * We got the first 4KBytes of the bootloader pulled into the
+	 * steppingstone SRAM for free.  Now we pull the whole bootloader
+	 * image into SDRAM.
+	 *
+	 * So this doesn't trash position-dependent code, we took care in the
+	 * linker script to arrange all rodata* segment content to be in the
+	 * first 4K region.
+	 */
+
+	/* We randomly pull 24KBytes of bootloader */
+	if (nand_read_ll((unsigned char *)TEXT_BASE, 0, 24 * 1024) < 0)
+		goto unhappy;
+
+	/* ask all the boards we support in turn if they recognize this
+	 * hardware we are running on, accept the first positive answer
+	 */
+
+	this_board = boards[board];
+	while (!n) {
+		if (board >= (sizeof(boards) / sizeof(boards[0])))
+			/* can't put diagnostic on serial... too early */
+			goto unhappy;
+
+		if (this_board->is_this_board())
+			n = 1;
+		else 
+			this_board = boards[board++];
+	}
+
+	/* okay, do the critical port and serial init for our board */
+
+	this_board->port_init();
+
+	/* stick some hello messages on debug console */
+
+	puts("\n\n\nQi Bootloader  "stringify2(BUILD_HOST)" "
+				    stringify2(BUILD_VERSION)" "
+				    stringify2(BUILD_DATE)"\n");
+
+	puts("Copyright (C) 2008 Openmoko, Inc.\n");
+	puts("This is free software; see the source for copying conditions.\n"
+	     "There is NO warranty; not even for MERCHANTABILITY or "
+	     "FITNESS FOR A PARTICULAR PURPOSE.\n\n     Detected: ");
+
+	puts(this_board->name);
+	puts(", ");
+	board_variant = (this_board->get_board_variant)();
+	puts(board_variant->name);
+	puts("\n");
+
+	/*
+	 * jump to bootloader_second_phase() running from DRAM copy
+	 */
+	bootloader_second_phase();
+
+unhappy:
+	while(1)
+		blink_led();
+
+}
diff --git a/src/utils.c b/src/utils.c
index 55fc3f1..45605af 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -23,8 +23,6 @@
 #include <qi.h>
 #include <string.h>
 
-#define DEBUG_CONSOLE_UART UART2
-
 size_t strlen(const char *s)
 {
 	size_t n = 0;
@@ -41,6 +39,7 @@ char *strcpy(char *dest, const char *src)
 
 	while (*src)
 		*dest++ = *src++;
+	*dest = '\0';
 
 	return dest_orig;
 }
@@ -53,8 +52,7 @@ unsigned int _ntohl(unsigned int n) {
 int puts(const char *string)
 {
 	while (*string)
-		serial_putc(DEBUG_CONSOLE_UART, *string++);
-	serial_putc(DEBUG_CONSOLE_UART, '\n');
+		serial_putc(this_board->debug_serial_port, *string++);
 
 	return 1;
 }
@@ -63,9 +61,9 @@ int puts(const char *string)
 void printnybble(unsigned char n)
 {
 	if (n < 10)
-		serial_putc(DEBUG_CONSOLE_UART, '0' + n);
+		serial_putc(this_board->debug_serial_port, '0' + n);
 	else
-		serial_putc(DEBUG_CONSOLE_UART, 'a' + n - 10);
+		serial_putc(this_board->debug_serial_port, 'a' + n - 10);
 }
 
 void printhex(unsigned char n)
@@ -88,14 +86,100 @@ void hexdump(unsigned char *start, int len)
 
 	while (len > 0) {
 		print32((int)start);
-		serial_putc(DEBUG_CONSOLE_UART, ':');
-		serial_putc(DEBUG_CONSOLE_UART, ' ');
+		serial_putc(this_board->debug_serial_port, ':');
+		serial_putc(this_board->debug_serial_port, ' ');
 		for (n = 0; n < 16; n++) {
 			printhex(*start++);
-			serial_putc(DEBUG_CONSOLE_UART, ' ');
+			serial_putc(this_board->debug_serial_port, ' ');
 		}
-		serial_putc(DEBUG_CONSOLE_UART, '\n');
+		serial_putc(this_board->debug_serial_port, '\n');
 		len -= 16;
 	}
 }
 
+/* original copyright notice for this crc code  (it is from U-Boot) --> */
+/*
+ * This file is derived from crc32.c from the zlib-1.1.3 distribution
+ * by Jean-loup Gailly and Mark Adler.
+ */
+
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+const unsigned long crc_table[256] = {
+  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+  0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+  0x2d02ef8dL
+};
+
+#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
+#define DO2(buf)  DO1(buf); DO1(buf);
+#define DO4(buf)  DO2(buf); DO2(buf);
+#define DO8(buf)  DO4(buf); DO4(buf);
+
+unsigned long crc32(unsigned long crc, const unsigned char *buf,
+							       unsigned int len)
+{
+	crc = crc ^ 0xffffffffL;
+	while (len >= 8) {
+		DO8(buf);
+		len -= 8;
+	}
+	if (len)
+		do {
+			DO1(buf);
+		} while (--len);
+
+	return crc ^ 0xffffffffL;
+}




More information about the openmoko-kernel mailing list