1 /*
2 * Copyright 2024 NXP
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/logging/log.h>
8 #include "mailbox.h"
9
10 LOG_MODULE_REGISTER(scmi_mbox);
11
scmi_mbox_cb(const struct device * mbox,mbox_channel_id_t channel_id,void * user_data,struct mbox_msg * data)12 static void scmi_mbox_cb(const struct device *mbox,
13 mbox_channel_id_t channel_id,
14 void *user_data,
15 struct mbox_msg *data)
16 {
17 struct scmi_channel *scmi_chan = user_data;
18
19 if (scmi_chan->cb) {
20 scmi_chan->cb(scmi_chan);
21 }
22 }
23
scmi_mbox_send_message(const struct device * transport,struct scmi_channel * chan,struct scmi_message * msg)24 static int scmi_mbox_send_message(const struct device *transport,
25 struct scmi_channel *chan,
26 struct scmi_message *msg)
27 {
28 struct scmi_mbox_channel *mbox_chan;
29 int ret;
30
31 mbox_chan = chan->data;
32
33 ret = scmi_shmem_write_message(mbox_chan->shmem, msg);
34 if (ret < 0) {
35 LOG_ERR("failed to write message to shmem: %d", ret);
36 return ret;
37 }
38
39 ret = mbox_send_dt(&mbox_chan->tx, NULL);
40 if (ret < 0) {
41 LOG_ERR("failed to ring doorbell: %d", ret);
42 return ret;
43 }
44
45 return 0;
46 }
47
scmi_mbox_read_message(const struct device * transport,struct scmi_channel * chan,struct scmi_message * msg)48 static int scmi_mbox_read_message(const struct device *transport,
49 struct scmi_channel *chan,
50 struct scmi_message *msg)
51 {
52 struct scmi_mbox_channel *mbox_chan;
53
54 mbox_chan = chan->data;
55
56 return scmi_shmem_read_message(mbox_chan->shmem, msg);
57 }
58
scmi_mbox_channel_is_free(const struct device * transport,struct scmi_channel * chan)59 static bool scmi_mbox_channel_is_free(const struct device *transport,
60 struct scmi_channel *chan)
61 {
62 struct scmi_mbox_channel *mbox_chan = chan->data;
63
64 return scmi_shmem_channel_status(mbox_chan->shmem) &
65 SCMI_SHMEM_CHAN_STATUS_BUSY_BIT;
66 }
67
scmi_mbox_setup_chan(const struct device * transport,struct scmi_channel * chan,bool tx)68 static int scmi_mbox_setup_chan(const struct device *transport,
69 struct scmi_channel *chan,
70 bool tx)
71 {
72 int ret;
73 struct scmi_mbox_channel *mbox_chan;
74 struct mbox_dt_spec *tx_reply;
75
76 mbox_chan = chan->data;
77
78 if (!tx) {
79 return -ENOTSUP;
80 }
81
82 if (mbox_chan->tx_reply.dev) {
83 tx_reply = &mbox_chan->tx_reply;
84 } else {
85 tx_reply = &mbox_chan->tx;
86 }
87
88 ret = mbox_register_callback_dt(tx_reply, scmi_mbox_cb, chan);
89 if (ret < 0) {
90 LOG_ERR("failed to register tx reply cb");
91 return ret;
92 }
93
94 ret = mbox_set_enabled_dt(tx_reply, true);
95 if (ret < 0) {
96 LOG_ERR("failed to enable tx reply dbell");
97 }
98
99 /* enable interrupt-based communication */
100 scmi_shmem_update_flags(mbox_chan->shmem,
101 SCMI_SHMEM_CHAN_FLAG_IRQ_BIT,
102 SCMI_SHMEM_CHAN_FLAG_IRQ_BIT);
103
104 return 0;
105 }
106
107 static struct scmi_transport_api scmi_mbox_api = {
108 .setup_chan = scmi_mbox_setup_chan,
109 .send_message = scmi_mbox_send_message,
110 .read_message = scmi_mbox_read_message,
111 .channel_is_free = scmi_mbox_channel_is_free,
112 };
113
114 DT_INST_SCMI_MAILBOX_DEFINE(0, PRE_KERNEL_1,
115 CONFIG_ARM_SCMI_TRANSPORT_INIT_PRIORITY,
116 &scmi_mbox_api);
117