drv_qspi.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Email: opensource_embedded@phytium.com.cn
  7. *
  8. * Change Logs:
  9. * Date Author Notes
  10. * 2023-03-20 zhangyan first version
  11. * 2023-05-31 zhangyan improve functions
  12. *
  13. */
  14. #include "rtconfig.h"
  15. #include "rtdevice.h"
  16. #define LOG_TAG "qspi_drv"
  17. #include "drv_log.h"
  18. #include <rtthread.h>
  19. #ifdef RT_USING_SMART
  20. #include <ioremap.h>
  21. #include "tlb.h"
  22. #endif
  23. #include "drv_qspi.h"
  24. #include "fqspi_flash.h"
  25. #include "fiopad.h"
  26. #include "fqspi_hw.h"
  27. #include "fio_mux.h"
  28. #include <string.h>
  29. #define QSPI_ALIGNED_BYTE 4
  30. static rt_err_t FQspiInit(phytium_qspi_bus *phytium_qspi_bus)
  31. {
  32. FError ret = FT_SUCCESS;
  33. rt_uint32_t qspi_id = phytium_qspi_bus->fqspi_id;
  34. FIOPadSetQspiMux(qspi_id, FQSPI_CS_0);
  35. FIOPadSetQspiMux(qspi_id, FQSPI_CS_1);
  36. FQspiDeInitialize(&(phytium_qspi_bus->fqspi));
  37. FQspiConfig pconfig = *FQspiLookupConfig(qspi_id);
  38. #ifdef RT_USING_SMART
  39. pconfig.base_addr = (uintptr)rt_ioremap((void *)pconfig.base_addr, 0x1000);
  40. #endif
  41. /* Norflash init, include reset and read flash_size */
  42. ret = FQspiCfgInitialize(&(phytium_qspi_bus->fqspi), &pconfig);
  43. if (FT_SUCCESS != ret)
  44. {
  45. LOG_E("Qspi init failed.\n");
  46. return -RT_ERROR;
  47. }
  48. else
  49. {
  50. LOG_D("Qspi init successfully.\n");
  51. }
  52. /* Detect connected flash infomation */
  53. ret = FQspiFlashDetect(&(phytium_qspi_bus->fqspi));
  54. if (FT_SUCCESS != ret)
  55. {
  56. LOG_E("Qspi flash detect failed.\n");
  57. return -RT_ERROR;
  58. }
  59. else
  60. {
  61. LOG_D("Qspi flash detect successfully.\n");
  62. }
  63. #ifdef USING_QSPI_CHANNEL0
  64. phytium_qspi_bus->fqspi.config.channel = 0;
  65. #elif defined USING_QSPI_CHANNEL1
  66. phytium_qspi_bus->fqspi.config.channel = 1;
  67. #endif
  68. phytium_qspi_bus->init = RT_EOK;
  69. return RT_EOK;
  70. }
  71. #define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
  72. void FtDumpHexByte(const u8 *ptr, u32 buflen)
  73. {
  74. u8 *buf = (u8 *)ptr;
  75. fsize_t i, j;
  76. for (i = 0; i < buflen; i += 16)
  77. {
  78. rt_kprintf("%p: ", ptr + i);
  79. for (j = 0; j < 16; j++)
  80. if (i + j < buflen)
  81. {
  82. rt_kprintf("%02X ", buf[i + j]);
  83. }
  84. else
  85. {
  86. rt_kprintf(" ");
  87. }
  88. rt_kprintf(" ");
  89. for (j = 0; j < 16; j++)
  90. if (i + j < buflen)
  91. {
  92. rt_kprintf("%c", (char)(__is_print(buf[i + j]) ? buf[i + j] : '.'));
  93. }
  94. rt_kprintf("\r\n");
  95. }
  96. }
  97. FError RTQspiFlashWriteData(FQspiCtrl *pctrl, uintptr addr, const u8 *buf, size_t len)
  98. {
  99. FASSERT(pctrl && buf);
  100. FError ret = FQSPI_SUCCESS;
  101. u32 loop = 0;
  102. const u32 mask = (u32)GENMASK(1, 0);
  103. u32 reg_val = 0;
  104. u32 val = 0;
  105. u32 aligned_bit = 0;
  106. u8 tmp[QSPI_ALIGNED_BYTE] = {0xff, 0xff, 0xff, 0xff};
  107. uintptr base_addr = pctrl->config.base_addr;
  108. if (FT_COMPONENT_IS_READY != pctrl->is_ready)
  109. {
  110. LOG_E("Nor flash not ready !!!");
  111. return FQSPI_NOT_READY;
  112. }
  113. /* Flash write enable */
  114. ret = FQspiFlashEnableWrite(pctrl);
  115. if (ret != FT_SUCCESS)
  116. {
  117. LOG_E("FQspiFlashEnableWrite failed!");
  118. return ret;
  119. }
  120. if (IS_ALIGNED(addr, QSPI_ALIGNED_BYTE)) /* if copy src is aligned by 4 bytes */
  121. {
  122. /* write alligned data into memory space */
  123. for (loop = 0; loop < (len >> 2); loop++)
  124. {
  125. FQSPI_DAT_WRITE(addr + QSPI_ALIGNED_BYTE * loop, *(u32 *)(buf + QSPI_ALIGNED_BYTE * loop));
  126. }
  127. /* write not alligned data into memory space */
  128. if (len & mask)
  129. {
  130. addr = addr + (len & ~mask);
  131. memcpy(tmp, buf + (len & ~mask), len & mask);
  132. FQSPI_DAT_WRITE(addr, *(u32 *)(tmp));
  133. }
  134. }
  135. else
  136. {
  137. aligned_bit = (addr & mask);
  138. addr = addr - aligned_bit;
  139. reg_val = FQSPI_READ_REG32(addr, 0);
  140. for (loop = 0; loop < (QSPI_ALIGNED_BYTE - aligned_bit); loop++)
  141. {
  142. val = (val << 8) | (buf[loop]);
  143. reg_val &= (~(0xff << (loop * 8)));
  144. }
  145. reg_val |= val;
  146. reg_val = __builtin_bswap32(reg_val);
  147. FQSPI_DAT_WRITE(addr, reg_val);
  148. buf = buf + loop;
  149. len = len - loop;
  150. addr = addr + QSPI_ALIGNED_BYTE;
  151. LOG_D("addr=%p, buf=%p, len=%d, value=%#x\r\n", addr, buf, len, *(u32 *)(buf));
  152. for (loop = 0; loop < (len >> 2); loop++)
  153. {
  154. FQSPI_DAT_WRITE(addr + QSPI_ALIGNED_BYTE * loop, *(u32 *)(buf + QSPI_ALIGNED_BYTE * loop));
  155. }
  156. if (!IS_ALIGNED(len, QSPI_ALIGNED_BYTE))
  157. {
  158. buf = buf + QSPI_ALIGNED_BYTE * loop;
  159. len = len - QSPI_ALIGNED_BYTE * loop;
  160. addr = addr + QSPI_ALIGNED_BYTE * loop;
  161. memcpy(tmp, buf, len);
  162. FQSPI_DAT_WRITE(addr, *(u32 *)(tmp));
  163. }
  164. }
  165. /* flush buffer data to Flash */
  166. FQspiWriteFlush(base_addr);
  167. ret = FQspiFlashWaitForCmd(pctrl);
  168. return ret;
  169. }
  170. size_t RTQspiFlashReadData(FQspiCtrl *pctrl, uintptr addr, u8 *buf, size_t len)
  171. {
  172. /* addr of copy dst or src might be zero */
  173. FASSERT(pctrl && buf);
  174. size_t loop = 0;
  175. const size_t cnt = len / QSPI_ALIGNED_BYTE; /* cnt number of 4-bytes need copy */
  176. const size_t remain = len % QSPI_ALIGNED_BYTE; /* remain number of 1-byte not aligned */
  177. u8 align_buf[QSPI_ALIGNED_BYTE];
  178. size_t copy_len = 0;
  179. intptr src_addr = (intptr)addr; /* conver to 32/64 bit addr */
  180. intptr dst_addr = (intptr)buf;
  181. if (FT_COMPONENT_IS_READY != pctrl->is_ready)
  182. {
  183. LOG_E("Nor flash not ready !!!");
  184. return 0;
  185. }
  186. if (0 == pctrl->rd_cfg.rd_cmd)
  187. {
  188. LOG_E("Nor flash read command is not ready !!!");
  189. return 0;
  190. }
  191. if (0 == len)
  192. {
  193. return 0;
  194. }
  195. if (IS_ALIGNED(src_addr, QSPI_ALIGNED_BYTE)) /* if copy src is aligned by 4 bytes */
  196. {
  197. /* read 4-bytes aligned buf part */
  198. for (loop = 0; loop < cnt; loop++)
  199. {
  200. *(u32 *)dst_addr = *(volatile u32 *)(src_addr);
  201. src_addr += QSPI_ALIGNED_BYTE;
  202. dst_addr += QSPI_ALIGNED_BYTE;
  203. }
  204. copy_len += (loop << 2);
  205. if (remain > 0)
  206. {
  207. *(u32 *)align_buf = *(volatile u32 *)(src_addr);
  208. }
  209. /* read remain un-aligned buf byte by byte */
  210. for (loop = 0; loop < remain; loop++)
  211. {
  212. *(u8 *)dst_addr = align_buf[loop];
  213. dst_addr += 1;
  214. }
  215. copy_len += loop;
  216. }
  217. else /* if copy src is not aligned */
  218. {
  219. /* read byte by byte */
  220. for (loop = 0; loop < len; loop++)
  221. {
  222. *(u8 *)dst_addr = *(volatile u8 *)(src_addr);
  223. dst_addr += 1;
  224. src_addr += 1;
  225. }
  226. copy_len += loop;
  227. }
  228. return copy_len;
  229. }
  230. static rt_err_t phytium_qspi_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration)
  231. {
  232. RT_ASSERT(device != RT_NULL);
  233. RT_ASSERT(configuration != RT_NULL);
  234. phytium_qspi_bus *qspi_bus;
  235. qspi_bus = (phytium_qspi_bus *) device->bus->parent.user_data;
  236. rt_err_t ret = RT_EOK;
  237. ret = FQspiInit(qspi_bus);
  238. if (RT_EOK != ret)
  239. {
  240. qspi_bus->init = RT_FALSE;
  241. LOG_E("Qspi init failed!!!\n");
  242. return -RT_ERROR;
  243. }
  244. return RT_EOK;
  245. }
  246. static rt_ssize_t phytium_qspi_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
  247. {
  248. RT_ASSERT(device != RT_NULL);
  249. RT_ASSERT(message != RT_NULL);
  250. FError ret = FT_SUCCESS;
  251. phytium_qspi_bus *qspi_bus;
  252. struct rt_qspi_message *qspi_message = (struct rt_qspi_message *)message;
  253. rt_uint32_t cmd = qspi_message->instruction.content;
  254. rt_uint32_t flash_addr = qspi_message->address.content;
  255. rt_uint32_t len = message->length;
  256. const void *rcvb = message->recv_buf;
  257. const void *sndb = message->send_buf;
  258. qspi_bus = (phytium_qspi_bus *) device->bus->parent.user_data;
  259. uintptr addr = flash_addr;
  260. for (u32 index = 0; index < qspi_bus->fqspi.config.channel; index++)
  261. {
  262. addr = qspi_bus->fqspi.flash_size[index];
  263. }
  264. /*Distinguish the write mode according to different commands*/
  265. if (cmd == FQSPI_FLASH_CMD_PP || cmd == FQSPI_FLASH_CMD_QPP || cmd == FQSPI_FLASH_CMD_4PP || cmd == FQSPI_FLASH_CMD_4QPP)
  266. {
  267. ret = FQspiFlashErase(&(qspi_bus->fqspi), FQSPI_FLASH_CMD_SE, flash_addr);
  268. if (FT_SUCCESS != ret)
  269. {
  270. LOG_E("Failed to erase mem, test result 0x%x.\r\n", ret);
  271. return -RT_ERROR;
  272. }
  273. ret = FQspiFlashWriteDataConfig(&(qspi_bus->fqspi), cmd);
  274. if (FQSPI_SUCCESS != ret)
  275. {
  276. LOG_E("Failed to config write, test result 0x%x.\r\n", ret);
  277. return -RT_ERROR;
  278. } /* write norflash data */
  279. #ifdef RT_USING_SMART
  280. addr = (uintptr)rt_ioremap((void *)addr, len);
  281. #endif
  282. ret = RTQspiFlashWriteData(&(qspi_bus->fqspi), addr, (u8 *)message->send_buf, len);
  283. #ifdef RT_USING_SMART
  284. rt_iounmap(addr);
  285. rt_hw_tlb_invalidate_all();
  286. #endif
  287. if (FT_SUCCESS != ret)
  288. {
  289. LOG_E("Failed to write mem, test result 0x%x.\r\n", ret);
  290. return -RT_ERROR;
  291. }
  292. else
  293. {
  294. LOG_I("Write successfully!!!\r\n");
  295. }
  296. return RT_EOK;
  297. }
  298. /*Distinguish the read mode according to different commands*/
  299. if (cmd == FQSPI_FLASH_CMD_READ || cmd == FQSPI_FLASH_CMD_4READ || cmd == FQSPI_FLASH_CMD_FAST_READ || cmd == FQSPI_FLASH_CMD_4FAST_READ ||
  300. cmd == FQSPI_FLASH_CMD_DUAL_READ || cmd == FQSPI_FLASH_CMD_QIOR || cmd == FQSPI_FLASH_CMD_4QIOR)
  301. {
  302. ret |= FQspiFlashReadDataConfig(&(qspi_bus->fqspi), cmd);
  303. if (FT_SUCCESS != ret)
  304. {
  305. LOG_E("Failed to config read, test result 0x%x.\r\n", ret);
  306. return -RT_ERROR;
  307. }
  308. /* read norflash data */
  309. #ifdef RT_USING_SMART
  310. addr = (uintptr)rt_ioremap((void *)addr, len);
  311. #endif
  312. size_t read_len = RTQspiFlashReadData(&(qspi_bus->fqspi), addr, (u8 *)message->recv_buf, len);
  313. #ifdef RT_USING_SMART
  314. rt_iounmap(addr);
  315. rt_hw_tlb_invalidate_all();
  316. #endif
  317. if (read_len != len)
  318. {
  319. LOG_E("Failed to read mem, read len = %d.\r\n", read_len);
  320. return -RT_ERROR;
  321. }
  322. else
  323. {
  324. LOG_I("Read successfully!!!, read_len = %d\r\n", read_len);
  325. }
  326. FtDumpHexByte(message->recv_buf, read_len);
  327. return read_len;
  328. }
  329. if (rcvb)
  330. {
  331. if (cmd == FQSPI_FLASH_CMD_RDID || cmd == FQSPI_FLASH_CMD_RDSR1 || cmd == FQSPI_FLASH_CMD_RDSR2 || cmd == FQSPI_FLASH_CMD_RDSR3)
  332. {
  333. ret |= FQspiFlashSpecialInstruction(&(qspi_bus->fqspi), cmd, (u8 *)rcvb, sizeof(rcvb));
  334. if (FT_SUCCESS != ret)
  335. {
  336. LOG_E("Failed to read flash information.\n");
  337. return -RT_ERROR;
  338. }
  339. }
  340. return 1;
  341. }
  342. if (sndb)
  343. {
  344. ret |= FQspiFlashEnableWrite(&(qspi_bus->fqspi));
  345. if (FT_SUCCESS != ret)
  346. {
  347. LOG_E("Failed to enable flash reg write.\n");
  348. return -RT_ERROR;
  349. }
  350. ret |= FQspiFlashWriteReg(&(qspi_bus->fqspi), cmd, (u8 *)sndb, 1);
  351. if (FT_SUCCESS != ret)
  352. {
  353. LOG_E("Failed to write flash reg.\n");
  354. return -RT_ERROR;
  355. }
  356. return 1;
  357. }
  358. LOG_E("cmd not found!!!\r\n");
  359. return -RT_ERROR;
  360. }
  361. static struct rt_spi_ops phytium_qspi_ops =
  362. {
  363. .configure = phytium_qspi_configure,
  364. .xfer = phytium_qspi_xfer,
  365. };
  366. rt_err_t phytium_qspi_bus_attach_device(const char *bus_name, const char *device_name)
  367. {
  368. struct rt_qspi_device *qspi_device;
  369. rt_err_t result = RT_EOK;
  370. RT_ASSERT(bus_name != RT_NULL);
  371. RT_ASSERT(device_name != RT_NULL);
  372. qspi_device = (struct rt_qspi_device *)rt_malloc(sizeof(struct rt_qspi_device));
  373. if (qspi_device == RT_NULL)
  374. {
  375. LOG_E("Qspi bus attach device failed.");
  376. result = RT_ENOMEM;
  377. goto __exit;
  378. }
  379. result = rt_spi_bus_attach_device(&(qspi_device->parent), device_name, bus_name, RT_NULL);
  380. __exit:
  381. if (result != RT_EOK)
  382. {
  383. if (qspi_device)
  384. {
  385. rt_free(qspi_device);
  386. }
  387. }
  388. return result;
  389. }
  390. static int rt_qspi_init(phytium_qspi_bus *phytium_qspi)
  391. {
  392. rt_err_t result = RT_EOK;
  393. phytium_qspi->qspi_bus.parent.user_data = phytium_qspi;
  394. if (rt_qspi_bus_register(&phytium_qspi->qspi_bus, phytium_qspi->name, &phytium_qspi_ops) == RT_EOK)
  395. {
  396. LOG_D("Qspi bus register successfully!!!\n");
  397. }
  398. else
  399. {
  400. LOG_E("Qspi bus register Failed!!!\n");
  401. result = -RT_ERROR;
  402. }
  403. return result;
  404. }
  405. #if defined(RT_USING_QSPI0)
  406. static phytium_qspi_bus phytium_qspi0_bus;
  407. #endif
  408. int rt_hw_qspi_init(void)
  409. {
  410. #if defined(RT_USING_QSPI0)
  411. phytium_qspi0_bus.name = "QSPI0";
  412. phytium_qspi0_bus.fqspi_id = FQSPI0_ID;
  413. rt_qspi_init(&phytium_qspi0_bus);
  414. FQspiInit(&phytium_qspi0_bus);
  415. #endif
  416. return 0;
  417. }
  418. INIT_BOARD_EXPORT(rt_hw_qspi_init);