1 /*
2 * Copyright (c) 2022 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "ipc_icmsg.h"
8
9 #include <zephyr/kernel.h>
10 #include <zephyr/device.h>
11 #include <zephyr/ipc/icmsg.h>
12
13 #include <zephyr/ipc/ipc_service_backend.h>
14
15 #define DT_DRV_COMPAT zephyr_ipc_icmsg
16
register_ept(const struct device * instance,void ** token,const struct ipc_ept_cfg * cfg)17 static int register_ept(const struct device *instance, void **token,
18 const struct ipc_ept_cfg *cfg)
19 {
20 const struct icmsg_config_t *conf = instance->config;
21 struct icmsg_data_t *dev_data = instance->data;
22
23 /* Only one endpoint is supported. No need for a token. */
24 *token = NULL;
25
26 return icmsg_open(conf, dev_data, &cfg->cb, cfg->priv);
27 }
28
deregister_ept(const struct device * instance,void * token)29 static int deregister_ept(const struct device *instance, void *token)
30 {
31 const struct icmsg_config_t *conf = instance->config;
32 struct icmsg_data_t *dev_data = instance->data;
33
34 return icmsg_close(conf, dev_data);
35 }
36
send(const struct device * instance,void * token,const void * msg,size_t len)37 static int send(const struct device *instance, void *token,
38 const void *msg, size_t len)
39 {
40 const struct icmsg_config_t *conf = instance->config;
41 struct icmsg_data_t *dev_data = instance->data;
42
43 return icmsg_send(conf, dev_data, msg, len);
44 }
45
46 const static struct ipc_service_backend backend_ops = {
47 .register_endpoint = register_ept,
48 .deregister_endpoint = deregister_ept,
49 .send = send,
50 };
51
backend_init(const struct device * instance)52 static int backend_init(const struct device *instance)
53 {
54 return 0;
55 }
56
57 #define UNBOUND_MODE(i) CONCAT(ICMSG_UNBOUND_MODE_, DT_INST_STRING_UPPER_TOKEN(i, unbound))
58
59 #define DEFINE_BACKEND_DEVICE(i) \
60 static const struct icmsg_config_t backend_config_##i = { \
61 .mbox_tx = MBOX_DT_SPEC_INST_GET(i, tx), \
62 .mbox_rx = MBOX_DT_SPEC_INST_GET(i, rx), \
63 .unbound_mode = UNBOUND_MODE(i), \
64 }; \
65 \
66 PBUF_DEFINE(tx_pb_##i, \
67 DT_REG_ADDR(DT_INST_PHANDLE(i, tx_region)), \
68 DT_REG_SIZE(DT_INST_PHANDLE(i, tx_region)), \
69 DT_INST_PROP_OR(i, dcache_alignment, 0), \
70 UNBOUND_MODE(i) != ICMSG_UNBOUND_MODE_DISABLE, \
71 UNBOUND_MODE(i) == ICMSG_UNBOUND_MODE_DETECT); \
72 PBUF_DEFINE(rx_pb_##i, \
73 DT_REG_ADDR(DT_INST_PHANDLE(i, rx_region)), \
74 DT_REG_SIZE(DT_INST_PHANDLE(i, rx_region)), \
75 DT_INST_PROP_OR(i, dcache_alignment, 0), \
76 UNBOUND_MODE(i) != ICMSG_UNBOUND_MODE_DISABLE, \
77 UNBOUND_MODE(i) == ICMSG_UNBOUND_MODE_DETECT); \
78 \
79 BUILD_ASSERT(UNBOUND_MODE(i) != ICMSG_UNBOUND_MODE_DISABLE || \
80 IS_ENABLED(CONFIG_IPC_SERVICE_ICMSG_UNBOUND_DISABLED_ALLOWED), \
81 "Unbound mode \"disabled\" is was forbidden in Kconfig."); \
82 \
83 BUILD_ASSERT(UNBOUND_MODE(i) != ICMSG_UNBOUND_MODE_ENABLE || \
84 IS_ENABLED(CONFIG_IPC_SERVICE_ICMSG_UNBOUND_ENABLED_ALLOWED), \
85 "Unbound mode \"enabled\" is was forbidden in Kconfig."); \
86 \
87 BUILD_ASSERT(UNBOUND_MODE(i) != ICMSG_UNBOUND_MODE_DETECT || \
88 IS_ENABLED(CONFIG_IPC_SERVICE_ICMSG_UNBOUND_DETECT_ALLOWED), \
89 "Unbound mode \"detect\" is was forbidden in Kconfig."); \
90 \
91 static struct icmsg_data_t backend_data_##i = { \
92 .tx_pb = &tx_pb_##i, \
93 .rx_pb = &rx_pb_##i, \
94 }; \
95 \
96 DEVICE_DT_INST_DEFINE(i, \
97 &backend_init, \
98 NULL, \
99 &backend_data_##i, \
100 &backend_config_##i, \
101 POST_KERNEL, \
102 CONFIG_IPC_SERVICE_REG_BACKEND_PRIORITY, \
103 &backend_ops);
104
105 DT_INST_FOREACH_STATUS_OKAY(DEFINE_BACKEND_DEVICE)
106