mirror of
git://projects.qi-hardware.com/xburst-tools.git
synced 2024-11-01 12:09:40 +02:00
-add nandboot to xburst-tool
-nandboot load the zImage kernel Signed-off-by: Xiangfu Liu <xiangfu.z@gmail.com>
This commit is contained in:
parent
fe6e51cd2a
commit
056ecbbe29
22
nandboot/README
Normal file
22
nandboot/README
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
This is the source code of the NAND Secondary Program Loader (SPL).
|
||||
The NAND SPL itself will be first loaded by the IPL (Initial Program Loader)
|
||||
inside the CPU, then it loads the kernel image from NAND into RAM and
|
||||
starts the kernel from RAM.
|
||||
|
||||
To build the NAND SPL, follow next steps:
|
||||
|
||||
$ cd src/
|
||||
$ make
|
||||
|
||||
And you will get a binary file called n-boot.bin.
|
||||
|
||||
Before building the SPL, you should open config.h and check the
|
||||
configuration is correct for your system.
|
||||
|
||||
For JZ4730, the n-boot.bin must be less than 4KB.
|
||||
|
||||
For JZ4740, the n-boot.bin must be less than 8KB.
|
||||
|
||||
The platform definitions were declared in include/jz47xx_board.h.
|
||||
Please check and modify it according to your system.
|
14
nandboot/config.h
Normal file
14
nandboot/config.h
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* config.h
|
||||
*
|
||||
*/
|
||||
#ifndef __CONFIG_H__
|
||||
#define __CONFIG_H__
|
||||
|
||||
/*
|
||||
* Select one of the following definitions
|
||||
*/
|
||||
//#define CONFIG_JZ4730 1
|
||||
#define CONFIG_JZ4740 1
|
||||
|
||||
#endif /* __CONFIG_H__ */
|
5045
nandboot/include/jz4730.h
Normal file
5045
nandboot/include/jz4730.h
Normal file
File diff suppressed because it is too large
Load Diff
52
nandboot/include/jz4730_board.h
Normal file
52
nandboot/include/jz4730_board.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* jz4730_board.h
|
||||
*
|
||||
* JZ4730 board definitions.
|
||||
*
|
||||
* Copyright (c) 2005-2008 Ingenic Semiconductor Inc.
|
||||
*
|
||||
*/
|
||||
#ifndef __JZ4730_BOARD_H__
|
||||
#define __JZ4730_BOARD_H__
|
||||
|
||||
/*-------------------------------------------------------------------
|
||||
* Frequency of the external OSC in Hz.
|
||||
*/
|
||||
#define CFG_EXTAL 12000000
|
||||
|
||||
/*-------------------------------------------------------------------
|
||||
* CPU speed.
|
||||
*/
|
||||
#define CFG_CPU_SPEED 336000000
|
||||
|
||||
/*-------------------------------------------------------------------
|
||||
* Serial console.
|
||||
*/
|
||||
#define CFG_UART_BASE UART3_BASE
|
||||
|
||||
#define CONFIG_BAUDRATE 9600
|
||||
|
||||
/*-------------------------------------------------------------------
|
||||
* SDRAM info.
|
||||
*/
|
||||
|
||||
// SDRAM paramters
|
||||
#define CFG_SDRAM_BW16 0 /* Data bus width: 0-32bit, 1-16bit */
|
||||
#define CFG_SDRAM_BANK4 1 /* Banks each chip: 0-2bank, 1-4bank */
|
||||
#define CFG_SDRAM_ROW 13 /* Row address: 11 to 13 */
|
||||
#define CFG_SDRAM_COL 9 /* Column address: 8 to 12 */
|
||||
#define CFG_SDRAM_CASL 2 /* CAS latency: 2 or 3 */
|
||||
|
||||
// SDRAM Timings, unit: ns
|
||||
#define CFG_SDRAM_TRAS 45 /* RAS# Active Time */
|
||||
#define CFG_SDRAM_RCD 20 /* RAS# to CAS# Delay */
|
||||
#define CFG_SDRAM_TPC 20 /* RAS# Precharge Time */
|
||||
#define CFG_SDRAM_TRWL 7 /* Write Latency Time */
|
||||
#define CFG_SDRAM_TREF 7812 /* Refresh period: 8192 refresh cycles/64ms */
|
||||
|
||||
/*-------------------------------------------------------------------
|
||||
* Linux kernel command line.
|
||||
*/
|
||||
#define CFG_CMDLINE "mem=32M console=ttyS0,57600n8 ip=off rootfstype=yaffs2 root=/dev/mtdblock2 rw init=/etc/inittab"
|
||||
|
||||
#endif /* __JZ4730_BOARD_H__ */
|
4762
nandboot/include/jz4740.h
Normal file
4762
nandboot/include/jz4740.h
Normal file
File diff suppressed because it is too large
Load Diff
57
nandboot/include/jz4740_board.h
Normal file
57
nandboot/include/jz4740_board.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* jz4740_board.h
|
||||
*
|
||||
* JZ4740 board definitions.
|
||||
*
|
||||
* Copyright (c) 2005-2008 Ingenic Semiconductor Inc.
|
||||
*
|
||||
*/
|
||||
#ifndef __JZ4740_BOARD_H__
|
||||
#define __JZ4740_BOARD_H__
|
||||
|
||||
/*-------------------------------------------------------------------
|
||||
* NAND Boot config code
|
||||
*/
|
||||
#define JZ4740_NANDBOOT_CFG JZ4740_NANDBOOT_B8R3 /* NAND Boot config code */
|
||||
|
||||
/*-------------------------------------------------------------------
|
||||
* Frequency of the external OSC in Hz.
|
||||
*/
|
||||
#define CFG_EXTAL 12000000
|
||||
|
||||
/*-------------------------------------------------------------------
|
||||
* CPU speed.
|
||||
*/
|
||||
#define CFG_CPU_SPEED 336000000
|
||||
|
||||
/*-------------------------------------------------------------------
|
||||
* Serial console.
|
||||
*/
|
||||
#define CFG_UART_BASE UART0_BASE
|
||||
|
||||
#define CONFIG_BAUDRATE 57600
|
||||
|
||||
/*-------------------------------------------------------------------
|
||||
* SDRAM info.
|
||||
*/
|
||||
|
||||
// SDRAM paramters
|
||||
#define CFG_SDRAM_BW16 0 /* Data bus width: 0-32bit, 1-16bit */
|
||||
#define CFG_SDRAM_BANK4 1 /* Banks each chip: 0-2bank, 1-4bank */
|
||||
#define CFG_SDRAM_ROW 13 /* Row address: 11 to 13 */
|
||||
#define CFG_SDRAM_COL 9 /* Column address: 8 to 12 */
|
||||
#define CFG_SDRAM_CASL 2 /* CAS latency: 2 or 3 */
|
||||
|
||||
// SDRAM Timings, unit: ns
|
||||
#define CFG_SDRAM_TRAS 45 /* RAS# Active Time */
|
||||
#define CFG_SDRAM_RCD 20 /* RAS# to CAS# Delay */
|
||||
#define CFG_SDRAM_TPC 20 /* RAS# Precharge Time */
|
||||
#define CFG_SDRAM_TRWL 7 /* Write Latency Time */
|
||||
#define CFG_SDRAM_TREF 7812 /* Refresh period: 8192 refresh cycles/64ms */
|
||||
|
||||
/*-------------------------------------------------------------------
|
||||
* Linux kernel command line.
|
||||
*/
|
||||
#define CFG_CMDLINE "mem=32M console=ttyS0,57600n8 ip=off rootfstype=yaffs2 root=/dev/mtdblock2 rw init=/etc/inittab"
|
||||
|
||||
#endif /* __JZ4740_BOARD_H__ */
|
70
nandboot/include/nand.h
Normal file
70
nandboot/include/nand.h
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* nand.h
|
||||
*
|
||||
* Standard NAND Flash definitions.
|
||||
*/
|
||||
#ifndef __NAND_H__
|
||||
#define __NAND_H__
|
||||
|
||||
/*
|
||||
* Standard NAND flash commands
|
||||
*/
|
||||
#define NAND_CMD_READ0 0
|
||||
#define NAND_CMD_READ1 1
|
||||
#define NAND_CMD_RNDOUT 5
|
||||
#define NAND_CMD_PAGEPROG 0x10
|
||||
#define NAND_CMD_READOOB 0x50
|
||||
#define NAND_CMD_ERASE1 0x60
|
||||
#define NAND_CMD_STATUS 0x70
|
||||
#define NAND_CMD_STATUS_MULTI 0x71
|
||||
#define NAND_CMD_SEQIN 0x80
|
||||
#define NAND_CMD_RNDIN 0x85
|
||||
#define NAND_CMD_READID 0x90
|
||||
#define NAND_CMD_ERASE2 0xd0
|
||||
#define NAND_CMD_RESET 0xff
|
||||
|
||||
/* Extended commands for large page devices */
|
||||
#define NAND_CMD_READSTART 0x30
|
||||
#define NAND_CMD_RNDOUTSTART 0xE0
|
||||
#define NAND_CMD_CACHEDPROG 0x15
|
||||
|
||||
/* Status bits */
|
||||
#define NAND_STATUS_FAIL 0x01
|
||||
#define NAND_STATUS_FAIL_N1 0x02
|
||||
#define NAND_STATUS_TRUE_READY 0x20
|
||||
#define NAND_STATUS_READY 0x40
|
||||
#define NAND_STATUS_WP 0x80
|
||||
|
||||
/*
|
||||
* NAND Flash Manufacturer ID Codes
|
||||
*/
|
||||
#define NAND_MFR_TOSHIBA 0x98
|
||||
#define NAND_MFR_SAMSUNG 0xec
|
||||
#define NAND_MFR_FUJITSU 0x04
|
||||
#define NAND_MFR_NATIONAL 0x8f
|
||||
#define NAND_MFR_RENESAS 0x07
|
||||
#define NAND_MFR_STMICRO 0x20
|
||||
#define NAND_MFR_HYNIX 0xad
|
||||
#define NAND_MFR_MICRON 0x2c
|
||||
|
||||
/*
|
||||
* NAND parameter struct
|
||||
*/
|
||||
struct nand_param {
|
||||
unsigned int bus_width; /* data bus width: 8-bit/16-bit */
|
||||
unsigned int row_cycle; /* row address cycles: 2/3 */
|
||||
unsigned int page_size; /* page size in bytes: 512/2048 */
|
||||
unsigned int oob_size; /* oob size in bytes: 16/64 */
|
||||
unsigned int page_per_block; /* pages per block: 32/64/128 */
|
||||
unsigned int bad_block_pos; /* bad block pos in oob: 0/5 */
|
||||
};
|
||||
|
||||
/*
|
||||
* NAND routines
|
||||
*/
|
||||
extern void nand_enable(void);
|
||||
extern void nand_disable(void);
|
||||
extern int block_is_bad(struct nand_param *nandp, int block);
|
||||
extern int nand_read_page(struct nand_param *nandp, int block, int page, unsigned char *dst);
|
||||
|
||||
#endif /* __NAND_H__ */
|
8
nandboot/include/types.h
Normal file
8
nandboot/include/types.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef __TYPES_H__
|
||||
#define __TYPES_H__
|
||||
|
||||
#define u32 unsigned int
|
||||
#define u16 unsigned short
|
||||
#define u8 unsigned char
|
||||
|
||||
#endif /* __TYPES_H__ */
|
36
nandboot/src/Makefile
Normal file
36
nandboot/src/Makefile
Normal file
@ -0,0 +1,36 @@
|
||||
#
|
||||
# Makefile of the n-boot
|
||||
#
|
||||
# Copyright (c) 2005-2008 Ingenic Semiconductor Inc.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
OBJS := head.o nand_boot.o cpu.o jz_serial.o \
|
||||
jz4730.o jz4730_nand.o jz4730_board.o \
|
||||
jz4740.o jz4740_nand.o jz4740_board.o
|
||||
|
||||
CROSS := mipsel-openwrt-linux-
|
||||
|
||||
CFLAGS := -O2 -G 0 -mno-abicalls -fno-pic -mips32 -I../include -I../
|
||||
AFLAGS = -D__ASSEMBLY__ $(CFLAGS)
|
||||
LDFLAGS := -T ld.script -nostdlib -EL
|
||||
|
||||
.c.o:
|
||||
$(CROSS)gcc $(CFLAGS) -c $< -o $@
|
||||
.S.o:
|
||||
$(CROSS)gcc $(AFLAGS) -c $< -o $@
|
||||
|
||||
n-boot.bin: n-boot
|
||||
$(CROSS)objdump -D n-boot $< > n-boot.dump
|
||||
$(CROSS)objcopy -O binary $< $@
|
||||
|
||||
n-boot: $(OBJS)
|
||||
$(CROSS)ld $(LDFLAGS) $^ -o $@
|
||||
|
||||
clean:
|
||||
rm -fr *.o n-boot n-boot.bin n-boot.dump
|
||||
|
106
nandboot/src/cpu.c
Normal file
106
nandboot/src/cpu.c
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* cpu.c
|
||||
*
|
||||
* CPU common routines
|
||||
*
|
||||
* Copyright (c) 2005-2008 Ingenic Semiconductor Inc.
|
||||
* Author: Peter Wei <jlwei@ingenic.cn>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include <types.h>
|
||||
|
||||
/*
|
||||
* Cache Operations
|
||||
*/
|
||||
#define Index_Invalidate_I 0x00
|
||||
#define Index_Writeback_Inv_D 0x01
|
||||
#define Index_Invalidate_SI 0x02
|
||||
#define Index_Writeback_Inv_SD 0x03
|
||||
#define Index_Load_Tag_I 0x04
|
||||
#define Index_Load_Tag_D 0x05
|
||||
#define Index_Load_Tag_SI 0x06
|
||||
#define Index_Load_Tag_SD 0x07
|
||||
#define Index_Store_Tag_I 0x08
|
||||
#define Index_Store_Tag_D 0x09
|
||||
#define Index_Store_Tag_SI 0x0A
|
||||
#define Index_Store_Tag_SD 0x0B
|
||||
#define Create_Dirty_Excl_D 0x0d
|
||||
#define Create_Dirty_Excl_SD 0x0f
|
||||
#define Hit_Invalidate_I 0x10
|
||||
#define Hit_Invalidate_D 0x11
|
||||
#define Hit_Invalidate_SI 0x12
|
||||
#define Hit_Invalidate_SD 0x13
|
||||
#define Fill 0x14
|
||||
#define Hit_Writeback_Inv_D 0x15
|
||||
/* 0x16 is unused */
|
||||
#define Hit_Writeback_Inv_SD 0x17
|
||||
#define Hit_Writeback_I 0x18
|
||||
#define Hit_Writeback_D 0x19
|
||||
/* 0x1a is unused */
|
||||
#define Hit_Writeback_SD 0x1b
|
||||
/* 0x1c is unused */
|
||||
/* 0x1e is unused */
|
||||
#define Hit_Set_Virtual_SI 0x1e
|
||||
#define Hit_Set_Virtual_SD 0x1f
|
||||
|
||||
#define CFG_DCACHE_SIZE 16384
|
||||
#define CFG_ICACHE_SIZE 16384
|
||||
#define CFG_CACHELINE_SIZE 32
|
||||
|
||||
#define K0BASE 0x80000000
|
||||
|
||||
void flush_icache_all(void)
|
||||
{
|
||||
unsigned int addr, t = 0;
|
||||
|
||||
asm volatile ("mtc0 $0, $28"); /* Clear Taglo */
|
||||
asm volatile ("mtc0 $0, $29"); /* Clear TagHi */
|
||||
|
||||
for (addr = K0BASE; addr < K0BASE + CFG_ICACHE_SIZE;
|
||||
addr += CFG_CACHELINE_SIZE) {
|
||||
asm volatile (
|
||||
".set mips3\n\t"
|
||||
" cache %0, 0(%1)\n\t"
|
||||
".set mips2\n\t"
|
||||
:
|
||||
: "I" (Index_Store_Tag_I), "r"(addr));
|
||||
}
|
||||
|
||||
/* invalicate btb */
|
||||
asm volatile (
|
||||
".set mips32\n\t"
|
||||
"mfc0 %0, $16, 7\n\t"
|
||||
"nop\n\t"
|
||||
"ori %0,2\n\t"
|
||||
"mtc0 %0, $16, 7\n\t"
|
||||
".set mips2\n\t"
|
||||
:
|
||||
: "r" (t));
|
||||
}
|
||||
|
||||
void flush_dcache_all(void)
|
||||
{
|
||||
unsigned int addr;
|
||||
|
||||
for (addr = K0BASE; addr < K0BASE + CFG_DCACHE_SIZE;
|
||||
addr += CFG_CACHELINE_SIZE) {
|
||||
asm volatile (
|
||||
".set mips3\n\t"
|
||||
" cache %0, 0(%1)\n\t"
|
||||
".set mips2\n\t"
|
||||
:
|
||||
: "I" (Index_Writeback_Inv_D), "r"(addr));
|
||||
}
|
||||
|
||||
asm volatile ("sync");
|
||||
}
|
||||
|
||||
void flush_cache_all(void)
|
||||
{
|
||||
flush_dcache_all();
|
||||
flush_icache_all();
|
||||
}
|
50
nandboot/src/head.S
Normal file
50
nandboot/src/head.S
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* head.S
|
||||
*
|
||||
* Entry of n-boot
|
||||
*
|
||||
* Copyright (c) 2005-2008 Ingenic Semiconductor Inc.
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include <config.h>
|
||||
#ifdef CONFIG_JZ4740
|
||||
#include <jz4740.h>
|
||||
#include <jz4740_board.h>
|
||||
#endif
|
||||
|
||||
.text
|
||||
.set noreorder
|
||||
.global startup
|
||||
startup:
|
||||
#ifdef CONFIG_JZ4740
|
||||
.word JZ4740_NANDBOOT_CFG /* fetched by CPU during NAND Boot */
|
||||
#endif
|
||||
/*
|
||||
* Disable all interrupts
|
||||
*/
|
||||
la $8, 0xB0001004 /* INTC_IMR */
|
||||
li $9, 0xffffffff
|
||||
sw $9, 0($8)
|
||||
|
||||
/*
|
||||
* CU0=UM=EXL=IE=0, BEV=ERL=1, IP2~7=1
|
||||
*/
|
||||
li $26, 0x0040FC04
|
||||
mtc0 $26, $12 /* CP0_STATUS */
|
||||
|
||||
/* IV=1, use the specical interrupt vector (0x200) */
|
||||
li $26, 0x00800000
|
||||
mtc0 $26, $13 /* CP0_CAUSE */
|
||||
|
||||
/* Setup stack pointer */
|
||||
la $29, 0x80004000
|
||||
|
||||
/* Jump to the nand boot routine */
|
||||
j nand_boot
|
||||
nop
|
||||
.set reorder
|
161
nandboot/src/jz4730.c
Normal file
161
nandboot/src/jz4730.c
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* jz4730.c
|
||||
*
|
||||
* JZ4730 common routines
|
||||
*
|
||||
* Copyright (c) 2005-2007 Ingenic Semiconductor Inc.
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#ifdef CONFIG_JZ4730
|
||||
|
||||
#include <jz4730.h>
|
||||
#include <jz4730_board.h>
|
||||
|
||||
void pll_init(void)
|
||||
{
|
||||
unsigned int nf, plcr1;
|
||||
|
||||
nf = CFG_CPU_SPEED * 2 / CFG_EXTAL;
|
||||
plcr1 = ((nf-2) << CPM_PLCR1_PLL1FD_BIT) |
|
||||
(0 << CPM_PLCR1_PLL1RD_BIT) | /* RD=0, NR=2, 1.8432 = 3.6864/2 */
|
||||
(0 << CPM_PLCR1_PLL1OD_BIT) | /* OD=0, NO=1 */
|
||||
(0x20 << CPM_PLCR1_PLL1ST_BIT) | /* PLL stable time */
|
||||
CPM_PLCR1_PLL1EN; /* enable PLL */
|
||||
|
||||
/* Clock divisors.
|
||||
*
|
||||
* CFCR values: when CPM_CFCR_UCS(bit 28) is set, select external USB clock.
|
||||
*
|
||||
* 0x00411110 -> 1:2:2:2:2
|
||||
* 0x00422220 -> 1:3:3:3:3
|
||||
* 0x00433330 -> 1:4:4:4:4
|
||||
* 0x00444440 -> 1:6:6:6:6
|
||||
* 0x00455550 -> 1:8:8:8:8
|
||||
* 0x00466660 -> 1:12:12:12:12
|
||||
*/
|
||||
REG_CPM_CFCR = 0x00422220 | (((CFG_CPU_SPEED/48000000) - 1) << 25);
|
||||
|
||||
/* PLL out frequency */
|
||||
REG_CPM_PLCR1 = plcr1;
|
||||
}
|
||||
|
||||
#define MEM_CLK (CFG_CPU_SPEED / 3)
|
||||
|
||||
/*
|
||||
* Init SDRAM memory.
|
||||
*/
|
||||
void sdram_init(void)
|
||||
{
|
||||
register unsigned int dmcr0, dmcr, sdmode, tmp, ns;
|
||||
|
||||
unsigned int cas_latency_sdmr[2] = {
|
||||
EMC_SDMR_CAS_2,
|
||||
EMC_SDMR_CAS_3,
|
||||
};
|
||||
|
||||
unsigned int cas_latency_dmcr[2] = {
|
||||
1 << EMC_DMCR_TCL_BIT, /* CAS latency is 2 */
|
||||
2 << EMC_DMCR_TCL_BIT /* CAS latency is 3 */
|
||||
};
|
||||
|
||||
REG_EMC_BCR = 0; /* Disable bus release */
|
||||
REG_EMC_RTCSR = 0; /* Disable clock for counting */
|
||||
|
||||
/* Fault DMCR value for mode register setting*/
|
||||
#define SDRAM_ROW0 11
|
||||
#define SDRAM_COL0 8
|
||||
#define SDRAM_BANK40 0
|
||||
|
||||
dmcr0 = ((SDRAM_ROW0-11)<<EMC_DMCR_RA_BIT) |
|
||||
((SDRAM_COL0-8)<<EMC_DMCR_CA_BIT) |
|
||||
(SDRAM_BANK40<<EMC_DMCR_BA_BIT) |
|
||||
(CFG_SDRAM_BW16<<EMC_DMCR_BW_BIT) |
|
||||
EMC_DMCR_EPIN |
|
||||
cas_latency_dmcr[((CFG_SDRAM_CASL == 3) ? 1 : 0)];
|
||||
|
||||
/* Basic DMCR value */
|
||||
dmcr = ((CFG_SDRAM_ROW-11)<<EMC_DMCR_RA_BIT) |
|
||||
((CFG_SDRAM_COL-8)<<EMC_DMCR_CA_BIT) |
|
||||
(CFG_SDRAM_BANK4<<EMC_DMCR_BA_BIT) |
|
||||
(CFG_SDRAM_BW16<<EMC_DMCR_BW_BIT) |
|
||||
EMC_DMCR_EPIN |
|
||||
cas_latency_dmcr[((CFG_SDRAM_CASL == 3) ? 1 : 0)];
|
||||
|
||||
/* SDRAM timing */
|
||||
ns = 1000000000 / MEM_CLK;
|
||||
tmp = CFG_SDRAM_TRAS/ns;
|
||||
if (tmp < 4)
|
||||
tmp = 4;
|
||||
if (tmp > 11)
|
||||
tmp = 11;
|
||||
dmcr |= ((tmp-4) << EMC_DMCR_TRAS_BIT);
|
||||
tmp = CFG_SDRAM_RCD/ns;
|
||||
if (tmp > 3)
|
||||
tmp = 3;
|
||||
dmcr |= (tmp << EMC_DMCR_RCD_BIT);
|
||||
tmp = CFG_SDRAM_TPC/ns;
|
||||
if (tmp > 7)
|
||||
tmp = 7;
|
||||
dmcr |= (tmp << EMC_DMCR_TPC_BIT);
|
||||
tmp = CFG_SDRAM_TRWL/ns;
|
||||
if (tmp > 3)
|
||||
tmp = 3;
|
||||
dmcr |= (tmp << EMC_DMCR_TRWL_BIT);
|
||||
tmp = (CFG_SDRAM_TRAS + CFG_SDRAM_TPC)/ns;
|
||||
if (tmp > 14)
|
||||
tmp = 14;
|
||||
dmcr |= (((tmp + 1) >> 1) << EMC_DMCR_TRC_BIT);
|
||||
|
||||
/* SDRAM mode value */
|
||||
sdmode = EMC_SDMR_BT_SEQ |
|
||||
EMC_SDMR_OM_NORMAL |
|
||||
EMC_SDMR_BL_4 |
|
||||
cas_latency_sdmr[((CFG_SDRAM_CASL == 3) ? 1 : 0)];
|
||||
if (CFG_SDRAM_BW16)
|
||||
sdmode <<= 1;
|
||||
else
|
||||
sdmode <<= 2;
|
||||
|
||||
/* Stage 1. Precharge all banks by writing SDMR with DMCR.MRSET=0 */
|
||||
REG_EMC_DMCR = dmcr;
|
||||
REG8(EMC_SDMR0|sdmode) = 0;
|
||||
REG8(EMC_SDMR1|sdmode) = 0;
|
||||
|
||||
/* Wait for precharge, > 200us */
|
||||
tmp = (CFG_CPU_SPEED / 1000000) * 1000;
|
||||
while (tmp--);
|
||||
|
||||
/* Stage 2. Enable auto-refresh */
|
||||
REG_EMC_DMCR = dmcr | EMC_DMCR_RFSH;
|
||||
|
||||
tmp = CFG_SDRAM_TREF/ns;
|
||||
tmp = tmp/64 + 1;
|
||||
if (tmp > 0xff) tmp = 0xff;
|
||||
REG_EMC_RTCOR = tmp;
|
||||
REG_EMC_RTCNT = 0;
|
||||
REG_EMC_RTCSR = EMC_RTCSR_CKS_64; /* Divisor is 64, CKO/64 */
|
||||
|
||||
/* Wait for number of auto-refresh cycles */
|
||||
tmp = (CFG_CPU_SPEED / 1000000) * 1000;
|
||||
while (tmp--);
|
||||
|
||||
/* Stage 3. Mode Register Set */
|
||||
REG_EMC_DMCR = dmcr0 | EMC_DMCR_RFSH | EMC_DMCR_MRSET;
|
||||
REG8(EMC_SDMR0|sdmode) = 0;
|
||||
REG8(EMC_SDMR1|sdmode) = 0;
|
||||
|
||||
/* Set back to the ture basic DMCR value */
|
||||
REG_EMC_DMCR = dmcr | EMC_DMCR_RFSH | EMC_DMCR_MRSET;
|
||||
|
||||
/* everything is ok now */
|
||||
}
|
||||
|
||||
#endif /* CONFIG_JZ4730 */
|
29
nandboot/src/jz4730_board.c
Normal file
29
nandboot/src/jz4730_board.c
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* board-pmp.c
|
||||
*
|
||||
* JZ4730-based PMP board routines.
|
||||
*
|
||||
* Copyright (c) 2005-2008 Ingenic Semiconductor Inc.
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <jz4730.h>
|
||||
#include <jz4730_board.h>
|
||||
|
||||
#ifdef CONFIG_JZ4730
|
||||
|
||||
void gpio_init(void)
|
||||
{
|
||||
__harb_usb0_uhc();
|
||||
__gpio_as_emc();
|
||||
__gpio_as_uart0();
|
||||
__gpio_as_uart3();
|
||||
}
|
||||
|
||||
#endif /* CONFIG_JZ4730 */
|
254
nandboot/src/jz4730_nand.c
Normal file
254
nandboot/src/jz4730_nand.c
Normal file
@ -0,0 +1,254 @@
|
||||
/*
|
||||
* jz4730_nand.c
|
||||
*
|
||||
* NAND read routine for JZ4730
|
||||
*
|
||||
* Copyright (c) 2005-2008 Ingenic Semiconductor Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#ifdef CONFIG_JZ4730
|
||||
|
||||
#include <nand.h>
|
||||
#include <jz4730.h>
|
||||
|
||||
/* NAND command/address/data port */
|
||||
#define NAND_DATAPORT 0xB4000000 /* read-write area */
|
||||
#define NAND_CMDPORT 0xB4040000 /* write only area */
|
||||
#define NAND_ADDRPORT 0xB4080000 /* write only area */
|
||||
|
||||
#define ECC_BLOCK 256 /* 3-bytes HW ECC per 256-bytes data */
|
||||
#define ECC_POS 4 /* ECC offset to spare area */
|
||||
|
||||
#define __nand_enable() (REG_EMC_NFCSR |= EMC_NFCSR_NFE | EMC_NFCSR_FCE)
|
||||
#define __nand_disable() (REG_EMC_NFCSR &= ~(EMC_NFCSR_NFE | EMC_NFCSR_FCE))
|
||||
#define __nand_ecc_enable() (REG_EMC_NFCSR |= EMC_NFCSR_ECCE | EMC_NFCSR_ERST)
|
||||
#define __nand_ecc_disable() (REG_EMC_NFCSR &= ~EMC_NFCSR_ECCE)
|
||||
#define __nand_ready() (REG_EMC_NFCSR & EMC_NFCSR_RB)
|
||||
#define __nand_sync() while (!__nand_ready())
|
||||
#define __nand_ecc() (REG_EMC_NFECC & 0x00ffffff)
|
||||
#define __nand_cmd(n) (REG8(NAND_CMDPORT) = (n))
|
||||
#define __nand_addr(n) (REG8(NAND_ADDRPORT) = (n))
|
||||
#define __nand_data8() REG8(NAND_DATAPORT)
|
||||
#define __nand_data16() REG16(NAND_DATAPORT)
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
static inline void nand_wait_ready(void)
|
||||
{
|
||||
__nand_sync();
|
||||
}
|
||||
|
||||
static inline void nand_read_buf16(void *buf, int count)
|
||||
{
|
||||
int i;
|
||||
u16 *p = (u16 *)buf;
|
||||
|
||||
for (i = 0; i < count; i += 2)
|
||||
*p++ = __nand_data16();
|
||||
}
|
||||
|
||||
static inline void nand_read_buf8(void *buf, int count)
|
||||
{
|
||||
int i;
|
||||
u8 *p = (u8 *)buf;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
*p++ = __nand_data8();
|
||||
}
|
||||
|
||||
static inline void nand_read_buf(void *buf, int count, int bw)
|
||||
{
|
||||
if (bw == 8)
|
||||
nand_read_buf8(buf, count);
|
||||
else
|
||||
nand_read_buf16(buf, count);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read oob
|
||||
*/
|
||||
static int nand_read_oob(struct nand_param *nandp, int page_addr, u8 *buf, int size)
|
||||
{
|
||||
int page_size, row_cycle, bus_width;
|
||||
int col_addr;
|
||||
|
||||
page_size = nandp->page_size;
|
||||
row_cycle = nandp->row_cycle;
|
||||
bus_width = nandp->bus_width;
|
||||
|
||||
if (page_size == 2048)
|
||||
col_addr = 2048;
|
||||
else
|
||||
col_addr = 0;
|
||||
|
||||
if (page_size == 2048)
|
||||
/* Send READ0 command */
|
||||
__nand_cmd(NAND_CMD_READ0);
|
||||
else
|
||||
/* Send READOOB command */
|
||||
__nand_cmd(NAND_CMD_READOOB);
|
||||
|
||||
/* Send column address */
|
||||
__nand_addr(col_addr & 0xff);
|
||||
if (page_size == 2048)
|
||||
__nand_addr((col_addr >> 8) & 0xff);
|
||||
|
||||
/* Send page address */
|
||||
__nand_addr(page_addr & 0xff);
|
||||
__nand_addr((page_addr >> 8) & 0xff);
|
||||
if (row_cycle == 3)
|
||||
__nand_addr((page_addr >> 16) & 0xff);
|
||||
|
||||
/* Send READSTART command for 2048 ps NAND */
|
||||
if (page_size == 2048)
|
||||
__nand_cmd(NAND_CMD_READSTART);
|
||||
|
||||
/* Wait for device ready */
|
||||
nand_wait_ready();
|
||||
|
||||
/* Read oob data */
|
||||
nand_read_buf(buf, size, bus_width);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* nand_read_page()
|
||||
*
|
||||
* Input:
|
||||
*
|
||||
* nandp - pointer to nand info
|
||||
* block - block number: 0, 1, 2, ...
|
||||
* page - page number within a block: 0, 1, 2, ...
|
||||
* dst - pointer to target buffer
|
||||
*/
|
||||
int nand_read_page(struct nand_param *nandp, int block, int page, u8 *dst)
|
||||
{
|
||||
int page_size, oob_size, page_per_block;
|
||||
int row_cycle, bus_width, ecc_count;
|
||||
int page_addr, i, j;
|
||||
u8 *databuf;
|
||||
u8 oob_buf[64];
|
||||
u32 calc_ecc[8];
|
||||
|
||||
page_size = nandp->page_size;
|
||||
oob_size = nandp->oob_size;
|
||||
page_per_block = nandp->page_per_block;
|
||||
row_cycle = nandp->row_cycle;
|
||||
bus_width = nandp->bus_width;
|
||||
|
||||
page_addr = page + block * page_per_block;
|
||||
|
||||
/*
|
||||
* Read page data
|
||||
*/
|
||||
|
||||
/* Send READ0 command */
|
||||
__nand_cmd(NAND_CMD_READ0);
|
||||
|
||||
/* Send column address */
|
||||
__nand_addr(0);
|
||||
if (page_size == 2048)
|
||||
__nand_addr(0);
|
||||
|
||||
/* Send page address */
|
||||
__nand_addr(page_addr & 0xff);
|
||||
__nand_addr((page_addr >> 8) & 0xff);
|
||||
if (row_cycle == 3)
|
||||
__nand_addr((page_addr >> 16) & 0xff);
|
||||
|
||||
/* Send READSTART command for 2048 ps NAND */
|
||||
if (page_size == 2048)
|
||||
__nand_cmd(NAND_CMD_READSTART);
|
||||
|
||||
/* Wait for device ready */
|
||||
nand_wait_ready();
|
||||
|
||||
/* Read page data */
|
||||
databuf = dst;
|
||||
|
||||
ecc_count = page_size / ECC_BLOCK;
|
||||
|
||||
for (i = 0; i < ecc_count; i++) {
|
||||
|
||||
/* Enable HW ECC */
|
||||
__nand_ecc_enable();
|
||||
|
||||
/* Read data */
|
||||
nand_read_buf((void *)databuf, ECC_BLOCK, bus_width);
|
||||
|
||||
/* Disable HW ECC */
|
||||
__nand_ecc_disable();
|
||||
|
||||
/* Record the ECC */
|
||||
calc_ecc[i] = __nand_ecc();
|
||||
|
||||
databuf += ECC_BLOCK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read oob data
|
||||
*/
|
||||
nand_read_oob(nandp, page_addr, oob_buf, oob_size);
|
||||
|
||||
/*
|
||||
* ECC correction
|
||||
*
|
||||
* Note: the ECC correction algorithm should be conformed to
|
||||
* the encoding algorithm. It depends on what encoding algorithm
|
||||
* is used? SW ECC? HW ECC?
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check bad block
|
||||
*
|
||||
* Note: the bad block flag may be store in either the first or the last
|
||||
* page of the block.
|
||||
*/
|
||||
int block_is_bad(struct nand_param *nandp, int block)
|
||||
{
|
||||
int page_addr;
|
||||
u8 oob_buf[64];
|
||||
|
||||
page_addr = block * nandp->page_per_block;
|
||||
nand_read_oob(nandp, page_addr, oob_buf, nandp->oob_size);
|
||||
if (oob_buf[nandp->bad_block_pos] != 0xff)
|
||||
return 1;
|
||||
|
||||
page_addr = (block + 1) * nandp->page_per_block - 1;
|
||||
nand_read_oob(nandp, page_addr, oob_buf, nandp->oob_size);
|
||||
if (oob_buf[nandp->bad_block_pos] != 0xff)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable NAND controller
|
||||
*/
|
||||
void nand_enable(void)
|
||||
{
|
||||
__nand_enable();
|
||||
|
||||
REG_EMC_SMCR3 = 0x04444400;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable NAND controller
|
||||
*/
|
||||
void nand_disable(void)
|
||||
{
|
||||
__nand_disable();
|
||||
}
|
||||
|
||||
#endif /* CONFIG_JZ4730 */
|
165
nandboot/src/jz4740.c
Normal file
165
nandboot/src/jz4740.c
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
* jz4740.c
|
||||
*
|
||||
* JZ4740 common routines
|
||||
*
|
||||
* Copyright (c) 2005-2008 Ingenic Semiconductor Inc.
|
||||
* Author: Peter Wei <jlwei@ingenic.cn>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#ifdef CONFIG_JZ4740
|
||||
|
||||
#include <jz4740.h>
|
||||
#include <jz4740_board.h>
|
||||
|
||||
/* PLL output clock = EXTAL * NF / (NR * NO)
|
||||
*
|
||||
* NF = FD + 2, NR = RD + 2
|
||||
* NO = 1 (if OD = 0), NO = 2 (if OD = 1 or 2), NO = 4 (if OD = 3)
|
||||
*/
|
||||
void pll_init(void)
|
||||
{
|
||||
register unsigned int cfcr, plcr1;
|
||||
int n2FR[33] = {
|
||||
0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0,
|
||||
7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,
|
||||
9
|
||||
};
|
||||
int div[5] = {1, 3, 3, 3, 3}; /* divisors of I:S:P:M:L */
|
||||
int nf, pllout2;
|
||||
|
||||
cfcr = CPM_CPCCR_CLKOEN |
|
||||
CPM_CPCCR_PCS |
|
||||
(n2FR[div[0]] << CPM_CPCCR_CDIV_BIT) |
|
||||
(n2FR[div[1]] << CPM_CPCCR_HDIV_BIT) |
|
||||
(n2FR[div[2]] << CPM_CPCCR_PDIV_BIT) |
|
||||
(n2FR[div[3]] << CPM_CPCCR_MDIV_BIT) |
|
||||
(n2FR[div[4]] << CPM_CPCCR_LDIV_BIT);
|
||||
|
||||
pllout2 = (cfcr & CPM_CPCCR_PCS) ? CFG_CPU_SPEED : (CFG_CPU_SPEED / 2);
|
||||
|
||||
/* Init USB Host clock, pllout2 must be n*48MHz */
|
||||
REG_CPM_UHCCDR = pllout2 / 48000000 - 1;
|
||||
|
||||
nf = CFG_CPU_SPEED * 2 / CFG_EXTAL;
|
||||
plcr1 = ((nf - 2) << CPM_CPPCR_PLLM_BIT) | /* FD */
|
||||
(0 << CPM_CPPCR_PLLN_BIT) | /* RD=0, NR=2 */
|
||||
(0 << CPM_CPPCR_PLLOD_BIT) | /* OD=0, NO=1 */
|
||||
(0x20 << CPM_CPPCR_PLLST_BIT) | /* PLL stable time */
|
||||
CPM_CPPCR_PLLEN; /* enable PLL */
|
||||
|
||||
/* init PLL */
|
||||
REG_CPM_CPCCR = cfcr;
|
||||
REG_CPM_CPPCR = plcr1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Init SDRAM memory.
|
||||
*/
|
||||
void sdram_init(void)
|
||||
{
|
||||
register unsigned int dmcr0, dmcr, sdmode, tmp, cpu_clk, mem_clk, ns;
|
||||
|
||||
unsigned int cas_latency_sdmr[2] = {
|
||||
EMC_SDMR_CAS_2,
|
||||
EMC_SDMR_CAS_3,
|
||||
};
|
||||
|
||||
unsigned int cas_latency_dmcr[2] = {
|
||||
1 << EMC_DMCR_TCL_BIT, /* CAS latency is 2 */
|
||||
2 << EMC_DMCR_TCL_BIT /* CAS latency is 3 */
|
||||
};
|
||||
|
||||
int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
|
||||
|
||||
cpu_clk = CFG_CPU_SPEED;
|
||||
mem_clk = cpu_clk * div[__cpm_get_cdiv()] / div[__cpm_get_mdiv()];
|
||||
|
||||
REG_EMC_BCR = 0; /* Disable bus release */
|
||||
REG_EMC_RTCSR = 0; /* Disable clock for counting */
|
||||
|
||||
/* Fault DMCR value for mode register setting*/
|
||||
#define SDRAM_ROW0 11
|
||||
#define SDRAM_COL0 8
|
||||
#define SDRAM_BANK40 0
|
||||
|
||||
dmcr0 = ((SDRAM_ROW0-11)<<EMC_DMCR_RA_BIT) |
|
||||
((SDRAM_COL0-8)<<EMC_DMCR_CA_BIT) |
|
||||
(SDRAM_BANK40<<EMC_DMCR_BA_BIT) |
|
||||
(CFG_SDRAM_BW16<<EMC_DMCR_BW_BIT) |
|
||||
EMC_DMCR_EPIN |
|
||||
cas_latency_dmcr[((CFG_SDRAM_CASL == 3) ? 1 : 0)];
|
||||
|
||||
/* Basic DMCR value */
|
||||
dmcr = ((CFG_SDRAM_ROW-11)<<EMC_DMCR_RA_BIT) |
|
||||
((CFG_SDRAM_COL-8)<<EMC_DMCR_CA_BIT) |
|
||||
(CFG_SDRAM_BANK4<<EMC_DMCR_BA_BIT) |
|
||||
(CFG_SDRAM_BW16<<EMC_DMCR_BW_BIT) |
|
||||
EMC_DMCR_EPIN |
|
||||
cas_latency_dmcr[((CFG_SDRAM_CASL == 3) ? 1 : 0)];
|
||||
|
||||
/* SDRAM timimg */
|
||||
ns = 1000000000 / mem_clk;
|
||||
tmp = CFG_SDRAM_TRAS/ns;
|
||||
if (tmp < 4) tmp = 4;
|
||||
if (tmp > 11) tmp = 11;
|
||||
dmcr |= ((tmp-4) << EMC_DMCR_TRAS_BIT);
|
||||
tmp = CFG_SDRAM_RCD/ns;
|
||||
if (tmp > 3) tmp = 3;
|
||||
dmcr |= (tmp << EMC_DMCR_RCD_BIT);
|
||||
tmp = CFG_SDRAM_TPC/ns;
|
||||
if (tmp > 7) tmp = 7;
|
||||
dmcr |= (tmp << EMC_DMCR_TPC_BIT);
|
||||
tmp = CFG_SDRAM_TRWL/ns;
|
||||
if (tmp > 3) tmp = 3;
|
||||
dmcr |= (tmp << EMC_DMCR_TRWL_BIT);
|
||||
tmp = (CFG_SDRAM_TRAS + CFG_SDRAM_TPC)/ns;
|
||||
if (tmp > 14) tmp = 14;
|
||||
dmcr |= (((tmp + 1) >> 1) << EMC_DMCR_TRC_BIT);
|
||||
|
||||
/* SDRAM mode value */
|
||||
sdmode = EMC_SDMR_BT_SEQ |
|
||||
EMC_SDMR_OM_NORMAL |
|
||||
EMC_SDMR_BL_4 |
|
||||
cas_latency_sdmr[((CFG_SDRAM_CASL == 3) ? 1 : 0)];
|
||||
|
||||
/* Stage 1. Precharge all banks by writing SDMR with DMCR.MRSET=0 */
|
||||
REG_EMC_DMCR = dmcr;
|
||||
REG8(EMC_SDMR0|sdmode) = 0;
|
||||
|
||||
/* Wait for precharge, > 200us */
|
||||
tmp = (cpu_clk / 1000000) * 1000;
|
||||
while (tmp--);
|
||||
|
||||
/* Stage 2. Enable auto-refresh */
|
||||
REG_EMC_DMCR = dmcr | EMC_DMCR_RFSH;
|
||||
|
||||
tmp = CFG_SDRAM_TREF/ns;
|
||||
tmp = tmp/64 + 1;
|
||||
if (tmp > 0xff) tmp = 0xff;
|
||||
REG_EMC_RTCOR = tmp;
|
||||
REG_EMC_RTCNT = 0;
|
||||
REG_EMC_RTCSR = EMC_RTCSR_CKS_64; /* Divisor is 64, CKO/64 */
|
||||
|
||||
/* Wait for number of auto-refresh cycles */
|
||||
tmp = (cpu_clk / 1000000) * 1000;
|
||||
while (tmp--);
|
||||
|
||||
/* Stage 3. Mode Register Set */
|
||||
REG_EMC_DMCR = dmcr0 | EMC_DMCR_RFSH | EMC_DMCR_MRSET;
|
||||
REG8(EMC_SDMR0|sdmode) = 0;
|
||||
|
||||
/* Set back to basic DMCR value */
|
||||
REG_EMC_DMCR = dmcr | EMC_DMCR_RFSH | EMC_DMCR_MRSET;
|
||||
|
||||
/* everything is ok now */
|
||||
}
|
||||
|
||||
#endif /* CONFIG_JZ4740 */
|
28
nandboot/src/jz4740_board.c
Normal file
28
nandboot/src/jz4740_board.c
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* board-pmp.c
|
||||
*
|
||||
* JZ4730-based PMP board routines.
|
||||
*
|
||||
* Copyright (c) 2005-2008 Ingenic Semiconductor Inc.
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#ifdef CONFIG_JZ4740
|
||||
|
||||
#include <jz4740.h>
|
||||
#include <jz4740_board.h>
|
||||
|
||||
void gpio_init(void)
|
||||
{
|
||||
__gpio_as_uart0();
|
||||
__gpio_as_sdram_32bit();
|
||||
}
|
||||
|
||||
#endif /* CONFIG_JZ4740 */
|
329
nandboot/src/jz4740_nand.c
Normal file
329
nandboot/src/jz4740_nand.c
Normal file
@ -0,0 +1,329 @@
|
||||
/*
|
||||
* jz4740_nand.c
|
||||
*
|
||||
* NAND read routine for JZ4740
|
||||
*
|
||||
* Copyright (c) 2005-2008 Ingenic Semiconductor Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#ifdef CONFIG_JZ4740
|
||||
|
||||
#include <nand.h>
|
||||
#include <jz4740.h>
|
||||
|
||||
#define NAND_DATAPORT 0xb8000000
|
||||
#define NAND_ADDRPORT 0xb8010000
|
||||
#define NAND_COMMPORT 0xb8008000
|
||||
|
||||
#define ECC_BLOCK 512
|
||||
#define ECC_POS 6
|
||||
#define PAR_SIZE 9
|
||||
|
||||
#define __nand_cmd(n) (REG8(NAND_COMMPORT) = (n))
|
||||
#define __nand_addr(n) (REG8(NAND_ADDRPORT) = (n))
|
||||
#define __nand_data8() REG8(NAND_DATAPORT)
|
||||
#define __nand_data16() REG16(NAND_DATAPORT)
|
||||
|
||||
#define __nand_enable() (REG_EMC_NFCSR |= EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1)
|
||||
#define __nand_disable() (REG_EMC_NFCSR &= ~(EMC_NFCSR_NFCE1))
|
||||
#define __nand_ecc_rs_encoding() \
|
||||
(REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_ENCODING)
|
||||
#define __nand_ecc_rs_decoding() \
|
||||
(REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_DECODING)
|
||||
#define __nand_ecc_disable() (REG_EMC_NFECR &= ~EMC_NFECR_ECCE)
|
||||
#define __nand_ecc_encode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_ENCF))
|
||||
#define __nand_ecc_decode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_DECF))
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
static inline void nand_wait_ready(void)
|
||||
{
|
||||
unsigned int timeout = 1000;
|
||||
while ((REG_GPIO_PXPIN(2) & 0x40000000) && timeout--);
|
||||
while (!(REG_GPIO_PXPIN(2) & 0x40000000));
|
||||
}
|
||||
|
||||
static inline void nand_read_buf16(void *buf, int count)
|
||||
{
|
||||
int i;
|
||||
u16 *p = (u16 *)buf;
|
||||
|
||||
for (i = 0; i < count; i += 2)
|
||||
*p++ = __nand_data16();
|
||||
}
|
||||
|
||||
static inline void nand_read_buf8(void *buf, int count)
|
||||
{
|
||||
int i;
|
||||
u8 *p = (u8 *)buf;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
*p++ = __nand_data8();
|
||||
}
|
||||
|
||||
static inline void nand_read_buf(void *buf, int count, int bw)
|
||||
{
|
||||
if (bw == 8)
|
||||
nand_read_buf8(buf, count);
|
||||
else
|
||||
nand_read_buf16(buf, count);
|
||||
}
|
||||
|
||||
/*
|
||||
* Correct 1~9-bit errors in 512-bytes data
|
||||
*/
|
||||
static void rs_correct(unsigned char *dat, int idx, int mask)
|
||||
{
|
||||
int i, j;
|
||||
unsigned short d, d1, dm;
|
||||
|
||||
i = (idx * 9) >> 3;
|
||||
j = (idx * 9) & 0x7;
|
||||
|
||||
i = (j == 0) ? (i - 1) : i;
|
||||
j = (j == 0) ? 7 : (j - 1);
|
||||
|
||||
if (i > 512) return;
|
||||
|
||||
if (i == 512)
|
||||
d = dat[i - 1];
|
||||
else
|
||||
d = (dat[i] << 8) | dat[i - 1];
|
||||
|
||||
d1 = (d >> j) & 0x1ff;
|
||||
d1 ^= mask;
|
||||
|
||||
dm = ~(0x1ff << j);
|
||||
d = (d & dm) | (d1 << j);
|
||||
|
||||
dat[i - 1] = d & 0xff;
|
||||
if (i < 512)
|
||||
dat[i] = (d >> 8) & 0xff;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read oob
|
||||
*/
|
||||
static int nand_read_oob(struct nand_param *nandp, int page_addr, u8 *buf, int size)
|
||||
{
|
||||
int page_size, row_cycle, bus_width;
|
||||
int col_addr;
|
||||
|
||||
page_size = nandp->page_size;
|
||||
row_cycle = nandp->row_cycle;
|
||||
bus_width = nandp->bus_width;
|
||||
|
||||
if (page_size == 2048)
|
||||
col_addr = 2048;
|
||||
else
|
||||
col_addr = 0;
|
||||
|
||||
if (page_size == 2048)
|
||||
/* Send READ0 command */
|
||||
__nand_cmd(NAND_CMD_READ0);
|
||||
else
|
||||
/* Send READOOB command */
|
||||
__nand_cmd(NAND_CMD_READOOB);
|
||||
|
||||
/* Send column address */
|
||||
__nand_addr(col_addr & 0xff);
|
||||
if (page_size == 2048)
|
||||
__nand_addr((col_addr >> 8) & 0xff);
|
||||
|
||||
/* Send page address */
|
||||
__nand_addr(page_addr & 0xff);
|
||||
__nand_addr((page_addr >> 8) & 0xff);
|
||||
if (row_cycle == 3)
|
||||
__nand_addr((page_addr >> 16) & 0xff);
|
||||
|
||||
/* Send READSTART command for 2048 ps NAND */
|
||||
if (page_size == 2048)
|
||||
__nand_cmd(NAND_CMD_READSTART);
|
||||
|
||||
/* Wait for device ready */
|
||||
nand_wait_ready();
|
||||
|
||||
/* Read oob data */
|
||||
nand_read_buf(buf, size, bus_width);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* nand_read_page()
|
||||
*
|
||||
* Input:
|
||||
*
|
||||
* nandp - pointer to nand info
|
||||
* block - block number: 0, 1, 2, ...
|
||||
* page - page number within a block: 0, 1, 2, ...
|
||||
* dst - pointer to target buffer
|
||||
*/
|
||||
int nand_read_page(struct nand_param *nandp, int block, int page, u8 *dst)
|
||||
{
|
||||
int page_size, oob_size, page_per_block;
|
||||
int row_cycle, bus_width, ecc_count;
|
||||
int page_addr, i, j;
|
||||
u8 *data_buf;
|
||||
u8 oob_buf[64];
|
||||
|
||||
page_size = nandp->page_size;
|
||||
oob_size = nandp->oob_size;
|
||||
page_per_block = nandp->page_per_block;
|
||||
row_cycle = nandp->row_cycle;
|
||||
bus_width = nandp->bus_width;
|
||||
|
||||
page_addr = page + block * page_per_block;
|
||||
|
||||
/*
|
||||
* Read oob data
|
||||
*/
|
||||
nand_read_oob(nandp, page_addr, oob_buf, oob_size);
|
||||
|
||||
/*
|
||||
* Read page data
|
||||
*/
|
||||
|
||||
/* Send READ0 command */
|
||||
__nand_cmd(NAND_CMD_READ0);
|
||||
|
||||
/* Send column address */
|
||||
__nand_addr(0);
|
||||
if (page_size == 2048)
|
||||
__nand_addr(0);
|
||||
|
||||
/* Send page address */
|
||||
__nand_addr(page_addr & 0xff);
|
||||
__nand_addr((page_addr >> 8) & 0xff);
|
||||
if (row_cycle == 3)
|
||||
__nand_addr((page_addr >> 16) & 0xff);
|
||||
|
||||
/* Send READSTART command for 2048 ps NAND */
|
||||
if (page_size == 2048)
|
||||
__nand_cmd(NAND_CMD_READSTART);
|
||||
|
||||
/* Wait for device ready */
|
||||
nand_wait_ready();
|
||||
|
||||
/* Read page data */
|
||||
data_buf = dst;
|
||||
|
||||
ecc_count = page_size / ECC_BLOCK;
|
||||
|
||||
for (i = 0; i < ecc_count; i++) {
|
||||
volatile u8 *paraddr = (volatile u8 *)EMC_NFPAR0;
|
||||
unsigned int stat;
|
||||
|
||||
/* Enable RS decoding */
|
||||
REG_EMC_NFINTS = 0x0;
|
||||
__nand_ecc_rs_decoding();
|
||||
|
||||
/* Read data */
|
||||
nand_read_buf((void *)data_buf, ECC_BLOCK, bus_width);
|
||||
|
||||
/* Set PAR values */
|
||||
for (j = 0; j < PAR_SIZE; j++) {
|
||||
*paraddr++ = oob_buf[ECC_POS + i*PAR_SIZE + j];
|
||||
}
|
||||
|
||||
/* Set PRDY */
|
||||
REG_EMC_NFECR |= EMC_NFECR_PRDY;
|
||||
|
||||
/* Wait for completion */
|
||||
__nand_ecc_decode_sync();
|
||||
|
||||
/* Disable decoding */
|
||||
__nand_ecc_disable();
|
||||
|
||||
/* Check result of decoding */
|
||||
stat = REG_EMC_NFINTS;
|
||||
if (stat & EMC_NFINTS_ERR) {
|
||||
/* Error occurred */
|
||||
if (stat & EMC_NFINTS_UNCOR) {
|
||||
/* Uncorrectable error occurred */
|
||||
}
|
||||
else {
|
||||
unsigned int errcnt, index, mask;
|
||||
|
||||
errcnt = (stat & EMC_NFINTS_ERRCNT_MASK) >> EMC_NFINTS_ERRCNT_BIT;
|
||||
switch (errcnt) {
|
||||
case 4:
|
||||
index = (REG_EMC_NFERR3 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
|
||||
mask = (REG_EMC_NFERR3 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
|
||||
rs_correct(data_buf, index, mask);
|
||||
case 3:
|
||||
index = (REG_EMC_NFERR2 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
|
||||
mask = (REG_EMC_NFERR2 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
|
||||
rs_correct(data_buf, index, mask);
|
||||
case 2:
|
||||
index = (REG_EMC_NFERR1 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
|
||||
mask = (REG_EMC_NFERR1 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
|
||||
rs_correct(data_buf, index, mask);
|
||||
case 1:
|
||||
index = (REG_EMC_NFERR0 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
|
||||
mask = (REG_EMC_NFERR0 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
|
||||
rs_correct(data_buf, index, mask);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data_buf += ECC_BLOCK;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check bad block
|
||||
*
|
||||
* Note: the bad block flag may be store in either the first or the last
|
||||
* page of the block.
|
||||
*/
|
||||
int block_is_bad(struct nand_param *nandp, int block)
|
||||
{
|
||||
int page_addr;
|
||||
u8 oob_buf[64];
|
||||
|
||||
page_addr = block * nandp->page_per_block;
|
||||
nand_read_oob(nandp, page_addr, oob_buf, nandp->oob_size);
|
||||
if (oob_buf[nandp->bad_block_pos] != 0xff)
|
||||
return 1;
|
||||
|
||||
page_addr = (block + 1) * nandp->page_per_block - 1;
|
||||
nand_read_oob(nandp, page_addr, oob_buf, nandp->oob_size);
|
||||
if (oob_buf[nandp->bad_block_pos] != 0xff)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable NAND controller
|
||||
*/
|
||||
void nand_enable(void)
|
||||
{
|
||||
__nand_enable();
|
||||
|
||||
REG_EMC_SMCR1 = 0x04444400;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable NAND controller
|
||||
*/
|
||||
void nand_disable(void)
|
||||
{
|
||||
__nand_disable();
|
||||
}
|
||||
|
||||
#endif /* CONFIG_JZ4740 */
|
119
nandboot/src/jz_serial.c
Normal file
119
nandboot/src/jz_serial.c
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Jz47xx UART support
|
||||
*
|
||||
* Options hardcoded to 8N1
|
||||
*
|
||||
* Copyright (c) 2005 - 2008, Ingenic Semiconductor Inc.
|
||||
* Ingenic Semiconductor, <jlwei@ingenic.cn>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#ifdef CONFIG_JZ4730
|
||||
#include <jz4730.h>
|
||||
#include <jz4730_board.h>
|
||||
#endif
|
||||
#ifdef CONFIG_JZ4740
|
||||
#include <jz4740.h>
|
||||
#include <jz4740_board.h>
|
||||
#endif
|
||||
|
||||
#undef UART_BASE
|
||||
#ifndef CFG_UART_BASE
|
||||
#define UART_BASE UART0_BASE
|
||||
#else
|
||||
#define UART_BASE CFG_UART_BASE
|
||||
#endif
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* serial_init - initialize a channel
|
||||
*
|
||||
* This routine initializes the number of data bits, parity
|
||||
* and set the selected baud rate. Interrupts are disabled.
|
||||
* Set the modem control signals if the option is selected.
|
||||
*
|
||||
* RETURNS: N/A
|
||||
*/
|
||||
|
||||
static void serial_setbrg (void)
|
||||
{
|
||||
volatile u8 *uart_lcr = (volatile u8 *)(UART_BASE + OFF_LCR);
|
||||
volatile u8 *uart_dlhr = (volatile u8 *)(UART_BASE + OFF_DLHR);
|
||||
volatile u8 *uart_dllr = (volatile u8 *)(UART_BASE + OFF_DLLR);
|
||||
u32 baud_div, tmp;
|
||||
|
||||
baud_div = CFG_EXTAL / 16 / CONFIG_BAUDRATE;
|
||||
tmp = *uart_lcr;
|
||||
tmp |= UART_LCR_DLAB;
|
||||
*uart_lcr = tmp;
|
||||
|
||||
*uart_dlhr = (baud_div >> 8) & 0xff;
|
||||
*uart_dllr = baud_div & 0xff;
|
||||
|
||||
tmp &= ~UART_LCR_DLAB;
|
||||
*uart_lcr = tmp;
|
||||
}
|
||||
|
||||
int serial_init (void)
|
||||
{
|
||||
volatile u8 *uart_fcr = (volatile u8 *)(UART_BASE + OFF_FCR);
|
||||
volatile u8 *uart_lcr = (volatile u8 *)(UART_BASE + OFF_LCR);
|
||||
volatile u8 *uart_ier = (volatile u8 *)(UART_BASE + OFF_IER);
|
||||
volatile u8 *uart_sircr = (volatile u8 *)(UART_BASE + OFF_SIRCR);
|
||||
|
||||
/* Disable port interrupts while changing hardware */
|
||||
*uart_ier = 0;
|
||||
|
||||
/* Disable UART unit function */
|
||||
*uart_fcr = ~UART_FCR_UUE;
|
||||
|
||||
/* Set both receiver and transmitter in UART mode (not SIR) */
|
||||
*uart_sircr = ~(SIRCR_RSIRE | SIRCR_TSIRE);
|
||||
|
||||
/* Set databits, stopbits and parity. (8-bit data, 1 stopbit, no parity) */
|
||||
*uart_lcr = UART_LCR_WLEN_8 | UART_LCR_STOP_1;
|
||||
|
||||
/* Set baud rate */
|
||||
serial_setbrg();
|
||||
|
||||
/* Enable UART unit, enable and clear FIFO */
|
||||
*uart_fcr = UART_FCR_UUE | UART_FCR_FE | UART_FCR_TFLS | UART_FCR_RFLS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void serial_putc (const char c)
|
||||
{
|
||||
volatile u8 *uart_lsr = (volatile u8 *)(UART_BASE + OFF_LSR);
|
||||
volatile u8 *uart_tdr = (volatile u8 *)(UART_BASE + OFF_TDR);
|
||||
|
||||
if (c == '\n') serial_putc ('\r');
|
||||
|
||||
/* Wait for fifo to shift out some bytes */
|
||||
while ( !((*uart_lsr & (UART_LSR_TDRQ | UART_LSR_TEMT)) == 0x60) );
|
||||
|
||||
*uart_tdr = (u8)c;
|
||||
}
|
||||
|
||||
void serial_puts (const char *s)
|
||||
{
|
||||
while (*s) {
|
||||
serial_putc (*s++);
|
||||
}
|
||||
}
|
29
nandboot/src/ld.script
Normal file
29
nandboot/src/ld.script
Normal file
@ -0,0 +1,29 @@
|
||||
OUTPUT_ARCH(mips)
|
||||
ENTRY(startup)
|
||||
MEMORY
|
||||
{
|
||||
ram : ORIGIN = 0x80000000 , LENGTH = 0x100000
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = ALIGN(4);
|
||||
.text : { *(.text*) } > ram
|
||||
|
||||
. = ALIGN(4);
|
||||
.rodata : { *(.rodata*) } > ram
|
||||
|
||||
. = ALIGN(4);
|
||||
.sdata : { *(.sdata*) } > ram
|
||||
|
||||
. = ALIGN(4);
|
||||
.data : { *(.data*) *(.scommon*) *(.reginfo*) } > ram
|
||||
|
||||
_gp = ALIGN(16);
|
||||
.got : { *(.got*) } > ram
|
||||
|
||||
. = ALIGN(4);
|
||||
.sbss : { *(.sbss*) } > ram
|
||||
.bss : { *(.bss*) } > ram
|
||||
. = ALIGN (4);
|
||||
}
|
207
nandboot/src/nand_boot.c
Normal file
207
nandboot/src/nand_boot.c
Normal file
@ -0,0 +1,207 @@
|
||||
/*
|
||||
* nand_boot.c
|
||||
*
|
||||
* NAND boot routine.
|
||||
*
|
||||
* Then nand boot loader can load the zImage type to execute.
|
||||
* To get the zImage, build the kernel by 'make zImage'.
|
||||
*
|
||||
* Copyright (c) 2005-2008 Ingenic Semiconductor Inc.
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <nand.h>
|
||||
|
||||
#ifdef CONFIG_JZ4730
|
||||
#include <jz4730.h>
|
||||
#include <jz4730_board.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_JZ4740
|
||||
#include <jz4740.h>
|
||||
#include <jz4740_board.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* NAND Flash parameters (must be conformed to the NAND being used)
|
||||
*/
|
||||
static struct nand_param nand_p = {
|
||||
.bus_width = 8, /* data bus width: 8-bit/16-bit */
|
||||
.row_cycle = 3, /* row address cycles: 2/3 */
|
||||
.page_size = 2048, /* page size in bytes: 512/2048 */
|
||||
.oob_size = 64, /* oob size in bytes: 16/64 */
|
||||
.page_per_block = 128, /* pages per block: 32/64/128 */
|
||||
.bad_block_pos = 0 /* bad block pos in oob: 0/5 */
|
||||
};
|
||||
|
||||
#define SIZE_KB (1 * 1024)
|
||||
#define SIZE_MB (1 * 1024 * 1024)
|
||||
|
||||
/*
|
||||
* Kernel image
|
||||
*/
|
||||
#define CFG_KERNEL_OFFS (256 * SIZE_KB) /* NAND offset of kernel image being loaded, has to be aligned to a block address! */
|
||||
#define CFG_KERNEL_SIZE (2 * SIZE_MB) /* Size of kernel image, has to be integer multiply of a block size! */
|
||||
#define CFG_KERNEL_DST 0x80600000 /* Load kernel to this addr */
|
||||
#define CFG_KERNEL_START 0x80600000 /* Start kernel from this addr */
|
||||
|
||||
/*
|
||||
* Kernel parameters
|
||||
*/
|
||||
#define PARAM_BASE 0x80004000
|
||||
|
||||
/*
|
||||
* Local variables
|
||||
*/
|
||||
static u32 *param_addr = 0;
|
||||
static u8 *tmpbuf = 0;
|
||||
|
||||
static u8 cmdline[256] = CFG_CMDLINE;
|
||||
|
||||
extern void gpio_init(void);
|
||||
extern int serial_init (void);
|
||||
extern void pll_init(void);
|
||||
extern void sdram_init(void);
|
||||
|
||||
/*
|
||||
* Load kernel image from NAND into RAM
|
||||
*/
|
||||
static int nand_load(struct nand_param *nandp, int offs, int kernel_size, u8 *dst)
|
||||
{
|
||||
int page_size, page_per_block;
|
||||
int block;
|
||||
int block_size;
|
||||
int blockcopy_count;
|
||||
int page;
|
||||
|
||||
page_size = nandp->page_size;
|
||||
page_per_block = nandp->page_per_block;
|
||||
|
||||
/*
|
||||
* Enable NANDFlash controller
|
||||
*/
|
||||
nand_enable();
|
||||
|
||||
/*
|
||||
* offs has to be aligned to a block address!
|
||||
*/
|
||||
block_size = page_size * page_per_block;
|
||||
block = offs / block_size;
|
||||
blockcopy_count = 0;
|
||||
|
||||
while (blockcopy_count < (kernel_size / block_size)) {
|
||||
for (page = 0; page < page_per_block; page++) {
|
||||
if (page == 0) {
|
||||
/*
|
||||
* New block
|
||||
*/
|
||||
if (block_is_bad(nandp, block)) {
|
||||
block++;
|
||||
|
||||
/*
|
||||
* Skip bad block
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
nand_read_page(nandp, block, page, dst);
|
||||
|
||||
dst += page_size;
|
||||
}
|
||||
|
||||
block++;
|
||||
blockcopy_count++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable NANDFlash controller
|
||||
*/
|
||||
nand_disable();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAND Boot routine
|
||||
*/
|
||||
void nand_boot(void)
|
||||
{
|
||||
unsigned int boot_sel, i;
|
||||
|
||||
void (*kernel)(int, char **, char *);
|
||||
|
||||
/*
|
||||
* Init gpio, serial, pll and sdram
|
||||
*/
|
||||
gpio_init();
|
||||
serial_init();
|
||||
|
||||
serial_puts("\n\nNAND Secondary Program Loader\n\n");
|
||||
|
||||
pll_init();
|
||||
sdram_init();
|
||||
|
||||
#ifdef CONFIG_JZ4740
|
||||
/*
|
||||
* JZ4740 can detect some NAND parameters from the boot select
|
||||
*/
|
||||
boot_sel = REG_EMC_BCR >> 30;
|
||||
if (boot_sel == 0x2)
|
||||
nand_p.page_size = 512;
|
||||
else
|
||||
nand_p.page_size = 2048;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_JZ4730
|
||||
/*
|
||||
* JZ4730 can detect some NAND parameters from the boot select
|
||||
*/
|
||||
boot_sel = (REG_EMC_NFCSR & 0x70) >> 4;
|
||||
|
||||
nand_p.bus_width = (boot_sel & 0x1) ? 16 : 8;
|
||||
nand_p.page_size = (boot_sel & 0x2) ? 2048 : 512;
|
||||
nand_p.row_cycle = (boot_sel & 0x4) ? 3 : 2;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Load kernel image from NAND into RAM
|
||||
*/
|
||||
nand_load(&nand_p, CFG_KERNEL_OFFS, CFG_KERNEL_SIZE, (u8 *)CFG_KERNEL_DST);
|
||||
|
||||
serial_puts("Starting kernel ...\n\n");
|
||||
|
||||
/*
|
||||
* Prepare kernel parameters and environment
|
||||
*/
|
||||
param_addr = (u32 *)PARAM_BASE;
|
||||
param_addr[0] = 0; /* might be address of ascii-z string: "memsize" */
|
||||
param_addr[1] = 0; /* might be address of ascii-z string: "0x01000000" */
|
||||
param_addr[2] = 0;
|
||||
param_addr[3] = 0;
|
||||
param_addr[4] = 0;
|
||||
param_addr[5] = PARAM_BASE + 32;
|
||||
param_addr[6] = CFG_KERNEL_START;
|
||||
tmpbuf = (u8 *)(PARAM_BASE + 32);
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
tmpbuf[i] = cmdline[i]; /* linux command line */
|
||||
|
||||
kernel = (void (*)(int, char **, char *))CFG_KERNEL_START;
|
||||
|
||||
/*
|
||||
* Flush caches
|
||||
*/
|
||||
flush_cache_all();
|
||||
|
||||
/*
|
||||
* Jump to kernel image
|
||||
*/
|
||||
(*kernel)(2, (char **)(PARAM_BASE + 16), (char *)PARAM_BASE);
|
||||
}
|
Loading…
Reference in New Issue
Block a user