dfs_nand_if.c 7.8 KB

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