at91_nand.c 19 KB

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