mirror of
git://projects.qi-hardware.com/xburst-tools.git
synced 2024-11-01 10:15:19 +02:00
add jz4760 support to stage2
Signed-off-by: Xiangfu Liu <xiangfu@sharism.cc>
This commit is contained in:
parent
bcc23ae567
commit
7a5a090832
@ -61,31 +61,30 @@ int check_dump_cfg(struct hand *hand)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* check NAND */
|
/* 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 or OOBSIZE setting invalid!\n");
|
||||||
printf(" PAGESIZE is %d,\t OOBSIZE is %d\n",
|
printf(" PAGESIZE is %d,\t OOBSIZE is %d\n",
|
||||||
hand->nand_ps, hand->nand_os);
|
hand->nand_ps, hand->nand_os);
|
||||||
return 0;
|
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");
|
printf(" PAGESIZE or PAGEPERBLOCK setting invalid!\n");
|
||||||
return 0;
|
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 or OOBSIZE setting invalid!\n");
|
||||||
printf(" PAGESIZE is %d,\t OOBSIZE is %d\n",
|
printf(" PAGESIZE is %d,\t OOBSIZE is %d\n",
|
||||||
hand->nand_ps, hand->nand_os);
|
hand->nand_ps, hand->nand_os);
|
||||||
return 0;
|
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");
|
printf(" PAGESIZE or PAGEPERBLOCK setting invalid!\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
printf(" YES\n");
|
printf(" YES\n");
|
||||||
|
|
||||||
printf("Current device information:\n");
|
printf("Current device setup information:\n");
|
||||||
printf("CPU type is Ingenic XBurst Jz%x\n",hand->fw_args.cpu_id);
|
|
||||||
printf("Crystal work at %dMHz, the CCLK up to %dMHz and PMH_CLK up to %dMHz\n",
|
printf("Crystal work at %dMHz, the CCLK up to %dMHz and PMH_CLK up to %dMHz\n",
|
||||||
hand->fw_args.ext_clk,
|
hand->fw_args.ext_clk,
|
||||||
(unsigned int)hand->fw_args.cpu_speed * hand->fw_args.ext_clk,
|
(unsigned int)hand->fw_args.cpu_speed * hand->fw_args.ext_clk,
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
#include "ingenic_usb.h"
|
#include "ingenic_usb.h"
|
||||||
|
|
||||||
extern unsigned int total_size;
|
extern unsigned int total_size;
|
||||||
extern struct hand hand;
|
|
||||||
|
|
||||||
static int get_ingenic_device(struct ingenic_dev *ingenic_dev)
|
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_4740 ||
|
||||||
usb_dev->descriptor.idProduct == PRODUCT_ID_4760)) {
|
usb_dev->descriptor.idProduct == PRODUCT_ID_4760)) {
|
||||||
ingenic_dev->usb_dev = usb_dev;
|
ingenic_dev->usb_dev = usb_dev;
|
||||||
hand.fw_args.cpu_id = usb_dev->descriptor.idProduct;
|
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,31 +23,6 @@
|
|||||||
|
|
||||||
#include "xburst_types.h"
|
#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
|
#if 0
|
||||||
static inline void jz_flush_dcache(void)
|
static inline void jz_flush_dcache(void)
|
||||||
{
|
{
|
||||||
@ -76,6 +51,16 @@ static inline void jz_flush_icache(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#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 */
|
/* cpu pipeline flush */
|
||||||
static inline void jz_sync(void)
|
static inline void jz_sync(void)
|
||||||
{
|
{
|
||||||
@ -112,18 +97,6 @@ static inline u32 jz_readl(u32 address)
|
|||||||
return *((volatile 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 */
|
/* Boot ROM Specification */
|
||||||
|
|
||||||
/* NOR Boot config */
|
/* NOR Boot config */
|
||||||
|
@ -1,38 +1,27 @@
|
|||||||
/*
|
/*
|
||||||
* Include file for Ingenic Semiconductor's JZ4760 CPU.
|
* 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__
|
#ifndef __JZ4760_H__
|
||||||
#define __JZ4760_H__
|
#define __JZ4760_H__
|
||||||
|
|
||||||
#include "target/xburst_types.h"
|
#include "target/xburst_types.h"
|
||||||
|
|
||||||
#if 0 /* if 0, for spl program */
|
#if 1 /* if 0, for spl program */
|
||||||
#define UCOS_CSP 0
|
#if 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));
|
|
||||||
|
|
||||||
static inline void jz_flush_dcache(void)
|
static inline void jz_flush_dcache(void)
|
||||||
{
|
{
|
||||||
unsigned long start;
|
unsigned long start;
|
||||||
@ -58,6 +47,17 @@ static inline void jz_flush_icache(void)
|
|||||||
start += CFG_CACHELINE_SIZE;
|
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 */
|
/* cpu pipeline flush */
|
||||||
static inline void jz_sync(void)
|
static inline void jz_sync(void)
|
||||||
@ -91,6 +91,7 @@ static inline u16 jz_readw(u32 address)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline u32 jz_readl(u32 address)
|
static inline u32 jz_readl(u32 address)
|
||||||
|
|
||||||
{
|
{
|
||||||
return *((volatile u32 *)address);
|
return *((volatile u32 *)address);
|
||||||
}
|
}
|
||||||
|
@ -40,24 +40,24 @@ u32 nand_mark_bad_4740(int bad);
|
|||||||
void nand_enable_4740(u32 csn);
|
void nand_enable_4740(u32 csn);
|
||||||
void nand_disable_4740(u32 csn);
|
void nand_disable_4740(u32 csn);
|
||||||
|
|
||||||
/* Jz4750 nandflash interface */
|
/* Jz4760 nandflash interface */
|
||||||
unsigned int nand_query_4750(u8 *);
|
unsigned int nand_query_4760(u8 *);
|
||||||
//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,int,int,int);
|
// 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 bch_bit, int ecc_pos, int bad_pos, int bad_page, int force);
|
||||||
|
|
||||||
int nand_fini_4750(void);
|
int nand_fini_4760(void);
|
||||||
u32 nand_program_4750(void *context, int spage, int pages, int option);
|
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));
|
//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_erase_4760(int blk_num, int sblk, int force);
|
||||||
u32 nand_read_4750(void *buf, u32 startpage, u32 pagenum,int option);
|
u32 nand_read_4760(void *buf, u32 startpage, u32 pagenum,int option);
|
||||||
u32 nand_read_oob_4750(void *buf, u32 startpage, u32 pagenum);
|
u32 nand_read_oob_4760(void *buf, u32 startpage, u32 pagenum);
|
||||||
u32 nand_read_raw_4750(void *buf, u32 startpage, u32 pagenum,int);
|
u32 nand_read_raw_4760(void *buf, u32 startpage, u32 pagenum,int);
|
||||||
u32 nand_mark_bad_4750(int bad);
|
u32 nand_mark_bad_4760(int bad);
|
||||||
|
|
||||||
void nand_enable_4750(u32 csn);
|
void nand_enable_4760(u32 csn);
|
||||||
void nand_disable_4750(u32 csn);
|
void nand_disable_4760(u32 csn);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -22,7 +22,8 @@
|
|||||||
#ifndef __USB_BOOT_H__
|
#ifndef __USB_BOOT_H__
|
||||||
#define __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
|
enum UDC_STATE
|
||||||
{
|
{
|
||||||
|
@ -19,29 +19,7 @@
|
|||||||
#ifndef __USB_H
|
#ifndef __USB_H
|
||||||
#define __USB_H
|
#define __USB_H
|
||||||
|
|
||||||
#ifndef u8
|
#include "target/xburst_types.h"
|
||||||
#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
|
|
||||||
|
|
||||||
extern int usbdebug;
|
extern int usbdebug;
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ OBJCOPY = $(CROSS_COMPILE)objcopy
|
|||||||
NM = $(CROSS_COMPILE)nm
|
NM = $(CROSS_COMPILE)nm
|
||||||
OBJDUMP = $(CROSS_COMPILE)objdump
|
OBJDUMP = $(CROSS_COMPILE)objdump
|
||||||
|
|
||||||
|
DEVICE ?=NANONOTE
|
||||||
DEBUG_CFLAGS = -g -Wa,-a=$(basename $@).lst
|
DEBUG_CFLAGS = -g -Wa,-a=$(basename $@).lst
|
||||||
# Wolfgang saw data corruptions in stage2 when dealing with ECC data on random writes
|
# 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.
|
# 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.
|
# is to disable this optimization right now.
|
||||||
CFLAGS = -mips32 -O2 -fno-exceptions -fno-zero-initialized-in-bss \
|
CFLAGS = -mips32 -O2 -fno-exceptions -fno-zero-initialized-in-bss \
|
||||||
-ffunction-sections -fomit-frame-pointer -msoft-float -G 0 -fpie \
|
-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)
|
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
|
all: xburst_stage2.elf
|
||||||
$(OBJCOPY) -O binary xburst_stage2.elf xburst_stage2.bin
|
$(OBJCOPY) -O binary xburst_stage2.elf xburst_stage2.bin
|
||||||
|
@ -42,8 +42,9 @@ u32 (*nand_mark_bad) (int bad);
|
|||||||
void (*nand_enable) (unsigned int csn);
|
void (*nand_enable) (unsigned int csn);
|
||||||
void (*nand_disable) (unsigned int csn);
|
void (*nand_disable) (unsigned int csn);
|
||||||
|
|
||||||
struct hand Hand,*Hand_p;
|
struct hand Hand;
|
||||||
extern u32 Bulk_buf[BULK_BUF_SIZE];
|
extern u32 Bulk_out_buf[BULK_OUT_BUF_SIZE];
|
||||||
|
extern u32 Bulk_in_buf[BULK_IN_BUF_SIZE];
|
||||||
extern u16 handshake_PKT[4];
|
extern u16 handshake_PKT[4];
|
||||||
extern udc_state;
|
extern udc_state;
|
||||||
extern void *memset(void *s, int c, size_t count);
|
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 ops_length; //number of operation unit ,in byte or sector
|
||||||
u32 ram_addr;
|
u32 ram_addr;
|
||||||
|
|
||||||
void config_flash_info()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void dump_data(unsigned int *p, int size)
|
void dump_data(unsigned int *p, int size)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -65,38 +62,30 @@ void dump_data(unsigned int *p, int size)
|
|||||||
serial_put_hex(*p++);
|
serial_put_hex(*p++);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void config_flash_info()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void config_hand()
|
void config_hand()
|
||||||
{
|
{
|
||||||
struct hand *hand_p;
|
memcpy(&Hand, (unsigned char *)Bulk_out_buf, sizeof(struct hand));
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int GET_CUP_INFO_Handle()
|
int GET_CUP_INFO_Handle()
|
||||||
{
|
{
|
||||||
char temp1[8]="Boot4740",temp2[8]="Boot4750";
|
|
||||||
dprintf("\n GET_CPU_INFO:\t");
|
dprintf("\n GET_CPU_INFO:\t");
|
||||||
serial_put_hex(Hand.fw_args.cpu_id);
|
serial_put_hex(Hand.fw_args.cpu_id);
|
||||||
if (Hand.fw_args.cpu_id == 0x4740)
|
switch (Hand.fw_args.cpu_id) {
|
||||||
HW_SendPKT(0, temp1, 8);
|
case 0x4760:
|
||||||
else
|
HW_SendPKT(0, "Boot4760", 8);
|
||||||
HW_SendPKT(0, temp2, 8);
|
break;
|
||||||
|
case 0x4740:
|
||||||
|
HW_SendPKT(0, "Boot4740", 8);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
HW_SendPKT(0, " UNKNOW ", 8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
udc_state = IDLE;
|
udc_state = IDLE;
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
@ -165,8 +154,8 @@ int NAND_OPS_Handle(u8 *buf)
|
|||||||
{
|
{
|
||||||
case NAND_QUERY:
|
case NAND_QUERY:
|
||||||
dprintf("\n Request : NAND_QUERY!");
|
dprintf("\n Request : NAND_QUERY!");
|
||||||
nand_query((u8 *)Bulk_buf);
|
nand_query((u8 *)Bulk_in_buf);
|
||||||
HW_SendPKT(1, Bulk_buf, 8);
|
HW_SendPKT(1, Bulk_in_buf, 8);
|
||||||
handshake_PKT[3]=(u16)ERR_OK;
|
handshake_PKT[3]=(u16)ERR_OK;
|
||||||
udc_state = BULK_IN;
|
udc_state = BULK_IN;
|
||||||
break;
|
break;
|
||||||
@ -185,11 +174,11 @@ int NAND_OPS_Handle(u8 *buf)
|
|||||||
break;
|
break;
|
||||||
case NAND_READ_OOB:
|
case NAND_READ_OOB:
|
||||||
dprintf("\n Request : NAND_READ_OOB!");
|
dprintf("\n Request : NAND_READ_OOB!");
|
||||||
memset(Bulk_buf,0,ops_length*Hand.nand_ps);
|
memset(Bulk_in_buf,0,ops_length*Hand.nand_ps);
|
||||||
ret_dat = nand_read_oob(Bulk_buf,start_addr,ops_length);
|
ret_dat = nand_read_oob(Bulk_in_buf,start_addr,ops_length);
|
||||||
handshake_PKT[0] = (u16) ret_dat;
|
handshake_PKT[0] = (u16) ret_dat;
|
||||||
handshake_PKT[1] = (u16) (ret_dat>>16);
|
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;
|
udc_state = BULK_IN;
|
||||||
break;
|
break;
|
||||||
case NAND_READ_RAW:
|
case NAND_READ_RAW:
|
||||||
@ -197,15 +186,15 @@ int NAND_OPS_Handle(u8 *buf)
|
|||||||
switch (option)
|
switch (option)
|
||||||
{
|
{
|
||||||
case OOB_ECC:
|
case OOB_ECC:
|
||||||
nand_read_raw(Bulk_buf,start_addr,ops_length,option);
|
nand_read_raw(Bulk_in_buf,start_addr,ops_length,option);
|
||||||
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));
|
||||||
handshake_PKT[0] = (u16) ret_dat;
|
handshake_PKT[0] = (u16) ret_dat;
|
||||||
handshake_PKT[1] = (u16) (ret_dat>>16);
|
handshake_PKT[1] = (u16) (ret_dat>>16);
|
||||||
udc_state = BULK_IN;
|
udc_state = BULK_IN;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
nand_read_raw(Bulk_buf,start_addr,ops_length,option);
|
nand_read_raw(Bulk_in_buf,start_addr,ops_length,option);
|
||||||
HW_SendPKT(1,(u8 *)Bulk_buf,ops_length*Hand.nand_ps);
|
HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*Hand.nand_ps);
|
||||||
handshake_PKT[0] = (u16) ret_dat;
|
handshake_PKT[0] = (u16) ret_dat;
|
||||||
handshake_PKT[1] = (u16) (ret_dat>>16);
|
handshake_PKT[1] = (u16) (ret_dat>>16);
|
||||||
udc_state = BULK_IN;
|
udc_state = BULK_IN;
|
||||||
@ -226,24 +215,24 @@ int NAND_OPS_Handle(u8 *buf)
|
|||||||
dprintf("\n Request : NAND_READ!");
|
dprintf("\n Request : NAND_READ!");
|
||||||
switch (option) {
|
switch (option) {
|
||||||
case OOB_ECC:
|
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[0] = (u16) ret_dat;
|
||||||
handshake_PKT[1] = (u16) (ret_dat>>16);
|
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;
|
udc_state = BULK_IN;
|
||||||
break;
|
break;
|
||||||
case OOB_NO_ECC:
|
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[0] = (u16) ret_dat;
|
||||||
handshake_PKT[1] = (u16) (ret_dat>>16);
|
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;
|
udc_state = BULK_IN;
|
||||||
break;
|
break;
|
||||||
case NO_OOB:
|
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[0] = (u16) ret_dat;
|
||||||
handshake_PKT[1] = (u16) (ret_dat>>16);
|
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;
|
udc_state = BULK_IN;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -251,7 +240,7 @@ int NAND_OPS_Handle(u8 *buf)
|
|||||||
break;
|
break;
|
||||||
case NAND_PROGRAM:
|
case NAND_PROGRAM:
|
||||||
dprintf("\n Request : 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);
|
start_addr,ops_length,option);
|
||||||
handshake_PKT[0] = (u16) ret_dat;
|
handshake_PKT[0] = (u16) ret_dat;
|
||||||
handshake_PKT[1] = (u16) (ret_dat>>16);
|
handshake_PKT[1] = (u16) (ret_dat>>16);
|
||||||
@ -285,7 +274,7 @@ int SDRAM_OPS_Handle(u8 *buf)
|
|||||||
{
|
{
|
||||||
case SDRAM_LOAD:
|
case SDRAM_LOAD:
|
||||||
//dprintf("\n Request : 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[0] = (u16) ret_dat;
|
||||||
handshake_PKT[1] = (u16) (ret_dat>>16);
|
handshake_PKT[1] = (u16) (ret_dat>>16);
|
||||||
HW_SendPKT(1,handshake_PKT,sizeof(handshake_PKT));
|
HW_SendPKT(1,handshake_PKT,sizeof(handshake_PKT));
|
||||||
@ -316,25 +305,25 @@ void Borad_Init()
|
|||||||
nand_enable = nand_enable_4740;
|
nand_enable = nand_enable_4740;
|
||||||
nand_disable = nand_disable_4740;
|
nand_disable = nand_disable_4740;
|
||||||
nand_mark_bad = nand_mark_bad_4740;
|
nand_mark_bad = nand_mark_bad_4740;
|
||||||
break;
|
break;
|
||||||
case 0x4750:
|
case 0x4760:
|
||||||
//Init nand flash
|
//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_ppb, Hand.nand_bchbit, Hand.nand_eccpos,
|
||||||
Hand.nand_bbpos, Hand.nand_bbpage, Hand.nand_force_erase);
|
Hand.nand_bbpos, Hand.nand_bbpage, Hand.nand_force_erase);
|
||||||
|
|
||||||
nand_program = nand_program_4750;
|
nand_program=nand_program_4760;
|
||||||
nand_erase = nand_erase_4750;
|
nand_erase =nand_erase_4760;
|
||||||
nand_read = nand_read_4750;
|
nand_read =nand_read_4760;
|
||||||
nand_read_oob = nand_read_oob_4750;
|
nand_read_oob=nand_read_oob_4760;
|
||||||
nand_read_raw = nand_read_raw_4750;
|
nand_read_raw=nand_read_raw_4760;
|
||||||
nand_query = nand_query_4750;
|
nand_query = nand_query_4760;
|
||||||
nand_enable = nand_enable_4750;
|
nand_enable = nand_enable_4760;
|
||||||
nand_disable = nand_disable_4750;
|
nand_disable= nand_disable_4760;
|
||||||
nand_mark_bad = nand_mark_bad_4750;
|
nand_mark_bad = nand_mark_bad_4760;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
serial_puts("Not support CPU ID!");
|
serial_puts("\n Not support CPU ID!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
#include "usb_boot_defines.h"
|
#include "usb_boot_defines.h"
|
||||||
|
|
||||||
extern void usb_main();
|
extern void usb_main();
|
||||||
unsigned int start_addr,got_start,got_end;
|
|
||||||
extern unsigned int UART_BASE;
|
extern unsigned int UART_BASE;
|
||||||
struct fw_args *fw_args;
|
struct fw_args *fw_args;
|
||||||
|
unsigned int start_addr,got_start,got_end;
|
||||||
|
|
||||||
void c_main(void)
|
void c_main(void)
|
||||||
{
|
{
|
||||||
@ -47,14 +47,16 @@ void c_main(void)
|
|||||||
offset = start_addr - 0x80000000;
|
offset = start_addr - 0x80000000;
|
||||||
got_start += offset;
|
got_start += offset;
|
||||||
got_end += 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;
|
||||||
|
|
||||||
|
/* get the fw args from memory */
|
||||||
|
fw_args = (struct fw_args *)(start_addr + 0x8);
|
||||||
|
|
||||||
for ( addr = got_start + 8; addr < got_end; addr += 4 )
|
extern struct hand Hand;
|
||||||
{
|
Hand.fw_args.cpu_id = fw_args->cpu_id;
|
||||||
*((volatile unsigned int *)(addr)) += offset; //add offset to correct all GOT
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
UART_BASE = 0xB0030000 + fw_args->use_uart * 0x1000;
|
||||||
|
|
||||||
serial_puts("\n Stage2 start address is :\t");
|
serial_puts("\n Stage2 start address is :\t");
|
||||||
|
@ -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;
|
|
||||||
}
|
|
1443
usbboot/xburst_stage2/nandflash_4760.c
Normal file
1443
usbboot/xburst_stage2/nandflash_4760.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -16,15 +16,26 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
* Boston, MA 02110-1301, USA
|
* Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
#include "target/jz4740.h"
|
|
||||||
#include "usb/usb.h"
|
#include "usb/usb.h"
|
||||||
#include "usb/udc.h"
|
#include "usb/udc.h"
|
||||||
#include "target/usb_boot.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
|
#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;
|
u32 Bulk_in_size, Bulk_in_finish, Bulk_out_size;
|
||||||
u16 handshake_PKT[4] = {0, 0, 0, 0};
|
u16 handshake_PKT[4] = {0, 0, 0, 0};
|
||||||
u8 udc_state;
|
u8 udc_state;
|
||||||
@ -512,12 +523,12 @@ void EPIN_Handler(u8 EP)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Bulk_in_size - Bulk_in_finish <= fifosize[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);
|
Bulk_in_size - Bulk_in_finish);
|
||||||
usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY);
|
usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY);
|
||||||
Bulk_in_finish = Bulk_in_size;
|
Bulk_in_finish = Bulk_in_size;
|
||||||
} else {
|
} else {
|
||||||
udcWriteFifo((u8 *)((u32)Bulk_buf+Bulk_in_finish),
|
udcWriteFifo((u8 *)((u32)Bulk_in_buf+Bulk_in_finish),
|
||||||
fifosize[EP]);
|
fifosize[EP]);
|
||||||
usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY);
|
usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY);
|
||||||
Bulk_in_finish += fifosize[EP];
|
Bulk_in_finish += fifosize[EP];
|
||||||
@ -530,7 +541,7 @@ void EPOUT_Handler(u8 EP)
|
|||||||
jz_writeb(USB_REG_INDEX, EP);
|
jz_writeb(USB_REG_INDEX, EP);
|
||||||
size = jz_readw(USB_REG_OUTCOUNT);
|
size = jz_readw(USB_REG_OUTCOUNT);
|
||||||
fifo = fifoaddr[EP];
|
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);
|
usb_clearb(USB_REG_OUTCSR,USB_OUTCSR_OUTPKTRDY);
|
||||||
Bulk_out_size += size;
|
Bulk_out_size += size;
|
||||||
dprintf("\nEPOUT_handle return!");
|
dprintf("\nEPOUT_handle return!");
|
||||||
@ -541,7 +552,7 @@ void udc4740Proc ()
|
|||||||
volatile u8 IntrUSB;
|
volatile u8 IntrUSB;
|
||||||
volatile u16 IntrIn;
|
volatile u16 IntrIn;
|
||||||
volatile u16 IntrOut;
|
volatile u16 IntrOut;
|
||||||
/* Read interrupt registers */
|
/* Read interrupt registers */
|
||||||
IntrUSB = jz_readb(USB_REG_INTRUSB);
|
IntrUSB = jz_readb(USB_REG_INTRUSB);
|
||||||
IntrIn = jz_readw(USB_REG_INTRIN);
|
IntrIn = jz_readw(USB_REG_INTRIN);
|
||||||
IntrOut = jz_readw(USB_REG_INTROUT);
|
IntrOut = jz_readw(USB_REG_INTROUT);
|
||||||
@ -564,7 +575,7 @@ void udc4740Proc ()
|
|||||||
udc_reset();
|
udc_reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for endpoint 0 interrupt */
|
/* Check for endpoint 0 interrupt */
|
||||||
if (IntrIn & USB_INTR_EP0) {
|
if (IntrIn & USB_INTR_EP0) {
|
||||||
dprintf("\nUDC EP0 operations!");
|
dprintf("\nUDC EP0 operations!");
|
||||||
EP0_Handler();
|
EP0_Handler();
|
||||||
|
Loading…
Reference in New Issue
Block a user