dev_qspi_core.c 8.2 KB

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