Root/nandboot/src/jz4740_nand.c

1/*
2 * jz4740_nand.c
3 *
4 * NAND read routine for JZ4740
5 *
6 * Copyright (c) 2005-2008 Ingenic Semiconductor Inc.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 */
13
14#include <config.h>
15
16#ifdef CONFIG_JZ4740
17
18#include <nand.h>
19#include <jz4740.h>
20
21#define NAND_DATAPORT 0xb8000000
22#define NAND_ADDRPORT 0xb8010000
23#define NAND_COMMPORT 0xb8008000
24
25#define ECC_BLOCK 512
26#define ECC_POS 6
27#define PAR_SIZE 9
28
29#define __nand_cmd(n) (REG8(NAND_COMMPORT) = (n))
30#define __nand_addr(n) (REG8(NAND_ADDRPORT) = (n))
31#define __nand_data8() REG8(NAND_DATAPORT)
32#define __nand_data16() REG16(NAND_DATAPORT)
33
34#define __nand_enable() (REG_EMC_NFCSR |= EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1)
35#define __nand_disable() (REG_EMC_NFCSR &= ~(EMC_NFCSR_NFCE1))
36#define __nand_ecc_rs_encoding() \
37    (REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_ENCODING)
38#define __nand_ecc_rs_decoding() \
39    (REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_DECODING)
40#define __nand_ecc_disable() (REG_EMC_NFECR &= ~EMC_NFECR_ECCE)
41#define __nand_ecc_encode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_ENCF))
42#define __nand_ecc_decode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_DECF))
43
44/*--------------------------------------------------------------*/
45
46static inline void nand_wait_ready(void)
47{
48    unsigned int timeout = 1000;
49    while ((REG_GPIO_PXPIN(2) & 0x40000000) && timeout--);
50    while (!(REG_GPIO_PXPIN(2) & 0x40000000));
51}
52
53static inline void nand_read_buf16(void *buf, int count)
54{
55    int i;
56    u16 *p = (u16 *)buf;
57
58    for (i = 0; i < count; i += 2)
59        *p++ = __nand_data16();
60}
61
62static inline void nand_read_buf8(void *buf, int count)
63{
64    int i;
65    u8 *p = (u8 *)buf;
66
67    for (i = 0; i < count; i++)
68        *p++ = __nand_data8();
69}
70
71static inline void nand_read_buf(void *buf, int count, int bw)
72{
73    if (bw == 8)
74        nand_read_buf8(buf, count);
75    else
76        nand_read_buf16(buf, count);
77}
78
79/*
80 * Correct 1~9-bit errors in 512-bytes data
81 */
82static void rs_correct(unsigned char *dat, int idx, int mask)
83{
84    int i, j;
85    unsigned short d, d1, dm;
86
87    i = (idx * 9) >> 3;
88    j = (idx * 9) & 0x7;
89
90    i = (j == 0) ? (i - 1) : i;
91    j = (j == 0) ? 7 : (j - 1);
92
93    if (i > 512) return;
94
95    if (i == 512)
96        d = dat[i - 1];
97    else
98        d = (dat[i] << 8) | dat[i - 1];
99
100    d1 = (d >> j) & 0x1ff;
101    d1 ^= mask;
102
103    dm = ~(0x1ff << j);
104    d = (d & dm) | (d1 << j);
105
106    dat[i - 1] = d & 0xff;
107    if (i < 512)
108        dat[i] = (d >> 8) & 0xff;
109}
110
111/*
112 * Read oob
113 */
114static int nand_read_oob(struct nand_param *nandp, int page_addr, u8 *buf, int size)
115{
116    int page_size, row_cycle, bus_width;
117    int col_addr;
118
119    page_size = nandp->page_size;
120    row_cycle = nandp->row_cycle;
121    bus_width = nandp->bus_width;
122
123    if (page_size == 2048)
124        col_addr = 2048;
125    else
126        col_addr = 0;
127
128    if (page_size == 2048)
129        /* Send READ0 command */
130        __nand_cmd(NAND_CMD_READ0);
131    else
132        /* Send READOOB command */
133        __nand_cmd(NAND_CMD_READOOB);
134
135    /* Send column address */
136    __nand_addr(col_addr & 0xff);
137    if (page_size == 2048)
138        __nand_addr((col_addr >> 8) & 0xff);
139
140    /* Send page address */
141    __nand_addr(page_addr & 0xff);
142    __nand_addr((page_addr >> 8) & 0xff);
143    if (row_cycle == 3)
144        __nand_addr((page_addr >> 16) & 0xff);
145
146    /* Send READSTART command for 2048 ps NAND */
147    if (page_size == 2048)
148        __nand_cmd(NAND_CMD_READSTART);
149
150    /* Wait for device ready */
151    nand_wait_ready();
152
153    /* Read oob data */
154    nand_read_buf(buf, size, bus_width);
155
156    return 0;
157}
158
159
160/*
161 * nand_read_page()
162 *
163 * Input:
164 *
165 * nandp - pointer to nand info
166 * block - block number: 0, 1, 2, ...
167 * page - page number within a block: 0, 1, 2, ...
168 * dst - pointer to target buffer
169 */
170int nand_read_page(struct nand_param *nandp, int block, int page, u8 *dst)
171{
172    int page_size, oob_size, page_per_block;
173    int row_cycle, bus_width, ecc_count;
174    int page_addr, i, j;
175    u8 *data_buf;
176    u8 oob_buf[64];
177
178    page_size = nandp->page_size;
179    oob_size = nandp->oob_size;
180    page_per_block = nandp->page_per_block;
181    row_cycle = nandp->row_cycle;
182    bus_width = nandp->bus_width;
183
184    page_addr = page + block * page_per_block;
185
186    /*
187     * Read oob data
188     */
189    nand_read_oob(nandp, page_addr, oob_buf, oob_size);
190
191    /*
192     * Read page data
193     */
194
195    /* Send READ0 command */
196    __nand_cmd(NAND_CMD_READ0);
197
198    /* Send column address */
199    __nand_addr(0);
200    if (page_size == 2048)
201        __nand_addr(0);
202
203    /* Send page address */
204    __nand_addr(page_addr & 0xff);
205    __nand_addr((page_addr >> 8) & 0xff);
206    if (row_cycle == 3)
207        __nand_addr((page_addr >> 16) & 0xff);
208
209    /* Send READSTART command for 2048 ps NAND */
210    if (page_size == 2048)
211        __nand_cmd(NAND_CMD_READSTART);
212
213    /* Wait for device ready */
214    nand_wait_ready();
215
216    /* Read page data */
217    data_buf = dst;
218
219    ecc_count = page_size / ECC_BLOCK;
220
221    for (i = 0; i < ecc_count; i++) {
222        volatile u8 *paraddr = (volatile u8 *)EMC_NFPAR0;
223        unsigned int stat;
224
225        /* Enable RS decoding */
226        REG_EMC_NFINTS = 0x0;
227        __nand_ecc_rs_decoding();
228
229        /* Read data */
230        nand_read_buf((void *)data_buf, ECC_BLOCK, bus_width);
231
232        /* Set PAR values */
233        for (j = 0; j < PAR_SIZE; j++) {
234            *paraddr++ = oob_buf[ECC_POS + i*PAR_SIZE + j];
235        }
236
237        /* Set PRDY */
238        REG_EMC_NFECR |= EMC_NFECR_PRDY;
239
240        /* Wait for completion */
241        __nand_ecc_decode_sync();
242
243        /* Disable decoding */
244        __nand_ecc_disable();
245
246        /* Check result of decoding */
247        stat = REG_EMC_NFINTS;
248        if (stat & EMC_NFINTS_ERR) {
249            /* Error occurred */
250            if (stat & EMC_NFINTS_UNCOR) {
251                /* Uncorrectable error occurred */
252            }
253            else {
254                unsigned int errcnt, index, mask;
255
256                errcnt = (stat & EMC_NFINTS_ERRCNT_MASK) >> EMC_NFINTS_ERRCNT_BIT;
257                switch (errcnt) {
258                case 4:
259                    index = (REG_EMC_NFERR3 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
260                    mask = (REG_EMC_NFERR3 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
261                    rs_correct(data_buf, index, mask);
262                case 3:
263                    index = (REG_EMC_NFERR2 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
264                    mask = (REG_EMC_NFERR2 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
265                    rs_correct(data_buf, index, mask);
266                case 2:
267                    index = (REG_EMC_NFERR1 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
268                    mask = (REG_EMC_NFERR1 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
269                    rs_correct(data_buf, index, mask);
270                case 1:
271                    index = (REG_EMC_NFERR0 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
272                    mask = (REG_EMC_NFERR0 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
273                    rs_correct(data_buf, index, mask);
274                    break;
275                default:
276                    break;
277                }
278            }
279        }
280
281        data_buf += ECC_BLOCK;
282    }
283
284    return 0;
285}
286
287/*
288 * Check bad block
289 *
290 * Note: the bad block flag may be store in either the first or the last
291 * page of the block.
292 */
293int block_is_bad(struct nand_param *nandp, int block)
294{
295    int page_addr;
296    u8 oob_buf[64];
297
298    page_addr = block * nandp->page_per_block;
299    nand_read_oob(nandp, page_addr, oob_buf, nandp->oob_size);
300    if (oob_buf[nandp->bad_block_pos] != 0xff)
301        return 1;
302
303    page_addr = (block + 1) * nandp->page_per_block - 1;
304    nand_read_oob(nandp, page_addr, oob_buf, nandp->oob_size);
305    if (oob_buf[nandp->bad_block_pos] != 0xff)
306        return 1;
307
308    return 0;
309}
310
311/*
312 * Enable NAND controller
313 */
314void nand_enable(void)
315{
316    __nand_enable();
317
318    REG_EMC_SMCR1 = 0x04444400;
319}
320
321/*
322 * Disable NAND controller
323 */
324void nand_disable(void)
325{
326    __nand_disable();
327}
328
329#endif /* CONFIG_JZ4740 */
330

Archive Download this file



interactive