1
0
mirror of git://projects.qi-hardware.com/xburst-tools.git synced 2024-11-01 10:15:19 +02:00

add-per-board-init-change-qi.patch

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@openmoko.com>
This commit is contained in:
Andy Green 2008-11-28 10:16:36 +00:00 committed by Andy Green
parent 8cff2ca836
commit 4a8bada671
17 changed files with 619 additions and 294 deletions

View File

@ -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}

View File

@ -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

7
qiboot/dfu-qi Executable file
View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -1,40 +1,19 @@
/*
* (C) Copyright 2007 OpenMoko, Inc.
* Author: xiangfu liu <xiangfu@openmoko.org>
* Andy Green <andy@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>
#include "nand_read.h"
#define stringify2(s) stringify1(s)
#define stringify1(s) #s
static const struct board_variant board_variants[] = {
[0] = {
.name = "A5 PCB",
.machine_revision = 0x350,
},
[1] = {
.name = "A6 PCB",
.machine_revision = 0x360,
}
};
extern void bootloader_second_phase(void);
void port_init(void)
void port_init_gta02(void)
{
//CAUTION:Follow the configuration order for setting the ports.
// 1) setting value(GPnDAT)
@ -121,7 +100,7 @@ void port_init(void)
/*
* === 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
* 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!
@ -145,42 +124,113 @@ void port_init(void)
*/
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
*/
void start_kboot(void)
int gta02_get_pcb_revision(void)
{
void (*phase2)(void) = (void (*)(void))((int)bootloader_second_phase +
TEXT_BASE);
int n;
u32 u;
port_init();
serial_init(UART2);
/* 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));
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");
/* 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;
/*
* 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.
* 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);
/* 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)();
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"
},
},
};

View File

@ -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))

View File

@ -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

View File

@ -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;
}

View File

@ -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);
int kernel = 0;
const struct board_variant * board_variant =
(this_board->get_board_variant)();
puts("Checking kernel... ");
/* we try the possible kernels for this board in order */
if (nand_read_ll(kernel_nand, CFG_NAND_OFFSET_FOR_KERNEL_PARTITION,
4096) < 0) {
puts ("Kernel header read failed\n");
goto unhappy;
}
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;
hdr = (image_header_t *)kernel_nand;
/* eat leading white space */
for (p = cmdline; *p == ' '; p++);
if (_ntohl(hdr->ih_magic) != IH_MAGIC) {
puts("Unknown image magic ");
print32(hdr->ih_magic);
goto unhappy;
}
puts("\nTrying kernel: ");
puts(this_board->kernel_source[kernel].name);
puts("\n");
puts((const char *)hdr->ih_name);
/* 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;
}
puts("Fetching kernel...");
/* if there's a partition table implied, parse it, otherwise
* just use a fixed offset
*/
if (this_board->kernel_source[kernel].partition_index != -1) {
if (nand_read_ll(kernel_nand, CFG_NAND_OFFSET_FOR_KERNEL_PARTITION,
((32 * 1024) + (_ntohl(hdr->ih_size) + sizeof(hdr) + 2048)) &
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");
/* none of the kernels worked out */
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 */
unhappy:
puts("No usable kernel image found, we've had it :-(\n");
while (1)
blue_on(1);
}

View File

@ -37,24 +37,19 @@ SECTIONS
. = 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/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)
* (.rodata* .data)
src/nand_read.o (.text .rodata* .data)
src/serial.o (.text .rodata* .data)
}
. = ALIGN(4);
.everything_else : { *(.text) }
.everything_else ADDR (.text) + SIZEOF (.text) + 0x33000000 :
AT ( ADDR (.text) + SIZEOF (.text) ) { *(.text .rodata* .data) }
. = ALIGN(4);
.got :
{
*(.got)
}
. = 0x32000000 ;
. = 0x33800000 ;
__bss_start = .;
.bss (NOLOAD) :
{

View File

@ -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;
}
}

View File

@ -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,11 +121,39 @@ 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
/* reset nand controller, or it is dead to us */
@ -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
*/

108
qiboot/src/start_qi.c Normal file
View File

@ -0,0 +1,108 @@
/*
* (C) Copyright 2007 OpenMoko, Inc.
* Author: xiangfu liu <xiangfu@openmoko.org>
* Andy Green <andy@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();
}

View File

@ -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;
}