1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2011-05-25     Bernard      first version
9  */
10 
11 #include <rtdevice.h>
12 
13 #include "nand.h"
14 #include "mb9bf506r.h"
15 
16 /*
17  * NandFlash driver for SamSung K9F5608
18  * 32M x 8bit
19  */
20 #define PAGE_SIZE       512
21 #define PAGE_PER_BLOCK  32
22 #define BLOCK_NUM       2048
23 
24 /* device driver debug trace */
25 /* #define NAND_DEBUG */
26 #ifdef NAND_DEBUG
27 #define trace_log       rt_kprintf
28 #else
29 #define trace_log(...)
30 #endif
31 
32 /*
33  * OOB,
34  * when block has been erased,  OOB is 0xff.
35  * when block has been written, OOB is 0x00.
36  */
37 struct rt_device_nand
38 {
39     struct rt_device parent;    /* which is inherited from rt_device */
40 
41     rt_uint16_t block_num;      /* total block number in device     */
42     rt_uint16_t page_per_block; /* pages in one block               */
43     rt_uint16_t page_size;      /* page size                        */
44 
45     /* this buffer which used as to save data before erase block    */
46     rt_uint8_t  block_buffer[PAGE_SIZE * PAGE_PER_BLOCK];
47 };
48 static struct rt_device_nand _nand;
49 
50 /* Flash operation definition */
51 #define NF_CMD(cmd)     {*(volatile unsigned char*)(NF_FLASH_BASE_ADDR+NF_CMD_OFFSET) = (unsigned char)(cmd);}
52 #define NF_ADDR(addr)   {*(volatile unsigned char*)(NF_FLASH_BASE_ADDR+NF_ADDR_OFFSET)= (unsigned char)(addr);}
53 #define NF_RDDATA()     (*(volatile unsigned char*)(NF_FLASH_BASE_ADDR+NF_DATA_OFFSET))
54 #define NF_WRDATA(data) {*(volatile unsigned char*)(NF_FLASH_BASE_ADDR+NF_DATA_OFFSET)= (unsigned char)(data);}
55 #define NF_CLR_ALE()    {*(volatile unsigned char*)(NF_FLASH_BASE_ADDR+NF_ALE_OFFSET) = (unsigned char)0;}
56 
57 /* Flash Control IO definition */
58 #define NF_OE_H()       {IO_NF_PDOR |= NF_EN;}
59 #define NF_OE_L()       {IO_NF_PDOR &= ~NF_EN;}
60 
61 #define NF_DATA_OUT()   {IO_NF_PDOR &= ~NF_DATA_DIR;}
62 #define NF_DATA_IN()    {IO_NF_PDOR |= NF_DATA_DIR;}
63 
64 static unsigned char NF_ReadStatus(void);
65 static void Wait(unsigned int cnt);
66 static void NF_Reset(void);
67 
Wait(unsigned int cnt)68 static void Wait(unsigned int cnt)
69 {
70     while(cnt--);
71 }
72 
NF_Reset(void)73 static void NF_Reset(void)
74 {
75     NF_OE_L();
76     NF_DATA_OUT();
77     NF_CMD(NAND_CMD_RESET);
78     NF_OE_H();
79 
80     Wait(10000);  /* wait for Trst */
81 }
82 
NF_ReadStatus(void)83 static unsigned char NF_ReadStatus(void)
84 {
85     unsigned int timeout=0;
86     NF_DATA_OUT();
87     NF_CMD(NAND_CMD_STATUS);
88     NF_DATA_IN();
89 
90     while(!(NF_RDDATA() & 0x40))
91     {
92        timeout++;
93        if(timeout == 0x00080000)
94          return FLASH_NG;
95     }
96     if(NF_RDDATA() & 0x01)return FLASH_NG;
97 
98     return FLASH_OK;
99 }
100 
101 /*
102  * @ Funciton: NF_Init
103  *   Parameter: None
104  *   Return: None
105  */
NF_Init(void)106 static void NF_Init(void)
107 {
108     FM3_GPIO->PFR5 |= (0x7ff);      /*  D0-D5, CS7, ALE, CLE, WEX, REX */
109     FM3_GPIO->PFR3 |= (0x3);        /* D6-D7 */
110     FM3_GPIO->EPFR10 |= (1<<13      /* CS enable */
111                        |1<<6        /* ALE, CLE, WEX, REX enable */
112                        |1<<0);      /* D0-D7 enable */
113     FM3_EXBUS->AREA7 = 0x001f00e0;  /* Select CS7 area, 32Mbyte size */
114     FM3_EXBUS->MODE7 |= (1<<4);     /* Nand Flash mode turn on, set 8 bit width */
115 
116     IO_NF_PFR = IO_NF_PFR & ~(NF_EN|NF_DATA_DIR);
117     IO_NF_DDR = IO_NF_DDR | (NF_EN|NF_DATA_DIR);
118     IO_NF_PDOR = IO_NF_PDOR | (NF_EN | NF_DATA_DIR); /* disable Flash operation */
119 
120     /*Reset NAND*/
121     NF_Reset();
122 }
123 
NF_UnInit(void)124 static void NF_UnInit(void)
125 {
126     FM3_GPIO->PFR5 &= ~(0x7ff);     /*  disable D0-D5, CS7, ALE, CLE, WEX, REX */
127     FM3_GPIO->PFR3 &= ~(0x3);       /* disable D6-D7 */
128     FM3_GPIO->EPFR10 &= ~(1<<13     /* disable CS enable */
129                        |1<<6        /* disable ALE, CLE, WEX, REX enable */
130                        |1<<0);      /* disable D0-D7 enable */
131     FM3_EXBUS->MODE7 &= ~(1<<4);
132     IO_NF_PFR = IO_NF_PFR & ~(NF_EN|NF_DATA_DIR);
133     IO_NF_DDR = IO_NF_DDR | (NF_EN|NF_DATA_DIR);
134     IO_NF_PDOR = IO_NF_PDOR | (NF_EN | NF_DATA_DIR); /* disable Flash operation */
135 }
136 
137 /*
138  * @ Funciton: NF_ReadPage
139  *   Parameter: block (max: 2048)
140  *              page  (max:32)
141  *              buffer: pointer to data buffer
142  *   Return: 0: Flash Operation OK
143  *           1: Flash Operation NG
144  */
NF_ReadPage(unsigned int block,unsigned int page,unsigned char * buffer,unsigned char * oob)145 int NF_ReadPage(unsigned int block, unsigned int page, unsigned char *buffer,
146                 unsigned char *oob)
147 {
148     unsigned int blockPage,i;
149 
150     NF_Init();
151     blockPage=(block<<5)+page;                      /* 1 block=32 page */
152     NF_OE_L();
153     NF_DATA_OUT();
154     if (buffer != RT_NULL)
155     {
156         volatile unsigned char ch;
157 
158         NF_CMD(NAND_CMD_READ0);                     /* send read data */
159 
160         NF_ADDR(0);
161         NF_ADDR(blockPage & 0xff);
162         NF_ADDR((blockPage>>8) & 0xff);             /* send 3 byte address */
163         NF_CLR_ALE();
164         NF_DATA_IN();
165 
166         Wait(500);
167 
168         for(i=0;i<512;i++)                          /* read 512 bytes data */
169             buffer[i] = NF_RDDATA();
170         for(i=0;i<16;i++)                           /* read 16 bytes oob */
171             if (oob != RT_NULL)
172                 oob[i] = NF_RDDATA();
173             else
174                 ch = NF_RDDATA();
175     }
176     else
177     {
178         NF_CMD(NAND_CMD_READOOB);                   /* send read data */
179 
180         NF_ADDR(0);
181         NF_ADDR(blockPage & 0xff);
182         NF_ADDR((blockPage>>8) & 0xff);             /* send 3 byte address */
183         NF_CLR_ALE();
184         NF_DATA_IN();
185 
186         Wait(500);
187 
188         for (i=0; i<16; i++)                        /* read 16 bytes oob */
189            oob[i] = NF_RDDATA();
190     }
191 
192     NF_OE_H();
193     NF_UnInit();
194     return 0;
195 }
196 
197 /*
198  * @ Funciton: NF_EraseBlock
199  *   Parameter: block (max: 2048)
200  *   Return: 0: Flash Operation OK
201  *           1: Flash Operation NG
202  */
NF_EraseBlock(unsigned int block)203 int NF_EraseBlock(unsigned int block)
204 {
205     rt_uint32_t blockPage;
206 
207     trace_log("Erase block %d: ", block);
208 
209     NF_Init();
210     blockPage = (block << 5);
211     NF_OE_L();
212     NF_DATA_OUT();
213     NF_CMD(NAND_CMD_ERASE1);                        /* send erase command */
214     NF_ADDR(blockPage & 0xff);
215     NF_ADDR((blockPage >> 8) & 0xff);
216     NF_CMD(NAND_CMD_ERASE2);                        /* start erase */
217 
218     if(NF_ReadStatus())
219     {
220         NF_Reset();
221         NF_OE_H();
222         NF_UnInit();
223         trace_log("Failed\n");
224         rt_kprintf("erase block failed\n");
225 
226         return FLASH_NG;
227     }
228 
229     NF_OE_H();
230     NF_UnInit();
231 
232     trace_log("OK\n");
233 
234     return FLASH_OK;
235 }
236 
237 /*
238  * @ Funciton: NF_WritePage
239  *   Parameter: block (max: 2048)
240  *              page  (max:32)
241  *              buffer: pointer to data buffer
242  *   Return: 0: Flash Operation OK
243  *           1: Flash Operation NG
244  */
NF_WritePage(unsigned block,unsigned page,const rt_uint8_t * buffer)245 int NF_WritePage(unsigned block, unsigned page, const rt_uint8_t *buffer)
246 {
247     unsigned int blockPage,i;
248     unsigned char se[16] = {0};
249     unsigned char data;
250 
251     blockPage = (block<<5)+page;
252     NF_Init();
253     NF_OE_L();
254     NF_DATA_OUT();
255     NF_CMD(0x00);                                    /* set programming area */
256     NF_CMD(NAND_CMD_SEQIN);                          /* send write command */
257     NF_ADDR(0);
258     NF_ADDR(blockPage & 0xff);
259     NF_ADDR((blockPage>>8) & 0xff);
260     NF_CLR_ALE();
261 
262     for(i=0;i<512;i++) NF_WRDATA(buffer[i]);    /* write data */
263     for(i=0;i<16;i++) NF_WRDATA(se[i]);         /* dummy write */
264 
265     NF_CMD(NAND_CMD_PAGEPROG);                  /* start programming */
266 
267     if(NF_ReadStatus())
268     {
269         NF_Reset();
270         NF_OE_H();
271         NF_UnInit();
272 
273         trace_log("write failed\n");
274         return FLASH_NG;
275     }
276 
277     /* verify the write data */
278     NF_DATA_OUT();
279     NF_CMD(NAND_CMD_READ0);                     /* send read command */
280     NF_ADDR(0);
281     NF_ADDR(blockPage & 0xff);
282     NF_ADDR((blockPage>>8) & 0xff);
283     NF_CLR_ALE();
284     NF_DATA_IN();
285 
286     Wait(500);
287     for(i=0; i<512; i++)
288     {
289         data=NF_RDDATA();                       /* verify 1-512 byte */
290         if(data != buffer[i])
291         {
292             trace_log("block %d, page %d\n", block , page);
293             trace_log("write data failed[%d]: %02x %02x\n", i, data, buffer[i]);
294 
295             NF_Reset();
296             NF_OE_H();
297             NF_UnInit();
298             return FLASH_NG;
299         }
300     }
301 
302     for(i=0; i<16; i++)
303     {
304        data=NF_RDDATA();                        /* verify 16 byte dummy data */
305         if(data != se[i])
306         {
307             trace_log("block %d, page %d\n", block , page);
308             trace_log("write oob failed[%d]: %02x %02x\n", i, data, se[i]);
309             NF_Reset();
310             NF_OE_H();
311             NF_UnInit();
312             return FLASH_NG;
313         }
314     }
315 
316     NF_OE_H();
317     NF_UnInit();
318     return FLASH_OK;
319 }
320 
321 /*
322  * @ Funciton: NF_ReadID
323  *   Parameter: id: pointer to device ID
324  *   Return: None
325  */
NF_ReadID(unsigned char * id)326 void NF_ReadID(unsigned char *id)
327 {
328     unsigned char maker_code;
329     NF_Init();
330     NF_OE_L();
331     NF_DATA_OUT();
332     NF_CMD(NAND_CMD_READID);
333     NF_ADDR(0x00);
334     NF_CLR_ALE();
335     Wait(10);
336     NF_DATA_IN();
337     maker_code = NF_RDDATA();
338     maker_code = maker_code;
339     *id = NF_RDDATA();
340     NF_OE_H();
341     NF_UnInit();
342 }
343 
rt_nand_init(rt_device_t dev)344 static rt_err_t rt_nand_init (rt_device_t dev)
345 {
346     /* empty implementation */
347     return RT_EOK;
348 }
349 
rt_nand_open(rt_device_t dev,rt_uint16_t oflag)350 static rt_err_t rt_nand_open(rt_device_t dev, rt_uint16_t oflag)
351 {
352     /* empty implementation */
353     return RT_EOK;
354 }
355 
rt_nand_close(rt_device_t dev)356 static rt_err_t rt_nand_close(rt_device_t dev)
357 {
358     /* empty implementation */
359     return RT_EOK;
360 }
361 
362 /* nand device read */
rt_nand_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)363 static rt_ssize_t rt_nand_read (rt_device_t dev, rt_off_t pos, void* buffer,
364                                rt_size_t size)
365 {
366     rt_ubase_t block;           /* block of position */
367     rt_ubase_t page, index;     /* page in block of position */
368     rt_uint8_t *page_ptr, oob[16];
369     struct rt_device_nand *nand;
370 
371     /* get nand device */
372     nand = (struct rt_device_nand*) dev;
373     RT_ASSERT(nand != RT_NULL);
374 
375     /* get block and page */
376     block = pos / nand->page_per_block;
377     page  = pos % nand->page_per_block;
378 
379     trace_log("nand read: position %d, block %d, page %d, size %d\n",
380         pos, block, page, size);
381 
382     /* set page buffer pointer */
383     page_ptr = (rt_uint8_t*) buffer;
384     for (index = 0; index < size; index ++)
385     {
386         NF_ReadPage(block, page + index, page_ptr, oob);
387         page_ptr += nand->page_size;
388 
389         if (page + index > nand->page_per_block)
390         {
391             block += 1;
392             page = 0;
393         }
394     }
395 
396     /* return read size (count of block) */
397     return size;
398 }
399 
400 /*
401  * write pages by erase block first
402  * @param nand the nand device driver
403  * @param block the block of page
404  * @param page the page
405  * @param buffer the data buffer to be written
406  * @param pages the number of pages to be written
407  */
rt_nand_eraseblock_writepage(struct rt_device_nand * nand,rt_ubase_t block,rt_ubase_t page,const rt_uint8_t * buffer,rt_ubase_t pages)408 static int rt_nand_eraseblock_writepage(struct rt_device_nand* nand,
409                                         rt_ubase_t block, rt_ubase_t page,
410     const rt_uint8_t *buffer, rt_ubase_t pages)
411 {
412     rt_ubase_t index;
413     rt_uint32_t page_status;
414     rt_uint8_t *page_ptr, oob[16];
415 
416     /* set page status */
417     page_status = 0;
418 
419     /* read each page in block */
420     page_ptr = nand->block_buffer;
421     for (index = 0; index < nand->page_per_block; index ++)
422     {
423         NF_ReadPage(block, index, page_ptr, oob);
424         if (!oob[0])
425             page_status |= (1 << index);
426         page_ptr += nand->page_size;
427     }
428 
429     /* erase block */
430     NF_EraseBlock(block);
431 
432     page_ptr = &(nand->block_buffer[page * nand->page_size]);
433     /* merge buffer to page buffer */
434     for (index = 0; index < pages; index ++)
435     {
436         rt_memcpy(page_ptr, buffer, nand->page_size);
437 
438         /* set page status */
439         page_status |= (1 << (page + index));
440 
441         /* move to next page */
442         page_ptr += nand->page_size;
443         buffer += nand->page_size;
444     }
445 
446     /* write to flash */
447     page_ptr = nand->block_buffer;
448     for (index = 0; index < nand->page_per_block; index ++)
449     {
450         if (page_status & (1 << index))
451             NF_WritePage(block, index, page_ptr);
452 
453         /* move to next page */
454         page_ptr += nand->page_size;
455     }
456 
457     return 0;
458 }
459 
460 /* nand device write */
rt_nand_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)461 static rt_ssize_t rt_nand_write (rt_device_t dev, rt_off_t pos,
462                                 const void* buffer, rt_size_t size)
463 {
464     rt_ubase_t block, page;
465     rt_uint8_t oob[16];
466     struct rt_device_nand *nand;
467 
468     nand = (struct rt_device_nand*) dev;
469     RT_ASSERT(nand != RT_NULL);
470 
471     /* get block and page */
472     block = pos / nand->page_per_block;
473     page  = pos % nand->page_per_block;
474 
475     trace_log("nand write: position %d, block %d, page %d, size %d\n",
476         pos, block, page, size);
477 
478     if (size == 1)
479     {
480         /* write one page */
481 
482         /* read oob to get page status */
483         NF_ReadPage(block, page, RT_NULL, oob);
484         if (oob[0])
485             NF_WritePage(block, page, buffer);
486         else
487             /* erase block and then write page */
488             rt_nand_eraseblock_writepage(nand, block, page, buffer, 1);
489     }
490     else if (size > 1)
491     {
492         rt_ubase_t index;
493         rt_ubase_t need_erase_block;
494         const rt_uint8_t *page_ptr;
495         rt_ubase_t chunk_pages, pages;
496 
497         pages = size;
498         page_ptr = (const rt_uint8_t*) buffer;
499         do
500         {
501             need_erase_block = 0;
502             /* calculate pages in current chunk */
503             if (pages > nand->page_per_block - page)
504                 chunk_pages = nand->page_per_block - page;
505             else
506                 chunk_pages = pages;
507 
508             /* get page status in current block */
509             for (index = page; index < page + chunk_pages; index ++)
510             {
511                 NF_ReadPage(block, index, RT_NULL, oob);
512                 if (!oob[0])
513                 {
514                     /* this page has data, need erase this block firstly */
515                     need_erase_block = 1;
516                     break;
517                 }
518             }
519 
520             if (need_erase_block)
521             {
522                 /* erase block and then write it */
523                 rt_nand_eraseblock_writepage(nand, block, page, page_ptr, chunk_pages);
524                 page_ptr += chunk_pages * nand->page_size;
525             }
526             else
527             {
528                 /* write pages directly */
529                 for (index = page; index < page + chunk_pages; index ++)
530                 {
531                     NF_WritePage(block, index, page_ptr);
532                     page_ptr += nand->page_size;
533                 }
534             }
535 
536             pages -= chunk_pages;
537             page = 0; block ++; /* move to next block */
538         }
539         while (pages);
540     }
541 
542     return size;
543 }
544 
rt_nand_control(rt_device_t dev,int cmd,void * args)545 static rt_err_t rt_nand_control (rt_device_t dev, int cmd, void *args)
546 {
547     struct rt_device_nand *nand;
548 
549     nand = (struct rt_device_nand*) dev;
550     RT_ASSERT(dev != RT_NULL);
551 
552     switch (cmd)
553     {
554     case RT_DEVICE_CTRL_BLK_GETGEOME:
555         {
556             struct rt_device_blk_geometry *geometry;
557 
558             geometry = (struct rt_device_blk_geometry *)args;
559             if (geometry == RT_NULL) return -RT_ERROR;
560 
561             geometry->bytes_per_sector = nand->page_size;
562             geometry->block_size = nand->page_size * nand->page_per_block;
563             geometry->sector_count = nand->block_num * nand->page_per_block;
564         }
565         break;
566     }
567 
568     return RT_EOK;
569 }
570 
rt_hw_nand_init(void)571 void rt_hw_nand_init(void)
572 {
573     /* initialize nand flash structure */
574     _nand.block_num = BLOCK_NUM;
575     _nand.page_per_block = PAGE_PER_BLOCK;
576     _nand.page_size = PAGE_SIZE;
577 
578     rt_memset(_nand.block_buffer, 0, sizeof(_nand.block_buffer));
579 
580     _nand.parent.type       = RT_Device_Class_MTD;
581     _nand.parent.rx_indicate = RT_NULL;
582     _nand.parent.tx_complete = RT_NULL;
583     _nand.parent.init       = rt_nand_init;
584     _nand.parent.open       = rt_nand_open;
585     _nand.parent.close      = rt_nand_close;
586     _nand.parent.read       = rt_nand_read;
587     _nand.parent.write      = rt_nand_write;
588     _nand.parent.control    = rt_nand_control;
589 
590     /* register a MTD device */
591     rt_device_register(&(_nand.parent), "nand", RT_DEVICE_FLAG_RDWR);
592 }
593 
594 #ifdef NAND_DEBUG
595 #include <finsh.h>
596 unsigned char nand_buffer[512];
597 unsigned char nand_oob[16];
598 
dump_mem(unsigned char * buffer,int length)599 void dump_mem(unsigned char* buffer, int length)
600 {
601     int i;
602 
603     if (length > 64) length = 64;
604     for (i = 0; i < length; i ++)
605     {
606         rt_kprintf("%02x ", *buffer++);
607         if (((i+1) % 16) == 0)
608         rt_kprintf("\n");
609     }
610     rt_kprintf("\n");
611 }
612 
nand_read(int block,int page)613 void nand_read(int block, int page)
614 {
615     rt_kprintf("read block %d, page %d\n", block, page);
616 
617     NF_ReadPage(block, page, nand_buffer, nand_oob);
618     rt_kprintf("page data:\n");
619     dump_mem(nand_buffer, 512);
620     rt_kprintf("oob data:\n");
621     dump_mem(nand_oob, 16);
622 }
623 FINSH_FUNCTION_EXPORT_ALIAS(nand_read, read_page, read page[block/page]);
624 
nand_write(int block,int page)625 void nand_write(int block, int page)
626 {
627     int i;
628     for (i = 0; i < 512; i ++)
629         nand_buffer[i] = i;
630 
631     NF_WritePage(block, page, nand_buffer);
632 }
633 FINSH_FUNCTION_EXPORT_ALIAS(nand_write, write_page, write page[block/page]);
634 
nand_erase(int block)635 void nand_erase(int block)
636 {
637     NF_EraseBlock(block);
638 }
639 FINSH_FUNCTION_EXPORT_ALIAS(nand_erase, erase_block, erase block[block]);
640 
nand_readoob(int block,int page)641 void nand_readoob(int block, int page)
642 {
643     rt_kprintf("read oob on block %d, page %d\n", block, page);
644 
645     NF_ReadPage(block, page, RT_NULL, (unsigned char*)nand_oob);
646     rt_kprintf("oob data:\n");
647     dump_mem(nand_oob, 16);
648 }
649 FINSH_FUNCTION_EXPORT_ALIAS(nand_readoob, readoob, read oob[block/page]);
650 
nand_erase_chip(void)651 void nand_erase_chip(void)
652 {
653     int i;
654     unsigned char id;
655 
656     NF_ReadID(&id);
657     rt_kprintf("id: %02x\n", id);
658 
659     for (i = 0; i < 2048; i ++)
660     {
661         NF_EraseBlock(i);
662     }
663 }
664 FINSH_FUNCTION_EXPORT_ALIAS(nand_erase_chip, erase_chip, erase whole chip);
665 #endif
666