rpmsg.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  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. * 2023-02-25 GuEe-GUI the first version
  9. */
  10. #include <rthw.h>
  11. #include <rtthread.h>
  12. #include <drivers/ofw.h>
  13. #include <drivers/rpmsg.h>
  14. #include <drivers/core/bus.h>
  15. #include <drivers/core/power_domain.h>
  16. #define DBG_TAG "rtdm.rpmsg"
  17. #define DBG_LVL DBG_INFO
  18. #include <rtdbg.h>
  19. static rt_uint32_t rpmsg_mode = RT_RPMSG_MODE_SLAVE;
  20. static int rpmsg_mode_setup(void)
  21. {
  22. const char *mode = RT_NULL;
  23. #ifdef RT_USING_OFW
  24. mode = rt_ofw_bootargs_select("rpmsg.mode=", 0);
  25. #endif
  26. if (!mode)
  27. {
  28. goto _end;
  29. }
  30. if (!rt_strcmp(mode, "master"))
  31. {
  32. rpmsg_mode = RT_RPMSG_MODE_MASTER;
  33. }
  34. else if (!rt_strcmp(mode, "slave"))
  35. {
  36. rpmsg_mode = RT_RPMSG_MODE_SLAVE;
  37. }
  38. else
  39. {
  40. LOG_W("Unknown mode of RPMsg: %s", mode);
  41. return (int)-RT_EINVAL;
  42. }
  43. _end:
  44. LOG_D("RPMsg mode: %s", rpmsg_mode == RT_RPMSG_MODE_MASTER ? "master" : "slave");
  45. return 0;
  46. }
  47. INIT_CORE_EXPORT(rpmsg_mode_setup);
  48. rt_uint32_t rt_rpmsg_mode(void)
  49. {
  50. return rpmsg_mode;
  51. }
  52. struct rt_rpmsg_endpoint *rt_rpmsg_create_endpoint(struct rt_rpmsg_device *rdev,
  53. struct rt_rpmsg_endpoint_info *info, rt_rpmsg_rx_callback rx_cb)
  54. {
  55. rt_err_t err;
  56. rt_ubase_t level;
  57. struct rt_rpmsg_endpoint *ept;
  58. RT_ASSERT(rdev != RT_NULL);
  59. RT_ASSERT(info != RT_NULL);
  60. ept = rt_calloc(1, sizeof(*ept));
  61. if (!ept)
  62. {
  63. return rt_err_ptr(-RT_ENOMEM);
  64. }
  65. ept->rdev = rdev;
  66. rt_memcpy(&ept->info, info, sizeof(ept->info));
  67. ept->rx_callback = rx_cb ? : rt_container_of(rdev->parent.drv,
  68. struct rt_rpmsg_driver, parent)->rx_callback;
  69. RT_ASSERT(ept->rx_callback != RT_NULL);
  70. err = rdev->ops->create_endpoint(rdev, ept, info);
  71. if (err)
  72. {
  73. rt_free(ept);
  74. return rt_err_ptr(err);
  75. }
  76. rt_spin_lock_init(&ept->lock);
  77. rt_list_init(&ept->list);
  78. level = rt_spin_lock_irqsave(&rdev->lock);
  79. rt_list_insert_before(&rdev->ept_nodes, &ept->list);
  80. rt_spin_unlock_irqrestore(&rdev->lock, level);
  81. return ept;
  82. }
  83. rt_err_t rt_rpmsg_destroy_endpoint(struct rt_rpmsg_device *rdev,
  84. struct rt_rpmsg_endpoint *ept)
  85. {
  86. rt_err_t err;
  87. rt_ubase_t level;
  88. RT_ASSERT(rdev != RT_NULL);
  89. RT_ASSERT(ept != RT_NULL);
  90. err = rdev->ops->destroy_endpoint(rdev, ept);
  91. if (err)
  92. {
  93. return err;
  94. }
  95. level = rt_spin_lock_irqsave(&rdev->lock);
  96. rt_list_remove(&ept->list);
  97. rt_spin_unlock_irqrestore(&rdev->lock, level);
  98. rt_free(ept);
  99. return RT_EOK;
  100. }
  101. struct rt_rpmsg_endpoint *rt_rpmsg_find_endpoint(struct rt_rpmsg_device *rdev,
  102. struct rt_rpmsg_endpoint_info *info)
  103. {
  104. rt_ubase_t level;
  105. struct rt_rpmsg_endpoint *ept = RT_NULL, *ept_tmp;
  106. RT_ASSERT(rdev != RT_NULL);
  107. RT_ASSERT(info != RT_NULL);
  108. level = rt_spin_lock_irqsave(&rdev->lock);
  109. rt_list_for_each_entry(ept_tmp, &rdev->ept_nodes, list)
  110. {
  111. if (info->src != RT_RPMSG_ADDR_ANY && info->src != ept_tmp->info.src)
  112. {
  113. continue;
  114. }
  115. if (info->dst != RT_RPMSG_ADDR_ANY && info->dst != ept_tmp->info.dst)
  116. {
  117. continue;
  118. }
  119. if (info->name[0] &&
  120. rt_strncmp(info->name, ept_tmp->info.name, RT_RPMSG_NAME_SIZE))
  121. {
  122. continue;
  123. }
  124. ept = ept_tmp;
  125. break;
  126. }
  127. rt_spin_unlock_irqrestore(&rdev->lock, level);
  128. return ept;
  129. }
  130. rt_err_t rt_rpmsg_send(struct rt_rpmsg_endpoint *ept,
  131. const void *data, rt_size_t len)
  132. {
  133. RT_ASSERT(ept != RT_NULL);
  134. return rt_rpmsg_sendto(ept, ept->info.dst, data, len);
  135. }
  136. rt_err_t rt_rpmsg_sendto(struct rt_rpmsg_endpoint *ept, rt_uint32_t dst,
  137. const void *data, rt_size_t len)
  138. {
  139. RT_ASSERT(ept != RT_NULL);
  140. return rt_rpmsg_sendto_wait(ept, dst, data, len, 0);
  141. }
  142. rt_err_t rt_rpmsg_send_wait(struct rt_rpmsg_endpoint *ept,
  143. const void *data, rt_size_t len, rt_int32_t timeout)
  144. {
  145. RT_ASSERT(ept != RT_NULL);
  146. return rt_rpmsg_sendto_wait(ept, ept->info.dst, data, len, timeout);
  147. }
  148. rt_err_t rt_rpmsg_sendto_wait(struct rt_rpmsg_endpoint *ept, rt_uint32_t dst,
  149. const void *data, rt_size_t len, rt_int32_t timeout)
  150. {
  151. rt_err_t err;
  152. struct rt_rpmsg_device *rdev;
  153. RT_ASSERT(ept != RT_NULL);
  154. rdev = ept->rdev;
  155. rt_hw_spin_lock(&ept->lock.lock);
  156. err = rdev->ops->send(rdev, ept->info.src, dst, data, len, timeout);
  157. rt_hw_spin_unlock(&ept->lock.lock);
  158. return err;
  159. }
  160. static struct rt_bus rpmsg_bus;
  161. rt_err_t rt_rpmsg_driver_register(struct rt_rpmsg_driver *rdrv)
  162. {
  163. RT_ASSERT(rdrv != RT_NULL);
  164. rdrv->parent.bus = &rpmsg_bus;
  165. return rt_driver_register(&rdrv->parent);
  166. }
  167. rt_err_t rt_rpmsg_device_register(struct rt_rpmsg_device *rdev)
  168. {
  169. rt_err_t err;
  170. if ((err = rt_dm_dev_set_name_auto(&rdev->parent, rdev->id.name)) < 0)
  171. {
  172. return err;
  173. }
  174. rt_list_init(&rdev->ept_nodes);
  175. rt_spin_lock_init(&rdev->lock);
  176. return rt_bus_add_device(&rpmsg_bus, &rdev->parent);
  177. }
  178. static rt_bool_t rpmsg_match(rt_driver_t drv, rt_device_t dev)
  179. {
  180. const struct rt_rpmsg_device_id *id;
  181. struct rt_rpmsg_driver *rdrv = rt_container_of(drv, struct rt_rpmsg_driver, parent);
  182. struct rt_rpmsg_device *rdev = rt_container_of(dev, struct rt_rpmsg_device, parent);
  183. for (id = rdrv->ids; id->name[0]; ++id)
  184. {
  185. if (!rt_strncmp(id->name, rdev->id.name, RT_RPMSG_NAME_SIZE))
  186. {
  187. rdev->id.data = id->data;
  188. return RT_TRUE;
  189. }
  190. }
  191. return RT_FALSE;
  192. }
  193. static rt_err_t rpmsg_probe(rt_device_t dev)
  194. {
  195. rt_err_t err;
  196. struct rt_rpmsg_driver *rdrv = rt_container_of(dev->drv, struct rt_rpmsg_driver, parent);
  197. struct rt_rpmsg_device *rdev = rt_container_of(dev, struct rt_rpmsg_device, parent);
  198. err = rt_dm_power_domain_attach(dev, RT_TRUE);
  199. if (err && err != -RT_EEMPTY)
  200. {
  201. LOG_E("Attach power domain error = %s in device %s",
  202. rt_strerror(err), rt_dm_dev_get_name(dev));
  203. return err;
  204. }
  205. err = rdrv->probe(rdev);
  206. if (err)
  207. {
  208. rt_dm_power_domain_detach(dev, RT_TRUE);
  209. }
  210. return err;
  211. }
  212. static rt_err_t rpmsg_remove(rt_device_t dev)
  213. {
  214. rt_ubase_t level;
  215. struct rt_rpmsg_endpoint *ept, *ept_next;
  216. struct rt_rpmsg_driver *rdrv = rt_container_of(dev->drv, struct rt_rpmsg_driver, parent);
  217. struct rt_rpmsg_device *rdev = rt_container_of(dev, struct rt_rpmsg_device, parent);
  218. level = rt_spin_lock_irqsave(&rdev->lock);
  219. rt_list_for_each_entry_safe(ept, ept_next, &rdev->ept_nodes, list)
  220. {
  221. rt_spin_unlock_irqrestore(&rdev->lock, level);
  222. rt_rpmsg_destroy_endpoint(rdev, ept);
  223. level = rt_spin_lock_irqsave(&rdev->lock);
  224. }
  225. rt_spin_unlock_irqrestore(&rdev->lock, level);
  226. if (rdrv && rdrv->remove)
  227. {
  228. rdrv->remove(rdev);
  229. }
  230. rt_dm_power_domain_detach(dev, RT_TRUE);
  231. return RT_EOK;
  232. }
  233. static struct rt_bus rpmsg_bus =
  234. {
  235. .name = "rpmsg",
  236. .match = rpmsg_match,
  237. .probe = rpmsg_probe,
  238. .remove = rpmsg_remove,
  239. };
  240. static int rpmsg_bus_init(void)
  241. {
  242. rt_bus_register(&rpmsg_bus);
  243. return 0;
  244. }
  245. INIT_CORE_EXPORT(rpmsg_bus_init);