spinand.c 22 KB

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