spinand.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
  1. /**************************************************************************//**
  2. *
  3. * @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. *
  7. * Change Logs:
  8. * Date Author Notes
  9. * 2021-1-13 Wayne First version
  10. *
  11. ******************************************************************************/
  12. #include <rtthread.h>
  13. #if defined(NU_PKG_USING_SPINAND)
  14. #define LOG_TAG "spinand_flash"
  15. #define DBG_ENABLE
  16. #define DBG_SECTION_NAME LOG_TAG
  17. #define DBG_LEVEL DBG_INFO
  18. #define DBG_COLOR
  19. #include <rtdbg.h>
  20. #include "spinand.h"
  21. const struct nu_spinand_info g_spinandflash_list[] =
  22. {
  23. /* Winbond */
  24. /* Only tested */
  25. {
  26. 0xEFAA21, 2048, 64, 0x6b, 0xff, 0xff, 0xff, 0x1, 1024, 64, 0, "Winbond 128MB: 2048+64@64@1024",
  27. #if defined(RT_USING_DFS_UFFS)
  28. {
  29. /* For storing Seal-byte at 0x37. Need 15-Bytes */
  30. 0x04, 0x04, 0x14, 0x04, 0x24, 0x04, 0x34, 0x03, 0xFF, 0x00
  31. },
  32. {
  33. /* For storing Seal-byte at 0x37 and not report latest ECC part in Spare-3 */
  34. 0x08, 0x08, 0x18, 0x08, 0x28, 0x08, /*0x38, 0x08,*/ 0xFF, 0x00
  35. }
  36. #else
  37. {
  38. 0x04, 0x04, 0x14, 0x04, 0x24, 0x04, 0x34, 0x04, 0xFF, 0x00
  39. },
  40. {
  41. 0x08, 0x08, 0x18, 0x08, 0x28, 0x08, 0x38, 0x08, 0xFF, 0x00
  42. }
  43. #endif
  44. },
  45. {
  46. 0xEFBF22, 2048, 64, 0x6b, 0xff, 0xff, 0xff, 0x1, 2048, 64, 0, "Winbond 256MB: 2048+64@64@2048",
  47. #if defined(RT_USING_DFS_UFFS)
  48. {
  49. /* For storing Seal-byte at 0x39. Need 15-Bytes */
  50. 0x08, 0x04, 0x18, 0x04, 0x28, 0x04, 0x38, 0x03, 0xFF, 0x00
  51. },
  52. {
  53. /* For storing Seal-byte at 0x39 and not report latest ECC part in Spare-3 */
  54. 0x0C, 0x04, 0x1C, 0x04, 0x2C, 0x04, /*0x3C, 0x04,*/ 0xFF, 0x00
  55. }
  56. #else
  57. {
  58. 0x08, 0x04, 0x18, 0x04, 0x28, 0x04, 0x38, 0x04, 0xFF, 0x00
  59. },
  60. {
  61. 0x0C, 0x04, 0x1C, 0x04, 0x2C, 0x04, 0x3C, 0x04, 0xFF, 0x00
  62. }
  63. #endif
  64. },
  65. #if 0
  66. { 0xEFAA22, 2048, 64, 0x6b, 0xff, 0xff, 0xff, 0x1, 2048, 64, 0, "Winbond 256MB: 2048+64@64@1024" },
  67. { 0xEFAB21, 2048, 64, 0x6b, 0xff, 0xff, 0xff, 0x1, 1024, 64, 1, "Winbond 256MB: 2048+64@64@1024, MCP" },
  68. /* Not test and supporting yet. */
  69. /* MXIC */
  70. { 0x00C212, 2048, 64, 0x6b, 0x05, 0x01, 0x40, 0x1, 1024, 64, 0, "MXIC 128MB: 2048+64@64@1024" },
  71. /* XTX */
  72. { 0x0BE20B, 2048, 64, 0x6b, 0xff, 0xff, 0xff, 0x1, 2048, 64, 0, "XTX 256MB: 2048+64@64@2048" },
  73. { 0x0BF20B, 2048, 64, 0x6b, 0xff, 0xff, 0xff, 0x1, 2048, 64, 0, "XTX 256MB: 2048+64@64@2048" },
  74. { 0x0BE10B, 2048, 64, 0x6b, 0xff, 0xff, 0xff, 0x1, 1024, 64, 0, "XTX 256MB: 2048+64@64@1024" },
  75. { 0x0BF10B, 2048, 64, 0x6b, 0xff, 0xff, 0xff, 0x1, 1024, 64, 0, "XTX 256MB: 2048+64@64@1024" },
  76. /* ATO */
  77. { 0x9B129B, 2048, 64, 0x6b, 0x0f, 0x1f, 0x01, 0x1, 1024, 64, 0, "ATO 128MB: 2048+64@64@1024" },
  78. /* Micro */
  79. { 0x2C242C, 2048, 128, 0x6b, 0x0f, 0x1f, 0x01, 0x1, 2048, 64, 0, "Micro 256MB: 2048+128@64@2048" },
  80. /* GigaDevice */
  81. { 0xB148C8, 2048, 128, 0x6b, 0x0f, 0x1f, 0x01, 0x1, 1024, 64, 0, "GD 128MB: 2048+128@64@1024" },
  82. /* Unknown */
  83. { 0x00C8D1, 2048, 128, 0x6b, 0x0f, 0x1f, 0x01, 0x1, 1024, 64, 0, "Unknown 128MB: 2048+128@64@1024" },
  84. { 0x00C851, 2048, 128, 0x6b, 0x0f, 0x1f, 0x01, 0x1, 1024, 64, 0, "Unknown 128MB: 2048+128@64@1024" },
  85. { 0x98E240, 2048, 128, 0x6b, 0x0f, 0x1f, 0x01, 0x1, 1024, 64, 0, "Unknown 128MB: 2048+128@64@1024" }
  86. #endif
  87. };
  88. #define SPINAND_LIST_ELEMENT_NUM ( sizeof(g_spinandflash_list)/sizeof(struct nu_spinand_info) )
  89. /*
  90. ========================================================
  91. For 0xEFAA21 description:
  92. Data Area(2048-Byte)
  93. -----------------------------
  94. |Sect-0|Sect-1|Sect-2|Sect-3|
  95. |(512B)|(512B)|(512B)|(512B)|
  96. -----------------------------
  97. Spare Area(64-Byte)
  98. ---------------------------------
  99. |Spare-0|Spare-1|Spare-2|Spare-3|
  100. | (16B) | (16B) | (16B) | (16B) |
  101. ---------------------------------
  102. ----------------- Spare-0 -------------------
  103. / \
  104. -------------------------------------------------
  105. | BBM | UD2 | UD1 | ECC Sect-0 | ECC Spare |
  106. | 0 1 | 2 3 | 4 5 6 7 | 8 9 A B C D | E F |
  107. -------------------------------------------------
  108. | NO ECC | ECC PROTECTED | ECC 4-D |
  109. BBM: Bad block marker.
  110. UD1: User Data 1.
  111. UD2: User Data 2.
  112. ECC Sect-n: ECC for sector-n.
  113. ECC Spare: ECC for spare 4-D.
  114. ---------------- Spare-1 -------------------
  115. / \
  116. -----------------------------------------------
  117. | UD2 | UD1 | ECC Sect-1 | ECC Spare |
  118. | 0 1 2 3 | 4 5 6 7 | 8 9 A B C D | E F |
  119. -----------------------------------------------
  120. | NO ECC | ECC PROTECTED | ECC 14-1D |
  121. ---------------- Spare-2 -------------------
  122. / \
  123. -----------------------------------------------
  124. | UD2 | UD1 | ECC Sect-2 | ECC Spare |
  125. | 0 1 2 3 | 4 5 6 7 | 8 9 A B C D | E F |
  126. -----------------------------------------------
  127. | NO ECC | ECC PROTECTED | ECC 24-2D |
  128. ---------------- Spare-3 -------------------
  129. / \
  130. -----------------------------------------------
  131. | UD2 | UD1 | ECC Sect-3 | ECC Spare |
  132. | 0 1 2 3 | 4 5 6 7 | 8 9 A B C D | E F |
  133. -----------------------------------------------
  134. | NO ECC | ECC PROTECTED | ECC 34-3D |
  135. ========================================================
  136. ========================================================
  137. For 0xEFBF22 description:
  138. Data Area(2048-Byte)
  139. -----------------------------
  140. |Sect-0|Sect-1|Sect-2|Sect-3|
  141. |(512B)|(512B)|(512B)|(512B)|
  142. -----------------------------
  143. Spare Area(64-Byte)
  144. ---------------------------------
  145. |Spare-0|Spare-1|Spare-2|Spare-3|
  146. | (16B) | (16B) | (16B) | (16B) |
  147. ---------------------------------
  148. ----------------- Spare-0 -------------------
  149. / \
  150. -----------------------------------------
  151. | BBM | UD2 | UD1 | ECC UD1 |
  152. | 0 1 | 2 3 4 5 6 7 | 8 9 A B | C D E F |
  153. -----------------------------------------
  154. | NO ECC | ECC PROTECTED |
  155. BBM: Bad block marker.
  156. UD1: User Data 1.
  157. UD2: User Data 2.
  158. ECC UD1: ECC for UD1.
  159. ---------------- Spare-1 -------------------
  160. / \
  161. ---------------------------------------
  162. | UD2 | UD1 | ECC UD1 |
  163. | 0 1 2 3 4 5 6 7 | 8 9 A B | C D E F |
  164. ---------------------------------------
  165. | NO ECC | ECC PROTECTED |
  166. ---------------- Spare-2 -------------------
  167. / \
  168. ---------------------------------------
  169. | UD2 | UD1 | ECC UD1 |
  170. | 0 1 2 3 4 5 6 7 | 8 9 A B | C D E F |
  171. ---------------------------------------
  172. | NO ECC | ECC PROTECTED |
  173. ---------------- Spare-3 -------------------
  174. / \
  175. ---------------------------------------
  176. | UD2 | UD1 | ECC UD1 |
  177. | 0 1 2 3 4 5 6 7 | 8 9 A B | C D E F |
  178. ---------------------------------------
  179. | NO ECC | ECC PROTECTED |
  180. ========================================================
  181. */
  182. rt_uint8_t spinand_flash_data_layout[SPINAND_SPARE_LAYOUT_SIZE];
  183. rt_uint8_t spinand_flash_ecc_layout[SPINAND_SPARE_LAYOUT_SIZE];
  184. static rt_err_t spinand_info_read(struct rt_qspi_device *qspi);
  185. static rt_err_t spinand_die_select(struct rt_qspi_device *qspi, uint8_t select_die)
  186. {
  187. uint8_t au8Cmd[2] = { 0xC2, 0x0 };
  188. au8Cmd[1] = select_die;
  189. return nu_qspi_send(qspi, &au8Cmd[0], sizeof(au8Cmd));
  190. }
  191. static uint8_t spinand_isbusy(struct rt_qspi_device *qspi)
  192. {
  193. #define BUSY_CKECKING_TIMEOUT_MS 3000
  194. volatile uint8_t SR = 0xFF;
  195. rt_err_t result;
  196. uint8_t au8Cmd[2] = { 0x0F, 0xC0 };
  197. uint32_t u32CheckingDuration = rt_tick_from_millisecond(BUSY_CKECKING_TIMEOUT_MS);
  198. uint32_t u32Start = rt_tick_get();
  199. do
  200. {
  201. result = nu_qspi_send_then_recv(qspi, &au8Cmd[0], sizeof(au8Cmd), (void *)&SR, 1);
  202. if (result != RT_EOK)
  203. goto timeout_spinand_isbusy;
  204. if ((rt_tick_get() - u32Start) >= u32CheckingDuration)
  205. {
  206. goto timeout_spinand_isbusy;
  207. }
  208. }
  209. while ((SR & 0x1) != 0x00);
  210. return 0;
  211. timeout_spinand_isbusy:
  212. LOG_E("Error: spinand timeout.");
  213. return 1;
  214. }
  215. static rt_err_t spinand_program_dataload(
  216. struct rt_qspi_device *qspi,
  217. uint8_t u8AddrH,
  218. uint8_t u8AddrL,
  219. uint8_t *pu8DataBuff,
  220. uint32_t u32DataCount,
  221. uint8_t *pu8SpareBuff,
  222. uint32_t u32SpareCount)
  223. {
  224. uint8_t u8WECmd = 0x06;
  225. rt_err_t result = RT_EOK;
  226. struct rt_qspi_message qspi_messages[2] = {0};
  227. /* 1-bit mode */
  228. qspi_messages[0].instruction.content = 0x32;
  229. qspi_messages[0].instruction.qspi_lines = 1;
  230. qspi_messages[0].address.content = (u8AddrH << 8) | (u8AddrL);
  231. qspi_messages[0].address.size = 2 * 8;
  232. qspi_messages[0].address.qspi_lines = 1;
  233. /* 4-bit mode */
  234. qspi_messages[0].qspi_data_lines = 4;
  235. qspi_messages[0].parent.cs_take = 1;
  236. qspi_messages[0].parent.cs_release = 0;
  237. qspi_messages[0].parent.send_buf = pu8DataBuff;
  238. qspi_messages[0].parent.length = u32DataCount;
  239. qspi_messages[0].parent.next = &qspi_messages[1].parent;
  240. qspi_messages[1].qspi_data_lines = 4;
  241. qspi_messages[1].parent.cs_take = 0;
  242. qspi_messages[1].parent.cs_release = 1;
  243. qspi_messages[1].parent.send_buf = pu8SpareBuff;
  244. qspi_messages[1].parent.length = u32SpareCount;
  245. if ((result = nu_qspi_send(qspi, &u8WECmd, sizeof(u8WECmd))) != RT_EOK)
  246. goto exit_spinand_program_dataload;
  247. result = nu_qspi_transfer_message(qspi, (struct rt_qspi_message *)&qspi_messages[0]);
  248. exit_spinand_program_dataload:
  249. return result;
  250. }
  251. static uint8_t spinand_status_register_read(struct rt_qspi_device *qspi, uint8_t u8SRSel)
  252. {
  253. uint8_t u8SR = 0;
  254. uint8_t au8Cmd[2];
  255. switch (u8SRSel)
  256. {
  257. case 0x01:
  258. au8Cmd[0] = 0x05;
  259. au8Cmd[1] = 0xA0;
  260. break;
  261. case 0x02:
  262. au8Cmd[0] = 0x0F;
  263. au8Cmd[1] = 0xB0;
  264. break;
  265. case 0x03:
  266. au8Cmd[0] = 0x05;
  267. au8Cmd[1] = 0xC0;
  268. break;
  269. default:
  270. RT_ASSERT(0);
  271. break;
  272. }
  273. if (nu_qspi_send_then_recv(qspi, &au8Cmd[0], sizeof(au8Cmd), &u8SR, 1) != RT_EOK)
  274. RT_ASSERT(0);
  275. return u8SR;
  276. }
  277. static rt_err_t spinand_status_register_write(struct rt_qspi_device *qspi, uint8_t u8SRSel, uint8_t u8Value)
  278. {
  279. rt_err_t result = RT_EOK;
  280. uint8_t au8Cmd[3];
  281. switch (u8SRSel)
  282. {
  283. case 0x01:
  284. au8Cmd[0] = 0x01;
  285. au8Cmd[1] = 0xA0;
  286. break;
  287. case 0x02:
  288. au8Cmd[0] = 0x01;
  289. au8Cmd[1] = 0xB0;
  290. break;
  291. case 0x03:
  292. au8Cmd[0] = 0x01;
  293. au8Cmd[1] = 0xC0;
  294. break;
  295. default:
  296. result = RT_EINVAL;
  297. goto exit_spinand_status_register_write;
  298. }
  299. au8Cmd[2] = u8Value;
  300. if ((result = nu_qspi_send(qspi, &au8Cmd[0], sizeof(au8Cmd))) != RT_EOK)
  301. goto exit_spinand_status_register_write;
  302. if (spinand_isbusy(qspi))
  303. {
  304. result = RT_EIO;
  305. goto exit_spinand_status_register_write;
  306. }
  307. exit_spinand_status_register_write:
  308. return result;
  309. }
  310. static rt_err_t spinand_program_execute(struct rt_qspi_device *qspi, uint8_t u8Addr2, uint8_t u8Addr1, uint8_t u8Addr0)
  311. {
  312. rt_err_t result;
  313. uint8_t au8Cmd[4], u8SR;
  314. au8Cmd[0] = 0x10 ;
  315. au8Cmd[1] = u8Addr2;
  316. au8Cmd[2] = u8Addr1;
  317. au8Cmd[3] = u8Addr0;
  318. if ((result = nu_qspi_send(qspi, &au8Cmd, sizeof(au8Cmd))) != RT_EOK)
  319. goto exit_spinand_program_execute;
  320. if (spinand_isbusy(qspi))
  321. {
  322. result = -RT_MTD_EIO;
  323. goto exit_spinand_program_execute;
  324. }
  325. u8SR = (spinand_status_register_read(SPINAND_FLASH_QSPI, 3) & 0x0C) >> 2;
  326. if (u8SR == 1)
  327. {
  328. result = -RT_MTD_EIO;
  329. LOG_E("Error write status!");
  330. }
  331. exit_spinand_program_execute:
  332. return result;
  333. }
  334. static rt_err_t spinand_normal_read(struct rt_qspi_device *qspi, uint8_t u8AddrH, uint8_t u8AddrL, uint8_t *pu8Buff, uint32_t u32Count)
  335. {
  336. uint8_t au8Cmd[4];
  337. au8Cmd[0] = 0x03;
  338. au8Cmd[1] = u8AddrH;
  339. au8Cmd[2] = u8AddrL;
  340. au8Cmd[3] = 0x00;
  341. return nu_qspi_send_then_recv(qspi, &au8Cmd[0], sizeof(au8Cmd), pu8Buff, u32Count);
  342. }
  343. static rt_err_t spinand_protect_set(struct rt_qspi_device *qspi, uint8_t u8Protect)
  344. {
  345. /* Read status register 1 */
  346. uint8_t u8SR = spinand_status_register_read(qspi, 1);
  347. if (u8Protect)
  348. {
  349. /* protect */
  350. u8SR |= 0x7C;
  351. }
  352. else
  353. {
  354. /* unprotect */
  355. u8SR &= 0x83;
  356. }
  357. return spinand_status_register_write(qspi, 1, u8SR);
  358. }
  359. static uint8_t spinand_program_erase_isfail(struct rt_qspi_device *qspi)
  360. {
  361. /* Read status register 3 */
  362. uint8_t u8SR = spinand_status_register_read(qspi, 3);
  363. return (u8SR & 0x0C) >> 2; /* Check P-Fail, E-Fail bit */
  364. }
  365. static uint8_t spinand_hwecc_status_get(struct rt_qspi_device *qspi)
  366. {
  367. /* Read status register 3 */
  368. uint8_t u8SR = spinand_status_register_read(qspi, 3);
  369. return (u8SR & 0x30) >> 4; /* ECC-1, ECC0 bit */
  370. }
  371. static rt_err_t spinand_hwecc_set(struct rt_qspi_device *qspi, uint8_t u8Enable)
  372. {
  373. uint8_t u8SR = spinand_status_register_read(qspi, 2); // Read status register 2
  374. if (u8Enable)
  375. {
  376. u8SR |= 0x10; // Enable ECC-E bit
  377. }
  378. else
  379. {
  380. u8SR &= 0xEF; // Disable ECC-E bit
  381. }
  382. return spinand_status_register_write(qspi, 2, u8SR);
  383. }
  384. static uint8_t spinand_hwecc_get(struct rt_qspi_device *qspi)
  385. {
  386. /* Read status register 2 */
  387. uint8_t u8SR = spinand_status_register_read(qspi, 2);
  388. return (u8SR & 0x10) >> 4;
  389. }
  390. static rt_err_t spinand_read_dataload(struct rt_qspi_device *qspi, uint8_t u8Addr2, uint8_t u8Addr1, uint8_t u8Addr0)
  391. {
  392. rt_err_t result = RT_EOK;
  393. uint8_t au8Cmd[4];
  394. uint8_t u8SR;
  395. au8Cmd[0] = 0x13 ;
  396. au8Cmd[1] = u8Addr2;
  397. au8Cmd[2] = u8Addr1;
  398. au8Cmd[3] = u8Addr0;
  399. if ((result = nu_qspi_send(qspi, &au8Cmd[0], sizeof(au8Cmd))) != RT_EOK)
  400. goto exit_spinand_read_dataload;
  401. if (spinand_isbusy(qspi))
  402. {
  403. result = -RT_EIO;
  404. goto exit_spinand_read_dataload;
  405. }
  406. u8SR = spinand_hwecc_status_get(SPINAND_FLASH_QSPI);
  407. if ((u8SR != 0x00) && (u8SR != 0x01))
  408. {
  409. result = -RT_MTD_EECC;
  410. LOG_E("Error ECC status error[0x%x].", u8SR);
  411. }
  412. exit_spinand_read_dataload:
  413. return result;
  414. }
  415. static uint8_t spinand_block_isbad(struct rt_qspi_device *qspi, uint32_t u32PageAddr)
  416. {
  417. rt_err_t result;
  418. uint8_t read_buf;
  419. again_spinand_block_isbad:
  420. result = spinand_read_dataload(qspi, (u32PageAddr >> 16) & 0xFF, (u32PageAddr >> 8) & 0xFF, u32PageAddr & 0xFF); // Read the first page of a block
  421. RT_ASSERT(result == RT_EOK);
  422. result = spinand_normal_read(qspi, (SPINAND_FLASH_PAGE_SIZE >> 8) & 0xff, SPINAND_FLASH_PAGE_SIZE & 0xff, &read_buf, 1); // Read bad block mark at 0x800 update at v.1.0.8
  423. RT_ASSERT(result == RT_EOK);
  424. if (read_buf != 0xFF)
  425. {
  426. // update at v.1.0.7
  427. return 1;
  428. }
  429. if (((u32PageAddr % (SPINAND_FLASH_PAGE_PER_BLOCK_NUM * SPINAND_FLASH_PAGE_SIZE)) == 0))
  430. {
  431. /* Need check second page again. */
  432. u32PageAddr++;
  433. goto again_spinand_block_isbad;
  434. }
  435. return 0;
  436. }
  437. static rt_err_t spinand_buffermode_set(struct rt_qspi_device *qspi, uint8_t u8Enable)
  438. {
  439. uint8_t u8SR = spinand_status_register_read(qspi, 2); // Read status register 2
  440. if (u8Enable)
  441. {
  442. u8SR |= 0x08; // Enable BUF bit
  443. }
  444. else
  445. {
  446. u8SR &= 0xF7; // Disable BUF bit
  447. }
  448. return spinand_status_register_write(qspi, 2, u8SR);
  449. }
  450. static rt_err_t spinand_block_erase(struct rt_qspi_device *qspi, uint8_t u8Addr2, uint8_t u8Addr1, uint8_t u8Addr0)
  451. {
  452. rt_err_t result;
  453. uint8_t u8WECmd = 0x06;
  454. uint8_t au8EraseCmd[4], u8SR;
  455. au8EraseCmd[0] = 0xD8;
  456. au8EraseCmd[1] = u8Addr2;
  457. au8EraseCmd[2] = u8Addr1;
  458. au8EraseCmd[3] = u8Addr0;
  459. if ((result = nu_qspi_send(qspi, &u8WECmd, sizeof(u8WECmd))) != RT_EOK)
  460. goto exit_spinand_block_erase;
  461. if ((result = nu_qspi_send(qspi, &au8EraseCmd[0], sizeof(au8EraseCmd))) != RT_EOK)
  462. goto exit_spinand_block_erase;
  463. if (spinand_isbusy(qspi))
  464. return -RT_EIO;
  465. u8SR = spinand_program_erase_isfail(SPINAND_FLASH_QSPI);
  466. if (u8SR != 0)
  467. {
  468. /* Fail to erase */
  469. LOG_E("Fail to erase. Will mark it bad.");
  470. result = -RT_ERROR;
  471. goto exit_spinand_block_erase;
  472. }
  473. exit_spinand_block_erase:
  474. return result;
  475. }
  476. static rt_err_t spinand_block_markbad(struct rt_qspi_device *qspi, uint32_t u32PageAddr)
  477. {
  478. rt_err_t result = RT_EOK;
  479. uint8_t u8BadBlockMarker = 0xF0;
  480. result = spinand_block_erase(qspi, (u32PageAddr >> 16) & 0xFF, (u32PageAddr >> 8) & 0xFF, u32PageAddr & 0xFF);
  481. if (result != RT_EOK)
  482. return result;
  483. result = spinand_program_dataload(qspi, (SPINAND_FLASH_PAGE_SIZE >> 8) & 0xff, SPINAND_FLASH_PAGE_SIZE & 0xff, &u8BadBlockMarker, 1, 0, 0);
  484. if (result != RT_EOK)
  485. return result;
  486. return spinand_program_execute(qspi, (u32PageAddr >> 16) & 0xFF, (u32PageAddr >> 8) & 0xFF, u32PageAddr & 0xFF);
  487. }
  488. static rt_err_t spinand_read_quadoutput(
  489. struct rt_qspi_device *qspi,
  490. uint8_t u8AddrH,
  491. uint8_t u8AddrL,
  492. uint8_t *pu8DataBuff,
  493. uint32_t u32DataCount
  494. )
  495. {
  496. struct rt_qspi_message qspi_messages = {0};
  497. /* 1-bit mode */
  498. qspi_messages.instruction.content = SPINAND_FLASH_QUADREAD_CMDID;
  499. qspi_messages.instruction.qspi_lines = 1;
  500. qspi_messages.address.content = (u8AddrH << 8) | (u8AddrL);
  501. qspi_messages.address.size = 2 * 8;
  502. qspi_messages.address.qspi_lines = 1;
  503. qspi_messages.dummy_cycles = SPINAND_FLASH_DUMMYBYTE * 8; //In bit
  504. /* 4-bit mode */
  505. qspi_messages.qspi_data_lines = 4;
  506. qspi_messages.parent.cs_take = 1;
  507. qspi_messages.parent.cs_release = 1;
  508. qspi_messages.parent.recv_buf = pu8DataBuff;
  509. qspi_messages.parent.length = u32DataCount;
  510. qspi_messages.parent.next = RT_NULL;
  511. return nu_qspi_transfer_message(qspi, (struct rt_qspi_message *) &qspi_messages);
  512. }
  513. static rt_err_t spinand_jedecid_get(struct rt_qspi_device *qspi, uint32_t *pu32ID)
  514. {
  515. uint32_t u32JedecId = 0;
  516. uint32_t u32JedecId_real = 0;
  517. uint8_t u8Cmd = 0x9F;
  518. if (nu_qspi_send_then_recv(qspi, &u8Cmd, 1, &u32JedecId, 4) != RT_EOK)
  519. {
  520. return -RT_ERROR;
  521. }
  522. /* Reverse order. */
  523. nu_set32_be((uint8_t *)&u32JedecId_real, u32JedecId);
  524. /* Only keep 3-bytes. */
  525. u32JedecId_real &= 0x00ffffff;
  526. *pu32ID = u32JedecId_real;
  527. return RT_EOK;
  528. }
  529. static rt_err_t spinand_reset(struct rt_qspi_device *qspi)
  530. {
  531. rt_err_t result;
  532. uint8_t u8Cmd = 0xFF;
  533. if ((result = nu_qspi_send(qspi, &u8Cmd, 1)) != RT_EOK)
  534. goto exit_spinand_reset;
  535. if (spinand_isbusy(qspi))
  536. {
  537. result = RT_EIO;
  538. goto exit_spinand_reset;
  539. }
  540. exit_spinand_reset:
  541. return result;
  542. }
  543. rt_err_t spinand_flash_init(struct rt_qspi_device *qspi)
  544. {
  545. rt_err_t result;
  546. if ((result = spinand_reset(qspi)) != RT_EOK)
  547. goto exit_spinand_init;
  548. if ((result = spinand_info_read(qspi)) != RT_EOK)
  549. goto exit_spinand_init;
  550. /* Un-protect */
  551. if ((result = spinand_protect_set(qspi, 0)) != RT_EOK)
  552. goto exit_spinand_init;
  553. /* Enable BUF mode */
  554. if ((result = spinand_buffermode_set(qspi, 1)) != RT_EOK)
  555. goto exit_spinand_init;
  556. /* Enable HWECC */
  557. if ((result = spinand_hwecc_set(qspi, 1)) != RT_EOK)
  558. goto exit_spinand_init;
  559. /* Check HWECC */
  560. if (!(spinand_hwecc_get(qspi)))
  561. goto exit_spinand_init;
  562. if (SPINAND_FLASH_MCP == 1)
  563. {
  564. /* Select die. */
  565. if ((result = spinand_die_select(qspi, SPINAND_DIE_ID1)) != RT_EOK)
  566. goto exit_spinand_init;
  567. /* Unprotect */
  568. if ((result = spinand_protect_set(qspi, 0)) != RT_EOK)
  569. goto exit_spinand_init;
  570. }
  571. LOG_I("Enabled BUF, HWECC. Unprotected.");
  572. exit_spinand_init:
  573. return -result;
  574. }
  575. struct spinand_ops spinand_ops_wb =
  576. {
  577. .block_erase = spinand_block_erase,
  578. .block_isbad = spinand_block_isbad,
  579. .block_markbad = spinand_block_markbad,
  580. .die_select = spinand_die_select,
  581. .jedecid_get = spinand_jedecid_get,
  582. .program_dataload = spinand_program_dataload,
  583. .program_execute = spinand_program_execute,
  584. .read_dataload = spinand_read_dataload,
  585. .read_quadoutput = spinand_read_quadoutput
  586. };
  587. static rt_err_t spinand_info_read(struct rt_qspi_device *qspi)
  588. {
  589. int i;
  590. uint32_t u32JedecId = 0;
  591. if (spinand_jedecid_get(qspi, &u32JedecId) != RT_EOK)
  592. goto exit_spinand_info_read;
  593. for (i = 0 ; i < SPINAND_LIST_ELEMENT_NUM; i++)
  594. {
  595. if (u32JedecId == g_spinandflash_list[i].u32JEDECID) /* Match JEDECID? */
  596. {
  597. rt_memcpy((void *)&spinand_flash_data_layout[0], (void *)&g_spinandflash_list[i].au8DataLayout[0], SPINAND_SPARE_LAYOUT_SIZE);
  598. rt_memcpy((void *)&spinand_flash_ecc_layout[0], (void *)&g_spinandflash_list[i].au8EccLayout[0], SPINAND_SPARE_LAYOUT_SIZE);
  599. rt_memcpy(SPINAND_FLASH_INFO, &g_spinandflash_list[i], sizeof(struct nu_spinand_info));
  600. LOG_I("Found: [%08X] %s.", u32JedecId, SPINAND_FLASH_DESCRIPTION);
  601. switch (u32JedecId & 0xff0000)
  602. {
  603. case 0xEF0000: /* Winbond */
  604. SPINAND_FLASH_OPS = &spinand_ops_wb;
  605. break;
  606. default:
  607. goto exit_spinand_info_read;
  608. }
  609. return RT_EOK;
  610. }
  611. }
  612. exit_spinand_info_read:
  613. LOG_E("Can't find the flash[%08X] in supported list.", u32JedecId);
  614. return -RT_ERROR;
  615. }
  616. #endif