drv_qspi.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  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 "drv_qspi.h"
  14. #include "sdkconfig.h"
  15. #ifdef RT_USING_QSPI
  16. #include <rtthread.h>
  17. #include "rtdevice.h"
  18. #include "fqspi_flash.h"
  19. #include "fdebug.h"
  20. #include "fpinctrl.h"
  21. #define FQSPI_DEBUG_TAG "FQSPI"
  22. #define FQSPI_ERROR(format, ...) FT_DEBUG_PRINT_E(FQSPI_DEBUG_TAG, format, ##__VA_ARGS__)
  23. #define FQSPI_WARN(format, ...) FT_DEBUG_PRINT_W(FQSPI_DEBUG_TAG, format, ##__VA_ARGS__)
  24. #define FQSPI_INFO(format, ...) FT_DEBUG_PRINT_I(FQSPI_DEBUG_TAG, format, ##__VA_ARGS__)
  25. #define FQSPI_DEBUG(format, ...) FT_DEBUG_PRINT_D(FQSPI_DEBUG_TAG, format, ##__VA_ARGS__)
  26. #define DAT_LENGTH 128
  27. struct phytium_qspi_bus
  28. {
  29. char *name;
  30. rt_uint32_t init; /* 0 is init already */
  31. FQspiCtrl fqspi;
  32. struct rt_spi_bus qspi_bus;
  33. };
  34. static struct phytium_qspi_bus phytium_qspi; /* phytium qspi bus handle */
  35. static struct rt_qspi_device *qspi_device; /* phytium device bus handle */
  36. static char qspi_bus_name[RT_NAME_MAX] = "QSPIBUS";
  37. static char qspi_dev_name[RT_NAME_MAX] = "QSPIDEV";
  38. rt_err_t FQspiInit(FQspiCtrl *fqspi)
  39. {
  40. u32 qspi_id = FQSPI0_ID;
  41. FError ret = FT_SUCCESS;
  42. #if defined(CONFIG_TARGET_E2000)
  43. FIOPadSetQspiMux(qspi_id, FQSPI_CS_0);
  44. FIOPadSetQspiMux(qspi_id, FQSPI_CS_1);
  45. #endif
  46. FQspiDeInitialize(fqspi);
  47. FQspiConfig pconfig = *FQspiLookupConfig(qspi_id);
  48. /* Norflash init, include reset and read flash_size */
  49. ret = FQspiCfgInitialize(fqspi, &pconfig);
  50. if (FT_SUCCESS != ret)
  51. {
  52. FQSPI_DEBUG("Qspi init failed.\n");
  53. return RT_ERROR;
  54. }
  55. else
  56. {
  57. FQSPI_DEBUG("Qspi init successfully.\n");
  58. }
  59. /* Detect connected flash infomation */
  60. ret = FQspiFlashDetect(fqspi);
  61. if (FT_SUCCESS != ret)
  62. {
  63. FQSPI_DEBUG("Qspi flash detect failed.\n");
  64. return RT_ERROR;
  65. }
  66. else
  67. {
  68. FQSPI_DEBUG("Qspi flash detect successfully.\n");
  69. }
  70. return RT_EOK;
  71. }
  72. static rt_err_t phytium_qspi_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration)
  73. {
  74. RT_ASSERT(device != RT_NULL);
  75. RT_ASSERT(configuration != RT_NULL);
  76. struct phytium_qspi_bus *qspi_bus;
  77. qspi_bus = (struct phytium_qspi_bus *) device->bus->parent.user_data;
  78. rt_err_t ret = RT_EOK;
  79. ret = FQspiInit(&(qspi_bus->fqspi));
  80. if (RT_EOK != ret)
  81. {
  82. qspi_bus->init = RT_FALSE;
  83. FQSPI_DEBUG("Qspi init failed!!!\n");
  84. return RT_ERROR;
  85. }
  86. qspi_bus->init = RT_EOK;
  87. return RT_EOK;
  88. }
  89. static rt_uint32_t phytium_qspi_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
  90. {
  91. RT_ASSERT(device != RT_NULL);
  92. RT_ASSERT(message != RT_NULL);
  93. struct phytium_qspi_bus *qspi_bus;
  94. struct rt_qspi_message *qspi_message = (struct rt_qspi_message *)message;
  95. rt_uint32_t cmd = qspi_message->instruction.content;
  96. rt_uint32_t flash_addr = qspi_message->address.content;
  97. rt_uint8_t *rcvb = message->recv_buf;
  98. rt_uint8_t *sndb = message->send_buf;
  99. FError ret = FT_SUCCESS;
  100. qspi_bus = (struct phytium_qspi_bus *) device->bus->parent.user_data;
  101. /*Distinguish the write mode according to different commands*/
  102. if (cmd == FQSPI_FLASH_CMD_PP||cmd == FQSPI_FLASH_CMD_QPP||cmd ==FQSPI_FLASH_CMD_4PP||cmd ==FQSPI_FLASH_CMD_4QPP )
  103. {
  104. char *strs = (char *)message->send_buf;
  105. rt_uint8_t len = strlen(strs) + 1;
  106. rt_uint8_t *wr_buf = NULL;
  107. wr_buf = (rt_uint8_t *)rt_malloc(DAT_LENGTH * sizeof(rt_uint8_t));
  108. rt_memcpy(wr_buf, strs, len);
  109. message->length = len;
  110. ret = FQspiFlashErase(&(qspi_bus->fqspi), FQSPI_FLASH_CMD_SE, flash_addr);
  111. if (FT_SUCCESS != ret)
  112. {
  113. FQSPI_DEBUG("Failed to erase mem, test result 0x%x.\r\n", ret);
  114. return RT_ERROR;
  115. }
  116. /* write norflash data */
  117. ret = FQspiFlashWriteData(&(qspi_bus->fqspi), cmd, flash_addr, wr_buf, len);
  118. if (FT_SUCCESS != ret)
  119. {
  120. FQSPI_DEBUG("Failed to write mem, test result 0x%x.\r\n", ret);
  121. return RT_ERROR;
  122. }
  123. else
  124. {
  125. rt_kprintf("Write successfully!!!\r\n");
  126. }
  127. rt_free(wr_buf);
  128. return RT_EOK;
  129. }
  130. /*Distinguish the read mode according to different commands*/
  131. if (cmd == FQSPI_FLASH_CMD_READ||cmd == FQSPI_FLASH_CMD_4READ||cmd == FQSPI_FLASH_CMD_FAST_READ||cmd == FQSPI_FLASH_CMD_4FAST_READ||
  132. cmd == FQSPI_FLASH_CMD_DUAL_READ||cmd == FQSPI_FLASH_CMD_QIOR||cmd == FQSPI_FLASH_CMD_4QIOR)
  133. {
  134. rt_uint8_t *rd_buf = NULL;
  135. rd_buf = (rt_uint8_t *)rt_malloc(DAT_LENGTH * sizeof(rt_uint8_t));
  136. ret |= FQspiFlashReadDataConfig(&(qspi_bus->fqspi), cmd);
  137. if (FT_SUCCESS != ret)
  138. {
  139. FQSPI_DEBUG("Failed to config read, test result 0x%x.\r\n", ret);
  140. return RT_ERROR;
  141. }
  142. /* read norflash data */
  143. size_t read_len = FQspiFlashReadData(&(qspi_bus->fqspi), flash_addr, rd_buf, DAT_LENGTH);
  144. message->length = read_len;
  145. if (read_len != DAT_LENGTH)
  146. {
  147. FQSPI_DEBUG("Failed to read mem, read len = %d.\r\n", read_len);
  148. return RT_ERROR;
  149. }
  150. else
  151. {
  152. rt_kprintf("Read successfully!!!\r\n");
  153. message->recv_buf = rd_buf;
  154. rt_free(rd_buf);
  155. }
  156. FtDumpHexByte(message->recv_buf, DAT_LENGTH);
  157. return RT_EOK;
  158. }
  159. if (rcvb)
  160. {
  161. if (cmd == FQSPI_FLASH_CMD_RDID||cmd == FQSPI_FLASH_CMD_RDSR1||cmd == FQSPI_FLASH_CMD_RDSR2 ||cmd == FQSPI_FLASH_CMD_RDSR3)
  162. {
  163. ret |= FQspiFlashSpecialInstruction(&(qspi_bus->fqspi), cmd, rcvb, sizeof(rcvb));
  164. if (FT_SUCCESS != ret)
  165. {
  166. FQSPI_DEBUG("Failed to read flash information.\n");
  167. return RT_ERROR;
  168. }
  169. }
  170. return RT_EOK;
  171. }
  172. if (sndb)
  173. {
  174. ret |= FQspiFlashEnableWrite(&(qspi_bus->fqspi));
  175. if (FT_SUCCESS != ret)
  176. {
  177. FQSPI_DEBUG("Failed to enable flash reg write.\n");
  178. return RT_ERROR;
  179. }
  180. ret |= FQspiFlashWriteReg(&(qspi_bus->fqspi), cmd, sndb, 1);
  181. if (FT_SUCCESS != ret)
  182. {
  183. FQSPI_DEBUG("Failed to write flash reg.\n");
  184. return RT_ERROR;
  185. }
  186. return RT_EOK;
  187. }
  188. }
  189. static struct rt_spi_ops phytium_qspi_ops =
  190. {
  191. .configure = phytium_qspi_configure,
  192. .xfer = phytium_qspi_xfer,
  193. };
  194. rt_err_t phytium_qspi_bus_attach_device(const char *bus_name, const char *device_name)
  195. {
  196. struct rt_qspi_device *qspi_device;
  197. rt_err_t result = RT_EOK;
  198. RT_ASSERT(bus_name != RT_NULL);
  199. RT_ASSERT(device_name != RT_NULL);
  200. qspi_device = (struct rt_qspi_device *)rt_malloc(sizeof(struct rt_qspi_device));
  201. if (qspi_device == RT_NULL)
  202. {
  203. FQSPI_DEBUG("Qspi bus attach device failed.");
  204. result = RT_ENOMEM;
  205. goto __exit;
  206. }
  207. result = rt_spi_bus_attach_device(&(qspi_device->parent), device_name, bus_name, RT_NULL);
  208. __exit:
  209. if (result != RT_EOK)
  210. {
  211. if (qspi_device)
  212. {
  213. rt_free(qspi_device);
  214. }
  215. return result;
  216. }
  217. }
  218. int rt_hw_qspi_init(void)
  219. {
  220. int i = 0;
  221. int result = RT_EOK;
  222. phytium_qspi.qspi_bus.parent.user_data = &phytium_qspi;
  223. if(rt_qspi_bus_register(&phytium_qspi.qspi_bus, qspi_bus_name , &phytium_qspi_ops) == RT_EOK)
  224. {
  225. rt_kprintf("Qspi bus register successfully!!!\n");
  226. }
  227. else
  228. {
  229. FQSPI_DEBUG("Qspi bus register Failed!!!\n");
  230. result = -RT_ERROR;
  231. }
  232. return result;
  233. }
  234. INIT_BOARD_EXPORT(rt_hw_qspi_init);
  235. /*example*/
  236. struct rt_spi_message write_message;
  237. struct rt_spi_message read_message;
  238. rt_err_t qspi_init()
  239. {
  240. rt_err_t res = RT_EOK;
  241. res = phytium_qspi_bus_attach_device(qspi_bus_name, qspi_dev_name);
  242. RT_ASSERT(res == RT_EOK);
  243. qspi_device = (struct rt_qspi_device *)rt_device_find(qspi_dev_name);
  244. return res;
  245. }
  246. /*read cmd example message improvement*/
  247. void ReadCmd(struct rt_spi_message *spi_message)
  248. {
  249. struct rt_qspi_message *message = (struct rt_qspi_message*) spi_message;
  250. message->address.content = 0x360000 ;/*Flash address*/
  251. message->instruction.content = 0x03 ;/*read cmd*/
  252. rt_qspi_transfer_message(qspi_device, message);
  253. }
  254. /*write cmd example message improvement*/
  255. void WriteCmd(struct rt_spi_message *spi_message)
  256. {
  257. struct rt_qspi_message *message = (struct rt_qspi_message*) spi_message;
  258. message->address.content = 0x360000 ;/*Flash address*/
  259. message->instruction.content = 0x02 ;/*write cmd*/
  260. rt_qspi_transfer_message(qspi_device, message);
  261. }
  262. /*write cmd example message improvement*/
  263. void qspi_thread(void *parameter)
  264. {
  265. rt_err_t res;
  266. qspi_init();
  267. /*Read and write flash chip fixed area repeatedly*/
  268. write_message.send_buf = "111111111111111111111111";
  269. WriteCmd(&write_message);
  270. ReadCmd(&read_message);
  271. write_message.send_buf = "222222222222222222222222";
  272. WriteCmd(&write_message);
  273. ReadCmd(&read_message);
  274. write_message.send_buf = "333333333333333333333333";
  275. WriteCmd(&write_message);
  276. ReadCmd(&read_message);
  277. rt_uint8_t recv;
  278. rt_uint8_t cmd = 0x9F;/*read the flash status reg2*/
  279. res = rt_qspi_send_then_recv(qspi_device, &cmd, sizeof(cmd), &recv, sizeof(recv));
  280. RT_ASSERT(res!=RT_EOK);
  281. rt_kprintf("The status reg = %x \n" ,recv);
  282. return 0;
  283. }
  284. rt_err_t qspi_sample(int argc, char *argv[])
  285. {
  286. rt_thread_t thread;
  287. rt_err_t res;
  288. thread = rt_thread_create("qspi_thread", qspi_thread, RT_NULL, 1024, 25, 10);
  289. res = rt_thread_startup(thread);
  290. RT_ASSERT(res==RT_EOK);
  291. return res;
  292. }
  293. /* Enter qspi_sample command for testing */
  294. MSH_CMD_EXPORT(qspi_sample, qspi sample);
  295. #endif