Root/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 "target/xburst_types.h"
25#include "usb_boot_defines.h"
26
27#define USE_BCH 1
28#define USE_PN 1
29#define NEMC_PNCR (NEMC_BASE + 0x100)
30#define NEMC_PNDR (NEMC_BASE + 0x104)
31#define REG_NEMC_PNCR REG32(NEMC_PNCR)
32#define REG_NEMC_PNDR REG32(NEMC_PNDR)
33
34#define pn_enable() \
35    do {\
36        REG_NEMC_PNCR = 0x3;\
37    }while(0)
38#define pn_disable() \
39    do {\
40        REG_NEMC_PNCR = 0x0;\
41    }while(0)
42
43#ifdef DEBUG
44#define dprintf(n...) printf(n)
45#else
46#define dprintf(n...)
47#endif
48
49/* for spl */
50#define ECC_BLOCK0 256
51#define PAR_SIZE_SPL 78
52#define PAR_SIZE_SPL1 ((PAR_SIZE_SPL+1)/2)
53
54/*
55 * NAND flash definitions
56 */
57#define NAND_DATAPORT 0xBA000000
58#define NAND_ADDRPORT 0xBA800000
59#define NAND_COMMPORT 0xBA400000
60
61#define ECC_BLOCK 512
62static int par_size, par_size1;
63
64#define CMD_READA 0x00
65#define CMD_READB 0x01
66#define CMD_READC 0x50
67#define CMD_ERASE_SETUP 0x60
68#define CMD_ERASE 0xD0
69#define CMD_READ_STATUS 0x70
70#define CMD_CONFIRM 0x30
71#define CMD_SEQIN 0x80
72#define CMD_PGPROG 0x10
73#define CMD_READID 0x90
74
75#define __nand_cmd(n) (REG8(NAND_COMMPORT) = (n))
76#define __nand_addr(n) (REG8(NAND_ADDRPORT) = (n))
77#define __nand_data8() REG8(NAND_DATAPORT)
78#define __nand_data16() REG16(NAND_DATAPORT)
79
80#define __nand_enable() (REG_NEMC_NFCSR |= NEMC_NFCSR_NFE1 | NEMC_NFCSR_NFCE1)
81#define __nand_disable() (REG_NEMC_NFCSR &= ~(NEMC_NFCSR_NFCE1))
82
83static int bus = 8, row = 2, pagesize = 512, oobsize = 16, ppb = 32;
84static int eccpos = 3, bchbit = 8, par_size = 26, par_size1 = 13, forceerase = 1, wp_pin = 0;
85static int oobfs = 0; /* 1:store file system information in oob, 0:don't store */
86static int oobecc = 0; /* Whether the oob data of the binary contains ECC data? */
87static int bad_block_page = 127; /* Specify the page number of badblock flag inside a block */
88static u32 bad_block_pos = 0; /* Specify the badblock flag offset inside the oob */
89static u8 oob_buf[256] = {0};
90extern struct hand Hand;
91extern u16 handshake_PKT[4];
92
93static inline void __nand_sync(void)
94{
95    unsigned int timeout = 1000;
96    while ((REG_GPIO_PXPIN(0) & 0x00100000) && timeout--);
97    while (!(REG_GPIO_PXPIN(0) & 0x00100000));
98}
99
100/*
101 * External routines
102 */
103extern void flush_cache_all(void);
104extern int serial_init(void);
105extern void serial_puts(const char *s);
106extern void sdram_init(void);
107extern void pll_init(void);
108
109static int read_oob(void *buf, u32 size, u32 pg);
110static int nand_data_write8(char *buf, int count);
111static int nand_data_write16(char *buf, int count);
112static int nand_data_read8(char *buf, int count);
113static int nand_data_read16(char *buf, int count);
114
115static int (*write_proc)(char *, int) = NULL;
116static int (*read_proc)(char *, int) = NULL;
117
118int read_nand_spl_page(unsigned char *databuf, unsigned int pageaddr);
119int program_nand_spl_page(unsigned char *databuf, unsigned int pageaddr);
120
121/*
122 * NAND flash routines
123 */
124
125static inline void nand_read_buf16(void *buf, int count)
126{
127    int i;
128    u16 *p = (u16 *)buf;
129
130    for (i = 0; i < count; i += 2)
131        *p++ = __nand_data16();
132}
133
134static inline void nand_read_buf8(void *buf, int count)
135{
136    int i;
137    u8 *p = (u8 *)buf;
138
139    for (i = 0; i < count; i++)
140        *p++ = __nand_data8();
141}
142
143static inline void nand_read_buf(void *buf, int count, int bw)
144{
145    if (bw == 8)
146        nand_read_buf8(buf, count);
147    else
148        nand_read_buf16(buf, count);
149}
150
151inline void nand_enable_4760(unsigned int csn)
152{
153    //modify this fun to a specifical borad
154    //this fun to enable the chip select pin csn
155    //the choosn chip can work after this fun
156    //dprintf("\n Enable chip select :%d",csn);
157    __gpio_as_nand_8bit(1);
158    __nand_enable();
159}
160
161inline void nand_disable_4760(unsigned int csn)
162{
163    //modify this fun to a specifical borad
164    //this fun to enable the chip select pin csn
165    //the choosn chip can not work after this fun
166    //dprintf("\n Disable chip select :%d",csn);
167    __nand_disable();
168}
169
170void udelay(unsigned long usec)
171{
172    volatile int i, j;
173
174    for (i = 0; i < usec; i++) {
175        for (j = 0; j < 100; j++) {
176            ;
177        }
178    }
179}
180
181unsigned int nand_query_4760(u8 *id)
182{
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    udelay(1000);
192#if 1
193    id[0] = __nand_data8(); //VID
194    id[1] = __nand_data8(); //PID
195    id[2] = __nand_data8(); //CHIP ID
196    id[3] = __nand_data8(); //PAGE ID
197    id[4] = __nand_data8(); //PLANE ID
198
199    serial_put_hex(id[0]);
200    serial_put_hex(id[1]);
201    serial_put_hex(id[2]);
202    serial_put_hex(id[3]);
203    serial_put_hex(id[4]);
204    
205#endif
206
207    __nand_disable();
208    return 0;
209}
210
211int nand_init_4760(int bus_width, int row_cycle, int page_size, int page_per_block,
212           int bch_bit, int ecc_pos, int bad_pos, int bad_page, int force)
213{
214    bus = bus_width;
215    row = row_cycle;
216    pagesize = page_size;
217    oobsize = pagesize / 32;
218    ppb = page_per_block;
219    bchbit = bch_bit;
220    forceerase = force;
221    eccpos = ecc_pos;
222    bad_block_pos = bad_pos;
223    bad_block_page = bad_page;
224    wp_pin = Hand.nand_wppin;
225
226    if(bchbit == 4)
227        par_size = 13;
228    else if(bchbit == 8)
229        par_size = 26;
230    else if(bchbit == 12)
231        par_size =39;
232    else if(bchbit == 16)
233        par_size =52;
234    else if(bchbit == 20)
235        par_size = 65;
236    else
237        par_size ==78;
238
239    par_size1 = (par_size + 1)/2;
240
241    /* Initialize NAND Flash Pins */
242    if (bus == 8) {
243        REG_NEMC_SMCR1 = 0x0d444400;
244        __gpio_as_nand_8bit(1);
245        write_proc = nand_data_write8;
246        read_proc = nand_data_read8;
247    } else {
248        REG_NEMC_SMCR1 = 0x0d444400 | 0x40;
249        __gpio_as_nand_16bit(1);
250        write_proc = nand_data_write16;
251        read_proc = nand_data_read16;
252    }
253
254    if (wp_pin)
255    {
256        __gpio_as_output(wp_pin);
257        __gpio_disable_pull(wp_pin);
258    }
259    __nand_enable();
260
261       /* If ECCPOS isn't configured in config file, the initial value is 0 */
262     if (eccpos == 0) {
263        eccpos = 3;
264    }
265
266#ifdef USE_BCH
267    serial_puts("Use bch.\n");
268#else
269    serial_puts("Not use bch.\n");
270#endif
271#ifdef USE_PN
272    serial_puts("Use PN.\n");
273#else
274    serial_puts("Not use PN.\n");
275#endif
276    return 0;
277}
278
279/*
280 * Correct the error bit in ECC_BLOCK bytes data
281 */
282static void bch_correct(unsigned char *dat, int idx)
283{
284    int i, bit; // the 'bit' of i byte is error
285    i = (idx - 1) >> 3;
286    bit = (idx - 1) & 0x7;
287    if (i < ECC_BLOCK)
288        dat[i] ^= (1 << bit);
289}
290
291u32 nand_read_oob_4760(void *buf, u32 startpage, u32 pagenum)
292{
293    u32 cnt, cur_page;
294    u8 *tmpbuf;
295
296    tmpbuf = (u8 *)buf;
297
298    cur_page = startpage;
299    cnt = 0;
300
301    while (cnt < pagenum) {
302        read_oob((void *)tmpbuf, oobsize, cur_page);
303        tmpbuf += oobsize;
304        cur_page++;
305        cnt++;
306    }
307
308    return cur_page;
309}
310
311static int nand_check_block(u32 block)
312{
313    u32 pg,i;
314    
315    if ( bad_block_page >= ppb ) //do absolute bad block detect!
316    {
317        pg = block * ppb + 0;
318        read_oob(oob_buf, oobsize, pg);
319        if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
320        {
321            serial_puts("Absolute skip a bad block\n");
322            serial_put_hex(block);
323            return 1;
324        }
325
326        pg = block * ppb + 1;
327        read_oob(oob_buf, oobsize, pg);
328        if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
329        {
330            serial_puts("Absolute skip a bad block\n");
331            serial_put_hex(block);
332            return 1;
333        }
334
335        pg = block * ppb + ppb - 2 ;
336        read_oob(oob_buf, oobsize, pg);
337        if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
338        {
339            serial_puts("Absolute skip a bad block\n");
340            serial_put_hex(block);
341            return 1;
342        }
343
344        pg = block * ppb + ppb - 1 ;
345        read_oob(oob_buf, oobsize, pg);
346        if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
347        {
348            serial_puts("Absolute skip a bad block\n");
349            serial_put_hex(block);
350            return 1;
351        }
352
353    }
354    else
355    {
356        pg = block * ppb + bad_block_page;
357        read_oob(oob_buf, oobsize, pg);
358        if (oob_buf[bad_block_pos] != 0xff)
359        {
360            serial_put_hex(oob_buf[bad_block_pos]);
361            serial_puts("Skip a bad block at:\n");
362            serial_put_hex(block);
363
364            return 1;
365        }
366
367    }
368    return 0;
369}
370
371u32 nand_erase_4760(int blk_num, int sblk, int force)
372{
373    int i, j;
374    u32 cur, rowaddr;
375
376    __nand_enable();
377
378    if (wp_pin)
379        __gpio_set_pin(wp_pin);
380    cur = sblk * ppb;
381    for (i = 0; i < blk_num; i++) {
382        rowaddr = cur;
383
384        if (!force) /* if set, erase anything */
385            if (nand_check_block(cur/ppb))
386            {
387                cur += ppb;
388                blk_num += Hand.nand_plane;
389                continue;
390            }
391        
392        __nand_cmd(CMD_ERASE_SETUP);
393
394        for (j = 0; j < row; j++) {
395            __nand_addr(rowaddr & 0xff);
396            rowaddr >>= 8;
397        }
398        __nand_cmd(CMD_ERASE);
399        __nand_sync();
400        __nand_cmd(CMD_READ_STATUS);
401
402        if (__nand_data8() & 0x01)
403        {
404            serial_puts("Erase fail at ");
405            serial_put_hex(cur / ppb);
406            nand_mark_bad_4760(cur / ppb);
407            cur += ppb;
408            blk_num += Hand.nand_plane;
409            continue;
410        }
411        cur += ppb;
412    }
413
414    if (wp_pin)
415        __gpio_clear_pin(wp_pin);
416
417    __nand_disable();
418    return cur;
419}
420
421/*
422 * Read oob
423 */
424static int read_oob(void *buf, unsigned int size, unsigned int pg)
425{
426    unsigned int i, coladdr, rowaddr;
427
428    __nand_enable();
429
430    if (pagesize == 512)
431        coladdr = 0;
432    else {
433        if (bus == 8)
434            coladdr = pagesize;
435        else
436            coladdr = pagesize / 2;
437    }
438
439    if (pagesize == 512)
440        /* Send READOOB command */
441        __nand_cmd(CMD_READC);
442    else
443        /* Send READ0 command */
444        __nand_cmd(CMD_READA);
445
446    /* Send column address */
447    __nand_addr(coladdr & 0xff);
448    if (pagesize != 512)
449        __nand_addr(coladdr >> 8);
450
451    /* Send page address */
452    rowaddr = pg;
453    for (i = 0; i < row; i++) {
454        __nand_addr(rowaddr & 0xff);
455        rowaddr >>= 8;
456    }
457
458    /* Send READSTART command for 2048 ps NAND */
459    if (pagesize != 512)
460        __nand_cmd(CMD_CONFIRM);
461
462    /* Wait for device ready */
463    __nand_sync();
464
465    /* Read oob data */
466    read_proc(buf, size);
467
468    if (pagesize == 512)
469        __nand_sync();
470
471    __nand_disable();
472    return 0;
473}
474
475/*
476 * Read data <pagenum> pages from <startpage> page.
477 * Don't skip bad block.
478 * Don't use HW ECC.
479 */
480u32 nand_read_raw_4760(void *buf, u32 startpage, u32 pagenum, int option)
481{
482    u32 cnt, j;
483    u32 cur_page, rowaddr;
484    u8 *tmpbuf;
485
486    tmpbuf = (u8 *)buf;
487
488    cur_page = startpage;
489    cnt = 0;
490    while (cnt < pagenum) {
491        if ((cur_page % ppb) == 0) {
492            if (nand_check_block(cur_page / ppb)) {
493                cur_page += ppb; // Bad block, set to next block
494                continue;
495            }
496        }
497
498        __nand_cmd(CMD_READA);
499        __nand_addr(0);
500        if (pagesize != 512)
501            __nand_addr(0);
502
503        rowaddr = cur_page;
504        for (j = 0; j < row; j++) {
505            __nand_addr(rowaddr & 0xff);
506            rowaddr >>= 8;
507        }
508
509        if (pagesize != 512)
510            __nand_cmd(CMD_CONFIRM);
511
512        __nand_sync();
513#ifdef USE_PN
514    pn_enable();
515#endif
516
517        read_proc(tmpbuf, pagesize);
518
519        tmpbuf += pagesize;
520        if (option != NO_OOB)
521        {
522            read_oob(tmpbuf, oobsize, cur_page);
523            tmpbuf += oobsize;
524        }
525#ifdef USE_PN
526        pn_disable();
527#endif
528        cur_page++;
529        cnt++;
530    }
531
532    return cur_page;
533}
534
535#ifndef CFG_NAND_BADBLOCK_PAGE
536#define CFG_NAND_BADBLOCK_PAGE 0 /* NAND bad block was marked at this page in a block, starting from 0 */
537#endif
538
539/*
540 * Read data <pagenum> pages from <startpage> page.
541 * Skip bad block if detected.
542 * HW ECC is used.
543 */
544u32 nand_read_4760(void *buf, u32 startpage, u32 pagenum, int option)
545{
546    u32 j, k;
547    u32 cur_page, cur_blk, cnt, rowaddr, ecccnt;
548    u8 *tmpbuf, *p, flag = 0;
549    u32 oob_per_eccsize;
550    u32 spl_size = 8 * 1024 / pagesize;
551    ecccnt = pagesize / ECC_BLOCK;
552    oob_per_eccsize = eccpos / ecccnt;
553
554    cur_page = startpage;
555    cnt = 0;
556
557    if(startpage >= 0 && startpage < spl_size * 2)
558        tmpbuf = buf + 8 * 1024;
559    else
560        tmpbuf = buf;
561
562    __nand_enable();
563    while (cnt < pagenum) {
564        if (cur_page < spl_size * 2) {
565            u32 m;
566            for (m=0; (m < pagenum) && (m < spl_size); m++)
567                read_nand_spl_page(buf + pagesize * m, m * 2);
568            
569            cur_page = ppb * 2;
570            cnt = spl_size;
571            continue;
572        }
573
574        /* If this is the first page of the block, check for bad. */
575        if ((cur_page % ppb) == 0) {
576            cur_blk = cur_page / ppb;
577            if (nand_check_block(cur_blk)) {
578                cur_page += ppb; // Bad block, set to next block
579                continue;
580            }
581        }
582        __nand_cmd(CMD_READA);
583
584        __nand_addr(0);
585        if (pagesize != 512)
586            __nand_addr(0);
587
588        rowaddr = cur_page;
589        for (j = 0; j < row; j++) {
590            __nand_addr(rowaddr & 0xff);
591            rowaddr >>= 8;
592        }
593
594        if (pagesize != 512)
595            __nand_cmd(CMD_CONFIRM);
596
597        __nand_sync();
598
599#ifdef USE_PN
600// pn_enable();
601#endif
602        /* Read data */
603        read_proc((char *)tmpbuf, pagesize);
604
605        /* read oob first */
606        read_proc((char *)oob_buf, oobsize);
607#ifdef USE_PN
608// pn_disable();
609#endif
610
611        for (j = 0; j < ecccnt; j++) {
612            u32 stat;
613            flag = 0;
614            REG_BCH_INTS = 0xffffffff;
615
616            if (cur_page >= 16384 / pagesize)
617            {
618                if(bchbit == 4)
619                    __ecc_decoding_4bit();
620                else if(bchbit == 8)
621                    __ecc_decoding_8bit();
622                else if(bchbit == 12)
623                    __ecc_decoding_12bit();
624                else if(bchbit == 16)
625                    __ecc_decoding_16bit();
626                else if(bchbit == 20)
627                    __ecc_decoding_20bit();
628                else
629                    __ecc_decoding_24bit();
630            }
631            else
632            {
633                __ecc_decoding_24bit();
634            }
635
636            if (option != NO_OOB)
637                __ecc_cnt_dec(ECC_BLOCK*2 + oob_per_eccsize*2 + par_size);
638            else
639                __ecc_cnt_dec(ECC_BLOCK*2 + par_size);
640
641            for (k = 0; k < ECC_BLOCK; k++) {
642                REG_BCH_DR = tmpbuf[k];
643            }
644            
645            if (option != NO_OOB) {
646                for (k = 0; k < oob_per_eccsize; k++) {
647                    REG_BCH_DR = oob_buf[oob_per_eccsize * j + k];
648                }
649            }
650
651            for (k = 0; k < par_size1; k++) {
652                REG_BCH_DR = oob_buf[eccpos + j * par_size1 + k];
653                if (oob_buf[eccpos + j * par_size1 + k] != 0xff) //why?
654                    flag = 1;
655            }
656
657            /* Wait for completion */
658            __ecc_decode_sync();
659            __ecc_disable();
660            /* Check decoding */
661            stat = REG_BCH_INTS;
662        
663            if (stat & BCH_INTS_ERR) {
664                if (stat & BCH_INTS_UNCOR) {
665                    if (flag)
666                    {
667                        dprintf("Uncorrectable ECC error occurred\n");
668                        handshake_PKT[3] = 1;
669                    }
670                }
671                else {
672                    handshake_PKT[3] = 0;
673                    unsigned int errcnt = (stat & BCH_INTS_ERRC_MASK) >> BCH_INTS_ERRC_BIT;
674                    switch (errcnt) {
675                    case 24:
676                        dprintf("correct 24th error\n");
677                        bch_correct(tmpbuf, (REG_BCH_ERR11 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
678                    case 23:
679                        bch_correct(tmpbuf, (REG_BCH_ERR11 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
680                    case 22:
681                        bch_correct(tmpbuf, (REG_BCH_ERR10 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
682                    case 21:
683                        bch_correct(tmpbuf, (REG_BCH_ERR10 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
684                    case 20:
685                        bch_correct(tmpbuf, (REG_BCH_ERR9 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
686                    case 19:
687                        bch_correct(tmpbuf, (REG_BCH_ERR9 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
688                    case 18:
689                        bch_correct(tmpbuf, (REG_BCH_ERR8 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
690                    case 17:
691                        bch_correct(tmpbuf, (REG_BCH_ERR8 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
692                    case 16:
693                        bch_correct(tmpbuf, (REG_BCH_ERR7 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
694                    case 15:
695                        bch_correct(tmpbuf, (REG_BCH_ERR7 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
696                    case 14:
697                        bch_correct(tmpbuf, (REG_BCH_ERR6 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
698                    case 13:
699                        bch_correct(tmpbuf, (REG_BCH_ERR6 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
700                    case 12:
701                        bch_correct(tmpbuf, (REG_BCH_ERR5 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
702                    case 11:
703                        bch_correct(tmpbuf, (REG_BCH_ERR5 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
704                    case 10:
705                        bch_correct(tmpbuf, (REG_BCH_ERR4 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
706                    case 9:
707                        bch_correct(tmpbuf, (REG_BCH_ERR4 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
708                    case 8:
709                        dprintf("correct 8th error\n");
710                        bch_correct(tmpbuf, (REG_BCH_ERR3 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
711                    case 7:
712                        dprintf("correct 7th error\n");
713                        bch_correct(tmpbuf, (REG_BCH_ERR3 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
714                    case 6:
715                        dprintf("correct 6th error\n");
716                        bch_correct(tmpbuf, (REG_BCH_ERR2 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
717                    case 5:
718                        dprintf("correct 5th error\n");
719                        bch_correct(tmpbuf, (REG_BCH_ERR2 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
720                    case 4:
721                        dprintf("correct 4th error\n");
722                        bch_correct(tmpbuf, (REG_BCH_ERR1 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
723                    case 3:
724                        dprintf("correct 3th error\n");
725                        bch_correct(tmpbuf, (REG_BCH_ERR1 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
726                    case 2:
727                        dprintf("correct 2th error\n");
728                        bch_correct(tmpbuf, (REG_BCH_ERR0 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
729                    case 1:
730                        dprintf("correct 1th error\n");
731                        bch_correct(tmpbuf, (REG_BCH_ERR0 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
732                    break;
733                    default:
734                        dprintf("no error\n");
735                        break;
736                    }
737                }
738            }
739            /* increment pointer */
740            tmpbuf += ECC_BLOCK;
741        }
742
743        switch (option)
744        {
745        case OOB_ECC:
746            for (j = 0; j < oobsize; j++)
747                tmpbuf[j] = oob_buf[j];
748            tmpbuf += oobsize;
749            break;
750        case OOB_NO_ECC:
751            for (j = 0; j < par_size1 * ecccnt; j++)
752                oob_buf[eccpos + j] = 0xff;
753            for (j = 0; j < oobsize; j++)
754                tmpbuf[j] = oob_buf[j];
755            tmpbuf += oobsize;
756            break;
757        case NO_OOB:
758            break;
759        }
760
761        cur_page++;
762        cnt++;
763    }
764
765    __nand_disable();
766
767    return cur_page;
768}
769
770int read_nand_spl_page(unsigned char *databuf, unsigned int pageaddr)
771{
772    unsigned int i, j;
773    unsigned int rowaddr, ecccnt;
774    u8 *tmpbuf;
775    char eccbuf[1024];
776
777    for(i=0; i<1024; i++)
778        eccbuf[i] = 0xff;
779
780    /* read oob first */
781    __nand_enable();
782
783    ecccnt = pagesize / ECC_BLOCK0;
784    __nand_cmd(CMD_READA);
785
786    __nand_addr(0);
787    if (pagesize != 512)
788        __nand_addr(0);
789
790    rowaddr = pageaddr+1; //??
791
792    for (i = 0; i < row; i++) {
793        __nand_addr(rowaddr & 0xff);
794        rowaddr >>= 8;
795    }
796
797    if (pagesize != 512)
798        __nand_cmd(CMD_CONFIRM);
799
800    __nand_sync();
801
802#ifdef USE_PN
803    pn_enable();
804#endif
805    /* Read ecc */
806    read_proc(eccbuf, pagesize/ECC_BLOCK0*PAR_SIZE_SPL1);
807
808#ifdef USE_PN
809    pn_disable();
810#endif
811
812    __nand_disable();
813
814    /* read data */
815    __nand_enable();
816
817    ecccnt = pagesize / ECC_BLOCK0;
818    
819    __nand_cmd(CMD_READA);
820
821    __nand_addr(0);
822    if (pagesize != 512)
823        __nand_addr(0);
824
825    rowaddr = pageaddr;
826
827    for (i = 0; i < row; i++) {
828        __nand_addr(rowaddr & 0xff);
829        rowaddr >>= 8;
830    }
831
832    if (pagesize != 512)
833        __nand_cmd(CMD_CONFIRM);
834
835    __nand_sync();
836
837#ifdef USE_EFNAND
838    __nand_cmd(CMD_READ_STATUS);
839    
840    if (__nand_data8() & 0x01) { /* page program error */
841        __nand_disable();
842
843        return 1;
844    }
845    __nand_cmd(CMD_READA);
846#endif
847
848    tmpbuf = (u8 *)databuf;
849    for(i=0; i<pagesize; i++)
850        tmpbuf[i] = 0xff;
851
852    for (i = 0; i < ecccnt; i++) {
853        unsigned int stat;
854    
855#ifdef USE_PN
856        if (!(((pageaddr % 64) == 0) && (i == 0)))
857            pn_enable();
858        else
859            dprintf("don't use pn. pageaddr=%d ecccnt=%d\n", pageaddr,i);
860#endif
861        /* Read data */
862        read_proc((char *)tmpbuf, ECC_BLOCK0);
863#ifdef USE_PN
864        pn_disable();
865#endif
866
867#ifdef USE_BCH
868        REG_BCH_INTS = 0xffffffff;
869
870        __ecc_decoding_24bit();
871
872        __ecc_cnt_dec(2 * ECC_BLOCK0 + PAR_SIZE_SPL);
873
874        for (j = 0; j < ECC_BLOCK0; j++) {//if(i==1)serial_put_hex(tmpbuf[j]);
875            REG_BCH_DR = tmpbuf[j];
876        }
877
878                /* assume parities be wrote to data register not parity register */
879        for (j = 0; j < PAR_SIZE_SPL1; j++) {
880            REG_BCH_DR = eccbuf[i*PAR_SIZE_SPL1 + j];
881        }
882        
883        /* Wait for completion */
884        __ecc_decode_sync();
885        
886        __ecc_disable();
887
888        /* Check decoding */
889        stat = REG_BCH_INTS;
890
891        if (stat & BCH_INTS_ERR) {
892            if (stat & BCH_INTS_UNCOR) {
893                serial_puts("ecc Uncorrectable ECC error occurred __spl__\n");
894                serial_put_hex(i);
895            }
896            else {
897                unsigned int errcnt = (stat & BCH_INTS_ERRC_MASK) >> BCH_INTS_ERRC_BIT;
898                switch (errcnt) {
899                case 24:
900                    dprintf("correct 24th error\n");
901                    bch_correct(tmpbuf, (REG_BCH_ERR11 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
902                case 23:
903                    bch_correct(tmpbuf, (REG_BCH_ERR11 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
904                case 22:
905                    bch_correct(tmpbuf, (REG_BCH_ERR10 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
906                case 21:
907                    bch_correct(tmpbuf, (REG_BCH_ERR10 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
908                case 20:
909                    bch_correct(tmpbuf, (REG_BCH_ERR9 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
910                case 19:
911                    bch_correct(tmpbuf, (REG_BCH_ERR9 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
912                case 18:
913                    bch_correct(tmpbuf, (REG_BCH_ERR8 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
914                case 17:
915                    bch_correct(tmpbuf, (REG_BCH_ERR8 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
916                case 16:
917                    bch_correct(tmpbuf, (REG_BCH_ERR7 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
918                case 15:
919                    bch_correct(tmpbuf, (REG_BCH_ERR7 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
920                case 14:
921                    bch_correct(tmpbuf, (REG_BCH_ERR6 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
922                case 13:
923                    bch_correct(tmpbuf, (REG_BCH_ERR6 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
924                case 12:
925                    bch_correct(tmpbuf, (REG_BCH_ERR5 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
926                case 11:
927                    bch_correct(tmpbuf, (REG_BCH_ERR5 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
928                case 10:
929                    bch_correct(tmpbuf, (REG_BCH_ERR4 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
930                case 9:
931                    bch_correct(tmpbuf, (REG_BCH_ERR4 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
932                case 8:
933                    dprintf("correct 8th error\n");
934                    bch_correct(tmpbuf, (REG_BCH_ERR3 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
935                case 7:
936                    dprintf("correct 7th error\n");
937                    bch_correct(tmpbuf, (REG_BCH_ERR3 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
938                case 6:
939                    dprintf("correct 6th error\n");
940                    bch_correct(tmpbuf, (REG_BCH_ERR2 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
941                case 5:
942                    dprintf("correct 5th error\n");
943                    bch_correct(tmpbuf, (REG_BCH_ERR2 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
944                case 4:
945                    dprintf("correct 4th error\n");
946                    bch_correct(tmpbuf, (REG_BCH_ERR1 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
947                case 3:
948                    dprintf("correct 3th error\n");
949                    bch_correct(tmpbuf, (REG_BCH_ERR1 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
950                case 2:
951                    dprintf("correct 2th error\n");
952                    bch_correct(tmpbuf, (REG_BCH_ERR0 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
953                case 1:
954                    dprintf("correct 1th error\n");
955                    bch_correct(tmpbuf, (REG_BCH_ERR0 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
956                    break;
957                default:
958                    dprintf("no error\n");
959                    break;
960                }
961            }
962        }
963#endif
964        /* increment pointer */
965        tmpbuf += ECC_BLOCK0;
966    }
967
968    __nand_disable();
969
970    return 0;
971}
972
973u32 nand_program_4760(void *context, int spage, int pages, int option)
974{
975    u32 i, j, cur_page, cur_blk, rowaddr;
976    u8 *tmpbuf;
977    u32 ecccnt;
978    u8 ecc_buf[1024], oob_buf[512];
979    u32 oob_per_eccsize;
980    int spl_size = 8 * 1024 / pagesize;
981
982    if (wp_pin)
983        __gpio_set_pin(wp_pin);
984restart:
985    tmpbuf = (u8 *)context;
986    ecccnt = pagesize / ECC_BLOCK;
987    oob_per_eccsize = eccpos / ecccnt;
988
989    i = 0;
990    cur_page = spage;
991    
992    while (i < pages) {
993        if (cur_page == 0) {
994            int k;
995            for(k = 0; k < spl_size; k++) {
996                program_nand_spl_page(context + pagesize * k, k * 2);
997            }
998#if 0
999            for(k = 0; k < spl_size; k++) {
1000                program_nand_spl_page(context + pagesize * k, k * 2 + ppb );
1001            }
1002#endif
1003            tmpbuf += pagesize * spl_size;
1004            cur_page = 2 * ppb;
1005            i += spl_size;
1006            continue;
1007        }
1008
1009        if ((cur_page % ppb) == 0) { /* First page of block, test BAD. */
1010            if (nand_check_block(cur_page / ppb)) {
1011                cur_page += ppb; /* Bad block, set to next block */
1012                continue;
1013            }
1014        }
1015
1016        if ( option != NO_OOB ) //if NO_OOB do not perform vaild check!
1017        {
1018            for ( j = 0 ; j < pagesize + oobsize; j++)
1019            {
1020                if (tmpbuf[j] != 0xff)
1021                    break;
1022            }
1023            if ( j == oobsize + pagesize )
1024            {
1025                tmpbuf += (pagesize + oobsize) ;
1026                i ++;
1027                cur_page ++;
1028                continue;
1029            }
1030        }
1031
1032        __nand_enable();
1033        __nand_sync();
1034
1035        if (pagesize == 512)
1036            __nand_cmd(CMD_READA);
1037
1038        __nand_cmd(CMD_SEQIN);
1039        __nand_addr(0);
1040
1041        if (pagesize != 512)
1042            __nand_addr(0);
1043
1044        rowaddr = cur_page;
1045        for (j = 0; j < row; j++) {
1046            __nand_addr(rowaddr & 0xff);
1047            rowaddr >>= 8;
1048        }
1049
1050        /* write out data */
1051        for (j = 0; j < ecccnt; j++) {
1052            volatile u8 *paraddr;
1053            int k;
1054
1055            paraddr = (volatile u8 *)BCH_PAR0;
1056
1057            REG_BCH_INTS = 0xffffffff;
1058            if(bchbit == 4)
1059                __ecc_encoding_4bit();
1060            else if(bchbit == 8)
1061                __ecc_encoding_8bit();
1062            else if(bchbit == 12)
1063                __ecc_encoding_12bit();
1064            else if(bchbit == 16)
1065                __ecc_encoding_16bit();
1066            else if(bchbit == 20)
1067                __ecc_encoding_20bit();
1068            else
1069                __ecc_encoding_24bit();
1070                    
1071            /* Set BCHCNT.DEC_COUNT to data block size in bytes */
1072            if (option != NO_OOB)
1073                __ecc_cnt_enc((ECC_BLOCK + oob_per_eccsize) * 2);
1074            else
1075                __ecc_cnt_enc(ECC_BLOCK * 2);
1076            
1077            /* Write data in data area to BCH */
1078            for (k = 0; k < ECC_BLOCK; k++) {
1079                REG_BCH_DR = tmpbuf[ECC_BLOCK * j + k];
1080            }
1081            
1082            /* Write file system information in oob area to BCH */
1083            if (option != NO_OOB)
1084            {
1085                if(j == 0){
1086                    REG_BCH_DR = 0xff;
1087                    REG_BCH_DR = 0xff;
1088                    for(k = 2; k < oob_per_eccsize; k++)
1089                        REG_BCH_DR = tmpbuf[pagesize + k];
1090                } else {
1091                    for (k = 0; k < oob_per_eccsize; k++) {
1092                        REG_BCH_DR = tmpbuf[pagesize + oob_per_eccsize * j + k];
1093                    }
1094                }
1095            }
1096            
1097            __ecc_encode_sync();
1098            __ecc_disable();
1099                    
1100            /* Read PAR values */
1101            for (k = 0; k < par_size1; k++) {
1102                ecc_buf[j * par_size1 + k] = *paraddr++;
1103            }
1104#ifdef USE_PN
1105// pn_enable();
1106#endif
1107            write_proc((char *)&tmpbuf[ECC_BLOCK * j], ECC_BLOCK);
1108#ifdef USE_PN
1109// pn_disable();
1110#endif
1111        }
1112
1113        for(j=0; j<oobsize; j++)
1114            oob_buf[j] = 0xff;
1115        switch (option)
1116        {
1117        case OOB_ECC:
1118        case OOB_NO_ECC:
1119            for (j = 2; j < eccpos; j++) {
1120                oob_buf[j] = tmpbuf[pagesize + j];
1121            }
1122            for (j = 0; j < ecccnt * par_size1; j++) {
1123                oob_buf[eccpos + j] = ecc_buf[j];
1124            }
1125            tmpbuf += pagesize + oobsize;
1126            break;
1127        case NO_OOB: //bin image
1128            for (j = 0; j < ecccnt * par_size1; j++) {
1129                oob_buf[eccpos + j] = ecc_buf[j];
1130            }
1131            tmpbuf += pagesize;
1132            break;
1133        }
1134
1135#ifdef USE_PN
1136// pn_enable();
1137#endif
1138        /* write out oob buffer */
1139        write_proc((u8 *)oob_buf, oobsize);
1140
1141#ifdef USE_PN
1142#ifndef USE_STATUS_PORT
1143// pn_disable();
1144#endif
1145#endif
1146        /* send program confirm command */
1147        __nand_cmd(CMD_PGPROG);
1148        __nand_sync();
1149
1150        __nand_cmd(CMD_READ_STATUS);
1151        __nand_sync();
1152
1153        if (__nand_data8() & 0x01) /* page program error */
1154        {
1155            serial_puts("Skip a write fail block\n");
1156            nand_erase_4760( 1, cur_page/ppb, 1); //force erase before
1157            nand_mark_bad_4760(cur_page/ppb);
1158            spage += ppb;
1159            goto restart;
1160        }
1161        __nand_disable();
1162
1163        i++;
1164        cur_page++;
1165    }
1166
1167    if (wp_pin)
1168        __gpio_clear_pin(wp_pin);
1169
1170    return cur_page;
1171}
1172
1173int program_nand_spl_page(unsigned char *databuf, unsigned int pageaddr)
1174{
1175    int i, j, ecccnt;
1176    char *tmpbuf;
1177    char ecc_buf[1024]; // need 39*16 bytes at least for 24bit BCH
1178    unsigned int rowaddr;
1179
1180    for(i=0; i<1024; i++)
1181        ecc_buf[i] = 0xff;
1182  
1183    __nand_enable();
1184
1185    tmpbuf = (char *)databuf;
1186
1187    ecccnt = pagesize / ECC_BLOCK0;
1188
1189    if (pagesize == 512)
1190        __nand_cmd(CMD_READA);
1191
1192    __nand_cmd(CMD_SEQIN);
1193
1194    /* write out col addr */
1195    __nand_addr(0);
1196    if (pagesize != 512)
1197        __nand_addr(0);
1198
1199    rowaddr = pageaddr;
1200    /* write out row addr */
1201    for (i = 0; i < row; i++) {
1202        __nand_addr(rowaddr & 0xff);
1203        rowaddr >>= 8;
1204    }
1205    
1206    /* write out data */
1207
1208    for (i = 0; i < ecccnt; i++) {
1209#ifdef USE_BCH
1210        volatile char *paraddr = (volatile char *)BCH_PAR0;
1211        
1212        REG_BCH_INTS = 0xffffffff;
1213
1214        __ecc_encoding_24bit();
1215
1216                /* Set BCHCNT.DEC_COUNT to data block size in bytes */
1217        __ecc_cnt_enc(2 * ECC_BLOCK0);
1218
1219        for (j = 0; j < ECC_BLOCK0; j++) {
1220            REG_BCH_DR = tmpbuf[j];
1221        }
1222
1223        __ecc_encode_sync();
1224        __ecc_disable();
1225            
1226        /* Read PAR values for 256 bytes from BCH_PARn to ecc_buf */
1227        for (j=0;j<PAR_SIZE_SPL1;j++) {
1228            ecc_buf[j + PAR_SIZE_SPL1 * i] = *paraddr++;
1229        }
1230#endif
1231#ifdef MAKE_ERROR
1232        char tmpbuf0[ECC_BLOCK0];
1233        u8 k, n_err;
1234        u16 err_bit;
1235
1236        memcpy(tmpbuf0, tmpbuf, ECC_BLOCK0);
1237        n_err = 1 + random() % 24; // 1 ~ 24
1238        dprintf("generate %d error bits.\n",n_err);
1239        /* generate n_err error bits */
1240        for(k = 0; k < n_err; k++) {
1241            err_bit = random() % (256*8);
1242            dprintf("err_bit=%04x in databuf[%03d]=0x%x \n",err_bit,err_bit / 8,tmpbuf0[(err_bit / 8)]);
1243            tmpbuf0[(err_bit / 8)] ^= 1 << (err_bit % 8);
1244            dprintf(" error databuf[%03d]= 0x%x \n",err_bit / 8,databuf[(err_bit / 8)]);
1245        }
1246#endif
1247
1248#ifdef USE_PN
1249        if (!(((pageaddr % 64) == 0) && (i == 0)))
1250            pn_enable();
1251        else
1252            dprintf("don't use pn. pageaddr=%d ecccnt=%d\n", pageaddr,i);
1253#endif
1254
1255                /* write ECC_BLOCK0 bytes to nand */
1256#ifdef MAKE_ERROR
1257        write_proc((char *)tmpbuf0, ECC_BLOCK0);
1258#else
1259        write_proc((char *)tmpbuf, ECC_BLOCK0);
1260#endif
1261
1262#ifdef USE_PN
1263#ifndef USE_STATUS_PORT
1264        pn_disable();
1265#endif
1266#endif
1267        tmpbuf += ECC_BLOCK0;
1268    }
1269
1270    /* send program confirm command */
1271    __nand_cmd(CMD_PGPROG);
1272    dprintf("%s %d \n", __FUNCTION__, __LINE__);
1273    __nand_sync();
1274    dprintf("%s %d \n", __FUNCTION__, __LINE__);
1275
1276#if 1
1277    __nand_cmd(CMD_READ_STATUS);
1278    dprintf("%s %d \n", __FUNCTION__, __LINE__);
1279    u8 status;
1280#ifdef USE_STATUS_PORT
1281    status = __nand_status();
1282#else
1283    status = __nand_data8();
1284#endif
1285    if (status & 0x01) {
1286        __nand_disable();
1287        return 1;
1288    }
1289    else {
1290        __nand_disable();
1291    }
1292    dprintf("%s %d \n", __FUNCTION__, __LINE__);
1293    /* -----program ecc----- */
1294    __nand_enable();
1295#endif
1296    if (pagesize == 512)
1297        __nand_cmd(CMD_READA);
1298
1299    __nand_cmd(CMD_SEQIN);
1300
1301    /* write out col addr */
1302    __nand_addr(0);
1303    if (pagesize != 512)
1304        __nand_addr(0);
1305
1306    rowaddr = pageaddr + 1;
1307    /* write out row addr */
1308    for (i = 0; i < row; i++) {
1309        __nand_addr(rowaddr & 0xff);
1310        rowaddr >>= 8;
1311    }
1312
1313#ifdef USE_PN
1314#ifdef PN_ADD_DELAY
1315    udelay(1000);
1316    dprintf("delay should be add for pn.\n");
1317#endif
1318#endif
1319
1320#ifdef USE_PN
1321    pn_enable();
1322#endif
1323    dprintf("%s %d \n", __FUNCTION__, __LINE__);
1324    write_proc(ecc_buf, pagesize/ECC_BLOCK0*PAR_SIZE_SPL1);
1325
1326#ifdef USE_PN
1327    pn_disable();
1328#endif
1329
1330    /* send program confirm command */
1331    __nand_cmd(CMD_PGPROG);
1332    dprintf("%s %d \n", __FUNCTION__, __LINE__);
1333    __nand_sync();
1334    dprintf("%s %d \n", __FUNCTION__, __LINE__);
1335    __nand_cmd(CMD_READ_STATUS);
1336
1337    if (__nand_data8() & 0x01) { /* page program error */
1338        __nand_disable();
1339        return 1;
1340    }
1341    else {
1342        __nand_disable();
1343        return 0;
1344    }
1345}
1346
1347// be careful
1348static u32 nand_mark_bad_page(u32 page)
1349{
1350#if 1
1351    u8 badbuf[4096 + 128];
1352    u32 i;
1353
1354    if (wp_pin)
1355        __gpio_set_pin(wp_pin);
1356    for (i = 0; i < pagesize + oobsize; i++)
1357        badbuf[i] = 0x00;
1358    //all set to 0x00
1359
1360    __nand_cmd(CMD_READA);
1361    __nand_cmd(CMD_SEQIN);
1362
1363    __nand_addr(0);
1364    if (pagesize != 512)
1365        __nand_addr(0);
1366    for (i = 0; i < row; i++) {
1367        __nand_addr(page & 0xff);
1368        page >>= 8;
1369    }
1370
1371    write_proc((char *)badbuf, pagesize + oobsize);
1372    __nand_cmd(CMD_PGPROG);
1373    __nand_sync();
1374
1375    if (wp_pin)
1376        __gpio_clear_pin(wp_pin);
1377    return page;
1378#endif
1379}
1380
1381u32 nand_mark_bad_4760(int block)
1382{
1383    u32 rowaddr;
1384
1385    if ( bad_block_page >= ppb ) //absolute bad block mark!
1386    { //mark four page!
1387        rowaddr = block * ppb + 0;
1388        nand_mark_bad_page(rowaddr);
1389
1390        rowaddr = block * ppb + 1;
1391        nand_mark_bad_page(rowaddr);
1392
1393        rowaddr = block * ppb + ppb - 2;
1394        nand_mark_bad_page(rowaddr);
1395
1396        rowaddr = block * ppb + ppb - 1;
1397        nand_mark_bad_page(rowaddr);
1398    }
1399    else //mark one page only
1400    {
1401        rowaddr = block * ppb + bad_block_page;
1402        nand_mark_bad_page(rowaddr);
1403    }
1404
1405    return rowaddr;
1406}
1407
1408static int nand_data_write8(char *buf, int count)
1409{
1410    int i;
1411    u8 *p = (u8 *)buf;
1412    for (i=0;i<count;i++)
1413        __nand_data8() = *p++;
1414    return 0;
1415}
1416
1417static int nand_data_write16(char *buf, int count)
1418{
1419    int i;
1420    u16 *p = (u16 *)buf;
1421    for (i=0;i<count/2;i++)
1422        __nand_data16() = *p++;
1423    return 0;
1424}
1425
1426static int nand_data_read8(char *buf, int count)
1427{
1428    int i;
1429    u8 *p = (u8 *)buf;
1430    for (i=0;i<count;i++)
1431        *p++ = __nand_data8();
1432    return 0;
1433}
1434
1435static int nand_data_read16(char *buf, int count)
1436{
1437    int i;
1438    u16 *p = (u16 *)buf;
1439    for (i=0;i<count/2;i++)
1440        *p++ = __nand_data16();
1441    return 0;
1442}
1443

Archive Download this file



interactive