qspi_core.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /*
  2. * Copyright (c) 2006-2018, 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/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. struct rt_qspi_device *qspi_device = (struct rt_qspi_device *)device;
  16. rt_err_t result = RT_EOK;
  17. /* copy configuration items */
  18. qspi_device->config.parent.mode = cfg->parent.mode;
  19. qspi_device->config.parent.max_hz = cfg->parent.max_hz;
  20. qspi_device->config.parent.data_width = cfg->parent.data_width;
  21. qspi_device->config.parent.reserved = cfg->parent.reserved;
  22. qspi_device->config.medium_size = cfg->medium_size;
  23. qspi_device->config.ddr_mode = cfg->ddr_mode;
  24. qspi_device->config.qspi_dl_width = cfg->qspi_dl_width;
  25. result = rt_spi_configure(&device->parent, &cfg->parent);
  26. return result;
  27. }
  28. rt_err_t rt_qspi_bus_register(struct rt_spi_bus *bus, const char *name, const struct rt_spi_ops *ops)
  29. {
  30. rt_err_t result = RT_EOK;
  31. result = rt_spi_bus_register(bus, name, ops);
  32. if(result == RT_EOK)
  33. {
  34. /* set SPI bus to qspi modes */
  35. bus->mode = RT_SPI_BUS_MODE_QSPI;
  36. }
  37. return result;
  38. }
  39. rt_size_t rt_qspi_transfer_message(struct rt_qspi_device *device, struct rt_qspi_message *message)
  40. {
  41. rt_err_t result;
  42. RT_ASSERT(device != RT_NULL);
  43. RT_ASSERT(message != RT_NULL);
  44. result = rt_mutex_take(&(device->parent.bus->lock), RT_WAITING_FOREVER);
  45. if (result != RT_EOK)
  46. {
  47. rt_set_errno(-RT_EBUSY);
  48. return 0;
  49. }
  50. /* reset errno */
  51. rt_set_errno(RT_EOK);
  52. /* configure SPI bus */
  53. if (device->parent.bus->owner != &device->parent)
  54. {
  55. /* not the same owner as current, re-configure SPI bus */
  56. result = device->parent.bus->ops->configure(&device->parent, &device->parent.config);
  57. if (result == RT_EOK)
  58. {
  59. /* set SPI bus owner */
  60. device->parent.bus->owner = &device->parent;
  61. }
  62. else
  63. {
  64. /* configure SPI bus failed */
  65. rt_set_errno(-RT_EIO);
  66. goto __exit;
  67. }
  68. }
  69. /* transmit each SPI message */
  70. result = device->parent.bus->ops->xfer(&device->parent, &message->parent);
  71. if (result == 0)
  72. {
  73. rt_set_errno(-RT_EIO);
  74. }
  75. __exit:
  76. /* release bus lock */
  77. rt_mutex_release(&(device->parent.bus->lock));
  78. return result;
  79. }
  80. 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)
  81. {
  82. RT_ASSERT(send_buf);
  83. RT_ASSERT(recv_buf);
  84. RT_ASSERT(send_length != 0);
  85. struct rt_qspi_message message;
  86. unsigned char *ptr = (unsigned char *)send_buf;
  87. rt_size_t count = 0;
  88. rt_err_t result = 0;
  89. message.instruction.content = ptr[0];
  90. message.instruction.qspi_lines = 1;
  91. count++;
  92. /* get address */
  93. if (send_length > 1)
  94. {
  95. if (device->config.medium_size > 0x1000000 && send_length >= 5)
  96. {
  97. /* medium size greater than 16Mb, address size is 4 Byte */
  98. message.address.content = (ptr[1] << 24) | (ptr[2] << 16) | (ptr[3] << 8) | (ptr[4]);
  99. message.address.size = 32;
  100. count += 4;
  101. }
  102. else if (send_length >= 4)
  103. {
  104. /* address size is 3 Byte */
  105. message.address.content = (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
  106. message.address.size = 24;
  107. count += 3;
  108. }
  109. else
  110. {
  111. return -RT_ERROR;
  112. }
  113. message.address.qspi_lines = 1;
  114. }
  115. else
  116. {
  117. /* no address stage */
  118. message.address.content = 0 ;
  119. message.address.qspi_lines = 0;
  120. message.address.size = 0;
  121. }
  122. message.alternate_bytes.content = 0;
  123. message.alternate_bytes.size = 0;
  124. message.alternate_bytes.qspi_lines = 0;
  125. /* set dummy cycles */
  126. if (count != send_length)
  127. {
  128. message.dummy_cycles = (send_length - count) * 8;
  129. }
  130. else
  131. {
  132. message.dummy_cycles = 0;
  133. }
  134. /* set recv buf and recv size */
  135. message.parent.recv_buf = recv_buf;
  136. message.parent.send_buf = RT_NULL;
  137. message.parent.length = recv_length;
  138. message.parent.cs_take = 1;
  139. message.parent.cs_release = 1;
  140. message.qspi_data_lines = 1;
  141. result = rt_qspi_transfer_message(device, &message);
  142. if (result == 0)
  143. {
  144. result = -RT_EIO;
  145. }
  146. else
  147. {
  148. result = recv_length;
  149. }
  150. return result;
  151. }
  152. rt_err_t rt_qspi_send(struct rt_qspi_device *device, const void *send_buf, rt_size_t length)
  153. {
  154. RT_ASSERT(send_buf);
  155. RT_ASSERT(length != 0);
  156. struct rt_qspi_message message;
  157. char *ptr = (char *)send_buf;
  158. rt_size_t count = 0;
  159. rt_err_t result = 0;
  160. message.instruction.content = ptr[0];
  161. message.instruction.qspi_lines = 1;
  162. count++;
  163. /* get address */
  164. if (length > 1)
  165. {
  166. if (device->config.medium_size > 0x1000000 && length >= 5)
  167. {
  168. /* medium size greater than 16Mb, address size is 4 Byte */
  169. message.address.content = (ptr[1] << 24) | (ptr[2] << 16) | (ptr[3] << 8) | (ptr[4]);
  170. message.address.size = 32;
  171. message.address.qspi_lines = 1;
  172. count += 4;
  173. }
  174. else if (length >= 4)
  175. {
  176. /* address size is 3 Byte */
  177. message.address.content = (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
  178. message.address.size = 24;
  179. message.address.qspi_lines = 1;
  180. count += 3;
  181. }
  182. else
  183. {
  184. return -RT_ERROR;
  185. }
  186. }
  187. else
  188. {
  189. /* no address stage */
  190. message.address.content = 0 ;
  191. message.address.qspi_lines = 0;
  192. message.address.size = 0;
  193. }
  194. message.alternate_bytes.content = 0;
  195. message.alternate_bytes.size = 0;
  196. message.alternate_bytes.qspi_lines = 0;
  197. message.dummy_cycles = 0;
  198. /* determine if there is data to send */
  199. if (length - count > 0)
  200. {
  201. message.qspi_data_lines = 1;
  202. }
  203. else
  204. {
  205. message.qspi_data_lines = 0;
  206. }
  207. /* set send buf and send size */
  208. message.parent.send_buf = ptr + count;
  209. message.parent.recv_buf = RT_NULL;
  210. message.parent.length = length - count;
  211. message.parent.cs_take = 1;
  212. message.parent.cs_release = 1;
  213. result = rt_qspi_transfer_message(device, &message);
  214. if (result == 0)
  215. {
  216. result = -RT_EIO;
  217. }
  218. else
  219. {
  220. result = length;
  221. }
  222. return result;
  223. }