Root/nandprog/jz4740/nandflash_4740.c

1/*
2 * Common NAND Flash operations for JZ4740.
3 *
4 * This software is free.
5 */
6
7#include "jz4740.h"
8#include "include.h"
9
10extern struct nand_oobinfo oob_64[];
11
12#define __nand_enable() (REG_EMC_NFCSR |= EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1)
13#define __nand_disable() (REG_EMC_NFCSR &= ~(EMC_NFCSR_NFCE1|EMC_NFCSR_NFE1 ))
14#define __nand_ecc_rs_encoding() (REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_ENCODING)
15#define __nand_ecc_rs_decoding() (REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_DECODING)
16#define __nand_ecc_disable() (REG_EMC_NFECR &= ~EMC_NFECR_ECCE)
17#define __nand_ecc_encode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_ENCF))
18#define __nand_ecc_decode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_DECF))
19#define __nand_ecc_enable() (REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST )
20#define __nand_ecc_disable() (REG_EMC_NFECR &= ~EMC_NFECR_ECCE)
21
22#define __nand_select_hm_ecc() (REG_EMC_NFECR &= ~EMC_NFECR_RS )
23#define __nand_select_rs_ecc() (REG_EMC_NFECR |= EMC_NFECR_RS)
24
25#define __nand_read_hm_ecc() (REG_EMC_NFECC & 0x00ffffff)
26
27#define __nand_ecc() (REG_EMC_NFECC & 0x00ffffff)
28#define __nand_cmd(n) (REG8(cmdport+csn) = (n))
29#define __nand_addr(n) (REG8(addrport+csn) = (n))
30#define __nand_data8() REG8(dataport+csn)
31#define __nand_data16() REG16(dataport+csn)
32
33#define CMD_READA 0x00
34#define CMD_READB 0x01
35#define CMD_READC 0x50
36#define CMD_ERASE_SETUP 0x60
37#define CMD_ERASE 0xD0
38#define CMD_READ_STATUS 0x70
39#define CMD_CONFIRM 0x30
40#define CMD_SEQIN 0x80
41#define CMD_PGPROG 0x10
42#define CMD_READID 0x90
43
44#define OOB_BAD_OFF 0x00
45#define OOB_ECC_OFF 0x04
46
47#define OP_ERASE 0
48#define OP_WRITE 1
49#define OP_READ 2
50
51#define ECC_BLOCK 512
52#define ECC_POS 6
53#define PAR_SIZE 9
54
55static volatile unsigned char *gpio_base;
56static volatile unsigned char *emc_base;
57static volatile unsigned char *addrport;
58static volatile unsigned char *dataport;
59static volatile unsigned char *cmdport;
60unsigned int EMC_BASE;
61unsigned int GPIO_BASE;
62
63static int bus = 8, row = 2, pagesize = 512, oobsize = 16, ppb = 32;
64static u32 bad_block_pos = 0,bad_block_page=0, csn = 0;
65static u8 badbuf[2048 + 64] = {0};
66static u8 data_buf[2048] = {0};
67static u8 oob_buf[128] = {0};
68static struct nand_oobinfo *oob_pos;
69static np_data *np;
70
71static inline void __nand_sync(void)
72{
73    unsigned int timeout = 1000;
74    while ((REG_GPIO_PXPIN(2) & 0x40000000) && timeout--);
75    while (!(REG_GPIO_PXPIN(2) & 0x40000000));
76}
77
78static int read_oob(u8 *buf, u32 size, u32 pg);
79static int nand_data_write8(unsigned char *buf, int count);
80static int nand_data_write16(unsigned char *buf, int count);
81static int nand_data_read8(unsigned char *buf, int count);
82static int nand_data_read16(unsigned char *buf, int count);
83
84static int (*write_proc)(unsigned char *, int) = 0;
85static int (*read_proc)(unsigned char *, int) = 0;
86
87extern void dumpbuf(u8 *p, int count);
88
89unsigned int nand_query_4740(void)
90{
91    u16 vid, did;
92
93    __nand_sync();
94    __nand_cmd(CMD_READID);
95    __nand_addr(0);
96
97    vid = __nand_data8();
98    did = __nand_data8();
99
100    return (vid << 16) | did;
101}
102
103int chip_select_4740(u8 cs)
104{
105    csn = (u32)cs << 15; // modify this number for your board
106    return 0;
107}
108
109int nand_init_4740(np_data *npp)
110{
111    bus = npp->bw;
112    row = npp->rc;
113    pagesize = npp->ps;
114    oobsize = npp->os;
115    ppb = npp->ppb;
116    bad_block_pos = npp->bbp;
117    bad_block_page = npp->bba;
118    gpio_base = (u8 *)npp->gpio_map;
119    emc_base = (u8 *)npp->base_map;
120    dataport = (u8 *)npp->port_map;
121    addrport = (u8 *)((u32)dataport + npp->ap_offset);
122    cmdport = (u8 *)((u32)dataport + npp->cp_offset);
123
124    EMC_BASE = (u32)emc_base;
125    GPIO_BASE = (u32)gpio_base;
126
127    /* Initialize NAND Flash Pins */
128// __gpio_as_nand();
129// __nand_enable();
130
131    chip_select_4740(npp->cs);
132    if (bus == 8) {
133        write_proc = nand_data_write8;
134        read_proc = nand_data_read8;
135    } else {
136        write_proc = nand_data_write16;
137        read_proc = nand_data_read16;
138    }
139
140    oob_pos = &oob_64[npp->ep];
141// REG_EMC_SMCR1 = 0x0fff7700;
142    np = npp;
143    return 0;
144}
145
146int nand_fini_4740(void)
147{
148    __nand_disable();
149    return 0;
150}
151
152/*
153 * Read oob <pagenum> pages from <startpage> page.
154 * Don't skip bad block.
155 * Don't use HW ECC.
156 */
157int nand_read_oob_4740(u8 *buf, u32 startpage, u32 pagenum)
158{
159    u32 cnt, cur_page;
160    u8 *tmpbuf;
161
162    tmpbuf = (u8 *)buf;
163
164    cur_page = startpage;
165    cnt = 0;
166    while (cnt < pagenum) {
167        read_oob((void *)tmpbuf, oobsize, cur_page);
168
169        tmpbuf += oobsize;
170        cur_page++;
171        cnt++;
172    }
173
174    return 0;
175}
176
177int nand_check_block_4740(u32 block)
178{
179    u32 pg;
180
181    pg = block * ppb + bad_block_page;
182    read_oob(oob_buf, oobsize, pg);
183    if (oob_buf[bad_block_pos] != 0xff)
184        return -1;
185    read_oob(oob_buf, oobsize, pg + 1);
186    if (oob_buf[bad_block_pos] != 0xff)
187        return -1;
188
189    return 0;
190}
191
192/*
193 * Mark a block bad.
194 */
195void nand_block_markbad_4740(u32 block)
196{
197    u32 i, rowaddr;
198
199    for (i = 0; i < pagesize + oobsize; i++)
200        badbuf[i] = 0x00;
201    badbuf[pagesize + bad_block_pos] = 0; /* bad block flag */
202
203    rowaddr = block * ppb + bad_block_page;
204    //bad block ID locate No.bad_block_page page
205
206    __nand_cmd(CMD_READA);
207    __nand_cmd(CMD_SEQIN);
208
209    __nand_addr(0);
210    if (pagesize == 2048)
211        __nand_addr(0);
212    for (i = 0; i < row; i++) {
213        __nand_addr(rowaddr & 0xff);
214        rowaddr >>= 8;
215    }
216
217    write_proc((unsigned char *)badbuf, pagesize + oobsize);
218    __nand_cmd(CMD_PGPROG);
219    __nand_sync();
220}
221
222/*
223 * Read data <pagenum> pages from <startpage> page.
224 * Don't skip bad block.
225 * Don't use HW ECC.
226 */
227int nand_read_raw_4740(u8 *buf, u32 startpage, u32 pagenum)
228{
229    u32 cnt, j;
230    u32 cur_page, rowaddr;
231    u8 *tmpbuf;
232
233    tmpbuf = (u8 *)buf;
234
235    cur_page = startpage;
236    cnt = 0;
237    while (cnt < pagenum) {
238        __nand_sync();
239        __nand_cmd(CMD_READA);
240        __nand_addr(0);
241        if (pagesize == 2048)
242            __nand_addr(0);
243
244        rowaddr = cur_page;
245        for (j = 0; j < row; j++) {
246            __nand_addr(rowaddr & 0xff);
247            rowaddr >>= 8;
248        }
249
250        if (pagesize == 2048)
251            __nand_cmd(CMD_CONFIRM);
252
253        __nand_sync();
254        read_proc(tmpbuf, pagesize);
255
256        tmpbuf += pagesize;
257        cur_page++;
258        cnt++;
259    }
260
261    return 0;
262}
263
264
265int nand_erase_4740(int blk_num, int sblk, int force)
266{
267    int i, j;
268    u32 cur, rowaddr;
269
270    cur = sblk * ppb;
271    for (i = 0; i < blk_num; i++) {
272        rowaddr = cur;
273
274        if (!force) { /* if set, erase anything */
275            /* test Badflag. */
276            __nand_sync();
277
278            __nand_cmd(CMD_READA);
279
280            __nand_addr(0);
281            if (pagesize == 2048)
282                __nand_addr(0);
283            for (j=0;j<row;j++) {
284                __nand_addr(rowaddr & 0xff);
285                rowaddr >>= 8;
286            }
287
288            if (pagesize == 2048)
289                __nand_cmd(CMD_CONFIRM);
290
291            __nand_sync();
292
293            read_proc((u8 *)data_buf, pagesize);
294            read_proc((u8 *)oob_buf, oobsize);
295
296            if (oob_buf[0] != 0xff) { /* Bad block, skip */
297                cur += ppb;
298                continue;
299            }
300            rowaddr = cur;
301        }
302
303        __nand_cmd(CMD_ERASE_SETUP);
304
305        for (j = 0; j < row; j++) {
306            __nand_addr(rowaddr & 0xff);
307            rowaddr >>= 8;
308        }
309        __nand_cmd(CMD_ERASE);
310
311        __nand_sync();
312
313        __nand_cmd(CMD_READ_STATUS);
314
315        if (__nand_data8() & 0x01)
316        {
317            /* Erase Error, mark it as bad block */
318            nand_block_markbad(cur);
319        
320        } else ;
321
322        cur += ppb;
323    }
324
325    return 0;
326}
327
328static int read_oob(u8 *buf, u32 size, u32 pg)
329{
330    u32 i, coladdr, rowaddr;
331
332    if (pagesize == 512)
333        coladdr = 0;
334    else
335        coladdr = pagesize;
336
337    if (pagesize == 512)
338        /* Send READOOB command */
339        __nand_cmd(CMD_READC);
340    else
341        /* Send READ0 command */
342        __nand_cmd(CMD_READA);
343
344    /* Send column address */
345    __nand_addr(coladdr & 0xff);
346    if (pagesize != 512)
347        __nand_addr(coladdr >> 8);
348
349    /* Send page address */
350    rowaddr = pg;
351    for (i = 0; i < row; i++) {
352        __nand_addr(rowaddr & 0xff);
353        rowaddr >>= 8;
354    }
355
356    /* Send READSTART command for 2048 ps NAND */
357    if (pagesize != 512)
358        __nand_cmd(CMD_CONFIRM);
359
360    /* Wait for device ready */
361    __nand_sync();
362
363    /* Read oob data */
364    read_proc(buf, size);
365
366    return 0;
367}
368
369/* Correct 1~9-bit errors in 512-bytes data */
370static void rs_correct(unsigned char *dat, int idx, int mask)
371{
372    int i;
373
374    idx--;
375
376    i = idx + (idx >> 3);
377    if (i >= 512)
378        return;
379
380    mask <<= (idx & 0x7);
381
382    dat[i] ^= mask & 0xff;
383    if (i < 511)
384        dat[i+1] ^= (mask >> 8) & 0xff;
385}
386
387static int nand_hm_correct_data(u8 *dat, u8 *oob_s, u8 *calc_ecc,u8 p)
388{
389    u8 a, b, c, d1, d2, d3, add, bit, i;
390    u8 *e1,*e2,*e3;
391
392    e1 = &oob_s[oob_pos->eccpos[p+0]];
393    e2 = &oob_s[oob_pos->eccpos[p+1]];
394    e3 = &oob_s[oob_pos->eccpos[p+2]];
395// printf("read ecc :%x %x %x %d %d\n",*e1,*e2,*e3,
396// oob_pos->eccpos[p+0],oob_pos->eccpos[p+1]);
397
398    d1 = calc_ecc[0] ^ *e1;
399    d2 = calc_ecc[1] ^ *e2;
400    d3 = calc_ecc[2] ^ *e3;
401
402    if ((d1 | d2 | d3) == 0) {
403        /* No errors */
404        return 0;
405    }
406    else {
407        a = (d1 ^ (d1 >> 1)) & 0x55;
408        b = (d2 ^ (d2 >> 1)) & 0x55;
409        c = (d3 ^ (d3 >> 1)) & 0x54;
410
411        /* Found and will correct single bit error in the data */
412        if ((a == 0x55) && (b == 0x55) && (c == 0x54)) {
413            c = 0x80;
414            add = 0;
415            a = 0x80;
416            for (i=0; i<4; i++) {
417                if (d1 & c)
418                    add |= a;
419                c >>= 2;
420                a >>= 1;
421            }
422            c = 0x80;
423            for (i=0; i<4; i++) {
424                if (d2 & c)
425                    add |= a;
426                c >>= 2;
427                a >>= 1;
428            }
429            bit = 0;
430            b = 0x04;
431            c = 0x80;
432            for (i=0; i<3; i++) {
433                if (d3 & c)
434                    bit |= b;
435                c >>= 2;
436                b >>= 1;
437            }
438            b = 0x01;
439            a = dat[add];
440            a ^= (b << bit);
441            dat[add] = a;
442            return 0;
443        }
444        else {
445            i = 0;
446            while (d1) {
447                if (d1 & 0x01)
448                    ++i;
449                d1 >>= 1;
450            }
451            while (d2) {
452                if (d2 & 0x01)
453                    ++i;
454                d2 >>= 1;
455            }
456            while (d3) {
457                if (d3 & 0x01)
458                    ++i;
459                d3 >>= 1;
460            }
461            if (i == 1) {
462                /* ECC Code Error Correction */
463                *e1 = calc_ecc[0];
464                *e2 = calc_ecc[1];
465                *e3 = calc_ecc[2];
466                return 0;
467            }
468            else {
469                /* Uncorrectable Error */
470// printf("uncorrectable ECC error\n");
471                return -1;
472            }
473        }
474    }
475    
476    /* Should never happen */
477    return -1;
478}
479
480 /*
481 * Read data <pagenum> pages from <startpage> page.
482 * HW ECC is used.
483 */
484int nand_read_4740_hm(u8 *buf, u32 startpage, u32 pagenum)
485{
486    u32 j, calc_ecc;
487    u32 cur_page, cnt, rowaddr, ecccnt;
488    u8 *tmpbuf;
489    ecccnt = pagesize / 256;
490    
491    cur_page = startpage;
492    cnt = 0;
493    while (cnt < pagenum) {
494        /* read oob first */
495        read_oob(oob_buf, oobsize, cur_page);
496
497        __nand_sync();
498        __nand_cmd(CMD_READA);
499
500        __nand_addr(0);
501        if (pagesize == 2048)
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 == 2048)
511            __nand_cmd(CMD_CONFIRM);
512        __nand_sync();
513        tmpbuf = (u8 *)((u32)buf + cnt * ( pagesize+oobsize));
514
515        for (j = 0; j < ecccnt ; j++)
516        {
517            __nand_ecc_enable();
518            __nand_select_hm_ecc();
519            read_proc(tmpbuf, 256);
520            __nand_ecc_disable();
521            calc_ecc = __nand_read_hm_ecc();
522            if (oob_pos->eccname == LINUXHM)
523                calc_ecc = ~calc_ecc | 0x00030000;
524
525            nand_hm_correct_data(tmpbuf,oob_buf,(u8*)&calc_ecc,j*3);
526            tmpbuf += 256;
527        }
528
529        for (j = 0; j < oobsize; j++)
530            tmpbuf[j] = oob_buf[j];
531
532        cur_page++;
533        cnt++;
534
535    }
536    return 0;
537}
538
539 /*
540 * Read data <pagenum> pages from <startpage> page.
541 * HW ECC is used.
542 */
543int nand_read_4740_rs(u8 *buf, u32 startpage, u32 pagenum)
544{
545    u32 j, k;
546    u32 cur_page, cnt, rowaddr, ecccnt;
547    u8 *tmpbuf;
548    ecccnt = pagesize / ECC_BLOCK;
549    
550    cur_page = startpage;
551    cnt = 0;
552    while (cnt < pagenum) {
553        /* read oob first */
554        read_oob(oob_buf, oobsize, cur_page);
555
556        __nand_sync();
557        __nand_cmd(CMD_READA);
558
559        __nand_addr(0);
560        if (pagesize == 2048)
561            __nand_addr(0);
562
563        rowaddr = cur_page;
564        for (j = 0; j < row; j++) {
565            __nand_addr(rowaddr & 0xff);
566            rowaddr >>= 8;
567        }
568
569        if (pagesize == 2048)
570            __nand_cmd(CMD_CONFIRM);
571        __nand_sync();
572        tmpbuf = (u8 *)((u32)buf + cnt * ( pagesize+oobsize));
573
574        for (j = 0; j < ecccnt ; j++) {
575            volatile u8 *paraddr = (volatile u8 *)EMC_NFPAR0;
576            u32 stat;
577
578            /* Read data */
579            REG_EMC_NFINTS = 0x0;
580            __nand_ecc_rs_decoding();
581            read_proc(tmpbuf, ECC_BLOCK);
582
583            /* Set PAR values */
584            for (k = 0; k < PAR_SIZE; k++) {
585                *paraddr++ = oob_buf[oob_pos->eccpos[j*PAR_SIZE + k]];
586            }
587
588            /* Set PRDY */
589            REG_EMC_NFECR |= EMC_NFECR_PRDY;
590
591            /* Wait for completion */
592            __nand_ecc_decode_sync();
593            __nand_ecc_disable();
594
595            /* Check decoding */
596            stat = REG_EMC_NFINTS;
597
598            if (stat & EMC_NFINTS_ERR) {
599// printf("Error occured!\n");
600                if (stat & EMC_NFINTS_UNCOR) {
601                    int t;
602                    for (t = 0; t < oob_pos->eccbytes; t++)
603                        if (oob_buf[oob_pos->eccpos[t]] != 0xff) break;
604                    if (t < oob_pos->eccbytes-1) {
605// printf("Uncorrectable error occurred\n");
606                    }
607                }
608                else {
609                    u32 errcnt = (stat & EMC_NFINTS_ERRCNT_MASK) >> EMC_NFINTS_ERRCNT_BIT;
610                    switch (errcnt) {
611                    case 4:
612                        rs_correct(tmpbuf, (REG_EMC_NFERR3 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, (REG_EMC_NFERR3 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT);
613                    case 3:
614                        rs_correct(tmpbuf, (REG_EMC_NFERR2 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, (REG_EMC_NFERR2 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT);
615                    case 2:
616                        rs_correct(tmpbuf, (REG_EMC_NFERR1 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, (REG_EMC_NFERR1 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT);
617                    case 1:
618                        rs_correct(tmpbuf, (REG_EMC_NFERR0 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, (REG_EMC_NFERR0 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT);
619                        break;
620                    default:
621                        break;
622                    }
623
624                }
625            }
626            /* increment pointer */
627            tmpbuf += ECC_BLOCK ;
628        }
629
630        for (j = 0; j < oobsize; j++)
631            tmpbuf[j] = oob_buf[j];
632
633        cur_page++;
634        cnt++;
635    }
636
637    return 0;
638}
639
640int nand_program_4740(u8 *context, int spage, int pages)
641{
642    u32 i, j, cur, rowaddr;
643    u8 *tmpbuf;
644
645    tmpbuf = (u8 *)context;
646    i = 0;
647    cur = spage;
648
649    while (i < pages) {
650
651        for (j=0;j<np->os;j++)
652        {
653            if (tmpbuf[j+np->ps]!=0xff)
654                break;
655        }
656
657        if (j==np->os)
658        {
659            tmpbuf += np->ps+np->os;
660            i ++;
661            cur ++;
662            continue;
663        }
664        if (pagesize != 2048)
665            __nand_cmd(CMD_READA);
666
667        __nand_cmd(CMD_SEQIN);
668
669        __nand_addr(0);
670        if (pagesize == 2048)
671            __nand_addr(0);
672        rowaddr = cur;
673        for (j = 0; j < row; j++) {
674            __nand_addr(rowaddr & 0xff);
675            rowaddr >>= 8;
676        }
677
678        write_proc(tmpbuf, np->ps+np->os);
679        tmpbuf += np->ps+np->os;
680
681        /* send program confirm command */
682        __nand_cmd(CMD_PGPROG);
683        __nand_sync();
684
685        __nand_cmd(CMD_READ_STATUS);
686// __nand_sync();
687
688        if (__nand_data8() & 0x01) { /* page program error */
689            return -1;
690        } else ;
691
692        i ++;
693        cur ++;
694    }
695    return 0;
696}
697
698static int nand_data_write8(unsigned char *buf, int count)
699{
700    int i;
701    u8 *p = (u8 *)buf;
702    for (i=0;i<count;i++)
703        __nand_data8() = *p++;
704    return 0;
705}
706
707static int nand_data_write16(unsigned char *buf, int count)
708{
709    int i;
710    u16 *p = (u16 *)buf;
711    for (i=0;i<count/2;i++)
712        __nand_data16() = *p++;
713    return 0;
714}
715
716static int nand_data_read8(unsigned char *buf, int count)
717{
718    int i;
719    u8 *p = (u8 *)buf;
720    for (i=0;i<count;i++)
721        *p++ = __nand_data8();
722    return 0;
723}
724
725static int nand_data_read16(unsigned char *buf, int count)
726{
727    int i;
728    u16 *p = (u16 *)buf;
729    for (i=0;i<count/2;i++)
730        *p++ = __nand_data16();
731    return 0;
732}
733
734 
735

Archive Download this file



interactive