Date:2010-06-18 09:10:05 (13 years 9 months ago)
Author:Xiangfu Liu
Commit:4cdac88b855d1b8add6396d9e9e7c277c687f1b3
Message:add jz4760 support to stage2, make it can reflash jz4760 device

Signed-off-by: Xiangfu Liu <xiangfu@sharism.cc>
Files: usbboot/src/ingenic_cfg.c (1 diff)
usbboot/src/ingenic_usb.c (2 diffs)
usbboot/xburst_include/target/jz4740.h (3 diffs)
usbboot/xburst_include/target/jz4760.h (3 diffs)
usbboot/xburst_include/target/nandflash.h (1 diff)
usbboot/xburst_include/target/usb_boot.h (1 diff)
usbboot/xburst_include/usb/usb.h (1 diff)
usbboot/xburst_stage2/Makefile (2 diffs)
usbboot/xburst_stage2/boothandler.c (10 diffs)
usbboot/xburst_stage2/main.c (2 diffs)
usbboot/xburst_stage2/nandflash_4750.c (1 diff)
usbboot/xburst_stage2/nandflash_4760.c (1 diff)
usbboot/xburst_stage2/udc.c (5 diffs)

Change Details

usbboot/src/ingenic_cfg.c
6161    }
6262
6363    /* check NAND */
64    if ( hand->nand_ps < 2048 && hand->nand_os > 16 ) {
64    if (hand->nand_ps < 2048 && hand->nand_os > 16) {
6565        printf(" PAGESIZE or OOBSIZE setting invalid!\n");
6666        printf(" PAGESIZE is %d,\t OOBSIZE is %d\n",
6767               hand->nand_ps, hand->nand_os);
6868        return 0;
6969    }
70    if ( hand->nand_ps < 2048 && hand->nand_ppb > 32 ) {
70    if (hand->nand_ps < 2048 && hand->nand_ppb > 32) {
7171        printf(" PAGESIZE or PAGEPERBLOCK setting invalid!\n");
7272        return 0;
7373    }
7474
75    if ( hand->nand_ps > 512 && hand->nand_os <= 16 ) {
75    if (hand->nand_ps > 512 && hand->nand_os <= 16) {
7676        printf(" PAGESIZE or OOBSIZE setting invalid!\n");
7777        printf(" PAGESIZE is %d,\t OOBSIZE is %d\n",
7878               hand->nand_ps, hand->nand_os);
7979        return 0;
8080    }
81    if ( hand->nand_ps > 512 && hand->nand_ppb < 64 ) {
81    if (hand->nand_ps > 512 && hand->nand_ppb < 64) {
8282        printf(" PAGESIZE or PAGEPERBLOCK setting invalid!\n");
8383        return 0;
8484    }
8585    printf(" YES\n");
8686
87    printf("Current device information:\n");
88    printf("CPU type is Ingenic XBurst Jz%x\n",hand->fw_args.cpu_id);
87    printf("Current device setup information:\n");
8988    printf("Crystal work at %dMHz, the CCLK up to %dMHz and PMH_CLK up to %dMHz\n",
9089        hand->fw_args.ext_clk,
9190        (unsigned int)hand->fw_args.cpu_speed * hand->fw_args.ext_clk,
usbboot/src/ingenic_usb.c
2424#include "ingenic_usb.h"
2525
2626extern unsigned int total_size;
27extern struct hand hand;
2827
2928static int get_ingenic_device(struct ingenic_dev *ingenic_dev)
3029{
...... 
4241                (usb_dev->descriptor.idProduct == PRODUCT_ID_4740 ||
4342                usb_dev->descriptor.idProduct == PRODUCT_ID_4760)) {
4443                ingenic_dev->usb_dev = usb_dev;
45                hand.fw_args.cpu_id = usb_dev->descriptor.idProduct;
4644                count++;
4745            }
4846
usbboot/xburst_include/target/jz4740.h
2323
2424#include "xburst_types.h"
2525
26#ifndef __ASSEMBLY__
27#define UCOS_CSP 0
28
29#if UCOS_CSP
30#define __KERNEL__
31#include <bsp.h>
32#include <types.h>
33
34#include <sysdefs.h>
35#include <cacheops.h>
36#define KSEG0 KSEG0BASE
37#else
38/* #include <asm/cacheops.h> */
39#endif
40
41#define cache_unroll(base,op) \
42    __asm__ __volatile__(" \
43        .set noreorder; \
44        .set mips3; \
45        cache %1, (%0); \
46        .set mips0; \
47        .set reorder" \
48        : \
49        : "r" (base), \
50          "i" (op));
5126#if 0
5227static inline void jz_flush_dcache(void)
5328{
...... 
7651}
7752
7853#endif
54#define cache_unroll(base,op) \
55    __asm__ __volatile__(" \
56        .set noreorder; \
57        .set mips3; \
58        cache %1, (%0); \
59        .set mips0; \
60        .set reorder" \
61        : \
62        : "r" (base), \
63          "i" (op));
7964/* cpu pipeline flush */
8065static inline void jz_sync(void)
8166{
...... 
11297    return *((volatile u32 *)address);
11398}
11499
115#define REG8(addr) *((volatile u8 *)(addr))
116#define REG16(addr) *((volatile u16 *)(addr))
117#define REG32(addr) *((volatile u32 *)(addr))
118
119#else
120
121#define REG8(addr) (addr)
122#define REG16(addr) (addr)
123#define REG32(addr) (addr)
124
125#endif /* !ASSEMBLY */
126
127100/* Boot ROM Specification */
128101
129102/* NOR Boot config */
usbboot/xburst_include/target/jz4760.h
11/*
22 * Include file for Ingenic Semiconductor's JZ4760 CPU.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * version 3 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 * Boston, MA 02110-1301, USA
317 */
418#ifndef __JZ4760_H__
519#define __JZ4760_H__
620
721#include "target/xburst_types.h"
822
9#if 0 /* if 0, for spl program */
10#define UCOS_CSP 0
11
12#if UCOS_CSP
13#define __KERNEL__
14#include <bsp.h>
15#include <types.h>
16
17#include <sysdefs.h>
18#include <cacheops.h>
19#define KSEG0 KSEG0BASE
20#else
21#include <asm/addrspace.h>
22#include <asm/cacheops.h>
23#endif
24
25#define cache_unroll(base,op) \
26    __asm__ __volatile__(" \
27        .set noreorder; \
28        .set mips3; \
29        cache %1, (%0); \
30        .set mips0; \
31        .set reorder" \
32        : \
33        : "r" (base), \
34          "i" (op));
35
23#if 1 /* if 0, for spl program */
24#if 0
3625static inline void jz_flush_dcache(void)
3726{
3827    unsigned long start;
...... 
5847        start += CFG_CACHELINE_SIZE;
5948    }
6049}
50#endif
51#define cache_unroll(base,op) \
52    __asm__ __volatile__(" \
53        .set noreorder; \
54        .set mips3; \
55        cache %1, (%0); \
56        .set mips0; \
57        .set reorder" \
58        : \
59        : "r" (base), \
60          "i" (op));
6161
6262/* cpu pipeline flush */
6363static inline void jz_sync(void)
...... 
9191}
9292
9393static inline u32 jz_readl(u32 address)
94
9495{
9596    return *((volatile u32 *)address);
9697}
usbboot/xburst_include/target/nandflash.h
4040void nand_enable_4740(u32 csn);
4141void nand_disable_4740(u32 csn);
4242
43/* Jz4750 nandflash interface */
44unsigned int nand_query_4750(u8 *);
45//int nand_init_4750(int bus_width, int row_cycle, int page_size, int page_per_block,
43/* Jz4760 nandflash interface */
44unsigned int nand_query_4760(u8 *);
45//int nand_init_4760(int bus_width, int row_cycle, int page_size, int page_per_block,
4646// int,int,int,int);
4747
48int nand_init_4750(int bus_width, int row_cycle, int page_size, int page_per_block,
48int nand_init_4760(int bus_width, int row_cycle, int page_size, int page_per_block,
4949           int bch_bit, int ecc_pos, int bad_pos, int bad_page, int force);
5050
51int nand_fini_4750(void);
52u32 nand_program_4750(void *context, int spage, int pages, int option);
51int nand_fini_4760(void);
52u32 nand_program_4760(void *context, int spage, int pages, int option);
5353//int nand_program_oob_4740(void *context, int spage, int pages, void (*notify)(int));
54u32 nand_erase_4750(int blk_num, int sblk, int force);
55u32 nand_read_4750(void *buf, u32 startpage, u32 pagenum,int option);
56u32 nand_read_oob_4750(void *buf, u32 startpage, u32 pagenum);
57u32 nand_read_raw_4750(void *buf, u32 startpage, u32 pagenum,int);
58u32 nand_mark_bad_4750(int bad);
59
60void nand_enable_4750(u32 csn);
61void nand_disable_4750(u32 csn);
54u32 nand_erase_4760(int blk_num, int sblk, int force);
55u32 nand_read_4760(void *buf, u32 startpage, u32 pagenum,int option);
56u32 nand_read_oob_4760(void *buf, u32 startpage, u32 pagenum);
57u32 nand_read_raw_4760(void *buf, u32 startpage, u32 pagenum,int);
58u32 nand_mark_bad_4760(int bad);
59
60void nand_enable_4760(u32 csn);
61void nand_disable_4760(u32 csn);
6262
6363#endif
usbboot/xburst_include/target/usb_boot.h
2222#ifndef __USB_BOOT_H__
2323#define __USB_BOOT_H__
2424
25#define BULK_BUF_SIZE (2048 * 128)
25#define BULK_OUT_BUF_SIZE (2048 * 128)
26#define BULK_IN_BUF_SIZE (2048 * 128)
2627
2728enum UDC_STATE
2829{
usbboot/xburst_include/usb/usb.h
1919#ifndef __USB_H
2020#define __USB_H
2121
22#ifndef u8
23#define u8 unsigned char
24#endif
25
26#ifndef u16
27#define u16 unsigned short
28#endif
29
30#ifndef u32
31#define u32 unsigned int
32#endif
33
34#ifndef s8
35#define s8 char
36#endif
37
38#ifndef s16
39#define s16 short
40#endif
41
42#ifndef s32
43#define s32 int
44#endif
22#include "target/xburst_types.h"
4523
4624extern int usbdebug;
4725
usbboot/xburst_stage2/Makefile
2222NM = $(CROSS_COMPILE)nm
2323OBJDUMP = $(CROSS_COMPILE)objdump
2424
25DEVICE ?=NANONOTE
2526DEBUG_CFLAGS = -g -Wa,-a=$(basename $@).lst
2627# Wolfgang saw data corruptions in stage2 when dealing with ECC data on random writes
2728# to NAND. Disabling the unit-at-a-time optimization reproducibly fixed the bug.
...... 
3031# is to disable this optimization right now.
3132CFLAGS = -mips32 -O2 -fno-exceptions -fno-zero-initialized-in-bss \
3233    -ffunction-sections -fomit-frame-pointer -msoft-float -G 0 -fpie \
33    -I$(XBURST_INCLUDE_PATH) -I$(INFLASH_SRC_PATH)
34    -I$(XBURST_INCLUDE_PATH) -I$(INFLASH_SRC_PATH) -D$(DEVICE)
3435LDFLAGS = -nostdlib -T target.ld $(CFLAGS)
3536
36OBJS = main.o udc.o cache.o serial.o boothandler.o nandflash_4740.o nandflash_4750.o
37OBJS = main.o udc.o cache.o serial.o boothandler.o nandflash_4740.o nandflash_4760.o
3738
3839all: xburst_stage2.elf
3940    $(OBJCOPY) -O binary xburst_stage2.elf xburst_stage2.bin
usbboot/xburst_stage2/boothandler.c
4242void (*nand_enable) (unsigned int csn);
4343void (*nand_disable) (unsigned int csn);
4444
45struct hand Hand,*Hand_p;
46extern u32 Bulk_buf[BULK_BUF_SIZE];
45struct hand Hand;
46extern u32 Bulk_out_buf[BULK_OUT_BUF_SIZE];
47extern u32 Bulk_in_buf[BULK_IN_BUF_SIZE];
4748extern u16 handshake_PKT[4];
4849extern udc_state;
4950extern void *memset(void *s, int c, size_t count);
...... 
5455u32 ops_length; //number of operation unit ,in byte or sector
5556u32 ram_addr;
5657
57void config_flash_info()
58{
59}
60
6158void dump_data(unsigned int *p, int size)
6259{
6360    int i;
...... 
6562        serial_put_hex(*p++);
6663}
6764
68void config_hand()
65void config_flash_info()
6966{
70    struct hand *hand_p;
71    hand_p=(struct hand *)Bulk_buf;
72    memcpy(&Hand, (unsigned char *)Bulk_buf, sizeof(struct hand));
73
74#if 0
75    Hand.nand_bw=hand_p->nand_bw;
76    Hand.nand_rc=hand_p->nand_rc;
77    Hand.nand_ps=hand_p->nand_ps;
78    Hand.nand_ppb=hand_p->nand_ppb;
79    Hand.nand_force_erase=hand_p->nand_force_erase;
80    Hand.nand_pn=hand_p->nand_pn;
81    Hand.nand_os=hand_p->nand_os;
67}
8268
83    Hand.nand_eccpos=hand_p->nand_eccpos;
84    Hand.nand_bbpos=hand_p->nand_bbpos;
85    Hand.nand_bbpage=hand_p->nand_bbpage;
86    serial_put_hex(Hand.fw_args.cpu_id);
87    serial_put_hex(Hand.fw_args.ext_clk);
88#endif
69void config_hand()
70{
71    memcpy(&Hand, (unsigned char *)Bulk_out_buf, sizeof(struct hand));
8972}
9073
9174int GET_CUP_INFO_Handle()
9275{
93    char temp1[8]="Boot4740",temp2[8]="Boot4750";
9476    dprintf("\n GET_CPU_INFO:\t");
9577    serial_put_hex(Hand.fw_args.cpu_id);
96    if (Hand.fw_args.cpu_id == 0x4740)
97        HW_SendPKT(0, temp1, 8);
98    else
99        HW_SendPKT(0, temp2, 8);
78    switch (Hand.fw_args.cpu_id) {
79    case 0x4760:
80        HW_SendPKT(0, "Boot4760", 8);
81        break;
82    case 0x4740:
83        HW_SendPKT(0, "Boot4740", 8);
84        break;
85    default:
86        HW_SendPKT(0, " UNKNOW ", 8);
87        break;
88    }
10089    udc_state = IDLE;
10190    return ERR_OK;
10291}
...... 
165154    {
166155    case NAND_QUERY:
167156        dprintf("\n Request : NAND_QUERY!");
168        nand_query((u8 *)Bulk_buf);
169        HW_SendPKT(1, Bulk_buf, 8);
157        nand_query((u8 *)Bulk_in_buf);
158        HW_SendPKT(1, Bulk_in_buf, 8);
170159        handshake_PKT[3]=(u16)ERR_OK;
171160        udc_state = BULK_IN;
172161        break;
...... 
185174        break;
186175    case NAND_READ_OOB:
187176        dprintf("\n Request : NAND_READ_OOB!");
188        memset(Bulk_buf,0,ops_length*Hand.nand_ps);
189        ret_dat = nand_read_oob(Bulk_buf,start_addr,ops_length);
177        memset(Bulk_in_buf,0,ops_length*Hand.nand_ps);
178        ret_dat = nand_read_oob(Bulk_in_buf,start_addr,ops_length);
190179        handshake_PKT[0] = (u16) ret_dat;
191180        handshake_PKT[1] = (u16) (ret_dat>>16);
192        HW_SendPKT(1,(u8 *)Bulk_buf,ops_length*Hand.nand_ps);
181        HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*Hand.nand_ps);
193182        udc_state = BULK_IN;
194183        break;
195184    case NAND_READ_RAW:
...... 
197186        switch (option)
198187        {
199188        case OOB_ECC:
200            nand_read_raw(Bulk_buf,start_addr,ops_length,option);
201            HW_SendPKT(1,(u8 *)Bulk_buf,ops_length*(Hand.nand_ps + Hand.nand_os));
189            nand_read_raw(Bulk_in_buf,start_addr,ops_length,option);
190            HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*(Hand.nand_ps + Hand.nand_os));
202191            handshake_PKT[0] = (u16) ret_dat;
203192            handshake_PKT[1] = (u16) (ret_dat>>16);
204193            udc_state = BULK_IN;
205194            break;
206195        default:
207            nand_read_raw(Bulk_buf,start_addr,ops_length,option);
208            HW_SendPKT(1,(u8 *)Bulk_buf,ops_length*Hand.nand_ps);
196            nand_read_raw(Bulk_in_buf,start_addr,ops_length,option);
197            HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*Hand.nand_ps);
209198            handshake_PKT[0] = (u16) ret_dat;
210199            handshake_PKT[1] = (u16) (ret_dat>>16);
211200            udc_state = BULK_IN;
...... 
226215        dprintf("\n Request : NAND_READ!");
227216        switch (option) {
228217        case OOB_ECC:
229            ret_dat = nand_read(Bulk_buf,start_addr,ops_length,OOB_ECC);
218            ret_dat = nand_read(Bulk_in_buf,start_addr,ops_length,OOB_ECC);
230219            handshake_PKT[0] = (u16) ret_dat;
231220            handshake_PKT[1] = (u16) (ret_dat>>16);
232            HW_SendPKT(1,(u8 *)Bulk_buf,ops_length*(Hand.nand_ps + Hand.nand_os ));
221            HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*(Hand.nand_ps + Hand.nand_os ));
233222            udc_state = BULK_IN;
234223            break;
235224        case OOB_NO_ECC:
236            ret_dat = nand_read(Bulk_buf,start_addr,ops_length,OOB_NO_ECC);
225            ret_dat = nand_read(Bulk_in_buf,start_addr,ops_length,OOB_NO_ECC);
237226            handshake_PKT[0] = (u16) ret_dat;
238227            handshake_PKT[1] = (u16) (ret_dat>>16);
239            HW_SendPKT(1,(u8 *)Bulk_buf,ops_length*(Hand.nand_ps + Hand.nand_os));
228            HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*(Hand.nand_ps + Hand.nand_os));
240229            udc_state = BULK_IN;
241230            break;
242231        case NO_OOB:
243            ret_dat = nand_read(Bulk_buf,start_addr,ops_length,NO_OOB);
232            ret_dat = nand_read(Bulk_in_buf,start_addr,ops_length,NO_OOB);
244233            handshake_PKT[0] = (u16) ret_dat;
245234            handshake_PKT[1] = (u16) (ret_dat>>16);
246            HW_SendPKT(1,(u8 *)Bulk_buf,ops_length*Hand.nand_ps);
235            HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*Hand.nand_ps);
247236            udc_state = BULK_IN;
248237            break;
249238        }
...... 
251240        break;
252241    case NAND_PROGRAM:
253242        dprintf("\n Request : NAND_PROGRAM!");
254        ret_dat = nand_program((void *)Bulk_buf,
243        ret_dat = nand_program((void *)Bulk_out_buf,
255244                 start_addr,ops_length,option);
256245        handshake_PKT[0] = (u16) ret_dat;
257246        handshake_PKT[1] = (u16) (ret_dat>>16);
...... 
285274    {
286275    case SDRAM_LOAD:
287276        //dprintf("\n Request : SDRAM_LOAD!");
288        ret_dat = (u32)memcpy((u8 *)start_addr,Bulk_buf,ops_length);
277        ret_dat = (u32)memcpy((u8 *)start_addr,Bulk_out_buf,ops_length);
289278        handshake_PKT[0] = (u16) ret_dat;
290279        handshake_PKT[1] = (u16) (ret_dat>>16);
291280        HW_SendPKT(1,handshake_PKT,sizeof(handshake_PKT));
...... 
316305        nand_enable = nand_enable_4740;
317306        nand_disable = nand_disable_4740;
318307        nand_mark_bad = nand_mark_bad_4740;
319    break;
320    case 0x4750:
308        break;
309    case 0x4760:
321310        //Init nand flash
322        nand_init_4750(Hand.nand_bw, Hand.nand_rc, Hand.nand_ps,
311        nand_init_4760(Hand.nand_bw, Hand.nand_rc, Hand.nand_ps,
323312                   Hand.nand_ppb, Hand.nand_bchbit, Hand.nand_eccpos,
324313                   Hand.nand_bbpos, Hand.nand_bbpage, Hand.nand_force_erase);
325314
326        nand_program = nand_program_4750;
327        nand_erase = nand_erase_4750;
328        nand_read = nand_read_4750;
329        nand_read_oob = nand_read_oob_4750;
330        nand_read_raw = nand_read_raw_4750;
331        nand_query = nand_query_4750;
332        nand_enable = nand_enable_4750;
333        nand_disable = nand_disable_4750;
334        nand_mark_bad = nand_mark_bad_4750;
335    break;
315        nand_program=nand_program_4760;
316        nand_erase =nand_erase_4760;
317        nand_read =nand_read_4760;
318        nand_read_oob=nand_read_oob_4760;
319        nand_read_raw=nand_read_raw_4760;
320        nand_query = nand_query_4760;
321        nand_enable = nand_enable_4760;
322        nand_disable= nand_disable_4760;
323        nand_mark_bad = nand_mark_bad_4760;
324        break;
336325    default:
337        serial_puts("Not support CPU ID!");
326        serial_puts("\n Not support CPU ID!");
338327    }
339328}
340329
usbboot/xburst_stage2/main.c
1919#include "usb_boot_defines.h"
2020
2121extern void usb_main();
22unsigned int start_addr,got_start,got_end;
2322extern unsigned int UART_BASE;
2423struct fw_args *fw_args;
24unsigned int start_addr,got_start,got_end;
2525
2626void c_main(void)
2727{
...... 
4747    offset = start_addr - 0x80000000;
4848     got_start += offset;
4949    got_end += offset;
50    /* add offset to correct all GOT */
51    for(addr = got_start + 8; addr < got_end; addr += 4)
52        *((volatile unsigned int *)(addr)) += offset;
53
54    /* get the fw args from memory */
55    fw_args = (struct fw_args *)(start_addr + 0x8);
5056
51    for ( addr = got_start + 8; addr < got_end; addr += 4 )
52    {
53        *((volatile unsigned int *)(addr)) += offset; //add offset to correct all GOT
54    }
57    extern struct hand Hand;
58    Hand.fw_args.cpu_id = fw_args->cpu_id;
5559
56    fw_args = (struct fw_args *)(start_addr + 0x8); //get the fw args from memory
57    if ( fw_args->use_uart > 3 ) fw_args->use_uart = 0;
5860    UART_BASE = 0xB0030000 + fw_args->use_uart * 0x1000;
5961
6062    serial_puts("\n Stage2 start address is :\t");
usbboot/xburst_stage2/nandflash_4750.c
1/*
2 * Copyright (C) 2009 Qi Hardware Inc.,
3 * Author: Xiangfu Liu <xiangfu@qi-hardware.com>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 3 as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA
18 */
19#include "target/jz4750.h"
20#include "target/nandflash.h"
21#include "target/usb_boot.h"
22#include "usb_boot_defines.h"
23
24#define dprintf(n...)
25
26#define __nand_enable() (REG_EMC_NFCSR |= EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1)
27#define __nand_disable() (REG_EMC_NFCSR &= ~(EMC_NFCSR_NFCE1))
28#define __nand_ready() ((REG_GPIO_PXPIN(2) & 0x08000000) ? 1 : 0)
29#define __nand_cmd(n) (REG8(cmdport) = (n))
30#define __nand_addr(n) (REG8(addrport) = (n))
31#define __nand_data8() REG8(dataport)
32#define __nand_data16() REG16(dataport)
33
34#define CMD_READA 0x00
35#define CMD_READB 0x01
36#define CMD_READC 0x50
37#define CMD_ERASE_SETUP 0x60
38#define CMD_ERASE 0xD0
39#define CMD_READ_STATUS 0x70
40#define CMD_CONFIRM 0x30
41#define CMD_SEQIN 0x80
42#define CMD_PGPROG 0x10
43#define CMD_READID 0x90
44
45#define ECC_BLOCK 512
46
47static volatile unsigned char *gpio_base = (volatile unsigned char *)0xb0010000;
48static volatile unsigned char *emc_base = (volatile unsigned char *)0xb3010000;
49static volatile unsigned char *addrport = (volatile unsigned char *)0xb8010000;
50static volatile unsigned char *dataport = (volatile unsigned char *)0xb8000000;
51static volatile unsigned char *cmdport = (volatile unsigned char *)0xb8008000;
52
53static int bus = 8, row = 2, pagesize = 512, oobsize = 16, ppb = 32;
54static int eccpos = 3, bchbit = 8, par_size = 13, forceerase = 1, wp_pin;
55static int oobfs = 0; /* 1:store file system information in oob, 0:don't store */
56static int oobecc = 0; /* Whether the oob data of the binary contains ECC data? */
57static int bad_block_page = 127; /* Specify the page number of badblock flag inside a block */
58static u32 bad_block_pos = 0; /* Specify the badblock flag offset inside the oob */
59static u8 oob_buf[256] = {0};
60extern struct hand Hand;
61extern u16 handshake_PKT[4];
62
63static inline void __nand_sync(void)
64{
65    unsigned int timeout = 10000;
66    while ((REG_GPIO_PXPIN(2) & 0x08000000) && timeout--);
67    while (!(REG_GPIO_PXPIN(2) & 0x08000000));
68}
69
70static int read_oob(void *buf, u32 size, u32 pg);
71static int nand_data_write8(char *buf, int count);
72static int nand_data_write16(char *buf, int count);
73static int nand_data_read8(char *buf, int count);
74static int nand_data_read16(char *buf, int count);
75
76static int (*write_proc)(char *, int) = NULL;
77static int (*read_proc)(char *, int) = NULL;
78
79inline void nand_enable_4750(unsigned int csn)
80{
81    //modify this fun to a specifical borad
82    //this fun to enable the chip select pin csn
83    //the choosn chip can work after this fun
84    //dprintf("\n Enable chip select :%d",csn);
85    __nand_enable();
86}
87
88inline void nand_disable_4750(unsigned int csn)
89{
90    //modify this fun to a specifical borad
91    //this fun to enable the chip select pin csn
92    //the choosn chip can not work after this fun
93    //dprintf("\n Disable chip select :%d",csn);
94    __nand_disable();
95}
96
97unsigned int nand_query_4750(u8 *id)
98{
99    __nand_sync();
100    __nand_cmd(CMD_READID);
101    __nand_addr(0);
102
103    id[0] = __nand_data8(); //VID
104    id[1] = __nand_data8(); //PID
105    id[2] = __nand_data8(); //CHIP ID
106    id[3] = __nand_data8(); //PAGE ID
107    id[4] = __nand_data8(); //PLANE ID
108
109    return 0;
110}
111
112int nand_init_4750(int bus_width, int row_cycle, int page_size, int page_per_block,
113           int bch_bit, int ecc_pos, int bad_pos, int bad_page, int force)
114{
115    bus = bus_width;
116    row = row_cycle;
117    pagesize = page_size;
118    oobsize = pagesize / 32;
119    ppb = page_per_block;
120    bchbit = bch_bit;
121    forceerase = force;
122    eccpos = ecc_pos;
123    bad_block_pos = bad_pos;
124    bad_block_page = bad_page;
125    wp_pin = Hand.nand_wppin;
126
127    if (bchbit == 8)
128        par_size = 13;
129    else
130        par_size = 7;
131
132
133#if 0
134    gpio_base = (u8 *)gbase;
135    emc_base = (u8 *)ebase;
136    addrport = (u8 *)aport;
137    dataport = (u8 *)dport;
138    cmdport = (u8 *)cport;
139#endif
140    /* Initialize NAND Flash Pins */
141    if (bus == 8) {
142        __gpio_as_nand_8bit();
143    }
144
145    if (wp_pin)
146    {
147        __gpio_as_output(wp_pin);
148        __gpio_disable_pull(wp_pin);
149    }
150    __nand_enable();
151
152// REG_EMC_SMCR1 = 0x0fff7700; //slow speed
153    REG_EMC_SMCR1 = 0x04444400; //normal speed
154// REG_EMC_SMCR1 = 0x0d221200; //fast speed
155
156       /* If ECCPOS isn't configured in config file, the initial value is 0 */
157     if (eccpos == 0) {
158        eccpos = 3;
159    }
160
161    if (bus == 8) {
162        write_proc = nand_data_write8;
163        read_proc = nand_data_read8;
164    } else {
165        write_proc = nand_data_write16;
166        read_proc = nand_data_read16;
167    }
168    return 0;
169}
170
171int nand_fini_4750(void)
172{
173    __nand_disable();
174    return 0;
175}
176
177/*
178 * Read oob <pagenum> pages from <startpage> page.
179 * Don't skip bad block.
180 * Don't use HW ECC.
181 */
182u32 nand_read_oob_4750(void *buf, u32 startpage, u32 pagenum)
183{
184    u32 cnt, cur_page;
185    u8 *tmpbuf;
186
187    tmpbuf = (u8 *)buf;
188
189    cur_page = startpage;
190    cnt = 0;
191
192    while (cnt < pagenum) {
193        read_oob((void *)tmpbuf, oobsize, cur_page);
194        tmpbuf += oobsize;
195        cur_page++;
196        cnt++;
197    }
198
199    return cur_page;
200}
201
202static int nand_check_block(u32 block)
203{
204    u32 pg,i;
205
206    if ( bad_block_page >= ppb ) //do absolute bad block detect!
207    {
208        pg = block * ppb + 0;
209        read_oob(oob_buf, oobsize, pg);
210        if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
211        {
212            serial_puts("Absolute skip a bad block\n");
213            serial_put_hex(block);
214            return 1;
215        }
216
217        pg = block * ppb + 1;
218        read_oob(oob_buf, oobsize, pg);
219        if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
220        {
221            serial_puts("Absolute skip a bad block\n");
222            serial_put_hex(block);
223            return 1;
224        }
225
226        pg = block * ppb + ppb - 2 ;
227        read_oob(oob_buf, oobsize, pg);
228        if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
229        {
230            serial_puts("Absolute skip a bad block\n");
231            serial_put_hex(block);
232            return 1;
233        }
234
235        pg = block * ppb + ppb - 1 ;
236        read_oob(oob_buf, oobsize, pg);
237        if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
238        {
239            serial_puts("Absolute skip a bad block\n");
240            serial_put_hex(block);
241            return 1;
242        }
243
244    }
245    else
246    {
247        pg = block * ppb + bad_block_page;
248        read_oob(oob_buf, oobsize, pg);
249        if (oob_buf[bad_block_pos] != 0xff)
250        {
251            serial_puts("Skip a bad block at");
252            serial_put_hex(block);
253            return 1;
254        }
255
256    }
257    return 0;
258}
259
260
261/*
262 * Read data <pagenum> pages from <startpage> page.
263 * Don't skip bad block.
264 * Don't use HW ECC.
265 */
266u32 nand_read_raw_4750(void *buf, u32 startpage, u32 pagenum, int option)
267{
268    u32 cnt, j;
269    u32 cur_page, rowaddr;
270    u8 *tmpbuf;
271
272    tmpbuf = (u8 *)buf;
273
274    cur_page = startpage;
275    cnt = 0;
276    while (cnt < pagenum) {
277        if ((cur_page % ppb) == 0) {
278            if (nand_check_block(cur_page / ppb)) {
279                cur_page += ppb; // Bad block, set to next block
280                continue;
281            }
282        }
283
284        __nand_cmd(CMD_READA);
285        __nand_addr(0);
286        if (pagesize != 512)
287            __nand_addr(0);
288
289        rowaddr = cur_page;
290        for (j = 0; j < row; j++) {
291            __nand_addr(rowaddr & 0xff);
292            rowaddr >>= 8;
293        }
294
295        if (pagesize != 512)
296            __nand_cmd(CMD_CONFIRM);
297
298        __nand_sync();
299        read_proc(tmpbuf, pagesize);
300
301        tmpbuf += pagesize;
302        if (option != NO_OOB)
303        {
304            read_oob(tmpbuf, oobsize, cur_page);
305            tmpbuf += oobsize;
306        }
307
308        cur_page++;
309        cnt++;
310    }
311
312    return cur_page;
313}
314
315
316u32 nand_erase_4750(int blk_num, int sblk, int force)
317{
318    int i, j;
319    u32 cur, rowaddr;
320
321    if (wp_pin)
322        __gpio_set_pin(wp_pin);
323    cur = sblk * ppb;
324    for (i = 0; i < blk_num; i++) {
325        rowaddr = cur;
326
327        if (!force) /* if set, erase anything */
328            if (nand_check_block(cur/ppb))
329            {
330                cur += ppb;
331                blk_num += Hand.nand_plane;
332                continue;
333            }
334
335        __nand_cmd(CMD_ERASE_SETUP);
336
337        for (j = 0; j < row; j++) {
338            __nand_addr(rowaddr & 0xff);
339            rowaddr >>= 8;
340        }
341        __nand_cmd(CMD_ERASE);
342        __nand_sync();
343        __nand_cmd(CMD_READ_STATUS);
344
345        if (__nand_data8() & 0x01)
346        {
347            serial_puts("Erase fail at ");
348            serial_put_hex(cur / ppb);
349            nand_mark_bad_4750(cur / ppb);
350            cur += ppb;
351            blk_num += Hand.nand_plane;
352            continue;
353        }
354        cur += ppb;
355    }
356
357    if (wp_pin)
358        __gpio_clear_pin(wp_pin);
359    return cur;
360}
361
362static int read_oob(void *buf, u32 size, u32 pg)
363{
364    u32 i, coladdr, rowaddr;
365
366    if (pagesize == 512)
367        coladdr = 0;
368    else
369        coladdr = pagesize;
370
371    if (pagesize == 512)
372        /* Send READOOB command */
373        __nand_cmd(CMD_READC);
374    else
375        /* Send READ0 command */
376        __nand_cmd(CMD_READA);
377
378    /* Send column address */
379    __nand_addr(coladdr & 0xff);
380    if (pagesize != 512)
381        __nand_addr(coladdr >> 8);
382
383    /* Send page address */
384    rowaddr = pg;
385    for (i = 0; i < row; i++) {
386        __nand_addr(rowaddr & 0xff);
387        rowaddr >>= 8;
388    }
389
390    /* Send READSTART command for 2048 or 4096 ps NAND */
391    if (pagesize != 512)
392        __nand_cmd(CMD_CONFIRM);
393
394    /* Wait for device ready */
395    __nand_sync();
396
397    /* Read oob data */
398    read_proc(buf, size);
399
400    if (pagesize == 512)
401        __nand_sync();
402
403    return 0;
404}
405
406static void bch_correct(unsigned char *dat, int idx)
407{
408    int i, bit; // the 'bit' of i byte is error
409    i = (idx - 1) >> 3;
410    bit = (idx - 1) & 0x7;
411    dat[i] ^= (1 << bit);
412}
413
414 /*
415 * Read data <pagenum> pages from <startpage> page.
416 * Skip bad block if detected.
417 * HW ECC is used.
418 */
419u32 nand_read_4750(void *buf, u32 startpage, u32 pagenum, int option)
420{
421    u32 j, k;
422    u32 cur_page, cur_blk, cnt, rowaddr, ecccnt;
423    u8 *tmpbuf, *p, flag = 0;
424    u32 oob_per_eccsize;
425
426    ecccnt = pagesize / ECC_BLOCK;
427    oob_per_eccsize = eccpos / ecccnt;
428
429    cur_page = startpage;
430    cnt = 0;
431
432    tmpbuf = buf;
433
434    while (cnt < pagenum) {
435        /* If this is the first page of the block, check for bad. */
436        if ((cur_page % ppb) == 0) {
437            cur_blk = cur_page / ppb;
438            if (nand_check_block(cur_blk)) {
439                cur_page += ppb; // Bad block, set to next block
440                continue;
441            }
442        }
443        __nand_cmd(CMD_READA);
444
445        __nand_addr(0);
446        if (pagesize != 512)
447            __nand_addr(0);
448
449        rowaddr = cur_page;
450        for (j = 0; j < row; j++) {
451            __nand_addr(rowaddr & 0xff);
452            rowaddr >>= 8;
453        }
454
455        if (pagesize != 512)
456            __nand_cmd(CMD_CONFIRM);
457
458        __nand_sync();
459
460        /* Read data */
461        read_proc((char *)tmpbuf, pagesize);
462
463        /* read oob first */
464        read_proc((char *)oob_buf, oobsize);
465
466        for (j = 0; j < ecccnt; j++) {
467            u32 stat;
468            flag = 0;
469            REG_BCH_INTS = 0xffffffff;
470
471            if (cur_page >= 16384 / pagesize)
472            {
473                if (bchbit == 8)
474                {
475                    __ecc_decoding_8bit();
476                    par_size = 13;
477                }
478                else
479                {
480                    __ecc_decoding_4bit();
481                    par_size = 7;
482                }
483            }
484            else
485            {
486                __ecc_decoding_8bit();
487                par_size = 13;
488            }
489
490            if (option != NO_OOB)
491                __ecc_cnt_dec(ECC_BLOCK + oob_per_eccsize + par_size);
492            else
493                __ecc_cnt_dec(ECC_BLOCK + par_size);
494
495            for (k = 0; k < ECC_BLOCK; k++) {
496                REG_BCH_DR = tmpbuf[k];
497            }
498
499            if (option != NO_OOB) {
500                for (k = 0; k < oob_per_eccsize; k++) {
501                    REG_BCH_DR = oob_buf[oob_per_eccsize * j + k];
502                }
503            }
504
505            for (k = 0; k < par_size; k++) {
506                REG_BCH_DR = oob_buf[eccpos + j*par_size + k];
507                if (oob_buf[eccpos + j*par_size + k] != 0xff)
508                    flag = 1;
509            }
510
511            /* Wait for completion */
512            __ecc_decode_sync();
513            __ecc_disable();
514            /* Check decoding */
515            stat = REG_BCH_INTS;
516
517            if (stat & BCH_INTS_ERR) {
518                if (stat & BCH_INTS_UNCOR) {
519                    if (flag)
520                    {
521                        dprintf("Uncorrectable ECC error occurred\n");
522                        handshake_PKT[3] = 1;
523                    }
524                }
525                else {
526                    handshake_PKT[3] = 0;
527                    unsigned int errcnt = (stat & BCH_INTS_ERRC_MASK) >> BCH_INTS_ERRC_BIT;
528                    switch (errcnt) {
529                    case 8:
530                        dprintf("correct 8th error\n");
531                        bch_correct(tmpbuf, (REG_BCH_ERR3 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
532                    case 7:
533                        dprintf("correct 7th error\n");
534                        bch_correct(tmpbuf, (REG_BCH_ERR3 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
535                    case 6:
536                        dprintf("correct 6th error\n");
537                        bch_correct(tmpbuf, (REG_BCH_ERR2 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
538                    case 5:
539                        dprintf("correct 5th error\n");
540                        bch_correct(tmpbuf, (REG_BCH_ERR2 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
541                    case 4:
542                        dprintf("correct 4th error\n");
543                        bch_correct(tmpbuf, (REG_BCH_ERR1 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
544                    case 3:
545                        dprintf("correct 3th error\n");
546                        bch_correct(tmpbuf, (REG_BCH_ERR1 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
547                    case 2:
548                        dprintf("correct 2th error\n");
549                        bch_correct(tmpbuf, (REG_BCH_ERR0 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
550                    case 1:
551                        dprintf("correct 1th error\n");
552                        bch_correct(tmpbuf, (REG_BCH_ERR0 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
553                        break;
554                    default:
555                        dprintf("no error\n");
556                        break;
557                    }
558                }
559            }
560            /* increment pointer */
561            tmpbuf += ECC_BLOCK;
562        }
563
564        switch (option)
565        {
566        case OOB_ECC:
567            for (j = 0; j < oobsize; j++)
568                tmpbuf[j] = oob_buf[j];
569            tmpbuf += oobsize;
570            break;
571        case OOB_NO_ECC:
572            for (j = 0; j < par_size * ecccnt; j++)
573                oob_buf[eccpos + j] = 0xff;
574            for (j = 0; j < oobsize; j++)
575                tmpbuf[j] = oob_buf[j];
576            tmpbuf += oobsize;
577            break;
578        case NO_OOB:
579            break;
580        }
581
582        cur_page++;
583        cnt++;
584    }
585    return cur_page;
586}
587
588u32 nand_program_4750(void *context, int spage, int pages, int option)
589{
590    u32 i, j, cur_page, cur_blk, rowaddr;
591    u8 *tmpbuf;
592    u32 ecccnt;
593    u8 ecc_buf[256];
594    u32 oob_per_eccsize;
595    int eccpos_sav = eccpos, bchbit_sav = bchbit, par_size_sav = par_size;
596    int spl_size = 16 * 1024 / pagesize;
597
598    if (wp_pin)
599        __gpio_set_pin(wp_pin);
600restart:
601    tmpbuf = (u8 *)context;
602    ecccnt = pagesize / ECC_BLOCK;
603    oob_per_eccsize = eccpos / ecccnt;
604
605    i = 0;
606    cur_page = spage;
607
608    while (i < pages) {
609        if (cur_page < spl_size) {
610            bchbit = 8;
611            eccpos = 3;
612            par_size = 13;
613        } else if (cur_page >= spl_size) {
614            bchbit = bchbit_sav;
615            eccpos = eccpos_sav;
616            par_size = par_size_sav;
617        }
618
619        if ((cur_page % ppb) == 0) { /* First page of block, test BAD. */
620            if (nand_check_block(cur_page / ppb)) {
621                cur_page += ppb; /* Bad block, set to next block */
622                continue;
623            }
624        }
625
626        if ( option != NO_OOB ) //if NO_OOB do not perform vaild check!
627        {
628            for ( j = 0 ; j < pagesize + oobsize; j ++)
629            {
630                if (tmpbuf[j] != 0xff)
631                    break;
632            }
633            if ( j == oobsize + pagesize )
634            {
635                tmpbuf += ( pagesize + oobsize ) ;
636                i ++;
637                cur_page ++;
638                continue;
639            }
640        }
641
642        if (pagesize == 512)
643            __nand_cmd(CMD_READA);
644
645        __nand_cmd(CMD_SEQIN);
646        __nand_addr(0);
647
648        if (pagesize != 512)
649            __nand_addr(0);
650
651        rowaddr = cur_page;
652        for (j = 0; j < row; j++) {
653            __nand_addr(rowaddr & 0xff);
654            rowaddr >>= 8;
655        }
656
657        /* write out data */
658        for (j = 0; j < ecccnt; j++) {
659            volatile u8 *paraddr;
660            int k;
661
662            paraddr = (volatile u8 *)BCH_PAR0;
663
664            REG_BCH_INTS = 0xffffffff;
665
666            if (bchbit == 8)
667                __ecc_encoding_8bit();
668            else
669                __ecc_encoding_4bit();
670
671            /* Set BCHCNT.DEC_COUNT to data block size in bytes */
672            if (option != NO_OOB)
673                __ecc_cnt_enc(ECC_BLOCK + oob_per_eccsize);
674            else
675                __ecc_cnt_enc(ECC_BLOCK);
676
677            /* Write data in data area to BCH */
678            for (k = 0; k < ECC_BLOCK; k++) {
679                REG_BCH_DR = tmpbuf[ECC_BLOCK * j + k];
680            }
681
682            /* Write file system information in oob area to BCH */
683            if (option != NO_OOB)
684            {
685                for (k = 0; k < oob_per_eccsize; k++) {
686                    REG_BCH_DR = tmpbuf[pagesize + oob_per_eccsize * j + k];
687                }
688            }
689
690            __ecc_encode_sync();
691            __ecc_disable();
692
693            /* Read PAR values */
694            for (k = 0; k < par_size; k++) {
695                ecc_buf[j * par_size + k] = *paraddr++;
696            }
697
698            write_proc((char *)&tmpbuf[ECC_BLOCK * j], ECC_BLOCK);
699        }
700
701        switch (option)
702        {
703        case OOB_ECC:
704        case OOB_NO_ECC:
705            for (j = 0; j < eccpos; j++) {
706                oob_buf[j] = tmpbuf[pagesize + j];
707            }
708            for (j = 0; j < ecccnt * par_size; j++) {
709                oob_buf[eccpos + j] = ecc_buf[j];
710            }
711            tmpbuf += pagesize + oobsize;
712            break;
713        case NO_OOB: //bin image
714            for (j = 0; j < ecccnt * par_size; j++) {
715                oob_buf[eccpos + j] = ecc_buf[j];
716            }
717            tmpbuf += pagesize;
718            break;
719        }
720
721        /* write out oob buffer */
722        write_proc((u8 *)oob_buf, oobsize);
723
724        /* send program confirm command */
725        __nand_cmd(CMD_PGPROG);
726        __nand_sync();
727
728        __nand_cmd(CMD_READ_STATUS);
729
730        if (__nand_data8() & 0x01) /* page program error */
731        {
732            serial_puts("Skip a write fail block\n");
733            nand_erase_4750( 1, cur_page/ppb, 1); //force erase before
734            nand_mark_bad_4750(cur_page/ppb);
735            spage += ppb;
736            goto restart;
737        }
738
739        i++;
740        cur_page++;
741    }
742
743    if (wp_pin)
744        __gpio_clear_pin(wp_pin);
745    bchbit = bchbit_sav;
746    eccpos = eccpos_sav;
747    par_size = par_size_sav;
748
749    return cur_page;
750}
751
752static u32 nand_mark_bad_page(u32 page)
753{
754    u8 badbuf[4096 + 128];
755    u32 i;
756
757    if (wp_pin)
758        __gpio_set_pin(wp_pin);
759    for (i = 0; i < pagesize + oobsize; i++)
760        badbuf[i] = 0x00;
761    //all set to 0x00
762
763    __nand_cmd(CMD_READA);
764    __nand_cmd(CMD_SEQIN);
765
766    __nand_addr(0);
767    if (pagesize != 512)
768        __nand_addr(0);
769    for (i = 0; i < row; i++) {
770        __nand_addr(page & 0xff);
771        page >>= 8;
772    }
773
774    write_proc((char *)badbuf, pagesize + oobsize);
775    __nand_cmd(CMD_PGPROG);
776    __nand_sync();
777
778    if (wp_pin)
779        __gpio_clear_pin(wp_pin);
780    return page;
781}
782
783u32 nand_mark_bad_4750(int block)
784{
785    u32 rowaddr;
786
787    if ( bad_block_page >= ppb ) //absolute bad block mark!
788    { //mark four page!
789        rowaddr = block * ppb + 0;
790        nand_mark_bad_page(rowaddr);
791
792        rowaddr = block * ppb + 1;
793        nand_mark_bad_page(rowaddr);
794
795        rowaddr = block * ppb + ppb - 2;
796        nand_mark_bad_page(rowaddr);
797
798        rowaddr = block * ppb + ppb - 1;
799        nand_mark_bad_page(rowaddr);
800    }
801    else //mark one page only
802    {
803        rowaddr = block * ppb + bad_block_page;
804        nand_mark_bad_page(rowaddr);
805    }
806
807    return rowaddr;
808}
809
810static int nand_data_write8(char *buf, int count)
811{
812    int i;
813    u8 *p = (u8 *)buf;
814    for (i=0;i<count;i++)
815        __nand_data8() = *p++;
816    return 0;
817}
818
819static int nand_data_write16(char *buf, int count)
820{
821    int i;
822    u16 *p = (u16 *)buf;
823    for (i=0;i<count/2;i++)
824        __nand_data16() = *p++;
825    return 0;
826}
827
828static int nand_data_read8(char *buf, int count)
829{
830    int i;
831    u8 *p = (u8 *)buf;
832    for (i=0;i<count;i++)
833        *p++ = __nand_data8();
834    return 0;
835}
836
837static int nand_data_read16(char *buf, int count)
838{
839    int i;
840    u16 *p = (u16 *)buf;
841    for (i=0;i<count/2;i++)
842        *p++ = __nand_data16();
843    return 0;
844}
usbboot/xburst_stage2/nandflash_4760.c
1/*
2 * Copyright (C) 2007 Ingenic Semiconductor Inc.
3 * Author: Regen Huang <lhhuang@ingenic.cn>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18 * MA 02111-1307 USA
19 */
20
21#include "target/jz4760.h"
22#include "target/nandflash.h"
23#include "target/usb_boot.h"
24#include "usb_boot_defines.h"
25
26#define USE_BCH 1
27#define USE_PN 1
28#define NEMC_PNCR (NEMC_BASE + 0x100)
29#define NEMC_PNDR (NEMC_BASE + 0x104)
30#define REG_NEMC_PNCR REG32(NEMC_PNCR)
31#define REG_NEMC_PNDR REG32(NEMC_PNDR)
32
33#define pn_enable() \
34    do {\
35        REG_NEMC_PNCR = 0x3;\
36    }while(0)
37#define pn_disable() \
38    do {\
39        REG_NEMC_PNCR = 0x0;\
40    }while(0)
41
42#ifdef DEBUG
43#define dprintf(n...) printf(n)
44#else
45#define dprintf(n...)
46#endif
47
48/* for spl */
49#define ECC_BLOCK0 256
50#define PAR_SIZE_SPL 78
51#define PAR_SIZE_SPL1 ((PAR_SIZE_SPL+1)/2)
52
53/*
54 * NAND flash definitions
55 */
56#define NAND_DATAPORT 0x1A000000
57#define NAND_ADDRPORT 0x1A800000
58#define NAND_COMMPORT 0x1A400000
59
60#define ECC_BLOCK 512
61static int par_size, par_size1;
62
63#define CMD_READA 0x00
64#define CMD_READB 0x01
65#define CMD_READC 0x50
66#define CMD_ERASE_SETUP 0x60
67#define CMD_ERASE 0xD0
68#define CMD_READ_STATUS 0x70
69#define CMD_CONFIRM 0x30
70#define CMD_SEQIN 0x80
71#define CMD_PGPROG 0x10
72#define CMD_READID 0x90
73
74#define __nand_cmd(n) (REG8(NAND_COMMPORT) = (n))
75#define __nand_addr(n) (REG8(NAND_ADDRPORT) = (n))
76#define __nand_data8() REG8(NAND_DATAPORT)
77#define __nand_data16() REG16(NAND_DATAPORT)
78
79#define __nand_enable() (REG_NEMC_NFCSR |= NEMC_NFCSR_NFE1 | NEMC_NFCSR_NFCE1)
80#define __nand_disable() (REG_NEMC_NFCSR &= ~(NEMC_NFCSR_NFCE1))
81
82static int bus = 8, row = 2, pagesize = 512, oobsize = 16, ppb = 32;
83static int eccpos = 3, bchbit = 8, par_size = 26, par_size1 = 13, forceerase = 1, wp_pin = 0;
84static int oobfs = 0; /* 1:store file system information in oob, 0:don't store */
85static int oobecc = 0; /* Whether the oob data of the binary contains ECC data? */
86static int bad_block_page = 127; /* Specify the page number of badblock flag inside a block */
87static u32 bad_block_pos = 0; /* Specify the badblock flag offset inside the oob */
88static u8 oob_buf[256] = {0};
89extern struct hand Hand;
90extern u16 handshake_PKT[4];
91
92static inline void __nand_sync(void)
93{
94    unsigned int timeout = 1000;
95    while ((REG_GPIO_PXPIN(0) & 0x00100000) && timeout--);
96    while (!(REG_GPIO_PXPIN(0) & 0x00100000));
97}
98
99/*
100 * External routines
101 */
102extern void flush_cache_all(void);
103extern int serial_init(void);
104extern void serial_puts(const char *s);
105extern void sdram_init(void);
106extern void pll_init(void);
107
108static int read_oob(void *buf, u32 size, u32 pg);
109static int nand_data_write8(char *buf, int count);
110static int nand_data_write16(char *buf, int count);
111static int nand_data_read8(char *buf, int count);
112static int nand_data_read16(char *buf, int count);
113
114static int (*write_proc)(char *, int) = NULL;
115static int (*read_proc)(char *, int) = NULL;
116
117int read_nand_spl_page(unsigned char *databuf, unsigned int pageaddr);
118int program_nand_spl_page(unsigned char *databuf, unsigned int pageaddr);
119
120/*
121 * NAND flash routines
122 */
123
124static inline void nand_read_buf16(void *buf, int count)
125{
126    int i;
127    u16 *p = (u16 *)buf;
128
129    for (i = 0; i < count; i += 2)
130        *p++ = __nand_data16();
131}
132
133static inline void nand_read_buf8(void *buf, int count)
134{
135    int i;
136    u8 *p = (u8 *)buf;
137
138    for (i = 0; i < count; i++)
139        *p++ = __nand_data8();
140}
141
142static inline void nand_read_buf(void *buf, int count, int bw)
143{
144    if (bw == 8)
145        nand_read_buf8(buf, count);
146    else
147        nand_read_buf16(buf, count);
148}
149
150inline void nand_enable_4760(unsigned int csn)
151{
152    //modify this fun to a specifical borad
153    //this fun to enable the chip select pin csn
154    //the choosn chip can work after this fun
155    //dprintf("\n Enable chip select :%d",csn);
156    __nand_enable();
157    __gpio_as_nand_8bit(1);
158}
159
160inline void nand_disable_4760(unsigned int csn)
161{
162    //modify this fun to a specifical borad
163    //this fun to enable the chip select pin csn
164    //the choosn chip can not work after this fun
165    //dprintf("\n Disable chip select :%d",csn);
166    __nand_disable();
167}
168
169void udelay(unsigned long usec)
170{
171    volatile int i, j;
172
173    for (i = 0; i < usec; i++) {
174        for (j = 0; j < 100; j++) {
175            ;
176        }
177    }
178}
179
180unsigned int nand_query_4760(u8 *id)
181{
182    u8 i, vid=0, did=0;
183    __nand_disable();
184    __nand_enable();
185#if 1
186    __nand_cmd(0xff);
187    __nand_sync();
188#endif
189    __nand_cmd(CMD_READID);
190    __nand_addr(0);
191
192    udelay(1000);
193#if 1
194    id[0] = __nand_data8(); //VID
195    id[1] = __nand_data8(); //PID
196    id[2] = __nand_data8(); //CHIP ID
197    id[3] = __nand_data8(); //PAGE ID
198    id[4] = __nand_data8(); //PLANE ID
199
200    serial_put_hex(id[0]);
201    serial_put_hex(id[1]);
202    serial_put_hex(id[2]);
203    serial_put_hex(id[3]);
204    serial_put_hex(id[4]);
205
206#endif
207
208    __nand_disable();
209    return 0;
210}
211
212int nand_init_4760(int bus_width, int row_cycle, int page_size, int page_per_block,
213           int bch_bit, int ecc_pos, int bad_pos, int bad_page, int force)
214{
215    bus = bus_width;
216    row = row_cycle;
217    pagesize = page_size;
218    oobsize = pagesize / 32;
219    ppb = page_per_block;
220    bchbit = bch_bit;
221    forceerase = force;
222    eccpos = ecc_pos;
223    bad_block_pos = bad_pos;
224    bad_block_page = bad_page;
225    wp_pin = Hand.nand_wppin;
226
227    if(bchbit == 4)
228        par_size = 13;
229    else if(bchbit == 8)
230        par_size = 26;
231    else if(bchbit == 12)
232        par_size =39;
233    else if(bchbit == 16)
234        par_size =52;
235    else if(bchbit == 20)
236        par_size = 65;
237    else
238        par_size ==78;
239
240    par_size1 = (par_size + 1)/2;
241
242    /* Initialize NAND Flash Pins */
243    if (bus == 8) {
244        REG_NEMC_SMCR1 = 0x0d444400;
245// REG_NEMC_SMCR1 = 0x0fff7700; /* slower */
246        __gpio_as_nand_8bit(1);
247        write_proc = nand_data_write8;
248        read_proc = nand_data_read8;
249    } else {
250        REG_NEMC_SMCR1 = 0x0d444400 | 0x40;
251        __gpio_as_nand_16bit(1);
252        write_proc = nand_data_write16;
253        read_proc = nand_data_read16;
254    }
255
256    if (wp_pin)
257    {
258        __gpio_as_output(wp_pin);
259        __gpio_disable_pull(wp_pin);
260    }
261    __nand_enable();
262
263       /* If ECCPOS isn't configured in config file, the initial value is 0 */
264     if (eccpos == 0) {
265        eccpos = 3;
266    }
267
268#ifdef USE_BCH
269    serial_puts("Use bch.\n");
270#else
271    serial_puts("Not use bch.\n");
272#endif
273#ifdef USE_PN
274    serial_puts("Use PN.\n");
275#else
276    serial_puts("Not use PN.\n");
277#endif
278    return 0;
279}
280
281/*
282 * Correct the error bit in ECC_BLOCK bytes data
283 */
284static void bch_correct(unsigned char *dat, int idx)
285{
286    int i, bit; // the 'bit' of i byte is error
287    i = (idx - 1) >> 3;
288    bit = (idx - 1) & 0x7;
289    if (i < ECC_BLOCK)
290        dat[i] ^= (1 << bit);
291}
292
293u32 nand_read_oob_4760(void *buf, u32 startpage, u32 pagenum)
294{
295    u32 cnt, cur_page;
296    u8 *tmpbuf;
297
298    tmpbuf = (u8 *)buf;
299
300    cur_page = startpage;
301    cnt = 0;
302
303    while (cnt < pagenum) {
304        read_oob((void *)tmpbuf, oobsize, cur_page);
305        tmpbuf += oobsize;
306        cur_page++;
307        cnt++;
308    }
309
310    return cur_page;
311}
312
313static int nand_check_block(u32 block)
314{
315    u32 pg,i;
316
317    if ( bad_block_page >= ppb ) //do absolute bad block detect!
318    {
319        pg = block * ppb + 0;
320        read_oob(oob_buf, oobsize, pg);
321        if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
322        {
323            serial_puts("Absolute skip a bad block\n");
324            serial_put_hex(block);
325            return 1;
326        }
327
328        pg = block * ppb + 1;
329        read_oob(oob_buf, oobsize, pg);
330        if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
331        {
332            serial_puts("Absolute skip a bad block\n");
333            serial_put_hex(block);
334            return 1;
335        }
336
337        pg = block * ppb + ppb - 2 ;
338        read_oob(oob_buf, oobsize, pg);
339        if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
340        {
341            serial_puts("Absolute skip a bad block\n");
342            serial_put_hex(block);
343            return 1;
344        }
345
346        pg = block * ppb + ppb - 1 ;
347        read_oob(oob_buf, oobsize, pg);
348        if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
349        {
350            serial_puts("Absolute skip a bad block\n");
351            serial_put_hex(block);
352            return 1;
353        }
354
355    }
356    else
357    {
358        pg = block * ppb + bad_block_page;
359        read_oob(oob_buf, oobsize, pg);
360        if (oob_buf[bad_block_pos] != 0xff)
361        {
362            serial_put_hex(oob_buf[bad_block_pos]);
363            serial_puts("Skip a bad block at");
364            serial_put_hex(block);
365            return 1;
366        }
367
368    }
369    return 0;
370}
371
372u32 nand_erase_4760(int blk_num, int sblk, int force)
373{
374    int i, j;
375    u32 cur, rowaddr;
376
377    __nand_enable();
378
379    if (wp_pin)
380        __gpio_set_pin(wp_pin);
381    cur = sblk * ppb;
382    for (i = 0; i < blk_num; i++) {
383        rowaddr = cur;
384
385        if (!force) /* if set, erase anything */
386            if (nand_check_block(cur/ppb))
387            {
388                cur += ppb;
389                blk_num += Hand.nand_plane;
390                continue;
391            }
392
393        __nand_cmd(CMD_ERASE_SETUP);
394
395        for (j = 0; j < row; j++) {
396            __nand_addr(rowaddr & 0xff);
397            rowaddr >>= 8;
398        }
399        __nand_cmd(CMD_ERASE);
400        __nand_sync();
401        __nand_cmd(CMD_READ_STATUS);
402
403        if (__nand_data8() & 0x01)
404        {
405            serial_puts("Erase fail at ");
406            serial_put_hex(cur / ppb);
407            nand_mark_bad_4760(cur / ppb);
408            cur += ppb;
409            blk_num += Hand.nand_plane;
410            continue;
411        }
412        cur += ppb;
413    }
414
415    if (wp_pin)
416        __gpio_clear_pin(wp_pin);
417
418    __nand_disable();
419    return cur;
420}
421
422/*
423 * Read oob
424 */
425static int read_oob(void *buf, unsigned int size, unsigned int pg)
426{
427    unsigned int i, coladdr, rowaddr;
428
429    __nand_enable();
430
431    if (pagesize == 512)
432        coladdr = 0;
433    else {
434        if (bus == 8)
435            coladdr = pagesize;
436        else
437            coladdr = pagesize / 2;
438    }
439
440    if (pagesize == 512)
441        /* Send READOOB command */
442        __nand_cmd(CMD_READC);
443    else
444        /* Send READ0 command */
445        __nand_cmd(CMD_READA);
446
447    /* Send column address */
448    __nand_addr(coladdr & 0xff);
449    if (pagesize != 512)
450        __nand_addr(coladdr >> 8);
451
452    /* Send page address */
453    rowaddr = pg;
454    for (i = 0; i < row; i++) {
455        __nand_addr(rowaddr & 0xff);
456        rowaddr >>= 8;
457    }
458
459    /* Send READSTART command for 2048 ps NAND */
460    if (pagesize != 512)
461        __nand_cmd(CMD_CONFIRM);
462
463    /* Wait for device ready */
464    __nand_sync();
465
466    /* Read oob data */
467    read_proc(buf, size);
468
469    if (pagesize == 512)
470        __nand_sync();
471
472    __nand_disable();
473    return 0;
474}
475
476/*
477 * Read data <pagenum> pages from <startpage> page.
478 * Don't skip bad block.
479 * Don't use HW ECC.
480 */
481u32 nand_read_raw_4760(void *buf, u32 startpage, u32 pagenum, int option)
482{
483    u32 cnt, j;
484    u32 cur_page, rowaddr;
485    u8 *tmpbuf;
486
487    tmpbuf = (u8 *)buf;
488
489    cur_page = startpage;
490    cnt = 0;
491    while (cnt < pagenum) {
492        if ((cur_page % ppb) == 0) {
493            if (nand_check_block(cur_page / ppb)) {
494                cur_page += ppb; // Bad block, set to next block
495                continue;
496            }
497        }
498
499        __nand_cmd(CMD_READA);
500        __nand_addr(0);
501        if (pagesize != 512)
502            __nand_addr(0);
503
504        rowaddr = cur_page;
505        for (j = 0; j < row; j++) {
506            __nand_addr(rowaddr & 0xff);
507            rowaddr >>= 8;
508        }
509
510        if (pagesize != 512)
511            __nand_cmd(CMD_CONFIRM);
512
513        __nand_sync();
514#ifdef USE_PN
515    pn_enable();
516#endif
517
518        read_proc(tmpbuf, pagesize);
519
520        tmpbuf += pagesize;
521        if (option != NO_OOB)
522        {
523            read_oob(tmpbuf, oobsize, cur_page);
524            tmpbuf += oobsize;
525        }
526#ifdef USE_PN
527        pn_disable();
528#endif
529        cur_page++;
530        cnt++;
531    }
532
533    return cur_page;
534}
535
536#ifndef CFG_NAND_BADBLOCK_PAGE
537#define CFG_NAND_BADBLOCK_PAGE 0 /* NAND bad block was marked at this page in a block, starting from 0 */
538#endif
539
540/*
541 * Read data <pagenum> pages from <startpage> page.
542 * Skip bad block if detected.
543 * HW ECC is used.
544 */
545u32 nand_read_4760(void *buf, u32 startpage, u32 pagenum, int option)
546{
547    u32 j, k;
548    u32 cur_page, cur_blk, cnt, rowaddr, ecccnt;
549    u8 *tmpbuf, *p, flag = 0;
550    u32 oob_per_eccsize;
551    u32 spl_size = 8 * 1024 / pagesize;
552    ecccnt = pagesize / ECC_BLOCK;
553    oob_per_eccsize = eccpos / ecccnt;
554
555    cur_page = startpage;
556    cnt = 0;
557
558    if(startpage >= 0 && startpage < spl_size * 2)
559        tmpbuf = buf + 8 * 1024;
560    else
561        tmpbuf = buf;
562
563    __nand_enable();
564    while (cnt < pagenum) {
565        if (cur_page < spl_size * 2) {
566            u32 m;
567            for (m=0; (m < pagenum) && (m < spl_size); m++)
568                read_nand_spl_page(buf + pagesize * m, m * 2);
569
570            cur_page = ppb * 2;
571            cnt = spl_size;
572            continue;
573        }
574
575        /* If this is the first page of the block, check for bad. */
576        if ((cur_page % ppb) == 0) {
577            cur_blk = cur_page / ppb;
578            if (nand_check_block(cur_blk)) {
579                cur_page += ppb; // Bad block, set to next block
580                continue;
581            }
582        }
583        __nand_cmd(CMD_READA);
584
585        __nand_addr(0);
586        if (pagesize != 512)
587            __nand_addr(0);
588
589        rowaddr = cur_page;
590        for (j = 0; j < row; j++) {
591            __nand_addr(rowaddr & 0xff);
592            rowaddr >>= 8;
593        }
594
595        if (pagesize != 512)
596            __nand_cmd(CMD_CONFIRM);
597
598        __nand_sync();
599
600#ifdef USE_PN
601// pn_enable();
602#endif
603        /* Read data */
604        read_proc((char *)tmpbuf, pagesize);
605
606        /* read oob first */
607        read_proc((char *)oob_buf, oobsize);
608#ifdef USE_PN
609// pn_disable();
610#endif
611
612        for (j = 0; j < ecccnt; j++) {
613            u32 stat;
614            flag = 0;
615            REG_BCH_INTS = 0xffffffff;
616
617            if (cur_page >= 16384 / pagesize)
618            {
619                if(bchbit == 4)
620                    __ecc_decoding_4bit();
621                else if(bchbit == 8)
622                    __ecc_decoding_8bit();
623                else if(bchbit == 12)
624                    __ecc_decoding_12bit();
625                else if(bchbit == 16)
626                    __ecc_decoding_16bit();
627                else if(bchbit == 20)
628                    __ecc_decoding_20bit();
629                else
630                    __ecc_decoding_24bit();
631            }
632            else
633            {
634                __ecc_decoding_24bit();
635            }
636
637            if (option != NO_OOB)
638                __ecc_cnt_dec(ECC_BLOCK*2 + oob_per_eccsize*2 + par_size);
639            else
640                __ecc_cnt_dec(ECC_BLOCK*2 + par_size);
641
642            for (k = 0; k < ECC_BLOCK; k++) {
643                REG_BCH_DR = tmpbuf[k];
644            }
645
646            if (option != NO_OOB) {
647                for (k = 0; k < oob_per_eccsize; k++) {
648                    REG_BCH_DR = oob_buf[oob_per_eccsize * j + k];
649                }
650            }
651
652            for (k = 0; k < par_size1; k++) {
653                REG_BCH_DR = oob_buf[eccpos + j * par_size1 + k];
654                if (oob_buf[eccpos + j * par_size1 + k] != 0xff) //why?
655                    flag = 1;
656            }
657
658            /* Wait for completion */
659            __ecc_decode_sync();
660            __ecc_disable();
661            /* Check decoding */
662            stat = REG_BCH_INTS;
663
664            if (stat & BCH_INTS_ERR) {
665                if (stat & BCH_INTS_UNCOR) {
666                    if (flag)
667                    {
668                        dprintf("Uncorrectable ECC error occurred\n");
669                        handshake_PKT[3] = 1;
670                    }
671                }
672                else {
673                    handshake_PKT[3] = 0;
674                    unsigned int errcnt = (stat & BCH_INTS_ERRC_MASK) >> BCH_INTS_ERRC_BIT;
675                    switch (errcnt) {
676                    case 24:
677                        dprintf("correct 24th error\n");
678                        bch_correct(tmpbuf, (REG_BCH_ERR11 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
679                    case 23:
680                        bch_correct(tmpbuf, (REG_BCH_ERR11 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
681                    case 22:
682                        bch_correct(tmpbuf, (REG_BCH_ERR10 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
683                    case 21:
684                        bch_correct(tmpbuf, (REG_BCH_ERR10 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
685                    case 20:
686                        bch_correct(tmpbuf, (REG_BCH_ERR9 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
687                    case 19:
688                        bch_correct(tmpbuf, (REG_BCH_ERR9 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
689                    case 18:
690                        bch_correct(tmpbuf, (REG_BCH_ERR8 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
691                    case 17:
692                        bch_correct(tmpbuf, (REG_BCH_ERR8 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
693                    case 16:
694                        bch_correct(tmpbuf, (REG_BCH_ERR7 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
695                    case 15:
696                        bch_correct(tmpbuf, (REG_BCH_ERR7 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
697                    case 14:
698                        bch_correct(tmpbuf, (REG_BCH_ERR6 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
699                    case 13:
700                        bch_correct(tmpbuf, (REG_BCH_ERR6 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
701                    case 12:
702                        bch_correct(tmpbuf, (REG_BCH_ERR5 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
703                    case 11:
704                        bch_correct(tmpbuf, (REG_BCH_ERR5 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
705                    case 10:
706                        bch_correct(tmpbuf, (REG_BCH_ERR4 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
707                    case 9:
708                        bch_correct(tmpbuf, (REG_BCH_ERR4 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
709                    case 8:
710                        dprintf("correct 8th error\n");
711                        bch_correct(tmpbuf, (REG_BCH_ERR3 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
712                    case 7:
713                        dprintf("correct 7th error\n");
714                        bch_correct(tmpbuf, (REG_BCH_ERR3 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
715                    case 6:
716                        dprintf("correct 6th error\n");
717                        bch_correct(tmpbuf, (REG_BCH_ERR2 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
718                    case 5:
719                        dprintf("correct 5th error\n");
720                        bch_correct(tmpbuf, (REG_BCH_ERR2 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
721                    case 4:
722                        dprintf("correct 4th error\n");
723                        bch_correct(tmpbuf, (REG_BCH_ERR1 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
724                    case 3:
725                        dprintf("correct 3th error\n");
726                        bch_correct(tmpbuf, (REG_BCH_ERR1 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
727                    case 2:
728                        dprintf("correct 2th error\n");
729                        bch_correct(tmpbuf, (REG_BCH_ERR0 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
730                    case 1:
731                        dprintf("correct 1th error\n");
732                        bch_correct(tmpbuf, (REG_BCH_ERR0 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
733                    break;
734                    default:
735                        dprintf("no error\n");
736                        break;
737                    }
738                }
739            }
740            /* increment pointer */
741            tmpbuf += ECC_BLOCK;
742        }
743
744        switch (option)
745        {
746        case OOB_ECC:
747            for (j = 0; j < oobsize; j++)
748                tmpbuf[j] = oob_buf[j];
749            tmpbuf += oobsize;
750            break;
751        case OOB_NO_ECC:
752            for (j = 0; j < par_size1 * ecccnt; j++)
753                oob_buf[eccpos + j] = 0xff;
754            for (j = 0; j < oobsize; j++)
755                tmpbuf[j] = oob_buf[j];
756            tmpbuf += oobsize;
757            break;
758        case NO_OOB:
759            break;
760        }
761
762        cur_page++;
763        cnt++;
764    }
765
766    __nand_disable();
767
768    return cur_page;
769}
770
771int read_nand_spl_page(unsigned char *databuf, unsigned int pageaddr)
772{
773    unsigned int i, j;
774    unsigned int rowaddr, ecccnt;
775    u8 *tmpbuf;
776    char eccbuf[1024];
777
778    for(i=0; i<1024; i++)
779        eccbuf[i] = 0xff;
780
781    /* read oob first */
782    __nand_enable();
783
784    ecccnt = pagesize / ECC_BLOCK0;
785    __nand_cmd(CMD_READA);
786
787    __nand_addr(0);
788    if (pagesize != 512)
789        __nand_addr(0);
790
791    rowaddr = pageaddr+1; //??
792
793    for (i = 0; i < row; i++) {
794        __nand_addr(rowaddr & 0xff);
795        rowaddr >>= 8;
796    }
797
798    if (pagesize != 512)
799        __nand_cmd(CMD_CONFIRM);
800
801    __nand_sync();
802
803#ifdef USE_PN
804    pn_enable();
805#endif
806    /* Read ecc */
807    read_proc(eccbuf, pagesize/ECC_BLOCK0*PAR_SIZE_SPL1);
808
809#ifdef USE_PN
810    pn_disable();
811#endif
812
813    __nand_disable();
814
815    /* read data */
816    __nand_enable();
817
818    ecccnt = pagesize / ECC_BLOCK0;
819
820    __nand_cmd(CMD_READA);
821
822    __nand_addr(0);
823    if (pagesize != 512)
824        __nand_addr(0);
825
826    rowaddr = pageaddr;
827
828    for (i = 0; i < row; i++) {
829        __nand_addr(rowaddr & 0xff);
830        rowaddr >>= 8;
831    }
832
833    if (pagesize != 512)
834        __nand_cmd(CMD_CONFIRM);
835
836    __nand_sync();
837
838#ifdef USE_EFNAND
839    __nand_cmd(CMD_READ_STATUS);
840
841    if (__nand_data8() & 0x01) { /* page program error */
842        __nand_disable();
843
844        return 1;
845    }
846    __nand_cmd(CMD_READA);
847#endif
848
849    tmpbuf = (u8 *)databuf;
850    for(i=0; i<pagesize; i++)
851        tmpbuf[i] = 0xff;
852
853    for (i = 0; i < ecccnt; i++) {
854        unsigned int stat;
855
856#ifdef USE_PN
857        if (!(((pageaddr % 64) == 0) && (i == 0)))
858            pn_enable();
859        else
860            dprintf("don't use pn. pageaddr=%d ecccnt=%d\n", pageaddr,i);
861#endif
862        /* Read data */
863        read_proc((char *)tmpbuf, ECC_BLOCK0);
864#ifdef USE_PN
865        pn_disable();
866#endif
867
868#ifdef USE_BCH
869        REG_BCH_INTS = 0xffffffff;
870
871        __ecc_decoding_24bit();
872
873        __ecc_cnt_dec(2 * ECC_BLOCK0 + PAR_SIZE_SPL);
874
875        for (j = 0; j < ECC_BLOCK0; j++) {//if(i==1)serial_put_hex(tmpbuf[j]);
876            REG_BCH_DR = tmpbuf[j];
877        }
878
879                /* assume parities be wrote to data register not parity register */
880        for (j = 0; j < PAR_SIZE_SPL1; j++) {
881            REG_BCH_DR = eccbuf[i*PAR_SIZE_SPL1 + j];
882        }
883
884        /* Wait for completion */
885        __ecc_decode_sync();
886
887        __ecc_disable();
888
889        /* Check decoding */
890        stat = REG_BCH_INTS;
891
892        if (stat & BCH_INTS_ERR) {
893            if (stat & BCH_INTS_UNCOR) {
894                serial_puts("ecc Uncorrectable ECC error occurred __spl__\n");
895                serial_put_hex(i);
896            }
897            else {
898                unsigned int errcnt = (stat & BCH_INTS_ERRC_MASK) >> BCH_INTS_ERRC_BIT;
899                switch (errcnt) {
900                case 24:
901                    dprintf("correct 24th error\n");
902                    bch_correct(tmpbuf, (REG_BCH_ERR11 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
903                case 23:
904                    bch_correct(tmpbuf, (REG_BCH_ERR11 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
905                case 22:
906                    bch_correct(tmpbuf, (REG_BCH_ERR10 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
907                case 21:
908                    bch_correct(tmpbuf, (REG_BCH_ERR10 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
909                case 20:
910                    bch_correct(tmpbuf, (REG_BCH_ERR9 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
911                case 19:
912                    bch_correct(tmpbuf, (REG_BCH_ERR9 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
913                case 18:
914                    bch_correct(tmpbuf, (REG_BCH_ERR8 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
915                case 17:
916                    bch_correct(tmpbuf, (REG_BCH_ERR8 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
917                case 16:
918                    bch_correct(tmpbuf, (REG_BCH_ERR7 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
919                case 15:
920                    bch_correct(tmpbuf, (REG_BCH_ERR7 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
921                case 14:
922                    bch_correct(tmpbuf, (REG_BCH_ERR6 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
923                case 13:
924                    bch_correct(tmpbuf, (REG_BCH_ERR6 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
925                case 12:
926                    bch_correct(tmpbuf, (REG_BCH_ERR5 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
927                case 11:
928                    bch_correct(tmpbuf, (REG_BCH_ERR5 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
929                case 10:
930                    bch_correct(tmpbuf, (REG_BCH_ERR4 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
931                case 9:
932                    bch_correct(tmpbuf, (REG_BCH_ERR4 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
933                case 8:
934                    dprintf("correct 8th error\n");
935                    bch_correct(tmpbuf, (REG_BCH_ERR3 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
936                case 7:
937                    dprintf("correct 7th error\n");
938                    bch_correct(tmpbuf, (REG_BCH_ERR3 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
939                case 6:
940                    dprintf("correct 6th error\n");
941                    bch_correct(tmpbuf, (REG_BCH_ERR2 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
942                case 5:
943                    dprintf("correct 5th error\n");
944                    bch_correct(tmpbuf, (REG_BCH_ERR2 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
945                case 4:
946                    dprintf("correct 4th error\n");
947                    bch_correct(tmpbuf, (REG_BCH_ERR1 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
948                case 3:
949                    dprintf("correct 3th error\n");
950                    bch_correct(tmpbuf, (REG_BCH_ERR1 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
951                case 2:
952                    dprintf("correct 2th error\n");
953                    bch_correct(tmpbuf, (REG_BCH_ERR0 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
954                case 1:
955                    dprintf("correct 1th error\n");
956                    bch_correct(tmpbuf, (REG_BCH_ERR0 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
957                    break;
958                default:
959                    dprintf("no error\n");
960                    break;
961                }
962            }
963        }
964#endif
965        /* increment pointer */
966        tmpbuf += ECC_BLOCK0;
967    }
968
969    __nand_disable();
970
971    return 0;
972}
973
974u32 nand_program_4760(void *context, int spage, int pages, int option)
975{
976    u32 i, j, cur_page, cur_blk, rowaddr;
977    u8 *tmpbuf;
978    u32 ecccnt;
979    u8 ecc_buf[1024], oob_buf[512];
980    u32 oob_per_eccsize;
981    int spl_size = 8 * 1024 / pagesize;
982
983    if (wp_pin)
984        __gpio_set_pin(wp_pin);
985restart:
986    tmpbuf = (u8 *)context;
987    ecccnt = pagesize / ECC_BLOCK;
988    oob_per_eccsize = eccpos / ecccnt;
989
990    i = 0;
991    cur_page = spage;
992
993    while (i < pages) {
994        if (cur_page == 0) {
995            int k;
996            for(k = 0; k < spl_size; k++) {
997                program_nand_spl_page(context + pagesize * k, k * 2);
998            }
999#if 0
1000            for(k = 0; k < spl_size; k++) {
1001                program_nand_spl_page(context + pagesize * k, k * 2 + ppb );
1002            }
1003#endif
1004            tmpbuf += pagesize * spl_size;
1005            cur_page = 2 * ppb;
1006            i += spl_size;
1007            continue;
1008        }
1009
1010        if ((cur_page % ppb) == 0) { /* First page of block, test BAD. */
1011            if (nand_check_block(cur_page / ppb)) {
1012                cur_page += ppb; /* Bad block, set to next block */
1013                continue;
1014            }
1015        }
1016
1017        if ( option != NO_OOB ) //if NO_OOB do not perform vaild check!
1018        {
1019            for ( j = 0 ; j < pagesize + oobsize; j++)
1020            {
1021                if (tmpbuf[j] != 0xff)
1022                    break;
1023            }
1024            if ( j == oobsize + pagesize )
1025            {
1026                tmpbuf += (pagesize + oobsize) ;
1027                i ++;
1028                cur_page ++;
1029                continue;
1030            }
1031        }
1032
1033        __nand_enable();
1034        __nand_sync();
1035
1036        if (pagesize == 512)
1037            __nand_cmd(CMD_READA);
1038
1039        __nand_cmd(CMD_SEQIN);
1040        __nand_addr(0);
1041
1042        if (pagesize != 512)
1043            __nand_addr(0);
1044
1045        rowaddr = cur_page;
1046        for (j = 0; j < row; j++) {
1047            __nand_addr(rowaddr & 0xff);
1048            rowaddr >>= 8;
1049        }
1050
1051        /* write out data */
1052        for (j = 0; j < ecccnt; j++) {
1053            volatile u8 *paraddr;
1054            int k;
1055
1056            paraddr = (volatile u8 *)BCH_PAR0;
1057
1058            REG_BCH_INTS = 0xffffffff;
1059            if(bchbit == 4)
1060                __ecc_encoding_4bit();
1061            else if(bchbit == 8)
1062                __ecc_encoding_8bit();
1063            else if(bchbit == 12)
1064                __ecc_encoding_12bit();
1065            else if(bchbit == 16)
1066                __ecc_encoding_16bit();
1067            else if(bchbit == 20)
1068                __ecc_encoding_20bit();
1069            else
1070                __ecc_encoding_24bit();
1071
1072            /* Set BCHCNT.DEC_COUNT to data block size in bytes */
1073            if (option != NO_OOB)
1074                __ecc_cnt_enc((ECC_BLOCK + oob_per_eccsize) * 2);
1075            else
1076                __ecc_cnt_enc(ECC_BLOCK * 2);
1077
1078            /* Write data in data area to BCH */
1079            for (k = 0; k < ECC_BLOCK; k++) {
1080                REG_BCH_DR = tmpbuf[ECC_BLOCK * j + k];
1081            }
1082
1083            /* Write file system information in oob area to BCH */
1084            if (option != NO_OOB)
1085            {
1086                if(j == 0){
1087                    REG_BCH_DR = 0xff;
1088                    REG_BCH_DR = 0xff;
1089                    for(k = 2; k < oob_per_eccsize; k++)
1090                        REG_BCH_DR = tmpbuf[pagesize + k];
1091                } else {
1092                    for (k = 0; k < oob_per_eccsize; k++) {
1093                        REG_BCH_DR = tmpbuf[pagesize + oob_per_eccsize * j + k];
1094                    }
1095                }
1096            }
1097
1098            __ecc_encode_sync();
1099            __ecc_disable();
1100
1101            /* Read PAR values */
1102            for (k = 0; k < par_size1; k++) {
1103                ecc_buf[j * par_size1 + k] = *paraddr++;
1104            }
1105#ifdef USE_PN
1106// pn_enable();
1107#endif
1108            write_proc((char *)&tmpbuf[ECC_BLOCK * j], ECC_BLOCK);
1109#ifdef USE_PN
1110// pn_disable();
1111#endif
1112        }
1113
1114        for(j=0; j<oobsize; j++)
1115            oob_buf[j] = 0xff;
1116        switch (option)
1117        {
1118        case OOB_ECC:
1119        case OOB_NO_ECC:
1120            for (j = 2; j < eccpos; j++) {
1121                oob_buf[j] = tmpbuf[pagesize + j];
1122            }
1123            for (j = 0; j < ecccnt * par_size1; j++) {
1124                oob_buf[eccpos + j] = ecc_buf[j];
1125            }
1126            tmpbuf += pagesize + oobsize;
1127            break;
1128        case NO_OOB: //bin image
1129            for (j = 0; j < ecccnt * par_size1; j++) {
1130                oob_buf[eccpos + j] = ecc_buf[j];
1131            }
1132            tmpbuf += pagesize;
1133            break;
1134        }
1135
1136#ifdef USE_PN
1137// pn_enable();
1138#endif
1139        /* write out oob buffer */
1140        write_proc((u8 *)oob_buf, oobsize);
1141
1142#ifdef USE_PN
1143#ifndef USE_STATUS_PORT
1144// pn_disable();
1145#endif
1146#endif
1147        /* send program confirm command */
1148        __nand_cmd(CMD_PGPROG);
1149        __nand_sync();
1150
1151        __nand_cmd(CMD_READ_STATUS);
1152        __nand_sync();
1153
1154        if (__nand_data8() & 0x01) /* page program error */
1155        {
1156            serial_puts("Skip a write fail block\n");
1157            nand_erase_4760( 1, cur_page/ppb, 1); //force erase before
1158            nand_mark_bad_4760(cur_page/ppb);
1159            spage += ppb;
1160            goto restart;
1161        }
1162        __nand_disable();
1163
1164        i++;
1165        cur_page++;
1166    }
1167
1168    if (wp_pin)
1169        __gpio_clear_pin(wp_pin);
1170
1171    return cur_page;
1172}
1173
1174int program_nand_spl_page(unsigned char *databuf, unsigned int pageaddr)
1175{
1176    int i, j, ecccnt;
1177    char *tmpbuf;
1178    char ecc_buf[1024]; // need 39*16 bytes at least for 24bit BCH
1179    unsigned int rowaddr;
1180
1181    for(i=0; i<1024; i++)
1182        ecc_buf[i] = 0xff;
1183
1184    __nand_enable();
1185
1186    tmpbuf = (char *)databuf;
1187
1188    ecccnt = pagesize / ECC_BLOCK0;
1189
1190    if (pagesize == 512)
1191        __nand_cmd(CMD_READA);
1192
1193    __nand_cmd(CMD_SEQIN);
1194
1195    /* write out col addr */
1196    __nand_addr(0);
1197    if (pagesize != 512)
1198        __nand_addr(0);
1199
1200    rowaddr = pageaddr;
1201    /* write out row addr */
1202    for (i = 0; i < row; i++) {
1203        __nand_addr(rowaddr & 0xff);
1204        rowaddr >>= 8;
1205    }
1206
1207    /* write out data */
1208
1209    for (i = 0; i < ecccnt; i++) {
1210#ifdef USE_BCH
1211        volatile char *paraddr = (volatile char *)BCH_PAR0;
1212
1213        REG_BCH_INTS = 0xffffffff;
1214
1215        __ecc_encoding_24bit();
1216
1217                /* Set BCHCNT.DEC_COUNT to data block size in bytes */
1218        __ecc_cnt_enc(2 * ECC_BLOCK0);
1219
1220        for (j = 0; j < ECC_BLOCK0; j++) {
1221            REG_BCH_DR = tmpbuf[j];
1222        }
1223
1224        __ecc_encode_sync();
1225        __ecc_disable();
1226
1227        /* Read PAR values for 256 bytes from BCH_PARn to ecc_buf */
1228        for (j=0;j<PAR_SIZE_SPL1;j++) {
1229            ecc_buf[j + PAR_SIZE_SPL1 * i] = *paraddr++;
1230        }
1231#endif
1232#ifdef MAKE_ERROR
1233        char tmpbuf0[ECC_BLOCK0];
1234        u8 k, n_err;
1235        u16 err_bit;
1236
1237        memcpy(tmpbuf0, tmpbuf, ECC_BLOCK0);
1238        n_err = 1 + random() % 24; // 1 ~ 24
1239        dprintf("generate %d error bits.\n",n_err);
1240        /* generate n_err error bits */
1241        for(k = 0; k < n_err; k++) {
1242            err_bit = random() % (256*8);
1243            dprintf("err_bit=%04x in databuf[%03d]=0x%x \n",err_bit,err_bit / 8,tmpbuf0[(err_bit / 8)]);
1244            tmpbuf0[(err_bit / 8)] ^= 1 << (err_bit % 8);
1245            dprintf(" error databuf[%03d]= 0x%x \n",err_bit / 8,databuf[(err_bit / 8)]);
1246        }
1247#endif
1248
1249#ifdef USE_PN
1250        if (!(((pageaddr % 64) == 0) && (i == 0)))
1251            pn_enable();
1252        else
1253            dprintf("don't use pn. pageaddr=%d ecccnt=%d\n", pageaddr,i);
1254#endif
1255
1256                /* write ECC_BLOCK0 bytes to nand */
1257#ifdef MAKE_ERROR
1258        write_proc((char *)tmpbuf0, ECC_BLOCK0);
1259#else
1260        write_proc((char *)tmpbuf, ECC_BLOCK0);
1261#endif
1262
1263#ifdef USE_PN
1264#ifndef USE_STATUS_PORT
1265        pn_disable();
1266#endif
1267#endif
1268        tmpbuf += ECC_BLOCK0;
1269    }
1270
1271    /* send program confirm command */
1272    __nand_cmd(CMD_PGPROG);
1273    dprintf("%s %d \n", __FUNCTION__, __LINE__);
1274    __nand_sync();
1275    dprintf("%s %d \n", __FUNCTION__, __LINE__);
1276
1277#if 1
1278    __nand_cmd(CMD_READ_STATUS);
1279    dprintf("%s %d \n", __FUNCTION__, __LINE__);
1280    u8 status;
1281#ifdef USE_STATUS_PORT
1282    status = __nand_status();
1283#else
1284    status = __nand_data8();
1285#endif
1286    if (status & 0x01) {
1287        __nand_disable();
1288        return 1;
1289    }
1290    else {
1291        __nand_disable();
1292    }
1293    dprintf("%s %d \n", __FUNCTION__, __LINE__);
1294    /* -----program ecc----- */
1295    __nand_enable();
1296#endif
1297    if (pagesize == 512)
1298        __nand_cmd(CMD_READA);
1299
1300    __nand_cmd(CMD_SEQIN);
1301
1302    /* write out col addr */
1303    __nand_addr(0);
1304    if (pagesize != 512)
1305        __nand_addr(0);
1306
1307    rowaddr = pageaddr + 1;
1308    /* write out row addr */
1309    for (i = 0; i < row; i++) {
1310        __nand_addr(rowaddr & 0xff);
1311        rowaddr >>= 8;
1312    }
1313
1314#ifdef USE_PN
1315#ifdef PN_ADD_DELAY
1316    udelay(1000);
1317    dprintf("delay should be add for pn.\n");
1318#endif
1319#endif
1320
1321#ifdef USE_PN
1322    pn_enable();
1323#endif
1324    dprintf("%s %d \n", __FUNCTION__, __LINE__);
1325    write_proc(ecc_buf, pagesize/ECC_BLOCK0*PAR_SIZE_SPL1);
1326
1327#ifdef USE_PN
1328    pn_disable();
1329#endif
1330
1331    /* send program confirm command */
1332    __nand_cmd(CMD_PGPROG);
1333    dprintf("%s %d \n", __FUNCTION__, __LINE__);
1334    __nand_sync();
1335    dprintf("%s %d \n", __FUNCTION__, __LINE__);
1336    __nand_cmd(CMD_READ_STATUS);
1337
1338    if (__nand_data8() & 0x01) { /* page program error */
1339        __nand_disable();
1340        return 1;
1341    }
1342    else {
1343        __nand_disable();
1344        return 0;
1345    }
1346}
1347
1348// be careful
1349static u32 nand_mark_bad_page(u32 page)
1350{
1351#if 1
1352    u8 badbuf[4096 + 128];
1353    u32 i;
1354
1355    if (wp_pin)
1356        __gpio_set_pin(wp_pin);
1357    for (i = 0; i < pagesize + oobsize; i++)
1358        badbuf[i] = 0x00;
1359    //all set to 0x00
1360
1361    __nand_cmd(CMD_READA);
1362    __nand_cmd(CMD_SEQIN);
1363
1364    __nand_addr(0);
1365    if (pagesize != 512)
1366        __nand_addr(0);
1367    for (i = 0; i < row; i++) {
1368        __nand_addr(page & 0xff);
1369        page >>= 8;
1370    }
1371
1372    write_proc((char *)badbuf, pagesize + oobsize);
1373    __nand_cmd(CMD_PGPROG);
1374    __nand_sync();
1375
1376    if (wp_pin)
1377        __gpio_clear_pin(wp_pin);
1378    return page;
1379#endif
1380}
1381
1382u32 nand_mark_bad_4760(int block)
1383{
1384    u32 rowaddr;
1385
1386    if ( bad_block_page >= ppb ) //absolute bad block mark!
1387    { //mark four page!
1388        rowaddr = block * ppb + 0;
1389        nand_mark_bad_page(rowaddr);
1390
1391        rowaddr = block * ppb + 1;
1392        nand_mark_bad_page(rowaddr);
1393
1394        rowaddr = block * ppb + ppb - 2;
1395        nand_mark_bad_page(rowaddr);
1396
1397        rowaddr = block * ppb + ppb - 1;
1398        nand_mark_bad_page(rowaddr);
1399    }
1400    else //mark one page only
1401    {
1402        rowaddr = block * ppb + bad_block_page;
1403        nand_mark_bad_page(rowaddr);
1404    }
1405
1406    return rowaddr;
1407}
1408
1409static int nand_data_write8(char *buf, int count)
1410{
1411    int i;
1412    u8 *p = (u8 *)buf;
1413    for (i=0;i<count;i++)
1414        __nand_data8() = *p++;
1415    return 0;
1416}
1417
1418static int nand_data_write16(char *buf, int count)
1419{
1420    int i;
1421    u16 *p = (u16 *)buf;
1422    for (i=0;i<count/2;i++)
1423        __nand_data16() = *p++;
1424    return 0;
1425}
1426
1427static int nand_data_read8(char *buf, int count)
1428{
1429    int i;
1430    u8 *p = (u8 *)buf;
1431    for (i=0;i<count;i++)
1432        *p++ = __nand_data8();
1433    return 0;
1434}
1435
1436static int nand_data_read16(char *buf, int count)
1437{
1438    int i;
1439    u16 *p = (u16 *)buf;
1440    for (i=0;i<count/2;i++)
1441        *p++ = __nand_data16();
1442    return 0;
1443}
usbboot/xburst_stage2/udc.c
1616 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
1717 * Boston, MA 02110-1301, USA
1818 */
19#include "target/jz4740.h"
2019#include "usb/usb.h"
2120#include "usb/udc.h"
2221#include "target/usb_boot.h"
22#include "target/xburst_types.h"
2323
24#define dprintf(x...)
24#if defined(NANONOTE)
25#include "target/jz4740.h"
26#elif defined(LEPUS)
27#include "target/jz4760.h"
28#else
29    #error "Please Define JZ4740 or JZ4760"
30#endif
31
32#define dprintf(x...) serial_puts(x)
2533#define TXFIFOEP0 USB_FIFO_EP0
2634
27u32 Bulk_buf[BULK_BUF_SIZE];
35extern void serial_put_hex(int );
36
37u32 Bulk_in_buf[BULK_IN_BUF_SIZE];
38u32 Bulk_out_buf[BULK_OUT_BUF_SIZE];
2839u32 Bulk_in_size, Bulk_in_finish, Bulk_out_size;
2940u16 handshake_PKT[4] = {0, 0, 0, 0};
3041u8 udc_state;
...... 
512523    }
513524
514525    if (Bulk_in_size - Bulk_in_finish <= fifosize[EP]) {
515        udcWriteFifo((u8 *)((u32)Bulk_buf+Bulk_in_finish),
526        udcWriteFifo((u8 *)((u32)Bulk_in_buf+Bulk_in_finish),
516527                 Bulk_in_size - Bulk_in_finish);
517528        usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY);
518529        Bulk_in_finish = Bulk_in_size;
519530    } else {
520        udcWriteFifo((u8 *)((u32)Bulk_buf+Bulk_in_finish),
531        udcWriteFifo((u8 *)((u32)Bulk_in_buf+Bulk_in_finish),
521532                fifosize[EP]);
522533        usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY);
523534        Bulk_in_finish += fifosize[EP];
...... 
530541    jz_writeb(USB_REG_INDEX, EP);
531542    size = jz_readw(USB_REG_OUTCOUNT);
532543    fifo = fifoaddr[EP];
533    udcReadFifo((u8 *)((u32)Bulk_buf+Bulk_out_size), size);
544    udcReadFifo((u8 *)((u32)Bulk_out_buf+Bulk_out_size), size);
534545    usb_clearb(USB_REG_OUTCSR,USB_OUTCSR_OUTPKTRDY);
535546    Bulk_out_size += size;
536547    dprintf("\nEPOUT_handle return!");
...... 
541552    volatile u8 IntrUSB;
542553    volatile u16 IntrIn;
543554    volatile u16 IntrOut;
544/* Read interrupt registers */
555    /* Read interrupt registers */
545556    IntrUSB = jz_readb(USB_REG_INTRUSB);
546557    IntrIn = jz_readw(USB_REG_INTRIN);
547558    IntrOut = jz_readw(USB_REG_INTROUT);
...... 
564575        udc_reset();
565576    }
566577
567/* Check for endpoint 0 interrupt */
578    /* Check for endpoint 0 interrupt */
568579    if (IntrIn & USB_INTR_EP0) {
569580        dprintf("\nUDC EP0 operations!");
570581        EP0_Handler();

Archive Download the corresponding diff file



interactive