| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 |
- /*
- * Copyright (c) 2006-2023, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2023-02-25 GuEe-GUI the first version
- */
- #include <rthw.h>
- #include <rtthread.h>
- #include <drivers/ofw.h>
- #include <drivers/rpmsg.h>
- #include <drivers/core/bus.h>
- #include <drivers/core/power_domain.h>
- #define DBG_TAG "rtdm.rpmsg"
- #define DBG_LVL DBG_INFO
- #include <rtdbg.h>
- static rt_uint32_t rpmsg_mode = RT_RPMSG_MODE_SLAVE;
- static int rpmsg_mode_setup(void)
- {
- const char *mode = RT_NULL;
- #ifdef RT_USING_OFW
- mode = rt_ofw_bootargs_select("rpmsg.mode=", 0);
- #endif
- if (!mode)
- {
- goto _end;
- }
- if (!rt_strcmp(mode, "master"))
- {
- rpmsg_mode = RT_RPMSG_MODE_MASTER;
- }
- else if (!rt_strcmp(mode, "slave"))
- {
- rpmsg_mode = RT_RPMSG_MODE_SLAVE;
- }
- else
- {
- LOG_W("Unknown mode of RPMsg: %s", mode);
- return (int)-RT_EINVAL;
- }
- _end:
- LOG_D("RPMsg mode: %s", rpmsg_mode == RT_RPMSG_MODE_MASTER ? "master" : "slave");
- return 0;
- }
- INIT_CORE_EXPORT(rpmsg_mode_setup);
- rt_uint32_t rt_rpmsg_mode(void)
- {
- return rpmsg_mode;
- }
- struct rt_rpmsg_endpoint *rt_rpmsg_create_endpoint(struct rt_rpmsg_device *rdev,
- struct rt_rpmsg_endpoint_info *info, rt_rpmsg_rx_callback rx_cb)
- {
- rt_err_t err;
- rt_ubase_t level;
- struct rt_rpmsg_endpoint *ept;
- RT_ASSERT(rdev != RT_NULL);
- RT_ASSERT(info != RT_NULL);
- ept = rt_calloc(1, sizeof(*ept));
- if (!ept)
- {
- return rt_err_ptr(-RT_ENOMEM);
- }
- ept->rdev = rdev;
- rt_memcpy(&ept->info, info, sizeof(ept->info));
- ept->rx_callback = rx_cb ? : rt_container_of(rdev->parent.drv,
- struct rt_rpmsg_driver, parent)->rx_callback;
- RT_ASSERT(ept->rx_callback != RT_NULL);
- err = rdev->ops->create_endpoint(rdev, ept, info);
- if (err)
- {
- rt_free(ept);
- return rt_err_ptr(err);
- }
- rt_spin_lock_init(&ept->lock);
- rt_list_init(&ept->list);
- level = rt_spin_lock_irqsave(&rdev->lock);
- rt_list_insert_before(&rdev->ept_nodes, &ept->list);
- rt_spin_unlock_irqrestore(&rdev->lock, level);
- return ept;
- }
- rt_err_t rt_rpmsg_destroy_endpoint(struct rt_rpmsg_device *rdev,
- struct rt_rpmsg_endpoint *ept)
- {
- rt_err_t err;
- rt_ubase_t level;
- RT_ASSERT(rdev != RT_NULL);
- RT_ASSERT(ept != RT_NULL);
- err = rdev->ops->destroy_endpoint(rdev, ept);
- if (err)
- {
- return err;
- }
- level = rt_spin_lock_irqsave(&rdev->lock);
- rt_list_remove(&ept->list);
- rt_spin_unlock_irqrestore(&rdev->lock, level);
- rt_free(ept);
- return RT_EOK;
- }
- struct rt_rpmsg_endpoint *rt_rpmsg_find_endpoint(struct rt_rpmsg_device *rdev,
- struct rt_rpmsg_endpoint_info *info)
- {
- rt_ubase_t level;
- struct rt_rpmsg_endpoint *ept = RT_NULL, *ept_tmp;
- RT_ASSERT(rdev != RT_NULL);
- RT_ASSERT(info != RT_NULL);
- level = rt_spin_lock_irqsave(&rdev->lock);
- rt_list_for_each_entry(ept_tmp, &rdev->ept_nodes, list)
- {
- if (info->src != RT_RPMSG_ADDR_ANY && info->src != ept_tmp->info.src)
- {
- continue;
- }
- if (info->dst != RT_RPMSG_ADDR_ANY && info->dst != ept_tmp->info.dst)
- {
- continue;
- }
- if (info->name[0] &&
- rt_strncmp(info->name, ept_tmp->info.name, RT_RPMSG_NAME_SIZE))
- {
- continue;
- }
- ept = ept_tmp;
- break;
- }
- rt_spin_unlock_irqrestore(&rdev->lock, level);
- return ept;
- }
- rt_err_t rt_rpmsg_send(struct rt_rpmsg_endpoint *ept,
- const void *data, rt_size_t len)
- {
- RT_ASSERT(ept != RT_NULL);
- return rt_rpmsg_sendto(ept, ept->info.dst, data, len);
- }
- rt_err_t rt_rpmsg_sendto(struct rt_rpmsg_endpoint *ept, rt_uint32_t dst,
- const void *data, rt_size_t len)
- {
- RT_ASSERT(ept != RT_NULL);
- return rt_rpmsg_sendto_wait(ept, dst, data, len, 0);
- }
- rt_err_t rt_rpmsg_send_wait(struct rt_rpmsg_endpoint *ept,
- const void *data, rt_size_t len, rt_int32_t timeout)
- {
- RT_ASSERT(ept != RT_NULL);
- return rt_rpmsg_sendto_wait(ept, ept->info.dst, data, len, timeout);
- }
- rt_err_t rt_rpmsg_sendto_wait(struct rt_rpmsg_endpoint *ept, rt_uint32_t dst,
- const void *data, rt_size_t len, rt_int32_t timeout)
- {
- rt_err_t err;
- struct rt_rpmsg_device *rdev;
- RT_ASSERT(ept != RT_NULL);
- rdev = ept->rdev;
- rt_hw_spin_lock(&ept->lock.lock);
- err = rdev->ops->send(rdev, ept->info.src, dst, data, len, timeout);
- rt_hw_spin_unlock(&ept->lock.lock);
- return err;
- }
- static struct rt_bus rpmsg_bus;
- rt_err_t rt_rpmsg_driver_register(struct rt_rpmsg_driver *rdrv)
- {
- RT_ASSERT(rdrv != RT_NULL);
- rdrv->parent.bus = &rpmsg_bus;
- return rt_driver_register(&rdrv->parent);
- }
- rt_err_t rt_rpmsg_device_register(struct rt_rpmsg_device *rdev)
- {
- rt_err_t err;
- if ((err = rt_dm_dev_set_name_auto(&rdev->parent, rdev->id.name)) < 0)
- {
- return err;
- }
- rt_list_init(&rdev->ept_nodes);
- rt_spin_lock_init(&rdev->lock);
- return rt_bus_add_device(&rpmsg_bus, &rdev->parent);
- }
- static rt_bool_t rpmsg_match(rt_driver_t drv, rt_device_t dev)
- {
- const struct rt_rpmsg_device_id *id;
- struct rt_rpmsg_driver *rdrv = rt_container_of(drv, struct rt_rpmsg_driver, parent);
- struct rt_rpmsg_device *rdev = rt_container_of(dev, struct rt_rpmsg_device, parent);
- for (id = rdrv->ids; id->name[0]; ++id)
- {
- if (!rt_strncmp(id->name, rdev->id.name, RT_RPMSG_NAME_SIZE))
- {
- rdev->id.data = id->data;
- return RT_TRUE;
- }
- }
- return RT_FALSE;
- }
- static rt_err_t rpmsg_probe(rt_device_t dev)
- {
- rt_err_t err;
- struct rt_rpmsg_driver *rdrv = rt_container_of(dev->drv, struct rt_rpmsg_driver, parent);
- struct rt_rpmsg_device *rdev = rt_container_of(dev, struct rt_rpmsg_device, parent);
- err = rt_dm_power_domain_attach(dev, RT_TRUE);
- if (err && err != -RT_EEMPTY)
- {
- LOG_E("Attach power domain error = %s in device %s",
- rt_strerror(err), rt_dm_dev_get_name(dev));
- return err;
- }
- err = rdrv->probe(rdev);
- if (err)
- {
- rt_dm_power_domain_detach(dev, RT_TRUE);
- }
- return err;
- }
- static rt_err_t rpmsg_remove(rt_device_t dev)
- {
- rt_ubase_t level;
- struct rt_rpmsg_endpoint *ept, *ept_next;
- struct rt_rpmsg_driver *rdrv = rt_container_of(dev->drv, struct rt_rpmsg_driver, parent);
- struct rt_rpmsg_device *rdev = rt_container_of(dev, struct rt_rpmsg_device, parent);
- level = rt_spin_lock_irqsave(&rdev->lock);
- rt_list_for_each_entry_safe(ept, ept_next, &rdev->ept_nodes, list)
- {
- rt_spin_unlock_irqrestore(&rdev->lock, level);
- rt_rpmsg_destroy_endpoint(rdev, ept);
- level = rt_spin_lock_irqsave(&rdev->lock);
- }
- rt_spin_unlock_irqrestore(&rdev->lock, level);
- if (rdrv && rdrv->remove)
- {
- rdrv->remove(rdev);
- }
- rt_dm_power_domain_detach(dev, RT_TRUE);
- return RT_EOK;
- }
- static struct rt_bus rpmsg_bus =
- {
- .name = "rpmsg",
- .match = rpmsg_match,
- .probe = rpmsg_probe,
- .remove = rpmsg_remove,
- };
- static int rpmsg_bus_init(void)
- {
- rt_bus_register(&rpmsg_bus);
- return 0;
- }
- INIT_CORE_EXPORT(rpmsg_bus_init);
|