Root/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 "jz4750.h"
20#include "nandflash.h"
21#include "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}
845

Archive Download this file



interactive