dfs_nand_if.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /*
  2. This file is part of UFFS, the Ultra-low-cost Flash File System.
  3. Copyright (C) 2005-2009 Ricky Zheng <ricky_gz_zheng@yahoo.co.nz>
  4. This exception does not invalidate any other reasons why a work based
  5. on this file might be covered by the GNU General Public License.
  6. */
  7. /**
  8. * \file nand flash interface example
  9. * \brief example for using nand flash driver and multiple partitions, with system memory allocator.
  10. * \author Ricky Zheng, created at 27 Nov, 2007
  11. */
  12. #include <rtthread.h>
  13. #include <stdio.h>
  14. #include <dfs_fs.h>
  15. #include "uffs/uffs_device.h"
  16. #include "uffs/uffs_flash.h"
  17. #include "uffs/uffs_mtb.h"
  18. #include "uffs/uffs_fs.h"
  19. #include "uffs/uffs_utils.h"
  20. #include "uffs/uffs_find.h"
  21. #include "uffs/uffs_fd.h"
  22. #include "uffs_ext.h"
  23. #include "k9f2g08.h"
  24. #define PFX "nand-drv:"
  25. /*
  26. * Note: all=0,read manufacturer id and device id only.
  27. * all=1,read all bytes,comprise additional ids.
  28. */
  29. static void nand_read_chip_ids(u8* buf, UBOOL all)
  30. {
  31. K9F2G08_ReadChipID(buf, all);
  32. }
  33. static int nand_write_page_data(uffs_Device *dev, u32 block, u32 page, const u8 *buffer, int len, u8 *ecc)
  34. {
  35. K9F2G08_WritePage(block,page,buffer,len,ecc);
  36. dev->st.page_write_count++;
  37. return UFFS_FLASH_NO_ERR;
  38. }
  39. static int nand_write_page_spare(uffs_Device *dev, u32 block, u32 page, const u8 *spare, int ofs, int len, UBOOL eod)
  40. {
  41. K9F2G08_WriteTags(block,page,spare,ofs,len);
  42. dev->st.spare_write_count++;
  43. return UFFS_FLASH_NO_ERR;
  44. }
  45. static int nand_read_page_data(uffs_Device *dev, u32 block, u32 page, u8 *buffer, int len, u8 *ecc)
  46. {
  47. K9F2G08_ReadPage(block,page,buffer,len,ecc);
  48. dev->st.page_read_count++;
  49. return UFFS_FLASH_NO_ERR;
  50. }
  51. static int nand_read_page_spare(uffs_Device *dev, u32 block, u32 page, u8 *spare, int ofs, int len)
  52. {
  53. K9F2G08_ReadTags(block,page,spare,ofs,len);
  54. dev->st.spare_read_count++;
  55. return UFFS_FLASH_NO_ERR;
  56. }
  57. static int nand_erase_block(uffs_Device *dev, u32 block)
  58. {
  59. K9F2G08_EraseBlock(block);
  60. dev->st.block_erase_count++;
  61. return UFFS_FLASH_NO_ERR;
  62. }
  63. static int nand_mark_badblock(uffs_Device *dev,u32 block)
  64. {
  65. return K9F2G08_Mark_badblk(block);
  66. }
  67. static int nand_is_badblock(uffs_Device *dev,u32 block)
  68. {
  69. return K9F2G08_Check_badblk(block);
  70. }
  71. static uffs_FlashOps nand_driver_ops =
  72. {
  73. nand_read_page_data, //ReadPageData
  74. nand_read_page_spare, //ReadPageSpare
  75. NULL, //ReadPageSpareWithLayout
  76. nand_write_page_data, //WritePageData
  77. nand_write_page_spare, //WritePageSpare
  78. NULL, //WriteFullPage
  79. nand_is_badblock, //IsBadBlock
  80. nand_mark_badblock, //MarkBadBlock
  81. nand_erase_block, //EraseBlock
  82. };
  83. //change these parameters to fit your nand flash specification
  84. //#define MAN_ID MAN_ID_SAMSUNG // simulate Samsung's NAND flash
  85. static struct uffs_StorageAttrSt flash_storage = {0};
  86. static int initDevice(uffs_Device *dev)
  87. {
  88. dev->ops = &nand_driver_ops;
  89. return RT_EOK;
  90. }
  91. static int releaseDevice(uffs_Device *dev)
  92. {
  93. return RT_EOK;
  94. }
  95. #include <dfs_uffs.h>
  96. static uffs_Device uffs_device = {0};
  97. /* define mount table,UFFS FS private data */
  98. /* it is absolute accessing for uffs.*/
  99. static uffs_MountTable uffs_mount_table =
  100. {
  101. &uffs_device,
  102. 0,
  103. TOTAL_BLOCKS-1,
  104. "/" ,
  105. NULL,
  106. };
  107. #include "nand.h"
  108. extern struct nand_flash_dev nand_flash_ids[];
  109. extern struct nand_manufacturers nand_manuf_ids[];
  110. struct nand_flash_dev* nand_init(u8* buf)
  111. {
  112. struct nand_flash_dev* type=RT_NULL;
  113. int i, dev_id,maf_id;
  114. K9F2G08_Reset();
  115. rt_kprintf("nand: ");
  116. nand_read_chip_ids(buf,0);
  117. maf_id= buf[0];
  118. /* Try to identify manufacturer */
  119. for (i = 0; nand_manuf_ids[i].id != 0x0; i++)
  120. {
  121. if (nand_manuf_ids[i].id == maf_id)
  122. {
  123. rt_kprintf("%s ",nand_manuf_ids[i].name);
  124. break;
  125. }
  126. }
  127. if(nand_manuf_ids[i].id == 0x0)
  128. {
  129. rt_kprintf("%s\n",nand_manuf_ids[i].name);
  130. return RT_NULL;
  131. }
  132. dev_id = buf[1];
  133. /* Lookup the flash id */
  134. for(i = 0; nand_flash_ids[i].name != RT_NULL; i++)
  135. {
  136. if(dev_id == nand_flash_ids[i].id)
  137. {
  138. type = &nand_flash_ids[i];
  139. rt_kprintf("%s\n",nand_flash_ids[i].name);
  140. return type;
  141. }
  142. }
  143. return RT_NULL;
  144. }
  145. /* RT-Thread Device Driver Interface */
  146. /* UFFS FileSystem NandFlash InterFace */
  147. /* we don't use entity, let uffs autarky */
  148. struct rt_device nand_device;
  149. static rt_err_t rt_nand_init(rt_device_t dev)
  150. {
  151. return 0;
  152. }
  153. static rt_err_t rt_nand_open(rt_device_t dev, u16 oflag)
  154. {
  155. return 0;
  156. }
  157. static rt_err_t rt_nand_close(rt_device_t dev)
  158. {
  159. return 0;
  160. }
  161. static rt_err_t rt_nand_control(rt_device_t dev, u8 cmd, void *args)
  162. {
  163. return 0;
  164. }
  165. static rt_size_t rt_nand_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
  166. {
  167. return 0;
  168. }
  169. static rt_size_t rt_nand_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
  170. {
  171. return 0;
  172. }
  173. void rt_hw_nand_init(void)
  174. {
  175. struct nand_flash_dev *type = RT_NULL;
  176. u8 buf[5];
  177. if((type = nand_init(buf)) != RT_NULL)
  178. {
  179. uffs_MountTable *entry;
  180. struct uffs_StorageAttrSt *chip = &flash_storage;
  181. rt_device_t dev = &nand_device;
  182. /* fill in NandFlash device struct */
  183. dev->type = RT_Device_Class_Block;
  184. dev->init = rt_nand_init;
  185. dev->open = rt_nand_open;
  186. dev->close = rt_nand_close;
  187. dev->read = rt_nand_read;
  188. dev->write = rt_nand_write;
  189. dev->control = rt_nand_control;
  190. dev->user_data = &uffs_mount_table;
  191. /* register nandfalsh device */
  192. rt_device_register(&nand_device, "nand0",
  193. RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
  194. /* about uffs codes */
  195. entry = &uffs_mount_table;
  196. //entry->lock = rt_sem_create("sem_nand0", 1, RT_IPC_FLAG_FIFO);//??it's lonely!how to do?
  197. uffs_MemSetupSystemAllocator(&(entry->dev->mem));
  198. entry->dev->Init = initDevice;
  199. entry->dev->Release = releaseDevice;
  200. entry->dev->attr = chip;
  201. uffs_RegisterMountTable(entry);
  202. /* Newer devices have all the information in additional id bytes */
  203. if(!type->pagesize)
  204. {
  205. int extid;
  206. nand_read_chip_ids(buf,1);//reread chip ids,the all and the one.
  207. /* The 3rd id byte holds MLC / multichip data,untapped */
  208. /* The 4th id byte is the important one */
  209. extid = buf[3];
  210. /* Calc pagesize */
  211. chip->page_data_size = 1024 << (extid & 0x3);
  212. extid >>= 2;
  213. /* Calc oobsize */
  214. chip->spare_size = (8<<(extid & 0x01))*(chip->page_data_size>>9);
  215. extid >>= 2;
  216. /* Calc blocksize. Blocksize is multiples of 64KiB */
  217. chip->pages_per_block = ((64*1024)<<(extid & 0x03))/(chip->page_data_size);
  218. /* The 5th id byte */
  219. chip->total_blocks = (type->chipsize*1024*1024) /
  220. chip->page_data_size / chip->pages_per_block;
  221. }
  222. else
  223. { /* Old devices have chip data hardcoded in the device id table */
  224. chip->page_data_size = type->pagesize;
  225. chip->pages_per_block = type->blocksize / type->pagesize;
  226. chip->spare_size = chip->page_data_size / 32;
  227. chip->total_blocks = (type->chipsize*1024*1024) / type->blocksize;
  228. }
  229. if(type->options & NAND_SAMSUNG_LP_OPTIONS)
  230. chip->block_status_offs = NAND_LARGE_BADBLOCK_POS;
  231. else
  232. chip->block_status_offs = NAND_SMALL_BADBLOCK_POS;
  233. chip->ecc_opt = UFFS_ECC_SOFT; /* ecc option, do not use ECC,debug */
  234. chip->layout_opt = UFFS_LAYOUT_UFFS; /* let UFFS do the spare layout */
  235. #if (0) //DEBUG trace facility
  236. rt_kprintf("page_data_size = %d\n",chip->page_data_size);
  237. rt_kprintf("pages_per_block = %d\n",chip->pages_per_block);
  238. rt_kprintf("spare_size = %d\n",chip->spare_size);
  239. rt_kprintf("total_blocks = %d\n",chip->total_blocks);
  240. rt_kprintf("block_stat_offs = %d\n",chip->block_status_offs);
  241. #endif
  242. }
  243. }
  244. //end of file