1
0
mirror of git://projects.qi-hardware.com/xburst-tools.git synced 2024-11-25 15:59:21 +02:00

add jz4760 support to stage2

Signed-off-by: Xiangfu Liu <xiangfu@sharism.cc>
This commit is contained in:
Xiangfu Liu 2010-06-18 15:10:05 +08:00
parent bcc23ae567
commit 7a5a090832
13 changed files with 1583 additions and 1031 deletions

View File

@ -61,31 +61,30 @@ int check_dump_cfg(struct hand *hand)
}
/* check NAND */
if ( hand->nand_ps < 2048 && hand->nand_os > 16 ) {
if (hand->nand_ps < 2048 && hand->nand_os > 16) {
printf(" PAGESIZE or OOBSIZE setting invalid!\n");
printf(" PAGESIZE is %d,\t OOBSIZE is %d\n",
hand->nand_ps, hand->nand_os);
return 0;
}
if ( hand->nand_ps < 2048 && hand->nand_ppb > 32 ) {
if (hand->nand_ps < 2048 && hand->nand_ppb > 32) {
printf(" PAGESIZE or PAGEPERBLOCK setting invalid!\n");
return 0;
}
if ( hand->nand_ps > 512 && hand->nand_os <= 16 ) {
if (hand->nand_ps > 512 && hand->nand_os <= 16) {
printf(" PAGESIZE or OOBSIZE setting invalid!\n");
printf(" PAGESIZE is %d,\t OOBSIZE is %d\n",
hand->nand_ps, hand->nand_os);
return 0;
}
if ( hand->nand_ps > 512 && hand->nand_ppb < 64 ) {
if (hand->nand_ps > 512 && hand->nand_ppb < 64) {
printf(" PAGESIZE or PAGEPERBLOCK setting invalid!\n");
return 0;
}
printf(" YES\n");
printf("Current device information:\n");
printf("CPU type is Ingenic XBurst Jz%x\n",hand->fw_args.cpu_id);
printf("Current device setup information:\n");
printf("Crystal work at %dMHz, the CCLK up to %dMHz and PMH_CLK up to %dMHz\n",
hand->fw_args.ext_clk,
(unsigned int)hand->fw_args.cpu_speed * hand->fw_args.ext_clk,

View File

@ -24,7 +24,6 @@
#include "ingenic_usb.h"
extern unsigned int total_size;
extern struct hand hand;
static int get_ingenic_device(struct ingenic_dev *ingenic_dev)
{
@ -42,7 +41,6 @@ static int get_ingenic_device(struct ingenic_dev *ingenic_dev)
(usb_dev->descriptor.idProduct == PRODUCT_ID_4740 ||
usb_dev->descriptor.idProduct == PRODUCT_ID_4760)) {
ingenic_dev->usb_dev = usb_dev;
hand.fw_args.cpu_id = usb_dev->descriptor.idProduct;
count++;
}

View File

@ -23,31 +23,6 @@
#include "xburst_types.h"
#ifndef __ASSEMBLY__
#define UCOS_CSP 0
#if UCOS_CSP
#define __KERNEL__
#include <bsp.h>
#include <types.h>
#include <sysdefs.h>
#include <cacheops.h>
#define KSEG0 KSEG0BASE
#else
/* #include <asm/cacheops.h> */
#endif
#define cache_unroll(base,op) \
__asm__ __volatile__(" \
.set noreorder; \
.set mips3; \
cache %1, (%0); \
.set mips0; \
.set reorder" \
: \
: "r" (base), \
"i" (op));
#if 0
static inline void jz_flush_dcache(void)
{
@ -76,6 +51,16 @@ static inline void jz_flush_icache(void)
}
#endif
#define cache_unroll(base,op) \
__asm__ __volatile__(" \
.set noreorder; \
.set mips3; \
cache %1, (%0); \
.set mips0; \
.set reorder" \
: \
: "r" (base), \
"i" (op));
/* cpu pipeline flush */
static inline void jz_sync(void)
{
@ -112,18 +97,6 @@ static inline u32 jz_readl(u32 address)
return *((volatile u32 *)address);
}
#define REG8(addr) *((volatile u8 *)(addr))
#define REG16(addr) *((volatile u16 *)(addr))
#define REG32(addr) *((volatile u32 *)(addr))
#else
#define REG8(addr) (addr)
#define REG16(addr) (addr)
#define REG32(addr) (addr)
#endif /* !ASSEMBLY */
/* Boot ROM Specification */
/* NOR Boot config */

View File

@ -1,38 +1,27 @@
/*
* Include file for Ingenic Semiconductor's JZ4760 CPU.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* 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., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA
*/
#ifndef __JZ4760_H__
#define __JZ4760_H__
#include "target/xburst_types.h"
#if 0 /* if 0, for spl program */
#define UCOS_CSP 0
#if UCOS_CSP
#define __KERNEL__
#include <bsp.h>
#include <types.h>
#include <sysdefs.h>
#include <cacheops.h>
#define KSEG0 KSEG0BASE
#else
#include <asm/addrspace.h>
#include <asm/cacheops.h>
#endif
#define cache_unroll(base,op) \
__asm__ __volatile__(" \
.set noreorder; \
.set mips3; \
cache %1, (%0); \
.set mips0; \
.set reorder" \
: \
: "r" (base), \
"i" (op));
#if 1 /* if 0, for spl program */
#if 0
static inline void jz_flush_dcache(void)
{
unsigned long start;
@ -58,6 +47,17 @@ static inline void jz_flush_icache(void)
start += CFG_CACHELINE_SIZE;
}
}
#endif
#define cache_unroll(base,op) \
__asm__ __volatile__(" \
.set noreorder; \
.set mips3; \
cache %1, (%0); \
.set mips0; \
.set reorder" \
: \
: "r" (base), \
"i" (op));
/* cpu pipeline flush */
static inline void jz_sync(void)
@ -91,6 +91,7 @@ static inline u16 jz_readw(u32 address)
}
static inline u32 jz_readl(u32 address)
{
return *((volatile u32 *)address);
}

View File

@ -40,24 +40,24 @@ u32 nand_mark_bad_4740(int bad);
void nand_enable_4740(u32 csn);
void nand_disable_4740(u32 csn);
/* Jz4750 nandflash interface */
unsigned int nand_query_4750(u8 *);
//int nand_init_4750(int bus_width, int row_cycle, int page_size, int page_per_block,
/* Jz4760 nandflash interface */
unsigned int nand_query_4760(u8 *);
//int nand_init_4760(int bus_width, int row_cycle, int page_size, int page_per_block,
// int,int,int,int);
int nand_init_4750(int bus_width, int row_cycle, int page_size, int page_per_block,
int nand_init_4760(int bus_width, int row_cycle, int page_size, int page_per_block,
int bch_bit, int ecc_pos, int bad_pos, int bad_page, int force);
int nand_fini_4750(void);
u32 nand_program_4750(void *context, int spage, int pages, int option);
int nand_fini_4760(void);
u32 nand_program_4760(void *context, int spage, int pages, int option);
//int nand_program_oob_4740(void *context, int spage, int pages, void (*notify)(int));
u32 nand_erase_4750(int blk_num, int sblk, int force);
u32 nand_read_4750(void *buf, u32 startpage, u32 pagenum,int option);
u32 nand_read_oob_4750(void *buf, u32 startpage, u32 pagenum);
u32 nand_read_raw_4750(void *buf, u32 startpage, u32 pagenum,int);
u32 nand_mark_bad_4750(int bad);
u32 nand_erase_4760(int blk_num, int sblk, int force);
u32 nand_read_4760(void *buf, u32 startpage, u32 pagenum,int option);
u32 nand_read_oob_4760(void *buf, u32 startpage, u32 pagenum);
u32 nand_read_raw_4760(void *buf, u32 startpage, u32 pagenum,int);
u32 nand_mark_bad_4760(int bad);
void nand_enable_4750(u32 csn);
void nand_disable_4750(u32 csn);
void nand_enable_4760(u32 csn);
void nand_disable_4760(u32 csn);
#endif

View File

@ -22,7 +22,8 @@
#ifndef __USB_BOOT_H__
#define __USB_BOOT_H__
#define BULK_BUF_SIZE (2048 * 128)
#define BULK_OUT_BUF_SIZE (2048 * 128)
#define BULK_IN_BUF_SIZE (2048 * 128)
enum UDC_STATE
{

View File

@ -19,29 +19,7 @@
#ifndef __USB_H
#define __USB_H
#ifndef u8
#define u8 unsigned char
#endif
#ifndef u16
#define u16 unsigned short
#endif
#ifndef u32
#define u32 unsigned int
#endif
#ifndef s8
#define s8 char
#endif
#ifndef s16
#define s16 short
#endif
#ifndef s32
#define s32 int
#endif
#include "target/xburst_types.h"
extern int usbdebug;

View File

@ -22,6 +22,7 @@ OBJCOPY = $(CROSS_COMPILE)objcopy
NM = $(CROSS_COMPILE)nm
OBJDUMP = $(CROSS_COMPILE)objdump
DEVICE ?=NANONOTE
DEBUG_CFLAGS = -g -Wa,-a=$(basename $@).lst
# Wolfgang saw data corruptions in stage2 when dealing with ECC data on random writes
# to NAND. Disabling the unit-at-a-time optimization reproducibly fixed the bug.
@ -30,10 +31,10 @@ DEBUG_CFLAGS = -g -Wa,-a=$(basename $@).lst
# is to disable this optimization right now.
CFLAGS = -mips32 -O2 -fno-exceptions -fno-zero-initialized-in-bss \
-ffunction-sections -fomit-frame-pointer -msoft-float -G 0 -fpie \
-I$(XBURST_INCLUDE_PATH) -I$(INFLASH_SRC_PATH)
-I$(XBURST_INCLUDE_PATH) -I$(INFLASH_SRC_PATH) -D$(DEVICE)
LDFLAGS = -nostdlib -T target.ld $(CFLAGS)
OBJS = main.o udc.o cache.o serial.o boothandler.o nandflash_4740.o nandflash_4750.o
OBJS = main.o udc.o cache.o serial.o boothandler.o nandflash_4740.o nandflash_4760.o
all: xburst_stage2.elf
$(OBJCOPY) -O binary xburst_stage2.elf xburst_stage2.bin

View File

@ -42,8 +42,9 @@ u32 (*nand_mark_bad) (int bad);
void (*nand_enable) (unsigned int csn);
void (*nand_disable) (unsigned int csn);
struct hand Hand,*Hand_p;
extern u32 Bulk_buf[BULK_BUF_SIZE];
struct hand Hand;
extern u32 Bulk_out_buf[BULK_OUT_BUF_SIZE];
extern u32 Bulk_in_buf[BULK_IN_BUF_SIZE];
extern u16 handshake_PKT[4];
extern udc_state;
extern void *memset(void *s, int c, size_t count);
@ -54,10 +55,6 @@ u32 start_addr; //program operation start address or sector
u32 ops_length; //number of operation unit ,in byte or sector
u32 ram_addr;
void config_flash_info()
{
}
void dump_data(unsigned int *p, int size)
{
int i;
@ -65,38 +62,30 @@ void dump_data(unsigned int *p, int size)
serial_put_hex(*p++);
}
void config_flash_info()
{
}
void config_hand()
{
struct hand *hand_p;
hand_p=(struct hand *)Bulk_buf;
memcpy(&Hand, (unsigned char *)Bulk_buf, sizeof(struct hand));
#if 0
Hand.nand_bw=hand_p->nand_bw;
Hand.nand_rc=hand_p->nand_rc;
Hand.nand_ps=hand_p->nand_ps;
Hand.nand_ppb=hand_p->nand_ppb;
Hand.nand_force_erase=hand_p->nand_force_erase;
Hand.nand_pn=hand_p->nand_pn;
Hand.nand_os=hand_p->nand_os;
Hand.nand_eccpos=hand_p->nand_eccpos;
Hand.nand_bbpos=hand_p->nand_bbpos;
Hand.nand_bbpage=hand_p->nand_bbpage;
serial_put_hex(Hand.fw_args.cpu_id);
serial_put_hex(Hand.fw_args.ext_clk);
#endif
memcpy(&Hand, (unsigned char *)Bulk_out_buf, sizeof(struct hand));
}
int GET_CUP_INFO_Handle()
{
char temp1[8]="Boot4740",temp2[8]="Boot4750";
dprintf("\n GET_CPU_INFO:\t");
serial_put_hex(Hand.fw_args.cpu_id);
if (Hand.fw_args.cpu_id == 0x4740)
HW_SendPKT(0, temp1, 8);
else
HW_SendPKT(0, temp2, 8);
switch (Hand.fw_args.cpu_id) {
case 0x4760:
HW_SendPKT(0, "Boot4760", 8);
break;
case 0x4740:
HW_SendPKT(0, "Boot4740", 8);
break;
default:
HW_SendPKT(0, " UNKNOW ", 8);
break;
}
udc_state = IDLE;
return ERR_OK;
}
@ -165,8 +154,8 @@ int NAND_OPS_Handle(u8 *buf)
{
case NAND_QUERY:
dprintf("\n Request : NAND_QUERY!");
nand_query((u8 *)Bulk_buf);
HW_SendPKT(1, Bulk_buf, 8);
nand_query((u8 *)Bulk_in_buf);
HW_SendPKT(1, Bulk_in_buf, 8);
handshake_PKT[3]=(u16)ERR_OK;
udc_state = BULK_IN;
break;
@ -185,11 +174,11 @@ int NAND_OPS_Handle(u8 *buf)
break;
case NAND_READ_OOB:
dprintf("\n Request : NAND_READ_OOB!");
memset(Bulk_buf,0,ops_length*Hand.nand_ps);
ret_dat = nand_read_oob(Bulk_buf,start_addr,ops_length);
memset(Bulk_in_buf,0,ops_length*Hand.nand_ps);
ret_dat = nand_read_oob(Bulk_in_buf,start_addr,ops_length);
handshake_PKT[0] = (u16) ret_dat;
handshake_PKT[1] = (u16) (ret_dat>>16);
HW_SendPKT(1,(u8 *)Bulk_buf,ops_length*Hand.nand_ps);
HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*Hand.nand_ps);
udc_state = BULK_IN;
break;
case NAND_READ_RAW:
@ -197,15 +186,15 @@ int NAND_OPS_Handle(u8 *buf)
switch (option)
{
case OOB_ECC:
nand_read_raw(Bulk_buf,start_addr,ops_length,option);
HW_SendPKT(1,(u8 *)Bulk_buf,ops_length*(Hand.nand_ps + Hand.nand_os));
nand_read_raw(Bulk_in_buf,start_addr,ops_length,option);
HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*(Hand.nand_ps + Hand.nand_os));
handshake_PKT[0] = (u16) ret_dat;
handshake_PKT[1] = (u16) (ret_dat>>16);
udc_state = BULK_IN;
break;
default:
nand_read_raw(Bulk_buf,start_addr,ops_length,option);
HW_SendPKT(1,(u8 *)Bulk_buf,ops_length*Hand.nand_ps);
nand_read_raw(Bulk_in_buf,start_addr,ops_length,option);
HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*Hand.nand_ps);
handshake_PKT[0] = (u16) ret_dat;
handshake_PKT[1] = (u16) (ret_dat>>16);
udc_state = BULK_IN;
@ -226,24 +215,24 @@ int NAND_OPS_Handle(u8 *buf)
dprintf("\n Request : NAND_READ!");
switch (option) {
case OOB_ECC:
ret_dat = nand_read(Bulk_buf,start_addr,ops_length,OOB_ECC);
ret_dat = nand_read(Bulk_in_buf,start_addr,ops_length,OOB_ECC);
handshake_PKT[0] = (u16) ret_dat;
handshake_PKT[1] = (u16) (ret_dat>>16);
HW_SendPKT(1,(u8 *)Bulk_buf,ops_length*(Hand.nand_ps + Hand.nand_os ));
HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*(Hand.nand_ps + Hand.nand_os ));
udc_state = BULK_IN;
break;
case OOB_NO_ECC:
ret_dat = nand_read(Bulk_buf,start_addr,ops_length,OOB_NO_ECC);
ret_dat = nand_read(Bulk_in_buf,start_addr,ops_length,OOB_NO_ECC);
handshake_PKT[0] = (u16) ret_dat;
handshake_PKT[1] = (u16) (ret_dat>>16);
HW_SendPKT(1,(u8 *)Bulk_buf,ops_length*(Hand.nand_ps + Hand.nand_os));
HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*(Hand.nand_ps + Hand.nand_os));
udc_state = BULK_IN;
break;
case NO_OOB:
ret_dat = nand_read(Bulk_buf,start_addr,ops_length,NO_OOB);
ret_dat = nand_read(Bulk_in_buf,start_addr,ops_length,NO_OOB);
handshake_PKT[0] = (u16) ret_dat;
handshake_PKT[1] = (u16) (ret_dat>>16);
HW_SendPKT(1,(u8 *)Bulk_buf,ops_length*Hand.nand_ps);
HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*Hand.nand_ps);
udc_state = BULK_IN;
break;
}
@ -251,7 +240,7 @@ int NAND_OPS_Handle(u8 *buf)
break;
case NAND_PROGRAM:
dprintf("\n Request : NAND_PROGRAM!");
ret_dat = nand_program((void *)Bulk_buf,
ret_dat = nand_program((void *)Bulk_out_buf,
start_addr,ops_length,option);
handshake_PKT[0] = (u16) ret_dat;
handshake_PKT[1] = (u16) (ret_dat>>16);
@ -285,7 +274,7 @@ int SDRAM_OPS_Handle(u8 *buf)
{
case SDRAM_LOAD:
//dprintf("\n Request : SDRAM_LOAD!");
ret_dat = (u32)memcpy((u8 *)start_addr,Bulk_buf,ops_length);
ret_dat = (u32)memcpy((u8 *)start_addr,Bulk_out_buf,ops_length);
handshake_PKT[0] = (u16) ret_dat;
handshake_PKT[1] = (u16) (ret_dat>>16);
HW_SendPKT(1,handshake_PKT,sizeof(handshake_PKT));
@ -317,24 +306,24 @@ void Borad_Init()
nand_disable = nand_disable_4740;
nand_mark_bad = nand_mark_bad_4740;
break;
case 0x4750:
case 0x4760:
//Init nand flash
nand_init_4750(Hand.nand_bw, Hand.nand_rc, Hand.nand_ps,
nand_init_4760(Hand.nand_bw, Hand.nand_rc, Hand.nand_ps,
Hand.nand_ppb, Hand.nand_bchbit, Hand.nand_eccpos,
Hand.nand_bbpos, Hand.nand_bbpage, Hand.nand_force_erase);
nand_program = nand_program_4750;
nand_erase = nand_erase_4750;
nand_read = nand_read_4750;
nand_read_oob = nand_read_oob_4750;
nand_read_raw = nand_read_raw_4750;
nand_query = nand_query_4750;
nand_enable = nand_enable_4750;
nand_disable = nand_disable_4750;
nand_mark_bad = nand_mark_bad_4750;
nand_program=nand_program_4760;
nand_erase =nand_erase_4760;
nand_read =nand_read_4760;
nand_read_oob=nand_read_oob_4760;
nand_read_raw=nand_read_raw_4760;
nand_query = nand_query_4760;
nand_enable = nand_enable_4760;
nand_disable= nand_disable_4760;
nand_mark_bad = nand_mark_bad_4760;
break;
default:
serial_puts("Not support CPU ID!");
serial_puts("\n Not support CPU ID!");
}
}

View File

@ -19,9 +19,9 @@
#include "usb_boot_defines.h"
extern void usb_main();
unsigned int start_addr,got_start,got_end;
extern unsigned int UART_BASE;
struct fw_args *fw_args;
unsigned int start_addr,got_start,got_end;
void c_main(void)
{
@ -47,14 +47,16 @@ void c_main(void)
offset = start_addr - 0x80000000;
got_start += offset;
got_end += offset;
/* add offset to correct all GOT */
for(addr = got_start + 8; addr < got_end; addr += 4)
*((volatile unsigned int *)(addr)) += offset;
for ( addr = got_start + 8; addr < got_end; addr += 4 )
{
*((volatile unsigned int *)(addr)) += offset; //add offset to correct all GOT
}
/* get the fw args from memory */
fw_args = (struct fw_args *)(start_addr + 0x8);
extern struct hand Hand;
Hand.fw_args.cpu_id = fw_args->cpu_id;
fw_args = (struct fw_args *)(start_addr + 0x8); //get the fw args from memory
if ( fw_args->use_uart > 3 ) fw_args->use_uart = 0;
UART_BASE = 0xB0030000 + fw_args->use_uart * 0x1000;
serial_puts("\n Stage2 start address is :\t");

View File

@ -1,844 +0,0 @@
/*
* Copyright (C) 2009 Qi Hardware Inc.,
* Author: Xiangfu Liu <xiangfu@qi-hardware.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* 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., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA
*/
#include "target/jz4750.h"
#include "target/nandflash.h"
#include "target/usb_boot.h"
#include "usb_boot_defines.h"
#define dprintf(n...)
#define __nand_enable() (REG_EMC_NFCSR |= EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1)
#define __nand_disable() (REG_EMC_NFCSR &= ~(EMC_NFCSR_NFCE1))
#define __nand_ready() ((REG_GPIO_PXPIN(2) & 0x08000000) ? 1 : 0)
#define __nand_cmd(n) (REG8(cmdport) = (n))
#define __nand_addr(n) (REG8(addrport) = (n))
#define __nand_data8() REG8(dataport)
#define __nand_data16() REG16(dataport)
#define CMD_READA 0x00
#define CMD_READB 0x01
#define CMD_READC 0x50
#define CMD_ERASE_SETUP 0x60
#define CMD_ERASE 0xD0
#define CMD_READ_STATUS 0x70
#define CMD_CONFIRM 0x30
#define CMD_SEQIN 0x80
#define CMD_PGPROG 0x10
#define CMD_READID 0x90
#define ECC_BLOCK 512
static volatile unsigned char *gpio_base = (volatile unsigned char *)0xb0010000;
static volatile unsigned char *emc_base = (volatile unsigned char *)0xb3010000;
static volatile unsigned char *addrport = (volatile unsigned char *)0xb8010000;
static volatile unsigned char *dataport = (volatile unsigned char *)0xb8000000;
static volatile unsigned char *cmdport = (volatile unsigned char *)0xb8008000;
static int bus = 8, row = 2, pagesize = 512, oobsize = 16, ppb = 32;
static int eccpos = 3, bchbit = 8, par_size = 13, forceerase = 1, wp_pin;
static int oobfs = 0; /* 1:store file system information in oob, 0:don't store */
static int oobecc = 0; /* Whether the oob data of the binary contains ECC data? */
static int bad_block_page = 127; /* Specify the page number of badblock flag inside a block */
static u32 bad_block_pos = 0; /* Specify the badblock flag offset inside the oob */
static u8 oob_buf[256] = {0};
extern struct hand Hand;
extern u16 handshake_PKT[4];
static inline void __nand_sync(void)
{
unsigned int timeout = 10000;
while ((REG_GPIO_PXPIN(2) & 0x08000000) && timeout--);
while (!(REG_GPIO_PXPIN(2) & 0x08000000));
}
static int read_oob(void *buf, u32 size, u32 pg);
static int nand_data_write8(char *buf, int count);
static int nand_data_write16(char *buf, int count);
static int nand_data_read8(char *buf, int count);
static int nand_data_read16(char *buf, int count);
static int (*write_proc)(char *, int) = NULL;
static int (*read_proc)(char *, int) = NULL;
inline void nand_enable_4750(unsigned int csn)
{
//modify this fun to a specifical borad
//this fun to enable the chip select pin csn
//the choosn chip can work after this fun
//dprintf("\n Enable chip select :%d",csn);
__nand_enable();
}
inline void nand_disable_4750(unsigned int csn)
{
//modify this fun to a specifical borad
//this fun to enable the chip select pin csn
//the choosn chip can not work after this fun
//dprintf("\n Disable chip select :%d",csn);
__nand_disable();
}
unsigned int nand_query_4750(u8 *id)
{
__nand_sync();
__nand_cmd(CMD_READID);
__nand_addr(0);
id[0] = __nand_data8(); //VID
id[1] = __nand_data8(); //PID
id[2] = __nand_data8(); //CHIP ID
id[3] = __nand_data8(); //PAGE ID
id[4] = __nand_data8(); //PLANE ID
return 0;
}
int nand_init_4750(int bus_width, int row_cycle, int page_size, int page_per_block,
int bch_bit, int ecc_pos, int bad_pos, int bad_page, int force)
{
bus = bus_width;
row = row_cycle;
pagesize = page_size;
oobsize = pagesize / 32;
ppb = page_per_block;
bchbit = bch_bit;
forceerase = force;
eccpos = ecc_pos;
bad_block_pos = bad_pos;
bad_block_page = bad_page;
wp_pin = Hand.nand_wppin;
if (bchbit == 8)
par_size = 13;
else
par_size = 7;
#if 0
gpio_base = (u8 *)gbase;
emc_base = (u8 *)ebase;
addrport = (u8 *)aport;
dataport = (u8 *)dport;
cmdport = (u8 *)cport;
#endif
/* Initialize NAND Flash Pins */
if (bus == 8) {
__gpio_as_nand_8bit();
}
if (wp_pin)
{
__gpio_as_output(wp_pin);
__gpio_disable_pull(wp_pin);
}
__nand_enable();
// REG_EMC_SMCR1 = 0x0fff7700; //slow speed
REG_EMC_SMCR1 = 0x04444400; //normal speed
// REG_EMC_SMCR1 = 0x0d221200; //fast speed
/* If ECCPOS isn't configured in config file, the initial value is 0 */
if (eccpos == 0) {
eccpos = 3;
}
if (bus == 8) {
write_proc = nand_data_write8;
read_proc = nand_data_read8;
} else {
write_proc = nand_data_write16;
read_proc = nand_data_read16;
}
return 0;
}
int nand_fini_4750(void)
{
__nand_disable();
return 0;
}
/*
* Read oob <pagenum> pages from <startpage> page.
* Don't skip bad block.
* Don't use HW ECC.
*/
u32 nand_read_oob_4750(void *buf, u32 startpage, u32 pagenum)
{
u32 cnt, cur_page;
u8 *tmpbuf;
tmpbuf = (u8 *)buf;
cur_page = startpage;
cnt = 0;
while (cnt < pagenum) {
read_oob((void *)tmpbuf, oobsize, cur_page);
tmpbuf += oobsize;
cur_page++;
cnt++;
}
return cur_page;
}
static int nand_check_block(u32 block)
{
u32 pg,i;
if ( bad_block_page >= ppb ) //do absolute bad block detect!
{
pg = block * ppb + 0;
read_oob(oob_buf, oobsize, pg);
if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
{
serial_puts("Absolute skip a bad block\n");
serial_put_hex(block);
return 1;
}
pg = block * ppb + 1;
read_oob(oob_buf, oobsize, pg);
if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
{
serial_puts("Absolute skip a bad block\n");
serial_put_hex(block);
return 1;
}
pg = block * ppb + ppb - 2 ;
read_oob(oob_buf, oobsize, pg);
if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
{
serial_puts("Absolute skip a bad block\n");
serial_put_hex(block);
return 1;
}
pg = block * ppb + ppb - 1 ;
read_oob(oob_buf, oobsize, pg);
if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
{
serial_puts("Absolute skip a bad block\n");
serial_put_hex(block);
return 1;
}
}
else
{
pg = block * ppb + bad_block_page;
read_oob(oob_buf, oobsize, pg);
if (oob_buf[bad_block_pos] != 0xff)
{
serial_puts("Skip a bad block at");
serial_put_hex(block);
return 1;
}
}
return 0;
}
/*
* Read data <pagenum> pages from <startpage> page.
* Don't skip bad block.
* Don't use HW ECC.
*/
u32 nand_read_raw_4750(void *buf, u32 startpage, u32 pagenum, int option)
{
u32 cnt, j;
u32 cur_page, rowaddr;
u8 *tmpbuf;
tmpbuf = (u8 *)buf;
cur_page = startpage;
cnt = 0;
while (cnt < pagenum) {
if ((cur_page % ppb) == 0) {
if (nand_check_block(cur_page / ppb)) {
cur_page += ppb; // Bad block, set to next block
continue;
}
}
__nand_cmd(CMD_READA);
__nand_addr(0);
if (pagesize != 512)
__nand_addr(0);
rowaddr = cur_page;
for (j = 0; j < row; j++) {
__nand_addr(rowaddr & 0xff);
rowaddr >>= 8;
}
if (pagesize != 512)
__nand_cmd(CMD_CONFIRM);
__nand_sync();
read_proc(tmpbuf, pagesize);
tmpbuf += pagesize;
if (option != NO_OOB)
{
read_oob(tmpbuf, oobsize, cur_page);
tmpbuf += oobsize;
}
cur_page++;
cnt++;
}
return cur_page;
}
u32 nand_erase_4750(int blk_num, int sblk, int force)
{
int i, j;
u32 cur, rowaddr;
if (wp_pin)
__gpio_set_pin(wp_pin);
cur = sblk * ppb;
for (i = 0; i < blk_num; i++) {
rowaddr = cur;
if (!force) /* if set, erase anything */
if (nand_check_block(cur/ppb))
{
cur += ppb;
blk_num += Hand.nand_plane;
continue;
}
__nand_cmd(CMD_ERASE_SETUP);
for (j = 0; j < row; j++) {
__nand_addr(rowaddr & 0xff);
rowaddr >>= 8;
}
__nand_cmd(CMD_ERASE);
__nand_sync();
__nand_cmd(CMD_READ_STATUS);
if (__nand_data8() & 0x01)
{
serial_puts("Erase fail at ");
serial_put_hex(cur / ppb);
nand_mark_bad_4750(cur / ppb);
cur += ppb;
blk_num += Hand.nand_plane;
continue;
}
cur += ppb;
}
if (wp_pin)
__gpio_clear_pin(wp_pin);
return cur;
}
static int read_oob(void *buf, u32 size, u32 pg)
{
u32 i, coladdr, rowaddr;
if (pagesize == 512)
coladdr = 0;
else
coladdr = pagesize;
if (pagesize == 512)
/* Send READOOB command */
__nand_cmd(CMD_READC);
else
/* Send READ0 command */
__nand_cmd(CMD_READA);
/* Send column address */
__nand_addr(coladdr & 0xff);
if (pagesize != 512)
__nand_addr(coladdr >> 8);
/* Send page address */
rowaddr = pg;
for (i = 0; i < row; i++) {
__nand_addr(rowaddr & 0xff);
rowaddr >>= 8;
}
/* Send READSTART command for 2048 or 4096 ps NAND */
if (pagesize != 512)
__nand_cmd(CMD_CONFIRM);
/* Wait for device ready */
__nand_sync();
/* Read oob data */
read_proc(buf, size);
if (pagesize == 512)
__nand_sync();
return 0;
}
static void bch_correct(unsigned char *dat, int idx)
{
int i, bit; // the 'bit' of i byte is error
i = (idx - 1) >> 3;
bit = (idx - 1) & 0x7;
dat[i] ^= (1 << bit);
}
/*
* Read data <pagenum> pages from <startpage> page.
* Skip bad block if detected.
* HW ECC is used.
*/
u32 nand_read_4750(void *buf, u32 startpage, u32 pagenum, int option)
{
u32 j, k;
u32 cur_page, cur_blk, cnt, rowaddr, ecccnt;
u8 *tmpbuf, *p, flag = 0;
u32 oob_per_eccsize;
ecccnt = pagesize / ECC_BLOCK;
oob_per_eccsize = eccpos / ecccnt;
cur_page = startpage;
cnt = 0;
tmpbuf = buf;
while (cnt < pagenum) {
/* If this is the first page of the block, check for bad. */
if ((cur_page % ppb) == 0) {
cur_blk = cur_page / ppb;
if (nand_check_block(cur_blk)) {
cur_page += ppb; // Bad block, set to next block
continue;
}
}
__nand_cmd(CMD_READA);
__nand_addr(0);
if (pagesize != 512)
__nand_addr(0);
rowaddr = cur_page;
for (j = 0; j < row; j++) {
__nand_addr(rowaddr & 0xff);
rowaddr >>= 8;
}
if (pagesize != 512)
__nand_cmd(CMD_CONFIRM);
__nand_sync();
/* Read data */
read_proc((char *)tmpbuf, pagesize);
/* read oob first */
read_proc((char *)oob_buf, oobsize);
for (j = 0; j < ecccnt; j++) {
u32 stat;
flag = 0;
REG_BCH_INTS = 0xffffffff;
if (cur_page >= 16384 / pagesize)
{
if (bchbit == 8)
{
__ecc_decoding_8bit();
par_size = 13;
}
else
{
__ecc_decoding_4bit();
par_size = 7;
}
}
else
{
__ecc_decoding_8bit();
par_size = 13;
}
if (option != NO_OOB)
__ecc_cnt_dec(ECC_BLOCK + oob_per_eccsize + par_size);
else
__ecc_cnt_dec(ECC_BLOCK + par_size);
for (k = 0; k < ECC_BLOCK; k++) {
REG_BCH_DR = tmpbuf[k];
}
if (option != NO_OOB) {
for (k = 0; k < oob_per_eccsize; k++) {
REG_BCH_DR = oob_buf[oob_per_eccsize * j + k];
}
}
for (k = 0; k < par_size; k++) {
REG_BCH_DR = oob_buf[eccpos + j*par_size + k];
if (oob_buf[eccpos + j*par_size + k] != 0xff)
flag = 1;
}
/* Wait for completion */
__ecc_decode_sync();
__ecc_disable();
/* Check decoding */
stat = REG_BCH_INTS;
if (stat & BCH_INTS_ERR) {
if (stat & BCH_INTS_UNCOR) {
if (flag)
{
dprintf("Uncorrectable ECC error occurred\n");
handshake_PKT[3] = 1;
}
}
else {
handshake_PKT[3] = 0;
unsigned int errcnt = (stat & BCH_INTS_ERRC_MASK) >> BCH_INTS_ERRC_BIT;
switch (errcnt) {
case 8:
dprintf("correct 8th error\n");
bch_correct(tmpbuf, (REG_BCH_ERR3 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
case 7:
dprintf("correct 7th error\n");
bch_correct(tmpbuf, (REG_BCH_ERR3 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
case 6:
dprintf("correct 6th error\n");
bch_correct(tmpbuf, (REG_BCH_ERR2 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
case 5:
dprintf("correct 5th error\n");
bch_correct(tmpbuf, (REG_BCH_ERR2 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
case 4:
dprintf("correct 4th error\n");
bch_correct(tmpbuf, (REG_BCH_ERR1 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
case 3:
dprintf("correct 3th error\n");
bch_correct(tmpbuf, (REG_BCH_ERR1 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
case 2:
dprintf("correct 2th error\n");
bch_correct(tmpbuf, (REG_BCH_ERR0 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
case 1:
dprintf("correct 1th error\n");
bch_correct(tmpbuf, (REG_BCH_ERR0 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
break;
default:
dprintf("no error\n");
break;
}
}
}
/* increment pointer */
tmpbuf += ECC_BLOCK;
}
switch (option)
{
case OOB_ECC:
for (j = 0; j < oobsize; j++)
tmpbuf[j] = oob_buf[j];
tmpbuf += oobsize;
break;
case OOB_NO_ECC:
for (j = 0; j < par_size * ecccnt; j++)
oob_buf[eccpos + j] = 0xff;
for (j = 0; j < oobsize; j++)
tmpbuf[j] = oob_buf[j];
tmpbuf += oobsize;
break;
case NO_OOB:
break;
}
cur_page++;
cnt++;
}
return cur_page;
}
u32 nand_program_4750(void *context, int spage, int pages, int option)
{
u32 i, j, cur_page, cur_blk, rowaddr;
u8 *tmpbuf;
u32 ecccnt;
u8 ecc_buf[256];
u32 oob_per_eccsize;
int eccpos_sav = eccpos, bchbit_sav = bchbit, par_size_sav = par_size;
int spl_size = 16 * 1024 / pagesize;
if (wp_pin)
__gpio_set_pin(wp_pin);
restart:
tmpbuf = (u8 *)context;
ecccnt = pagesize / ECC_BLOCK;
oob_per_eccsize = eccpos / ecccnt;
i = 0;
cur_page = spage;
while (i < pages) {
if (cur_page < spl_size) {
bchbit = 8;
eccpos = 3;
par_size = 13;
} else if (cur_page >= spl_size) {
bchbit = bchbit_sav;
eccpos = eccpos_sav;
par_size = par_size_sav;
}
if ((cur_page % ppb) == 0) { /* First page of block, test BAD. */
if (nand_check_block(cur_page / ppb)) {
cur_page += ppb; /* Bad block, set to next block */
continue;
}
}
if ( option != NO_OOB ) //if NO_OOB do not perform vaild check!
{
for ( j = 0 ; j < pagesize + oobsize; j ++)
{
if (tmpbuf[j] != 0xff)
break;
}
if ( j == oobsize + pagesize )
{
tmpbuf += ( pagesize + oobsize ) ;
i ++;
cur_page ++;
continue;
}
}
if (pagesize == 512)
__nand_cmd(CMD_READA);
__nand_cmd(CMD_SEQIN);
__nand_addr(0);
if (pagesize != 512)
__nand_addr(0);
rowaddr = cur_page;
for (j = 0; j < row; j++) {
__nand_addr(rowaddr & 0xff);
rowaddr >>= 8;
}
/* write out data */
for (j = 0; j < ecccnt; j++) {
volatile u8 *paraddr;
int k;
paraddr = (volatile u8 *)BCH_PAR0;
REG_BCH_INTS = 0xffffffff;
if (bchbit == 8)
__ecc_encoding_8bit();
else
__ecc_encoding_4bit();
/* Set BCHCNT.DEC_COUNT to data block size in bytes */
if (option != NO_OOB)
__ecc_cnt_enc(ECC_BLOCK + oob_per_eccsize);
else
__ecc_cnt_enc(ECC_BLOCK);
/* Write data in data area to BCH */
for (k = 0; k < ECC_BLOCK; k++) {
REG_BCH_DR = tmpbuf[ECC_BLOCK * j + k];
}
/* Write file system information in oob area to BCH */
if (option != NO_OOB)
{
for (k = 0; k < oob_per_eccsize; k++) {
REG_BCH_DR = tmpbuf[pagesize + oob_per_eccsize * j + k];
}
}
__ecc_encode_sync();
__ecc_disable();
/* Read PAR values */
for (k = 0; k < par_size; k++) {
ecc_buf[j * par_size + k] = *paraddr++;
}
write_proc((char *)&tmpbuf[ECC_BLOCK * j], ECC_BLOCK);
}
switch (option)
{
case OOB_ECC:
case OOB_NO_ECC:
for (j = 0; j < eccpos; j++) {
oob_buf[j] = tmpbuf[pagesize + j];
}
for (j = 0; j < ecccnt * par_size; j++) {
oob_buf[eccpos + j] = ecc_buf[j];
}
tmpbuf += pagesize + oobsize;
break;
case NO_OOB: //bin image
for (j = 0; j < ecccnt * par_size; j++) {
oob_buf[eccpos + j] = ecc_buf[j];
}
tmpbuf += pagesize;
break;
}
/* write out oob buffer */
write_proc((u8 *)oob_buf, oobsize);
/* send program confirm command */
__nand_cmd(CMD_PGPROG);
__nand_sync();
__nand_cmd(CMD_READ_STATUS);
if (__nand_data8() & 0x01) /* page program error */
{
serial_puts("Skip a write fail block\n");
nand_erase_4750( 1, cur_page/ppb, 1); //force erase before
nand_mark_bad_4750(cur_page/ppb);
spage += ppb;
goto restart;
}
i++;
cur_page++;
}
if (wp_pin)
__gpio_clear_pin(wp_pin);
bchbit = bchbit_sav;
eccpos = eccpos_sav;
par_size = par_size_sav;
return cur_page;
}
static u32 nand_mark_bad_page(u32 page)
{
u8 badbuf[4096 + 128];
u32 i;
if (wp_pin)
__gpio_set_pin(wp_pin);
for (i = 0; i < pagesize + oobsize; i++)
badbuf[i] = 0x00;
//all set to 0x00
__nand_cmd(CMD_READA);
__nand_cmd(CMD_SEQIN);
__nand_addr(0);
if (pagesize != 512)
__nand_addr(0);
for (i = 0; i < row; i++) {
__nand_addr(page & 0xff);
page >>= 8;
}
write_proc((char *)badbuf, pagesize + oobsize);
__nand_cmd(CMD_PGPROG);
__nand_sync();
if (wp_pin)
__gpio_clear_pin(wp_pin);
return page;
}
u32 nand_mark_bad_4750(int block)
{
u32 rowaddr;
if ( bad_block_page >= ppb ) //absolute bad block mark!
{ //mark four page!
rowaddr = block * ppb + 0;
nand_mark_bad_page(rowaddr);
rowaddr = block * ppb + 1;
nand_mark_bad_page(rowaddr);
rowaddr = block * ppb + ppb - 2;
nand_mark_bad_page(rowaddr);
rowaddr = block * ppb + ppb - 1;
nand_mark_bad_page(rowaddr);
}
else //mark one page only
{
rowaddr = block * ppb + bad_block_page;
nand_mark_bad_page(rowaddr);
}
return rowaddr;
}
static int nand_data_write8(char *buf, int count)
{
int i;
u8 *p = (u8 *)buf;
for (i=0;i<count;i++)
__nand_data8() = *p++;
return 0;
}
static int nand_data_write16(char *buf, int count)
{
int i;
u16 *p = (u16 *)buf;
for (i=0;i<count/2;i++)
__nand_data16() = *p++;
return 0;
}
static int nand_data_read8(char *buf, int count)
{
int i;
u8 *p = (u8 *)buf;
for (i=0;i<count;i++)
*p++ = __nand_data8();
return 0;
}
static int nand_data_read16(char *buf, int count)
{
int i;
u16 *p = (u16 *)buf;
for (i=0;i<count/2;i++)
*p++ = __nand_data16();
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -16,15 +16,26 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA
*/
#include "target/jz4740.h"
#include "usb/usb.h"
#include "usb/udc.h"
#include "target/usb_boot.h"
#include "target/xburst_types.h"
#define dprintf(x...)
#if defined(NANONOTE)
#include "target/jz4740.h"
#elif defined(LEPUS)
#include "target/jz4760.h"
#else
#error "Please Define JZ4740 or JZ4760"
#endif
#define dprintf(x...) serial_puts(x)
#define TXFIFOEP0 USB_FIFO_EP0
u32 Bulk_buf[BULK_BUF_SIZE];
extern void serial_put_hex(int );
u32 Bulk_in_buf[BULK_IN_BUF_SIZE];
u32 Bulk_out_buf[BULK_OUT_BUF_SIZE];
u32 Bulk_in_size, Bulk_in_finish, Bulk_out_size;
u16 handshake_PKT[4] = {0, 0, 0, 0};
u8 udc_state;
@ -512,12 +523,12 @@ void EPIN_Handler(u8 EP)
}
if (Bulk_in_size - Bulk_in_finish <= fifosize[EP]) {
udcWriteFifo((u8 *)((u32)Bulk_buf+Bulk_in_finish),
udcWriteFifo((u8 *)((u32)Bulk_in_buf+Bulk_in_finish),
Bulk_in_size - Bulk_in_finish);
usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY);
Bulk_in_finish = Bulk_in_size;
} else {
udcWriteFifo((u8 *)((u32)Bulk_buf+Bulk_in_finish),
udcWriteFifo((u8 *)((u32)Bulk_in_buf+Bulk_in_finish),
fifosize[EP]);
usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY);
Bulk_in_finish += fifosize[EP];
@ -530,7 +541,7 @@ void EPOUT_Handler(u8 EP)
jz_writeb(USB_REG_INDEX, EP);
size = jz_readw(USB_REG_OUTCOUNT);
fifo = fifoaddr[EP];
udcReadFifo((u8 *)((u32)Bulk_buf+Bulk_out_size), size);
udcReadFifo((u8 *)((u32)Bulk_out_buf+Bulk_out_size), size);
usb_clearb(USB_REG_OUTCSR,USB_OUTCSR_OUTPKTRDY);
Bulk_out_size += size;
dprintf("\nEPOUT_handle return!");
@ -541,7 +552,7 @@ void udc4740Proc ()
volatile u8 IntrUSB;
volatile u16 IntrIn;
volatile u16 IntrOut;
/* Read interrupt registers */
/* Read interrupt registers */
IntrUSB = jz_readb(USB_REG_INTRUSB);
IntrIn = jz_readw(USB_REG_INTRIN);
IntrOut = jz_readw(USB_REG_INTROUT);
@ -564,7 +575,7 @@ void udc4740Proc ()
udc_reset();
}
/* Check for endpoint 0 interrupt */
/* Check for endpoint 0 interrupt */
if (IntrIn & USB_INTR_EP0) {
dprintf("\nUDC EP0 operations!");
EP0_Handler();