spi_core.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  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. * 2012-01-08 bernard first version.
  9. * 2012-02-03 bernard add const attribute to the ops.
  10. * 2012-05-15 dzzxzz fixed the return value in attach_device.
  11. * 2012-05-18 bernard Changed SPI message to message list.
  12. * Added take/release SPI device/bus interface.
  13. * 2012-09-28 aozima fixed rt_spi_release_bus assert error.
  14. */
  15. #include <drivers/spi.h>
  16. extern rt_err_t rt_spi_bus_device_init(struct rt_spi_bus *bus, const char *name);
  17. extern rt_err_t rt_spidev_device_init(struct rt_spi_device *dev, const char *name);
  18. rt_err_t rt_spi_bus_register(struct rt_spi_bus *bus,
  19. const char *name,
  20. const struct rt_spi_ops *ops)
  21. {
  22. rt_err_t result;
  23. result = rt_spi_bus_device_init(bus, name);
  24. if (result != RT_EOK)
  25. return result;
  26. /* initialize mutex lock */
  27. rt_mutex_init(&(bus->lock), name, RT_IPC_FLAG_FIFO);
  28. /* set ops */
  29. bus->ops = ops;
  30. /* initialize owner */
  31. bus->owner = RT_NULL;
  32. return RT_EOK;
  33. }
  34. rt_err_t rt_spi_bus_attach_device(struct rt_spi_device *device,
  35. const char *name,
  36. const char *bus_name,
  37. void *user_data)
  38. {
  39. rt_err_t result;
  40. rt_device_t bus;
  41. /* get physical spi bus */
  42. bus = rt_device_find(bus_name);
  43. if (bus != RT_NULL && bus->type == RT_Device_Class_SPIBUS)
  44. {
  45. device->bus = (struct rt_spi_bus *)bus;
  46. /* initialize spidev device */
  47. result = rt_spidev_device_init(device, name);
  48. if (result != RT_EOK)
  49. return result;
  50. rt_memset(&device->config, 0, sizeof(device->config));
  51. device->parent.user_data = user_data;
  52. return RT_EOK;
  53. }
  54. /* not found the host bus */
  55. return -RT_ERROR;
  56. }
  57. rt_err_t rt_spi_configure(struct rt_spi_device *device,
  58. struct rt_spi_configuration *cfg)
  59. {
  60. rt_err_t result;
  61. RT_ASSERT(device != RT_NULL);
  62. /* set configuration */
  63. device->config.data_width = cfg->data_width;
  64. device->config.mode = cfg->mode & RT_SPI_MODE_MASK ;
  65. device->config.max_hz = cfg->max_hz ;
  66. if (device->bus != RT_NULL)
  67. {
  68. result = rt_mutex_take(&(device->bus->lock), RT_WAITING_FOREVER);
  69. if (result == RT_EOK)
  70. {
  71. if (device->bus->owner == device)
  72. {
  73. device->bus->ops->configure(device, &device->config);
  74. }
  75. /* release lock */
  76. rt_mutex_release(&(device->bus->lock));
  77. }
  78. }
  79. return RT_EOK;
  80. }
  81. rt_err_t rt_spi_send_then_send(struct rt_spi_device *device,
  82. const void *send_buf1,
  83. rt_size_t send_length1,
  84. const void *send_buf2,
  85. rt_size_t send_length2)
  86. {
  87. rt_err_t result;
  88. struct rt_spi_message message;
  89. RT_ASSERT(device != RT_NULL);
  90. RT_ASSERT(device->bus != RT_NULL);
  91. result = rt_mutex_take(&(device->bus->lock), RT_WAITING_FOREVER);
  92. if (result == RT_EOK)
  93. {
  94. if (device->bus->owner != device)
  95. {
  96. /* not the same owner as current, re-configure SPI bus */
  97. result = device->bus->ops->configure(device, &device->config);
  98. if (result == RT_EOK)
  99. {
  100. /* set SPI bus owner */
  101. device->bus->owner = device;
  102. }
  103. else
  104. {
  105. /* configure SPI bus failed */
  106. result = -RT_EIO;
  107. goto __exit;
  108. }
  109. }
  110. /* send data1 */
  111. message.send_buf = send_buf1;
  112. message.recv_buf = RT_NULL;
  113. message.length = send_length1;
  114. message.cs_take = 1;
  115. message.cs_release = 0;
  116. message.next = RT_NULL;
  117. result = device->bus->ops->xfer(device, &message);
  118. if (result == 0)
  119. {
  120. result = -RT_EIO;
  121. goto __exit;
  122. }
  123. /* send data2 */
  124. message.send_buf = send_buf2;
  125. message.recv_buf = RT_NULL;
  126. message.length = send_length2;
  127. message.cs_take = 0;
  128. message.cs_release = 1;
  129. message.next = RT_NULL;
  130. result = device->bus->ops->xfer(device, &message);
  131. if (result == 0)
  132. {
  133. result = -RT_EIO;
  134. goto __exit;
  135. }
  136. result = RT_EOK;
  137. }
  138. else
  139. {
  140. return -RT_EIO;
  141. }
  142. __exit:
  143. rt_mutex_release(&(device->bus->lock));
  144. return result;
  145. }
  146. rt_err_t rt_spi_send_then_recv(struct rt_spi_device *device,
  147. const void *send_buf,
  148. rt_size_t send_length,
  149. void *recv_buf,
  150. rt_size_t recv_length)
  151. {
  152. rt_err_t result;
  153. struct rt_spi_message message;
  154. RT_ASSERT(device != RT_NULL);
  155. RT_ASSERT(device->bus != RT_NULL);
  156. result = rt_mutex_take(&(device->bus->lock), RT_WAITING_FOREVER);
  157. if (result == RT_EOK)
  158. {
  159. if (device->bus->owner != device)
  160. {
  161. /* not the same owner as current, re-configure SPI bus */
  162. result = device->bus->ops->configure(device, &device->config);
  163. if (result == RT_EOK)
  164. {
  165. /* set SPI bus owner */
  166. device->bus->owner = device;
  167. }
  168. else
  169. {
  170. /* configure SPI bus failed */
  171. result = -RT_EIO;
  172. goto __exit;
  173. }
  174. }
  175. /* send data */
  176. message.send_buf = send_buf;
  177. message.recv_buf = RT_NULL;
  178. message.length = send_length;
  179. message.cs_take = 1;
  180. message.cs_release = 0;
  181. message.next = RT_NULL;
  182. result = device->bus->ops->xfer(device, &message);
  183. if (result == 0)
  184. {
  185. result = -RT_EIO;
  186. goto __exit;
  187. }
  188. /* recv data */
  189. message.send_buf = RT_NULL;
  190. message.recv_buf = recv_buf;
  191. message.length = recv_length;
  192. message.cs_take = 0;
  193. message.cs_release = 1;
  194. message.next = RT_NULL;
  195. result = device->bus->ops->xfer(device, &message);
  196. if (result == 0)
  197. {
  198. result = -RT_EIO;
  199. goto __exit;
  200. }
  201. result = RT_EOK;
  202. }
  203. else
  204. {
  205. return -RT_EIO;
  206. }
  207. __exit:
  208. rt_mutex_release(&(device->bus->lock));
  209. return result;
  210. }
  211. rt_size_t rt_spi_transfer(struct rt_spi_device *device,
  212. const void *send_buf,
  213. void *recv_buf,
  214. rt_size_t length)
  215. {
  216. rt_err_t result;
  217. struct rt_spi_message message;
  218. RT_ASSERT(device != RT_NULL);
  219. RT_ASSERT(device->bus != RT_NULL);
  220. result = rt_mutex_take(&(device->bus->lock), RT_WAITING_FOREVER);
  221. if (result == RT_EOK)
  222. {
  223. if (device->bus->owner != device)
  224. {
  225. /* not the same owner as current, re-configure SPI bus */
  226. result = device->bus->ops->configure(device, &device->config);
  227. if (result == RT_EOK)
  228. {
  229. /* set SPI bus owner */
  230. device->bus->owner = device;
  231. }
  232. else
  233. {
  234. /* configure SPI bus failed */
  235. rt_set_errno(-RT_EIO);
  236. result = 0;
  237. goto __exit;
  238. }
  239. }
  240. /* initial message */
  241. message.send_buf = send_buf;
  242. message.recv_buf = recv_buf;
  243. message.length = length;
  244. message.cs_take = 1;
  245. message.cs_release = 1;
  246. message.next = RT_NULL;
  247. /* transfer message */
  248. result = device->bus->ops->xfer(device, &message);
  249. if (result == 0)
  250. {
  251. rt_set_errno(-RT_EIO);
  252. goto __exit;
  253. }
  254. }
  255. else
  256. {
  257. rt_set_errno(-RT_EIO);
  258. return 0;
  259. }
  260. __exit:
  261. rt_mutex_release(&(device->bus->lock));
  262. return result;
  263. }
  264. struct rt_spi_message *rt_spi_transfer_message(struct rt_spi_device *device,
  265. struct rt_spi_message *message)
  266. {
  267. rt_err_t result;
  268. struct rt_spi_message *index;
  269. RT_ASSERT(device != RT_NULL);
  270. /* get first message */
  271. index = message;
  272. if (index == RT_NULL)
  273. return index;
  274. result = rt_mutex_take(&(device->bus->lock), RT_WAITING_FOREVER);
  275. if (result != RT_EOK)
  276. {
  277. rt_set_errno(-RT_EBUSY);
  278. return index;
  279. }
  280. /* reset errno */
  281. rt_set_errno(RT_EOK);
  282. /* configure SPI bus */
  283. if (device->bus->owner != device)
  284. {
  285. /* not the same owner as current, re-configure SPI bus */
  286. result = device->bus->ops->configure(device, &device->config);
  287. if (result == RT_EOK)
  288. {
  289. /* set SPI bus owner */
  290. device->bus->owner = device;
  291. }
  292. else
  293. {
  294. /* configure SPI bus failed */
  295. rt_set_errno(-RT_EIO);
  296. goto __exit;
  297. }
  298. }
  299. /* transmit each SPI message */
  300. while (index != RT_NULL)
  301. {
  302. /* transmit SPI message */
  303. result = device->bus->ops->xfer(device, index);
  304. if (result == 0)
  305. {
  306. rt_set_errno(-RT_EIO);
  307. break;
  308. }
  309. index = index->next;
  310. }
  311. __exit:
  312. /* release bus lock */
  313. rt_mutex_release(&(device->bus->lock));
  314. return index;
  315. }
  316. rt_err_t rt_spi_take_bus(struct rt_spi_device *device)
  317. {
  318. rt_err_t result = RT_EOK;
  319. RT_ASSERT(device != RT_NULL);
  320. RT_ASSERT(device->bus != RT_NULL);
  321. result = rt_mutex_take(&(device->bus->lock), RT_WAITING_FOREVER);
  322. if (result != RT_EOK)
  323. {
  324. rt_set_errno(-RT_EBUSY);
  325. return -RT_EBUSY;
  326. }
  327. /* reset errno */
  328. rt_set_errno(RT_EOK);
  329. /* configure SPI bus */
  330. if (device->bus->owner != device)
  331. {
  332. /* not the same owner as current, re-configure SPI bus */
  333. result = device->bus->ops->configure(device, &device->config);
  334. if (result == RT_EOK)
  335. {
  336. /* set SPI bus owner */
  337. device->bus->owner = device;
  338. }
  339. else
  340. {
  341. /* configure SPI bus failed */
  342. rt_set_errno(-RT_EIO);
  343. /* release lock */
  344. rt_mutex_release(&(device->bus->lock));
  345. return -RT_EIO;
  346. }
  347. }
  348. return result;
  349. }
  350. rt_err_t rt_spi_release_bus(struct rt_spi_device *device)
  351. {
  352. RT_ASSERT(device != RT_NULL);
  353. RT_ASSERT(device->bus != RT_NULL);
  354. RT_ASSERT(device->bus->owner == device);
  355. /* release lock */
  356. rt_mutex_release(&(device->bus->lock));
  357. return RT_EOK;
  358. }
  359. rt_err_t rt_spi_take(struct rt_spi_device *device)
  360. {
  361. rt_err_t result;
  362. struct rt_spi_message message;
  363. RT_ASSERT(device != RT_NULL);
  364. RT_ASSERT(device->bus != RT_NULL);
  365. rt_memset(&message, 0, sizeof(message));
  366. message.cs_take = 1;
  367. result = device->bus->ops->xfer(device, &message);
  368. return result;
  369. }
  370. rt_err_t rt_spi_release(struct rt_spi_device *device)
  371. {
  372. rt_err_t result;
  373. struct rt_spi_message message;
  374. RT_ASSERT(device != RT_NULL);
  375. RT_ASSERT(device->bus != RT_NULL);
  376. rt_memset(&message, 0, sizeof(message));
  377. message.cs_release = 1;
  378. result = device->bus->ops->xfer(device, &message);
  379. return result;
  380. }