drv_qspi.c 14 KB

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