drv_qspi.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  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. #endif
  22. #include "drv_qspi.h"
  23. #include "fqspi_flash.h"
  24. #include "fiopad.h"
  25. #include "fqspi_hw.h"
  26. #include "fio_mux.h"
  27. #define QSPI_ALIGNED_BYTE 4
  28. typedef struct
  29. {
  30. rt_uint32_t fqspi_id;
  31. const char *name;
  32. rt_uint32_t init; /* 0 is init already */
  33. FQspiCtrl fqspi;
  34. struct rt_spi_bus qspi_bus;
  35. } phytium_qspi_bus;
  36. rt_err_t FQspiInit(phytium_qspi_bus *phytium_qspi_bus)
  37. {
  38. FError ret = FT_SUCCESS;
  39. rt_uint32_t qspi_id = phytium_qspi_bus->fqspi_id;
  40. FIOPadSetQspiMux(qspi_id, FQSPI_CS_0);
  41. FIOPadSetQspiMux(qspi_id, FQSPI_CS_1);
  42. FQspiDeInitialize(&(phytium_qspi_bus->fqspi));
  43. FQspiConfig pconfig = *FQspiLookupConfig(qspi_id);
  44. #ifdef RT_USING_SMART
  45. pconfig.base_addr = (uintptr)rt_ioremap((void *)pconfig.base_addr, 0x1000);
  46. #endif
  47. /* Norflash init, include reset and read flash_size */
  48. ret = FQspiCfgInitialize(&(phytium_qspi_bus->fqspi), &pconfig);
  49. if (FT_SUCCESS != ret)
  50. {
  51. LOG_E("Qspi init failed.\n");
  52. return -RT_ERROR;
  53. }
  54. else
  55. {
  56. LOG_D("Qspi init successfully.\n");
  57. }
  58. /* Detect connected flash infomation */
  59. ret = FQspiFlashDetect(&(phytium_qspi_bus->fqspi));
  60. if (FT_SUCCESS != ret)
  61. {
  62. LOG_E("Qspi flash detect failed.\n");
  63. return -RT_ERROR;
  64. }
  65. else
  66. {
  67. LOG_D("Qspi flash detect successfully.\n");
  68. }
  69. #ifdef USING_QSPI_CHANNEL0
  70. phytium_qspi_bus->fqspi.config.channel = 0;
  71. #elif defined USING_QSPI_CHANNEL1
  72. phytium_qspi_bus->fqspi.config.channel = 1;
  73. #endif
  74. #ifdef RT_USING_SMART
  75. phytium_qspi_bus->fqspi.config.mem_start = (uintptr)rt_ioremap((void *)phytium_qspi_bus->fqspi.config.mem_start, (phytium_qspi_bus->fqspi.config.channel + 1) * (phytium_qspi_bus->fqspi.flash_size));
  76. #endif
  77. return RT_EOK;
  78. }
  79. #define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
  80. void FtDumpHexByte(const u8 *ptr, u32 buflen)
  81. {
  82. u8 *buf = (u8 *)ptr;
  83. fsize_t i, j;
  84. for (i = 0; i < buflen; i += 16)
  85. {
  86. rt_kprintf("%p: ", ptr + i);
  87. for (j = 0; j < 16; j++)
  88. if (i + j < buflen)
  89. {
  90. rt_kprintf("%02X ", buf[i + j]);
  91. }
  92. else
  93. {
  94. rt_kprintf(" ");
  95. }
  96. rt_kprintf(" ");
  97. for (j = 0; j < 16; j++)
  98. if (i + j < buflen)
  99. {
  100. rt_kprintf("%c", (char)(__is_print(buf[i + j]) ? buf[i + j] : '.'));
  101. }
  102. rt_kprintf("\r\n");
  103. }
  104. }
  105. static rt_err_t phytium_qspi_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration)
  106. {
  107. RT_ASSERT(device != RT_NULL);
  108. RT_ASSERT(configuration != RT_NULL);
  109. phytium_qspi_bus *qspi_bus;
  110. qspi_bus = (phytium_qspi_bus *)(struct phytium_qspi_bus *) device->bus->parent.user_data;
  111. rt_err_t ret = RT_EOK;
  112. ret = FQspiInit(qspi_bus);
  113. if (RT_EOK != ret)
  114. {
  115. qspi_bus->init = RT_FALSE;
  116. LOG_E("Qspi init failed!!!\n");
  117. return -RT_ERROR;
  118. }
  119. qspi_bus->init = RT_EOK;
  120. return RT_EOK;
  121. }
  122. static rt_ssize_t phytium_qspi_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
  123. {
  124. RT_ASSERT(device != RT_NULL);
  125. RT_ASSERT(message != RT_NULL);
  126. FError ret = FT_SUCCESS;
  127. phytium_qspi_bus *qspi_bus;
  128. struct rt_qspi_message *qspi_message = (struct rt_qspi_message *)message;
  129. rt_uint32_t cmd = qspi_message->instruction.content;
  130. rt_uint32_t flash_addr = qspi_message->address.content;
  131. rt_uint32_t len = message->length;
  132. const void *rcvb = message->recv_buf;
  133. const void *sndb = message->send_buf;
  134. qspi_bus = (phytium_qspi_bus *)(struct phytium_qspi_bus *) device->bus->parent.user_data;
  135. /*Distinguish the write mode according to different commands*/
  136. if (cmd == FQSPI_FLASH_CMD_PP || cmd == FQSPI_FLASH_CMD_QPP || cmd == FQSPI_FLASH_CMD_4PP || cmd == FQSPI_FLASH_CMD_4QPP)
  137. {
  138. ret = FQspiFlashErase(&(qspi_bus->fqspi), FQSPI_FLASH_CMD_SE, flash_addr);
  139. if (FT_SUCCESS != ret)
  140. {
  141. LOG_E("Failed to erase mem, test result 0x%x.\r\n", ret);
  142. return -RT_ERROR;
  143. }
  144. /* write norflash data */
  145. ret = FQspiFlashWriteData(&(qspi_bus->fqspi), cmd, flash_addr, (u8 *)message->send_buf, len);
  146. if (FT_SUCCESS != ret)
  147. {
  148. LOG_E("Failed to write mem, test result 0x%x.\r\n", ret);
  149. return -RT_ERROR;
  150. }
  151. else
  152. {
  153. LOG_D("Write successfully!!!\r\n");
  154. }
  155. return RT_EOK;
  156. }
  157. /*Distinguish the read mode according to different commands*/
  158. if (cmd == FQSPI_FLASH_CMD_READ || cmd == FQSPI_FLASH_CMD_4READ || cmd == FQSPI_FLASH_CMD_FAST_READ || cmd == FQSPI_FLASH_CMD_4FAST_READ ||
  159. cmd == FQSPI_FLASH_CMD_DUAL_READ || cmd == FQSPI_FLASH_CMD_QIOR || cmd == FQSPI_FLASH_CMD_4QIOR)
  160. {
  161. ret |= FQspiFlashReadDataConfig(&(qspi_bus->fqspi), cmd);
  162. if (FT_SUCCESS != ret)
  163. {
  164. LOG_D("Failed to config read, test result 0x%x.\r\n", ret);
  165. return -RT_ERROR;
  166. }
  167. /* read norflash data */
  168. size_t read_len = FQspiFlashReadData(&(qspi_bus->fqspi), flash_addr, (u8 *)message->recv_buf, len);
  169. if (read_len != len)
  170. {
  171. LOG_E("Failed to read mem, read len = %d.\r\n", read_len);
  172. return -RT_ERROR;
  173. }
  174. else
  175. {
  176. LOG_D("Read successfully!!!, read_len = %d\r\n", read_len);
  177. }
  178. FtDumpHexByte(message->recv_buf, read_len);
  179. return read_len;
  180. }
  181. if (rcvb)
  182. {
  183. if (cmd == FQSPI_FLASH_CMD_RDID || cmd == FQSPI_FLASH_CMD_RDSR1 || cmd == FQSPI_FLASH_CMD_RDSR2 || cmd == FQSPI_FLASH_CMD_RDSR3)
  184. {
  185. ret |= FQspiFlashSpecialInstruction(&(qspi_bus->fqspi), cmd, (u8 *)rcvb, sizeof(rcvb));
  186. if (FT_SUCCESS != ret)
  187. {
  188. LOG_E("Failed to read flash information.\n");
  189. return -RT_ERROR;
  190. }
  191. }
  192. return 1;
  193. }
  194. if (sndb)
  195. {
  196. ret |= FQspiFlashEnableWrite(&(qspi_bus->fqspi));
  197. if (FT_SUCCESS != ret)
  198. {
  199. LOG_E("Failed to enable flash reg write.\n");
  200. return -RT_ERROR;
  201. }
  202. ret |= FQspiFlashWriteReg(&(qspi_bus->fqspi), cmd, (u8 *)sndb, 1);
  203. if (FT_SUCCESS != ret)
  204. {
  205. LOG_E("Failed to write flash reg.\n");
  206. return -RT_ERROR;
  207. }
  208. return 1;
  209. }
  210. LOG_E("cmd not found!!!\r\n");
  211. return ret;
  212. }
  213. static struct rt_spi_ops phytium_qspi_ops =
  214. {
  215. .configure = phytium_qspi_configure,
  216. .xfer = phytium_qspi_xfer,
  217. };
  218. rt_err_t phytium_qspi_bus_attach_device(const char *bus_name, const char *device_name)
  219. {
  220. struct rt_qspi_device *qspi_device;
  221. rt_err_t result = RT_EOK;
  222. RT_ASSERT(bus_name != RT_NULL);
  223. RT_ASSERT(device_name != RT_NULL);
  224. qspi_device = (struct rt_qspi_device *)rt_malloc(sizeof(struct rt_qspi_device));
  225. if (qspi_device == RT_NULL)
  226. {
  227. LOG_E("Qspi bus attach device failed.");
  228. result = RT_ENOMEM;
  229. goto __exit;
  230. }
  231. result = rt_spi_bus_attach_device(&(qspi_device->parent), device_name, bus_name, RT_NULL);
  232. __exit:
  233. if (result != RT_EOK)
  234. {
  235. if (qspi_device)
  236. {
  237. rt_free(qspi_device);
  238. }
  239. }
  240. return result;
  241. }
  242. static int rt_qspi_init(phytium_qspi_bus *phytium_qspi)
  243. {
  244. int result = RT_EOK;
  245. phytium_qspi->qspi_bus.parent.user_data = phytium_qspi;
  246. if (rt_qspi_bus_register(&phytium_qspi->qspi_bus, phytium_qspi->name, &phytium_qspi_ops) == RT_EOK)
  247. {
  248. LOG_D("Qspi bus register successfully!!!\n");
  249. }
  250. else
  251. {
  252. LOG_E("Qspi bus register Failed!!!\n");
  253. result = -RT_ERROR;
  254. }
  255. return result;
  256. }
  257. #if defined(RT_USING_QSPI0)
  258. static phytium_qspi_bus phytium_qspi0_bus;
  259. #endif
  260. int rt_hw_qspi_init(void)
  261. {
  262. #if defined(RT_USING_QSPI0)
  263. phytium_qspi0_bus.name = "QSPI0";
  264. phytium_qspi0_bus.fqspi_id = FQSPI0_ID;
  265. rt_qspi_init(&phytium_qspi0_bus);
  266. #endif
  267. return 0;
  268. }
  269. INIT_BOARD_EXPORT(rt_hw_qspi_init);