drv_qspi.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  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. #ifdef BSP_USING_QSPI
  15. #include <rtthread.h>
  16. #ifdef RT_USING_SMART
  17. #include <ioremap.h>
  18. #endif
  19. #include "rtdevice.h"
  20. #include "drv_qspi.h"
  21. #include "fqspi_flash.h"
  22. #define LOG_TAG "qspi_drv"
  23. #include "drv_log.h"
  24. #include "fiopad.h"
  25. #include "fqspi_hw.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. static phytium_qspi_bus phytium_qspi =
  31. {
  32. .fqspi_id = FQSPI0_ID,
  33. };
  34. static struct rt_qspi_device *qspi_device; /* phytium device bus handle */
  35. static char qspi_bus_name[RT_NAME_MAX] = "QSPIBUS";
  36. static char qspi_dev_name[RT_NAME_MAX] = "QSPIDEV";
  37. extern FIOPadCtrl iopad_ctrl;
  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. if (qspi_device == RT_NULL)
  388. {
  389. LOG_E("Qspi bus attach device failed.");
  390. result = RT_ENOMEM;
  391. goto __exit;
  392. }
  393. result = rt_spi_bus_attach_device(&(qspi_device->parent), device_name, bus_name, RT_NULL);
  394. __exit:
  395. if (result != RT_EOK)
  396. {
  397. if (qspi_device)
  398. {
  399. rt_free(qspi_device);
  400. }
  401. }
  402. return result;
  403. }
  404. int rt_hw_qspi_init(void)
  405. {
  406. int result = RT_EOK;
  407. phytium_qspi.qspi_bus.parent.user_data = &phytium_qspi;
  408. if (rt_qspi_bus_register(&phytium_qspi.qspi_bus, qspi_bus_name, &phytium_qspi_ops) == RT_EOK)
  409. {
  410. rt_kprintf("Qspi bus register successfully!!!\n");
  411. }
  412. else
  413. {
  414. LOG_E("Qspi bus register Failed!!!\n");
  415. result = -RT_ERROR;
  416. }
  417. return result;
  418. }
  419. INIT_BOARD_EXPORT(rt_hw_qspi_init);
  420. /*example*/
  421. struct rt_spi_message write_message;
  422. struct rt_spi_message read_message;
  423. rt_err_t qspi_init()
  424. {
  425. rt_err_t res = RT_EOK;
  426. res = phytium_qspi_bus_attach_device(qspi_bus_name, qspi_dev_name);
  427. RT_ASSERT(res == RT_EOK);
  428. qspi_device = (struct rt_qspi_device *)rt_device_find(qspi_dev_name);
  429. return res;
  430. }
  431. /*read cmd example message improvement*/
  432. void ReadCmd(struct rt_spi_message *spi_message)
  433. {
  434. struct rt_qspi_message *message = (struct rt_qspi_message *) spi_message;
  435. message->address.content = 0x360000 ;/*Flash address*/
  436. message->instruction.content = 0x03 ;/*read cmd*/
  437. rt_qspi_transfer_message(qspi_device, message);
  438. }
  439. /*write cmd example message improvement*/
  440. void WriteCmd(struct rt_spi_message *spi_message)
  441. {
  442. struct rt_qspi_message *message = (struct rt_qspi_message *) spi_message;
  443. message->address.content = 0x360000 ;/*Flash address*/
  444. message->instruction.content = 0x02 ;/*write cmd*/
  445. rt_qspi_transfer_message(qspi_device, message);
  446. }
  447. /*write cmd example message improvement*/
  448. void qspi_thread(void *parameter)
  449. {
  450. rt_err_t res;
  451. qspi_init();
  452. /*Read and write flash chip fixed area repeatedly*/
  453. write_message.send_buf = "phytium";
  454. write_message.length = strlen((char *)write_message.send_buf) + 1;
  455. WriteCmd(&write_message);
  456. ReadCmd(&read_message);
  457. write_message.send_buf = "phytium hello world!";
  458. write_message.length = strlen((char *)write_message.send_buf) + 1;
  459. WriteCmd(&write_message);
  460. ReadCmd(&read_message);
  461. write_message.send_buf = "Welcome to phytium chip";
  462. write_message.length = strlen((char *)write_message.send_buf) + 1;
  463. WriteCmd(&write_message);
  464. ReadCmd(&read_message);
  465. rt_uint8_t recv;
  466. rt_uint8_t cmd = 0x9F;/*read the flash status reg2*/
  467. res = rt_qspi_send_then_recv(qspi_device, &cmd, sizeof(cmd), &recv, sizeof(recv));
  468. RT_ASSERT(res != RT_EOK);
  469. rt_kprintf("The status reg = %x \n", recv);
  470. }
  471. rt_err_t qspi_sample(int argc, char *argv[])
  472. {
  473. rt_thread_t thread;
  474. rt_err_t res;
  475. thread = rt_thread_create("qspi_thread", qspi_thread, RT_NULL, 4096, 25, 10);
  476. res = rt_thread_startup(thread);
  477. RT_ASSERT(res == RT_EOK);
  478. return res;
  479. }
  480. /* Enter qspi_sample command for testing */
  481. MSH_CMD_EXPORT(qspi_sample, qspi sample);
  482. #endif