k9f2g08.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. /**
  2. * 用户要自己实现这个文件中的接口函数,不一样的芯片会有不同的访问命令
  3. * 这个例程文件是关于Samsung k9f2g08芯片的,属于大页nandflash
  4. */
  5. #include <nand.h>
  6. #include "s3c24x0.h"
  7. #include <k9f2g08.h>
  8. #define nand_write_cmd(cmd) (NFCMD = (cmd))
  9. #define nand_write_addr(addr) (NFADDR = (addr))
  10. #define nand_cs_en() (NFCONT &= ~(1<<1))
  11. #define nand_cs_ds() (NFCONT |= (1<<1))
  12. #define nand_Init_ECC() (NFCONT |= (1<<4))
  13. #define nand_read() (NFDATA8)
  14. #define nand_write(data) (NFDATA8 = (data))
  15. #define nand_wait() {while(!(NFSTAT&(1<<0)));} //wait tWB and check F_RNB pin.
  16. //NAND Flash Command.support K9F2G08
  17. #define K9F2G08_CMD_READ0 0x00 // Read0
  18. //#define K9F2G08_CMD_READ1 1 // Read1,K9F2G08 don't support the command.
  19. #define K9F2G08_CMD_RANDOM_DATA_OUT 0x05 // Random data output
  20. #define K9F2G08_CMD_PAGEPROG 0x10 // Write phase 2
  21. #define K9F2G08_CMD_READ30 0x30 // Read30
  22. #define K9F2G08_CMD_READ35 0x35 // Read35
  23. //#define K9F2G08_CMD_READOOB 0x50 // Read oob
  24. #define K9F2G08_CMD_ERASE1 0x60 // Erase phase 1
  25. #define K9F2G08_CMD_STATUS 0x70 // Status read
  26. #define K9F2G08_CMD_READ_EDC 0x7b // Read EDC Status
  27. #define K9F2G08_CMD_SEQIN 0x80 // Write phase 1
  28. #define K9F2G08_CMD_RANDOM_DATA_IN 0x85 // Random data input Copy-Back Program(0x85,0x10)
  29. #define K9F2G08_CMD_READID 0x90 // ReadID,all-purpose command
  30. #define K9F2G08_CMD_ERASE2 0xd0 // Erase phase 2
  31. #define K9F2G08_CMD_RESET 0xff // Reset
  32. #define BAD_CHECK (0)
  33. #define ECC_CHECK (0)
  34. //*************************************************
  35. //** H/W dependent functions **
  36. //*************************************************
  37. // HCLK=100Mhz
  38. #define TACLS 1 //1clk(0ns)
  39. #define TWRPH0 4 //3clk(25ns)
  40. #define TWRPH1 0 //1clk(10ns) //TACLS+TWRPH0+TWRPH1>=50ns
  41. int read_nand_stats(void) // R/B 未接好?
  42. {
  43. u8 stat;
  44. nand_write_cmd(K9F2G08_CMD_STATUS);//0x70
  45. stat = nand_read();//读出返回的数据
  46. if(stat&1) return 1; // I/O0=1失败
  47. else return 0; // I/O0=0成功
  48. }
  49. //擦除一个块
  50. //返回0,successful
  51. //返回1,error
  52. int K9F2G08_EraseBlock(u32 block)
  53. {
  54. int stat;
  55. u32 _page = block*PAGES_PER_BLOCK;
  56. nand_cs_en();
  57. nand_write_cmd(K9F2G08_CMD_ERASE1); // Erase one block 1st command
  58. nand_write_addr(_page&0xff); // Page number=0
  59. nand_write_addr((_page>>8)&0xff);
  60. nand_write_addr((_page>>16)&0xff);
  61. nand_write_cmd(K9F2G08_CMD_ERASE2); // Erase one blcok 2nd command
  62. nand_wait(); // Wait tBERS max 3ms.
  63. stat = read_nand_stats();
  64. nand_cs_ds();
  65. return stat;
  66. }
  67. //return 1 if it's a bad block, 0 if it's good.
  68. int K9F2G08_Check_badblk(u32 block) //0:bad,1:good
  69. {
  70. u8 data;
  71. u32 _page;//块的首页地址
  72. _page = block*PAGES_PER_BLOCK; // For 2'nd cycle I/O[7:5]
  73. nand_cs_en();
  74. nand_write_cmd(K9F2G08_CMD_READ0); // Spare array read command
  75. nand_write_addr(PAGE_DATA_SIZE&0xff); // Read the mark of bad block in spare array(M addr=5)
  76. nand_write_addr((PAGE_DATA_SIZE>>8)&0xff);
  77. nand_write_addr(_page&0xff); // The mark of bad block is in 0 page
  78. nand_write_addr((_page>>8)&0xff); // For block number A[24:17]
  79. nand_write_addr((_page>>16)&0xff); // For block number A[25]
  80. nand_write_cmd(K9F2G08_CMD_READ30);
  81. nand_wait(); // Wait tR(max 12us)
  82. data=nand_read();
  83. nand_cs_ds();
  84. if(data==0x00)
  85. return 1;//坏块
  86. else
  87. return 0;//好块
  88. }
  89. //return 0 if ok, 1:fail
  90. int K9F2G08_Mark_badblk(u32 block)
  91. {
  92. u8 stat;
  93. u32 _page = block*PAGES_PER_BLOCK;
  94. nand_cs_en();
  95. nand_write_cmd(K9F2G08_CMD_SEQIN); // Write 1st command
  96. nand_write_addr(PAGE_DATA_SIZE & 0xff); // The mark of bad block
  97. nand_write_addr((PAGE_DATA_SIZE>>8)&0xff);
  98. nand_write_addr(_page&0xff); // marked 5th spare array
  99. nand_write_addr((_page>>8)&0xff); // in the 1st page.
  100. nand_write_addr((_page>>16)&0xff); //
  101. nand_write(0x00); //坏块标记
  102. nand_write_cmd(K9F2G08_CMD_PAGEPROG); // Write 2nd command
  103. nand_wait(); // Wait tPROG(200~500us)
  104. stat = read_nand_stats();//查询是否成功
  105. nand_cs_ds();
  106. return stat;
  107. }
  108. int K9F2G08_ReadPage(u32 block, u32 page, u8 *buffer, int len, u8 *ecc)
  109. {
  110. int i;
  111. u32 _page = block*PAGES_PER_BLOCK + page;
  112. // NF_RSTECC(); // Initialize ECC
  113. nand_cs_en();
  114. nand_write_cmd(K9F2G08_CMD_READ0); // Read command
  115. nand_write_addr(0x00); // Column = 0
  116. nand_write_addr(0x00);
  117. nand_write_addr(_page&0xff); //
  118. nand_write_addr((_page>>8)&0xff); // Block & Page num.
  119. nand_write_addr((_page>>16)&0xff); //
  120. nand_write_cmd(K9F2G08_CMD_READ30);
  121. nand_wait(); // Wait tR(max 12us)
  122. for(i=0;i<len;i++)
  123. {
  124. buffer[i] = nand_read(); // Read one page
  125. }
  126. nand_cs_ds();
  127. return 1;
  128. }
  129. int K9F2G08_ReadTags(u32 block, u32 page, u8 *spare, int ofs, int len)
  130. {
  131. int i;
  132. u32 _page = block*PAGES_PER_BLOCK + page;
  133. // NF_RSTECC(); // Initialize ECC
  134. nand_cs_en();
  135. nand_write_cmd(K9F2G08_CMD_READ0); // Read command
  136. nand_write_addr((PAGE_DATA_SIZE+ofs)&0xff); // Column = 0
  137. nand_write_addr(((PAGE_DATA_SIZE+ofs)>>8)&0xff);
  138. nand_write_addr(_page&0xff); //
  139. nand_write_addr((_page>>8)&0xff); // Block & Page num.
  140. nand_write_addr((_page>>16)&0xff); //
  141. nand_write_cmd(K9F2G08_CMD_READ30);
  142. nand_wait(); // Wait tR(max 12us)
  143. for(i=0;i<len;i++)
  144. {
  145. spare[i] = nand_read(); // Read one page
  146. }
  147. nand_cs_ds();
  148. return 1;
  149. }
  150. //写一页数据
  151. //返回0,successful
  152. //返回1,error
  153. int K9F2G08_WritePage(u32 block, u32 page, const u8 *buffer, int len, const u8 *ecc)
  154. {
  155. int i,stat;
  156. u32 _page = block*PAGES_PER_BLOCK + page;
  157. //nand_Init_ECC(); // Initialize ECC
  158. nand_cs_en();
  159. nand_write_cmd(K9F2G08_CMD_SEQIN); //0x80 Write 1st command
  160. for(i=0;i<10;i++);
  161. nand_write_addr(0x00); // Column 0
  162. nand_write_addr(0x00);
  163. nand_write_addr(_page&0xff); //
  164. nand_write_addr((_page>>8)&0xff); // Block & page num.
  165. nand_write_addr((_page>>16)&0xff); //
  166. for(i=0;i<len;i++)
  167. {
  168. nand_write(*buffer++); // Write one page to NFM from buffer
  169. }
  170. nand_write_cmd(K9F2G08_CMD_PAGEPROG); //0x10 Write 2nd command
  171. nand_wait(); //wait tPROG 200~500us;
  172. stat = read_nand_stats();
  173. nand_cs_ds();
  174. return stat;
  175. }
  176. int K9F2G08_WriteTags(u32 block, u32 page, const u8 *spare, int ofs, int len)
  177. {
  178. int i,stat;
  179. u32 _page = block*PAGES_PER_BLOCK + page;
  180. //nand_Init_ECC(); // Initialize ECC
  181. nand_cs_en();
  182. nand_write_cmd(K9F2G08_CMD_SEQIN); //0x80 Write 1st command
  183. for(i=0;i<10;i++);
  184. nand_write_addr((PAGE_DATA_SIZE+ofs)&0xff); // Column 0
  185. nand_write_addr(((PAGE_DATA_SIZE+ofs)>>8)&0xff);
  186. nand_write_addr(_page&0xff); //
  187. nand_write_addr((_page>>8)&0xff); // Block & page num.
  188. nand_write_addr((_page>>16)&0xff); //
  189. for(i=0;i<len;i++)
  190. {
  191. nand_write(*spare++); // Write one page to NFM from buffer
  192. }
  193. nand_write_cmd(K9F2G08_CMD_PAGEPROG); //0x10 Write 2nd command
  194. nand_wait(); //wait tPROG 200~500us;
  195. stat = read_nand_stats();
  196. if(!stat) // Page write error
  197. {
  198. nand_cs_ds();
  199. return 0;
  200. }
  201. else
  202. {
  203. nand_cs_ds();
  204. return 1;
  205. }
  206. }
  207. //find frist shift bit
  208. //rt_inline int generic_ffs(int x)
  209. //{
  210. // int r = 1;
  211. //
  212. // if(!x)
  213. // return 0;
  214. //
  215. // if(!(x & 0xffff)) {x >>= 16;r += 16;}
  216. // if(!(x & 0xff)) {x >>= 8;r += 8;}
  217. // if(!(x & 0xf)) {x >>= 4;r += 4;}
  218. // if(!(x & 3)) {x >>= 2;r += 2;}
  219. // if(!(x & 1)) {x >>= 1;r += 1;}
  220. //
  221. // return r;
  222. //}
  223. /* when all is true,read all byte */
  224. void K9F2G08_ReadChipID(u8* buf, UBOOL all)
  225. {
  226. nand_cs_en();
  227. nand_write_cmd(K9F2G08_CMD_READID); //0x90
  228. nand_write_addr(K9F2G08_CMD_READ0);
  229. buf[0] = nand_read();//制造商ID
  230. buf[1] = nand_read();//芯片ID
  231. if(all)
  232. {
  233. buf[2] = nand_read();
  234. buf[3] = nand_read();
  235. //buf[4] = nand_read(); //有的芯片没有第5个字节
  236. }
  237. nand_cs_ds();
  238. }
  239. void K9F2G08_Init(void)
  240. {
  241. NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0);
  242. NFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0);
  243. NFSTAT = 0;
  244. // 1 1 1 1, 1 xxx, r xxx, r xxx
  245. // En 512B 4step ECCR nFCE=H tACLS tWRPH0 tWRPH1
  246. }
  247. void K9F2G08_Reset(void)
  248. {
  249. nand_cs_en();
  250. nand_write_cmd(0xFF); //reset command
  251. nand_wait(); //wait 200~500us;
  252. nand_cs_ds();
  253. K9F2G08_Init();
  254. }
  255. #if (0)
  256. int K9F2G08_ReadChunk(u32 chunk, u8 *data, u8 *tags)
  257. {
  258. int i;
  259. nand_cs_en();
  260. nand_write_cmd(K9F2G08_CMD_READ0); // Read command
  261. nand_write_addr(0x00);
  262. nand_write_addr(0x00);
  263. nand_write_addr(chunk & 0xff); //
  264. nand_write_addr((chunk >> 8) & 0xff); // Block & Page num.
  265. nand_write_addr((chunk >> 16) & 0xff); //
  266. //nand_Init_ECC();
  267. nand_write_cmd(K9F2G08_CMD_READ30); // Read command
  268. nand_wait(); // Wait tR(max 12us)
  269. for(i = 0; i < PAGE_DATA_SIZE; i++)
  270. {
  271. data[i] = nand_read(); // Read one page
  272. }
  273. for(i = 0; i < PAGE_SPARE_SIZE; i++)
  274. {
  275. tags[i] = nand_read(); // Read spare array
  276. }
  277. nand_cs_ds();
  278. return 1;
  279. }
  280. #endif