dev_qspi_core.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2018-11-16 zylx first version.
  9. */
  10. #include "drivers/dev_spi.h"
  11. rt_err_t rt_qspi_configure(struct rt_qspi_device *device, struct rt_qspi_configuration *cfg)
  12. {
  13. RT_ASSERT(device != RT_NULL);
  14. RT_ASSERT(cfg != RT_NULL);
  15. /* reset the CS pin */
  16. if (device->parent.cs_pin != PIN_NONE)
  17. {
  18. rt_err_t result = rt_mutex_take(&(device->parent.bus->lock), RT_WAITING_FOREVER);
  19. if (result == RT_EOK)
  20. {
  21. if (cfg->parent.mode & RT_SPI_CS_HIGH)
  22. {
  23. rt_pin_write(device->parent.cs_pin, PIN_LOW);
  24. }
  25. else
  26. {
  27. rt_pin_write(device->parent.cs_pin, PIN_HIGH);
  28. }
  29. rt_mutex_release(&(device->parent.bus->lock));
  30. }
  31. else
  32. {
  33. return result;
  34. }
  35. }
  36. /* If the configurations are the same, we don't need to set again. */
  37. if (device->config.medium_size == cfg->medium_size &&
  38. device->config.ddr_mode == cfg->ddr_mode &&
  39. device->config.qspi_dl_width == cfg->qspi_dl_width &&
  40. device->config.parent.data_width == cfg->parent.data_width &&
  41. device->config.parent.mode == (cfg->parent.mode & RT_SPI_MODE_MASK) &&
  42. device->config.parent.max_hz == cfg->parent.max_hz)
  43. {
  44. return RT_EOK;
  45. }
  46. /* copy configuration items */
  47. device->config.parent.mode = cfg->parent.mode;
  48. device->config.parent.max_hz = cfg->parent.max_hz;
  49. device->config.parent.data_width = cfg->parent.data_width;
  50. #ifdef RT_USING_DM
  51. device->config.parent.data_width_tx = cfg->parent.data_width_tx;
  52. device->config.parent.data_width_rx = cfg->parent.data_width_rx;
  53. #else
  54. device->config.parent.reserved = cfg->parent.reserved;
  55. #endif
  56. device->config.medium_size = cfg->medium_size;
  57. device->config.ddr_mode = cfg->ddr_mode;
  58. device->config.qspi_dl_width = cfg->qspi_dl_width;
  59. return rt_spi_bus_configure(&device->parent);
  60. }
  61. rt_err_t rt_qspi_bus_register(struct rt_spi_bus *bus, const char *name, const struct rt_spi_ops *ops)
  62. {
  63. rt_err_t result = RT_EOK;
  64. result = rt_spi_bus_register(bus, name, ops);
  65. if(result == RT_EOK)
  66. {
  67. /* set SPI bus to qspi modes */
  68. bus->mode = RT_SPI_BUS_MODE_QSPI;
  69. }
  70. return result;
  71. }
  72. rt_size_t rt_qspi_transfer_message(struct rt_qspi_device *device, struct rt_qspi_message *message)
  73. {
  74. rt_err_t result;
  75. RT_ASSERT(device != RT_NULL);
  76. RT_ASSERT(message != RT_NULL);
  77. result = rt_mutex_take(&(device->parent.bus->lock), RT_WAITING_FOREVER);
  78. if (result != RT_EOK)
  79. {
  80. rt_set_errno(-RT_EBUSY);
  81. return 0;
  82. }
  83. /* reset errno */
  84. rt_set_errno(RT_EOK);
  85. /* configure SPI bus */
  86. if (device->parent.bus->owner != &device->parent)
  87. {
  88. /* not the same owner as current, re-configure SPI bus */
  89. result = device->parent.bus->ops->configure(&device->parent, &device->parent.config);
  90. if (result == RT_EOK)
  91. {
  92. /* set SPI bus owner */
  93. device->parent.bus->owner = &device->parent;
  94. }
  95. else
  96. {
  97. /* configure SPI bus failed */
  98. rt_set_errno(-RT_EIO);
  99. goto __exit;
  100. }
  101. }
  102. /* transmit each SPI message */
  103. result = device->parent.bus->ops->xfer(&device->parent, &message->parent);
  104. if (result == 0)
  105. {
  106. rt_set_errno(-RT_EIO);
  107. }
  108. __exit:
  109. /* release bus lock */
  110. rt_mutex_release(&(device->parent.bus->lock));
  111. return result;
  112. }
  113. rt_err_t rt_qspi_send_then_recv(struct rt_qspi_device *device, const void *send_buf, rt_size_t send_length, void *recv_buf, rt_size_t recv_length)
  114. {
  115. RT_ASSERT(send_buf);
  116. RT_ASSERT(recv_buf);
  117. RT_ASSERT(send_length != 0);
  118. struct rt_qspi_message message;
  119. unsigned char *ptr = (unsigned char *)send_buf;
  120. rt_size_t count = 0;
  121. rt_err_t result = 0;
  122. message.instruction.content = ptr[0];
  123. message.instruction.qspi_lines = 1;
  124. count++;
  125. /* get address */
  126. if (send_length > 1)
  127. {
  128. if (device->config.medium_size > 0x1000000 && send_length >= 5)
  129. {
  130. /* medium size greater than 16Mb, address size is 4 Byte */
  131. message.address.content = (ptr[1] << 24) | (ptr[2] << 16) | (ptr[3] << 8) | (ptr[4]);
  132. message.address.size = 32;
  133. count += 4;
  134. }
  135. else if (send_length >= 4)
  136. {
  137. /* address size is 3 Byte */
  138. message.address.content = (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
  139. message.address.size = 24;
  140. count += 3;
  141. }
  142. else
  143. {
  144. return -RT_ERROR;
  145. }
  146. message.address.qspi_lines = 1;
  147. }
  148. else
  149. {
  150. /* no address stage */
  151. message.address.content = 0 ;
  152. message.address.qspi_lines = 0;
  153. message.address.size = 0;
  154. }
  155. message.alternate_bytes.content = 0;
  156. message.alternate_bytes.size = 0;
  157. message.alternate_bytes.qspi_lines = 0;
  158. /* set dummy cycles */
  159. if (count != send_length)
  160. {
  161. message.dummy_cycles = (send_length - count) * 8;
  162. }
  163. else
  164. {
  165. message.dummy_cycles = 0;
  166. }
  167. /* set recv buf and recv size */
  168. message.parent.recv_buf = recv_buf;
  169. message.parent.send_buf = RT_NULL;
  170. message.parent.length = recv_length;
  171. message.parent.cs_take = 1;
  172. message.parent.cs_release = 1;
  173. message.qspi_data_lines = 1;
  174. /* set next */
  175. /* Ensure correct QSPI message chaining by setting next pointer to NULL, preventing unintended data transmission issues.*/
  176. message.parent.next = RT_NULL;
  177. result = rt_qspi_transfer_message(device, &message);
  178. if (result == 0)
  179. {
  180. result = -RT_EIO;
  181. }
  182. else
  183. {
  184. result = recv_length;
  185. }
  186. return result;
  187. }
  188. rt_err_t rt_qspi_send(struct rt_qspi_device *device, const void *send_buf, rt_size_t length)
  189. {
  190. RT_ASSERT(send_buf);
  191. RT_ASSERT(length != 0);
  192. struct rt_qspi_message message;
  193. unsigned char *ptr = (unsigned char *)send_buf;
  194. rt_size_t count = 0;
  195. rt_err_t result = 0;
  196. message.instruction.content = ptr[0];
  197. message.instruction.qspi_lines = 1;
  198. count++;
  199. /* get address */
  200. if (length > 1)
  201. {
  202. if (device->config.medium_size > 0x1000000 && length >= 5)
  203. {
  204. /* medium size greater than 16Mb, address size is 4 Byte */
  205. message.address.content = (ptr[1] << 24) | (ptr[2] << 16) | (ptr[3] << 8) | (ptr[4]);
  206. message.address.size = 32;
  207. message.address.qspi_lines = 1;
  208. count += 4;
  209. }
  210. else if (length >= 4)
  211. {
  212. /* address size is 3 Byte */
  213. message.address.content = (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
  214. message.address.size = 24;
  215. message.address.qspi_lines = 1;
  216. count += 3;
  217. }
  218. else
  219. {
  220. return -RT_ERROR;
  221. }
  222. }
  223. else
  224. {
  225. /* no address stage */
  226. message.address.content = 0 ;
  227. message.address.qspi_lines = 0;
  228. message.address.size = 0;
  229. }
  230. message.alternate_bytes.content = 0;
  231. message.alternate_bytes.size = 0;
  232. message.alternate_bytes.qspi_lines = 0;
  233. message.dummy_cycles = 0;
  234. /* determine if there is data to send */
  235. if (length - count > 0)
  236. {
  237. message.qspi_data_lines = 1;
  238. }
  239. else
  240. {
  241. message.qspi_data_lines = 0;
  242. }
  243. /* set send buf and send size */
  244. message.parent.send_buf = ptr + count;
  245. message.parent.recv_buf = RT_NULL;
  246. message.parent.length = length - count;
  247. message.parent.cs_take = 1;
  248. message.parent.cs_release = 1;
  249. /* set next */
  250. /* Ensure correct QSPI message chaining by setting next pointer to NULL, preventing unintended data transmission issues.*/
  251. message.parent.next = RT_NULL;
  252. result = rt_qspi_transfer_message(device, &message);
  253. if (result == 0)
  254. {
  255. result = -RT_EIO;
  256. }
  257. else
  258. {
  259. result = length;
  260. }
  261. return result;
  262. }