mirror of
git://projects.qi-hardware.com/xburst-tools.git
synced 2024-11-25 17:07:31 +02:00
fix-nand.patch
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@openmoko.com>
This commit is contained in:
parent
fdb05a1e8b
commit
f26f60b0ac
@ -35,6 +35,7 @@ SECTIONS
|
|||||||
src/start.o (.text)
|
src/start.o (.text)
|
||||||
src/lowlevel_init.o(.text)
|
src/lowlevel_init.o(.text)
|
||||||
src/start_kboot.o (.text)
|
src/start_kboot.o (.text)
|
||||||
|
src/start_kboot.o (.rodata)
|
||||||
*(.text)
|
*(.text)
|
||||||
*(.rodata)
|
*(.rodata)
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,9 @@
|
|||||||
* MA 02111-1307 USA
|
* MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* NOTE this stuff runs in steppingstone context! */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* #include <config.h>
|
* #include <config.h>
|
||||||
* #include <version.h>
|
* #include <version.h>
|
||||||
|
@ -15,7 +15,11 @@
|
|||||||
* Author: Harald Welte <laforge@openmoko.org>
|
* Author: Harald Welte <laforge@openmoko.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* NOTE this stuff runs in steppingstone context! */
|
||||||
|
|
||||||
|
|
||||||
#include "nand_read.h"
|
#include "nand_read.h"
|
||||||
|
#include "kboot.h"
|
||||||
|
|
||||||
#define NAND_CMD_READ0 0
|
#define NAND_CMD_READ0 0
|
||||||
#define NAND_CMD_READSTART 0x30
|
#define NAND_CMD_READSTART 0x30
|
||||||
@ -67,6 +71,14 @@ static int is_bad_block(unsigned long i)
|
|||||||
NFCMD = NAND_CMD_READSTART;
|
NFCMD = NAND_CMD_READSTART;
|
||||||
nand_wait();
|
nand_wait();
|
||||||
data = (NFDATA & 0xff);
|
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)
|
if (data != 0xff)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@ -103,38 +115,65 @@ static int nand_read_page_ll(unsigned char *buf, unsigned long addr)
|
|||||||
/* low level nand read function */
|
/* low level nand read function */
|
||||||
int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)
|
int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
int bad_count = 0;
|
int bad_count = 0;
|
||||||
|
|
||||||
if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK))
|
if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK))
|
||||||
return -1; /* invalid alignment */
|
return -1; /* invalid alignment */
|
||||||
|
|
||||||
/* chip Enable */
|
/* chip Enable */
|
||||||
nand_select();
|
nand_select();
|
||||||
nand_clear_RnB();
|
nand_clear_RnB();
|
||||||
for (i=0; i<10; i++);
|
|
||||||
|
|
||||||
for (i=start_addr; i < (start_addr + size);) {
|
for (i = 0; i < 10; i++)
|
||||||
if (i % NAND_BLOCK_SIZE == 0) {
|
;
|
||||||
if (is_bad_block(i) ||
|
|
||||||
is_bad_block(i + NAND_PAGE_SIZE)) {
|
for (i = start_addr; i < (start_addr + size);) {
|
||||||
i += NAND_BLOCK_SIZE;
|
#ifdef DEBUG
|
||||||
size += NAND_BLOCK_SIZE;
|
serial_putc(2, 'i');
|
||||||
if(bad_count++ == 4) {
|
serial_putc(2, '0');
|
||||||
return -1;
|
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);
|
/* chip Disable */
|
||||||
i += j;
|
nand_deselect();
|
||||||
/* buf += j;*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/* chip Disable */
|
return 0;
|
||||||
nand_deselect();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
154
qiboot/src/phase2.c
Normal file
154
qiboot/src/phase2.c
Normal file
@ -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);
|
||||||
|
}
|
@ -140,6 +140,19 @@ start_code:
|
|||||||
str r1, [r0, #0x28] */
|
str r1, [r0, #0x28] */
|
||||||
|
|
||||||
bl cpu_init_crit
|
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 */
|
/* >> CFG_VIDEO_LOGO_MAX_SIZE */
|
||||||
#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
|
#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
|
||||||
stack_setup:
|
stack_setup:
|
||||||
|
@ -19,9 +19,15 @@
|
|||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||||
* MA 02111-1307 USA
|
* MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* NOTE this stuff runs in steppingstone context! */
|
||||||
|
|
||||||
|
|
||||||
#include "blink_led.h"
|
#include "blink_led.h"
|
||||||
#include "nand_read.h"
|
#include "nand_read.h"
|
||||||
#include "kboot.h"
|
#include "kboot.h"
|
||||||
|
#include <neo_gta02.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
unsigned char buf[]={
|
unsigned char buf[]={
|
||||||
0x0d,0xc0,0xa0,0xe1,0x00,0xd8,0x2d,0xe9,0x04,0xb0,0x4c,0xe2,0x4c,0x20,0x9f,0xe5,
|
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,
|
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};
|
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
|
#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 (*phase2)(void) = bootloader_second_phase + TEXT_BASE;
|
||||||
void (*p)(unsigned int) = print32;
|
|
||||||
|
|
||||||
port_init();
|
port_init();
|
||||||
serial_init(0x11, UART2);
|
serial_init(0x11, UART2);
|
||||||
|
|
||||||
|
puts("Openmoko KBOOT BUILD_HOST BUILD_VERSION BUILD_DATE\n");
|
||||||
|
|
||||||
|
#if 0
|
||||||
while(1) {
|
while(1) {
|
||||||
serial_putc(2, '0');
|
serial_putc(2, '0');
|
||||||
serial_putc(2, 'x');
|
serial_putc(2, 'x');
|
||||||
@ -63,21 +68,26 @@ int start_kboot(void)
|
|||||||
|
|
||||||
serial_putc(2, '\n');
|
serial_putc(2, '\n');
|
||||||
|
|
||||||
|
|
||||||
// printk("Openmoko KBOOT "stringify(BUILD_HOST)" "stringify(BUILD_VERSION)" "stringify(BUILD_DATE)"\n");
|
|
||||||
blue_on(1);
|
blue_on(1);
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*2. test nand flash */
|
#endif
|
||||||
if(nand_read_ll(buf, 0x000, sizeof(buf))==-1)
|
|
||||||
|
/*
|
||||||
|
* pull the whole U-Boot image into SDRAM
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (nand_read_ll((unsigned char *)TEXT_BASE, 0, 256 * 1024) < 0)
|
||||||
while(1)
|
while(1)
|
||||||
blink_led();
|
blink_led();
|
||||||
|
|
||||||
asm volatile("mov pc, %0\n"
|
serial_putc(2, '0');
|
||||||
: /* output */
|
serial_putc(2, 'x');
|
||||||
:"r"(ADDR) /* input */
|
print32((unsigned int)bootloader_second_phase);
|
||||||
);
|
serial_putc(2, ' ');
|
||||||
|
serial_putc(2, '\n');
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
(phase2)();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user