1 /*
2 * Copyright (c) 2006-2022, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date           Author        Notes
8 * 2022-01-08     brightsally   first version
9 */
10 
11 #include <rtdevice.h>
12 #include <stdio.h>
13 #include <stdint.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <at91sam926x.h>
17 #include "at91_nand.h"
18 
19 static struct nand_chip_id *chip;
20 static unsigned int bufsize = 528;
21 static unsigned char pages_per_block = 32;
22 static unsigned char eccsize = 6;
23 static struct rt_mtd_nand_device _partition[2];
24 /*****************************************************************************
25 nand_calculate_ecc function copy from uboot
26 *****************************************************************************/
27 #define u_char unsigned char
28 /* Define default oob placement schemes for large and small page devices */
29 static struct nand_ecclayout nand_oob_16 =
30 {
31 
32     .eccbytes = 6,
33       .eccpos = {0, 1, 2, 3, 6, 7},
34       .oobfree = {
35             {
36             .offset = 8,
37             . length = 8
38             }
39     }
40 };
41 
42 static struct nand_ecclayout nand_oob_64 =
43 {
44     .eccbytes = 24,
45       .eccpos = {
46         40, 41, 42, 43, 44, 45, 46, 47,
47         48, 49, 50, 51, 52, 53, 54, 55,
48         56, 57, 58, 59, 60, 61, 62, 63
49     },
50     .oobfree = {
51         {
52         .offset = 2,
53         .length = 38
54         }
55         }
56 };
57 /*
58 * Pre-calculated 256-way 1 byte column parity
59 */
60 
61 static const u_char nand_ecc_precalc_table[] =
62 {
63     0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
64     0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
65     0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
66     0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
67     0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
68     0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
69     0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
70     0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
71     0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
72     0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
73     0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
74     0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
75     0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
76     0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
77     0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
78     0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00
79 };
80 
81 /**
82 * nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256-byte block
83 * @mtd:    MTD block structure
84 * @dat:    raw data
85 * @ecc_code:   buffer for ECC
86 */
nand_calculate_ecc(const u_char * dat,u_char * ecc_code)87 int nand_calculate_ecc(const u_char *dat, u_char *ecc_code)
88 {
89     uint8_t idx, reg1, reg2, reg3, tmp1, tmp2;
90     int i;
91 
92     /* Initialize variables */
93     reg1 = reg2 = reg3 = 0;
94 
95     /* Build up column parity */
96     for (i = 0; i < 256; i++)
97     {
98         /* Get CP0 - CP5 from table */
99         idx = nand_ecc_precalc_table[*dat++];
100         reg1 ^= (idx & 0x3f);
101 
102         /* All bit XOR = 1 ? */
103         if (idx & 0x40)
104         {
105             reg3 ^= (uint8_t) i;
106             reg2 ^= ~((uint8_t) i);
107         }
108     }
109 
110     /* Create non-inverted ECC code from line parity */
111     tmp1  = (reg3 & 0x80) >> 0; /* B7 -> B7 */
112     tmp1 |= (reg2 & 0x80) >> 1; /* B7 -> B6 */
113     tmp1 |= (reg3 & 0x40) >> 1; /* B6 -> B5 */
114     tmp1 |= (reg2 & 0x40) >> 2; /* B6 -> B4 */
115     tmp1 |= (reg3 & 0x20) >> 2; /* B5 -> B3 */
116     tmp1 |= (reg2 & 0x20) >> 3; /* B5 -> B2 */
117     tmp1 |= (reg3 & 0x10) >> 3; /* B4 -> B1 */
118     tmp1 |= (reg2 & 0x10) >> 4; /* B4 -> B0 */
119 
120     tmp2  = (reg3 & 0x08) << 4; /* B3 -> B7 */
121     tmp2 |= (reg2 & 0x08) << 3; /* B3 -> B6 */
122     tmp2 |= (reg3 & 0x04) << 3; /* B2 -> B5 */
123     tmp2 |= (reg2 & 0x04) << 2; /* B2 -> B4 */
124     tmp2 |= (reg3 & 0x02) << 2; /* B1 -> B3 */
125     tmp2 |= (reg2 & 0x02) << 1; /* B1 -> B2 */
126     tmp2 |= (reg3 & 0x01) << 1; /* B0 -> B1 */
127     tmp2 |= (reg2 & 0x01) << 0; /* B7 -> B0 */
128 
129     /* Calculate final ECC code */
130 #ifdef CONFIG_MTD_NAND_ECC_SMC
131     ecc_code[0] = ~tmp2;
132     ecc_code[1] = ~tmp1;
133 #else
134     ecc_code[0] = ~tmp1;
135     ecc_code[1] = ~tmp2;
136 #endif
137     ecc_code[2] = ((~reg1) << 2) | 0x03;
138 
139     return 0;
140 }
141 /*********nand_calculate_ecc function copy from uboot end*********************/
at91_nand_udelay(rt_uint32_t us)142 static void at91_nand_udelay(rt_uint32_t us)
143 {
144     rt_uint32_t len;
145     for (; us > 0; us --)
146         for (len = 0; len < 10; len++);
147 }
wait_udelay()148 static void wait_udelay()
149 {
150     if (chip->pagesize == 2048)at91_nand_udelay(2000);
151     else    at91_nand_udelay(1);
152 }
nand_enable_cs(void)153 void nand_enable_cs(void)
154 {
155     writel(0x00004000, 0xfffff834);
156     readl(0xfffff838);
157     //rt_kprintf("===i=0x%x\r\n",i);
158     wait_udelay();
159 }
nand_disable_cs(void)160 void nand_disable_cs(void)
161 {
162     writeb(0xff, 0x40400000);
163     writel(0x00004000, 0xfffff830);
164     readl(0xfffff830);
165     wait_udelay();
166 }
167 
nand_write_cmd(unsigned char cmd)168 void nand_write_cmd(unsigned char cmd)
169 {
170     writeb(cmd, CMD_REG);
171     wait_udelay();
172 }
nand_write_addr(unsigned char addr)173 void nand_write_addr(unsigned char addr)
174 {
175     writeb(addr, ADDR_REG);
176     wait_udelay();
177 }
nand_write_data_byte(unsigned char data)178 void nand_write_data_byte(unsigned char data)
179 {
180     writeb(data, DATA_REG);
181     wait_udelay();
182 }
183 
nand_read_data_byte(void)184 unsigned char nand_read_data_byte(void)
185 {
186     return readb(DATA_REG);
187 }
188 
nand_wait_ready(void)189 static int  nand_wait_ready(void)
190 {
191     unsigned int timeout = 10000;
192 
193     nand_write_cmd(CMD_STATUS);
194     while ((!(nand_read_data_byte() & STATUS_READY)) && timeout--);
195     if (!timeout)return -1;
196     return 0;
197 }
198 
199 //----------------------------------------------------------------
200 /* read chip id */
at9260_nand_read_id(struct rt_mtd_nand_device * device)201 static rt_err_t at9260_nand_read_id(struct rt_mtd_nand_device *device)
202 {
203     int manf_id, dev_id;
204     unsigned int chipid;
205     unsigned int i;
206 
207     nand_enable_cs();
208 
209     nand_write_cmd(CMD_READID);
210     nand_write_addr(CMD_READ_1);
211     manf_id  = nand_read_data_byte();
212     dev_id   = nand_read_data_byte();
213     nand_disable_cs();
214 
215     chipid = (manf_id << 8) | dev_id;
216 
217     for (i = 0; i < ARRAY_SIZE(nand_ids); i++)
218     {
219         if (chipid == nand_ids[i].chip_id)
220             break;
221     }
222 
223     if (i == ARRAY_SIZE(nand_ids))
224     {
225         rt_kprintf("NAND: Not found Manufacturer ID: %x," \
226             "Chip ID: 0x%x\n", manf_id, dev_id);
227         return -1;
228     }
229 
230     //find nand chip
231     rt_kprintf("NAND: Manufacturer ID: %x Chip ID: %x Total Block:%d\n", manf_id, dev_id, nand_ids[i].numblocks);
232 
233     chip->numblocks = nand_ids[i].numblocks;
234     chip->pagesize  = nand_ids[i].pagesize;
235     chip->blocksize = nand_ids[i].blocksize;
236     chip->oobsize   = nand_ids[i].oobsize;
237     chip->buswidth  = nand_ids[i].buswidth;
238     chip->numblocks = nand_ids[i].numblocks;
239 
240     bufsize = chip->pagesize + chip->oobsize;
241     eccsize = (chip->pagesize) * 3 / 256;
242 
243     if (chip->pagesize == 512)
244     {
245         pages_per_block = 32;
246         rt_kprintf("===small block pages===== \n");
247     }
248     else if (chip->pagesize == 2048)
249     {
250         pages_per_block = 64;
251         rt_kprintf("===big   block pages===== \n");
252     }
253 
254     return i;
255 }
256 
nand_read_page9260(unsigned int block,unsigned int page,unsigned char * data,rt_uint32_t data_len,unsigned char * spare,rt_uint32_t spare_len)257 int nand_read_page9260(unsigned int block, unsigned int page, unsigned char *data, rt_uint32_t data_len, unsigned char *spare, rt_uint32_t spare_len)
258 {
259     int i = 0;
260     unsigned int blockpage;
261     unsigned char buff1[bufsize];
262 
263     blockpage = block * (pages_per_block) + page;
264     memset(buff1, 0xff, bufsize);
265 
266     nand_enable_cs();
267     nand_write_cmd(CMD_READ_A0);
268     nand_write_addr(0);
269     if (bufsize == 2112)nand_write_addr(0);
270     nand_write_addr(blockpage & 0xff);
271     nand_write_addr((blockpage >> 8) & 0xff);
272     nand_write_addr((blockpage >> 16) & 0xff);
273 
274     at91_nand_udelay(2000);
275 
276     if (bufsize == 528)nand_write_cmd(CMD_READ_1);
277     else if (bufsize == 2112)nand_write_cmd(CMD_READ_2);
278 
279     for (i = 0; i < chip->pagesize; i++)buff1[i] = nand_read_data_byte();
280     for (i = 0; i < chip->oobsize; i++)buff1[i + chip->pagesize] = nand_read_data_byte();
281 
282     nand_wait_ready();
283     nand_disable_cs();
284 
285     if (data != RT_NULL)
286         rt_memcpy(data, buff1, data_len);
287     if (spare != RT_NULL)
288         rt_memcpy(spare, &buff1[chip->pagesize], spare_len);
289 
290     return 0x00;
291 }
292 //============================================================================
at9260_nand_read_page(struct rt_mtd_nand_device * device,rt_off_t page,rt_uint8_t * data,rt_uint32_t data_len,rt_uint8_t * spare,rt_uint32_t spare_len)293 static rt_err_t at9260_nand_read_page(struct rt_mtd_nand_device *device,
294                                       rt_off_t page,
295                                       rt_uint8_t *data, rt_uint32_t data_len,
296                                       rt_uint8_t *spare, rt_uint32_t spare_len)
297 
298 {
299     return nand_read_page9260(page / pages_per_block, page % pages_per_block, data, data_len, spare, spare_len);
300 }
301 
nand_write_page9260(unsigned int block,unsigned int page,unsigned char * data,rt_uint32_t data_len,unsigned char * spare,rt_uint32_t spare_len)302 int nand_write_page9260(unsigned int block, unsigned int page, unsigned char *data, rt_uint32_t data_len, unsigned char *spare, rt_uint32_t spare_len)
303 {
304     unsigned int blockpage;
305     unsigned char buff2[chip->pagesize];
306     unsigned char se[chip->oobsize];
307     unsigned char ecc_code[eccsize];
308     int i = 0;
309 
310     blockpage = block * (pages_per_block) + page;
311     memset(buff2, 0xff, chip->pagesize);
312     memset(se, 0xff, chip->oobsize);
313     memset(ecc_code, 0xff, eccsize);
314 
315     nand_enable_cs();
316     nand_write_cmd(CMD_WRITE_1);
317 
318     nand_write_addr(0);
319     if (bufsize == 2112)nand_write_addr(0);
320     nand_write_addr(blockpage & 0xff);
321     nand_write_addr((blockpage >> 8) & 0xff);
322     nand_write_addr((blockpage >> 16) & 0xff);
323 
324     at91_nand_udelay(2000);
325 
326     for (i = 0; i < data_len; i++)buff2[i] = *(data + i);
327     for (i = 0; i < chip->pagesize; i++)
328     {
329         nand_write_data_byte(buff2[i]);
330     }
331 
332 #ifndef RT_USING_DFS_UFFS
333     if (bufsize == 528)
334     {
335         //caclu ECC
336         nand_calculate_ecc(buff2, ecc_code);
337         nand_calculate_ecc(&buff2[256], &ecc_code[3]);
338         //use uboot MTD ECC layout
339         for (i = 0; i < 6; i++)
340         {
341             se[nand_oob_16.eccpos[i]] = ecc_code[i];
342         }
343     }
344     else if (bufsize == 2112)
345     {
346         //caclu ECC
347         for (i = 0; i < 8; i++)
348         {
349             nand_calculate_ecc(&buff2[256 * i], &(ecc_code[3 * i]));
350         }
351         //use uboot MTD ECC layout
352         for (i = 0; i < 24; i++)
353         {
354             se[nand_oob_64.eccpos[i]] = ecc_code[i];
355         }
356     }
357 #else
358     //UFFS do ECC
359     for (i = 0; i < chip->oobsize; i++)
360     {
361         se[i] = *(spare + i);
362     }
363 #endif
364 
365     for (i = 0; i < chip->oobsize; i++)
366     {
367         nand_write_data_byte(se[i]);
368     }
369 
370     nand_write_cmd(CMD_WRITE_2);
371     nand_wait_ready();
372     nand_disable_cs();
373 
374     return RT_EOK;
375 }
376 //===========================================================================================
at9260_nand_write_page(struct rt_mtd_nand_device * device,rt_off_t page,rt_uint8_t * data,rt_uint32_t data_len,rt_uint8_t * oob,rt_uint32_t spare_len)377 static rt_err_t at9260_nand_write_page(struct rt_mtd_nand_device *device,
378                                        rt_off_t page,
379                                        rt_uint8_t *data, rt_uint32_t data_len,
380                                        rt_uint8_t *oob, rt_uint32_t spare_len)
381 {
382 
383     return nand_write_page9260(page / pages_per_block, page % pages_per_block, data, data_len, oob, spare_len);
384 }
385 //===========================================================================================
at9260_nand_move_page(struct rt_mtd_nand_device * device,rt_off_t src_page,rt_off_t dst_page)386 static rt_err_t at9260_nand_move_page(struct rt_mtd_nand_device *device, rt_off_t src_page, rt_off_t dst_page)
387 {
388     return RT_EOK;
389 }
390 //===========================================================================================
at9260_nand_isbad(struct rt_mtd_nand_device * nand,uint32_t blk)391 static long at9260_nand_isbad(struct rt_mtd_nand_device *nand, uint32_t blk)
392 {
393     int i = 0;
394     unsigned char buff2[bufsize];
395     unsigned int blockpage = blk * (chip->blocksize / chip->pagesize) + 0;
396 
397     memset(buff2, 0xff, bufsize);
398 
399     //read blk page 0
400     nand_enable_cs();
401     nand_write_cmd(CMD_READ_A0);
402     nand_write_addr(0);
403     if (bufsize == 2112)nand_write_addr(0);
404     nand_write_addr(blockpage & 0xff);
405     nand_write_addr((blockpage >> 8) & 0xff);
406     nand_write_addr((blockpage >> 16) & 0xff);
407 
408     at91_nand_udelay(2000);
409 
410     if (bufsize == 528)nand_write_cmd(CMD_READ_1);
411     else if (bufsize == 2112)nand_write_cmd(CMD_READ_2);
412 
413     for (i = 0; i < bufsize; i++)
414     {
415         buff2[i] = nand_read_data_byte();
416     }
417     nand_disable_cs();
418 
419     if (bufsize == 528)
420     {
421         if (buff2[5 + 512] != 0xff)
422         {
423             rt_kprintf("\r\n Bad Block=0x%x: Cannot read page #0 of block #%d,addr=0x%x \n\r", buff2[5 + 512], blk, blk * 512 * 32);
424             return buff2[5 + 512];
425         }
426     }
427     else if (bufsize == 2112)
428     {
429         if ((buff2[2048 + 0] != 0xff) && (buff2[2048 + 1] != 0xff))
430         {
431             rt_kprintf("\r\n Bad Block=0x%x: Cannot read page #0 of block #%d,addr=0x%x \n\r", buff2[0 + 2048], blk, blk * 2048 * 64);
432             return buff2[0 + 2048] << 8 | buff2[0 + 2048];
433         }
434     }
435 
436     //read blk page 1
437     blockpage = blockpage + 1;
438     memset(buff2, 0xff, bufsize);
439     nand_enable_cs();
440     nand_write_cmd(CMD_READ_A0);
441     nand_write_addr(0);
442     if (bufsize == 2112)nand_write_addr(0);
443     nand_write_addr(blockpage & 0xff);
444     nand_write_addr((blockpage >> 8) & 0xff);
445     nand_write_addr((blockpage >> 16) & 0xff);
446     at91_nand_udelay(2000);
447 
448     if (bufsize == 528)nand_write_cmd(CMD_READ_1);
449     else if (bufsize == 2112)nand_write_cmd(CMD_READ_2);
450 
451 
452     for (i = 0; i < bufsize; i++)
453     {
454         buff2[i] = nand_read_data_byte();
455     }
456 
457     nand_disable_cs();
458 
459     if (bufsize == 528)
460     {
461         if (buff2[5 + 512] != 0xff)
462         {
463             rt_kprintf("\r\n Bad Block=0x%x: Cannot read page #1 of block #%d,addr=0x%x \n\r", buff2[5 + 512], blk, blk * 512 * 32);
464             return buff2[5 + 512];
465         }
466     }
467     else if (bufsize == 2112)
468     {
469         if ((buff2[2048 + 0] != 0xff) && (buff2[2048 + 1] != 0xff))
470         {
471             rt_kprintf("\r\n Bad Block=0x%x: Cannot read page #1 of block #%d,addr=0x%x \n\r", buff2[0 + 2048], blk, blk * 2048 * 64);
472             return buff2[0 + 2048] << 8 | buff2[0 + 2048];
473         }
474     }
475 
476     return GOODBLOCK;
477 }
478 
at9260_nand_markbad(struct rt_mtd_nand_device * nand,uint32_t blk)479 static long at9260_nand_markbad(struct rt_mtd_nand_device *nand, uint32_t blk)
480 {
481     unsigned int i = 0;
482     unsigned int blockpage = blk * (chip->blocksize / chip->pagesize) + 0;
483     unsigned char bad_flag = 0xff;
484     long ret_bad;
485 
486     ret_bad = at9260_nand_isbad(nand, blk);
487 
488     if (bufsize == 528)bad_flag = ret_bad & 0xff;
489     else if (bufsize == 2112)
490     {
491         if (bad_flag == 0xff)bad_flag = (ret_bad >> 8) & 0xff;
492     }
493 
494     if (bad_flag != 0xff)
495     {
496         nand_enable_cs();
497         nand_write_cmd(CMD_WRITE_1);
498         nand_write_addr(0);
499         if (bufsize == 2112)nand_write_addr(0);
500         nand_write_addr(blockpage & 0xff);
501         nand_write_addr((blockpage >> 8) & 0xff);
502         nand_write_addr((blockpage >> 16) & 0xff);
503         at91_nand_udelay(2000);
504 
505         for (i = 0; i < bufsize; i++)
506         {
507             nand_write_data_byte(0x00);
508         }
509 
510         nand_write_cmd(CMD_WRITE_2);
511         nand_wait_ready();
512         nand_disable_cs();
513     }
514     return RT_EOK;
515 }
516 //---------------------------------------------------------------------------------------------
517 /* erase block */
at9260_nand_erase_block(struct rt_mtd_nand_device * device,rt_uint32_t block)518 static rt_err_t at9260_nand_erase_block(struct rt_mtd_nand_device *device, rt_uint32_t block)
519 {
520     unsigned int row_address;
521 
522 
523     //Calculate address used for erase
524     row_address = (block) * (chip->blocksize / chip->pagesize);
525 
526     nand_enable_cs();
527     nand_write_cmd(CMD_ERASE_1);
528     nand_write_addr(row_address & 0xff);
529     nand_write_addr((row_address >> 8) & 0xff);
530     nand_write_addr((row_address >> 16) & 0xff);
531     nand_write_cmd(CMD_ERASE_2);
532 
533     at91_nand_udelay(2000);
534     nand_wait_ready();
535     nand_disable_cs();
536     return RT_EOK;
537 }
538 
539 const static struct rt_mtd_nand_driver_ops _ops =
540 {
541     at9260_nand_read_id,
542     at9260_nand_read_page,
543     at9260_nand_write_page,
544     at9260_nand_move_page,
545     at9260_nand_erase_block,
546 #ifndef RT_USING_DFS_UFFS
547     at9260_nand_isbad,
548     at9260_nand_markbad,
549 #else
550     RT_NULL,
551     RT_NULL,
552 #endif
553 };
554 
555 void nand_eraseall(void);
556 
rt_hw_mtd_nand_init(void)557 int rt_hw_mtd_nand_init(void)
558 {
559     unsigned int i, reg, index;
560 
561     /* Setup Smart Media, first enable the address range of CS3 in HMATRIX user interface  */
562     reg = readl(AT91C_BASE_CCFG + CCFG_EBICSA);
563     reg |= AT91C_EBI_CS3A_SM;
564     writel(reg, AT91C_BASE_CCFG + CCFG_EBICSA);
565     /* Configure SMC CS3 */
566     writel((AT91C_SMC_NWESETUP_(1) | AT91C_SMC_NCS_WRSETUP_(0)   | AT91C_SMC_NRDSETUP_(1) | AT91C_SMC_NCS_RDSETUP_(0)), AT91C_BASE_SMC + SMC_SETUP3);
567     writel((AT91C_SMC_NWEPULSE_(3) | AT91C_SMC_NCS_WRPULSE_(3)   | AT91C_SMC_NRDPULSE_(3) | AT91C_SMC_NCS_RDPULSE_(3)), AT91C_BASE_SMC + SMC_PULSE3);
568     writel((AT91C_SMC_NWECYCLE_(5) | AT91C_SMC_NRDCYCLE_(5)), AT91C_BASE_SMC + SMC_CYCLE3);
569     writel((AT91C_SMC_READMODE  | AT91C_SMC_WRITEMODE   | (0x0 << 5) | AT91C_SMC_DBW_WIDTH_BITS_8 | AT91_SMC_TDF_(2)),    AT91C_BASE_SMC + SMC_CTRL3);
570     /* {"NANDCS", AT91C_PIN_PC(14), 1, PIO_PULLUP, PIO_OUTPUT} */
571     writel((0x01 << 14), 0xfffff800 + 0x0044);
572     writel((0x01 << 14), 0xfffff800 + 0x0060);
573     writel((0x01 << 14), 0xfffff800 + 0x0030);
574     writel((0x01 << 14), 0xfffff800 + 0x0010);
575     writel((0x01 << 14), 0xfffff800 + 0x0000);
576     /* enable PIOC clock  */
577     writel(0x01 << 4, 0x10 + AT91C_BASE_PMC);
578     i = at9260_nand_read_id(RT_NULL);
579     index = i;
580 
581     chip->pagesize  = nand_ids[index].pagesize;
582     chip->blocksize = nand_ids[index].blocksize;
583     chip->oobsize   = nand_ids[index].oobsize;
584     chip->buswidth  = nand_ids[index].buswidth;
585     chip->numblocks = nand_ids[index].numblocks;
586 
587     _partition[0].page_size = chip->pagesize;
588     _partition[1].page_size = chip->pagesize;
589     _partition[0].pages_per_block = chip->blocksize / chip->pagesize;
590       _partition[1].pages_per_block = chip->blocksize / chip->pagesize;
591     _partition[0].oob_size = _partition[1].oob_size = chip->oobsize;
592     _partition[0].oob_free = _partition[1].oob_free = chip->oobsize - (chip->pagesize / 256 * 3); //oob_free = oob_size - ecc_size
593 
594 
595     _partition[0].block_total  = DATA_PART_ADDR / (chip->blocksize);
596     _partition[0].block_start  = 0;
597     _partition[0].block_end    = DATA_PART_ADDR / (chip->blocksize) - 1;
598 
599     _partition[1].block_total  = chip->numblocks - _partition[0].block_total;
600     _partition[1].block_start  = _partition[0].block_end + 1;
601     _partition[1].block_end    = chip->numblocks - 1;
602 
603     _partition[0].ops = &_ops;
604       _partition[1].ops = &_ops;
605 
606     rt_mtd_nand_register_device("nand0", &_partition[0]);
607     rt_mtd_nand_register_device("nand1", &_partition[1]);
608 
609     return RT_EOK;
610 }
611 INIT_DEVICE_EXPORT(rt_hw_mtd_nand_init);
612 
613 #if defined(RT_USING_FINSH)
614 #include <finsh.h>
nand_eraseall()615 void nand_eraseall()
616 {
617     int tmp=0;
618     int index=0;
619 
620 
621     if (chip->pagesize == 512)
622         tmp = (DATA_PART_ADDR / 0x4000);            //0X4000=512*32=PAGER_SIZE*PAGES_PER_BLOCK
623     else if (chip->pagesize == 2048)
624         tmp = (DATA_PART_ADDR / 0x20000);                     //0X20000=2048*64
625 
626     for (index=tmp; index < chip->numblocks; index ++)
627     {
628         at9260_nand_erase_block(RT_NULL, index);
629     }
630 }
631 FINSH_FUNCTION_EXPORT(nand_eraseall, erase all of block in the nand flash);
632 
633 #endif //RT_USING_FINSH
634 
635 
636