1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2020 Linaro Limited.
6 #define LOG_CATEGORY UCLASS_SCMI_AGENT
12 #include <scmi_agent.h>
13 #include <scmi_agent-uclass.h>
14 #include <dm/device_compat.h>
15 #include <dm/devres.h>
16 #include <linux/compat.h>
20 #define TIMEOUT_US_10MS 10000
23 * struct scmi_mbox_channel - Description of an SCMI mailbox transport
24 * @smt: Shared memory buffer
25 * @mbox: Mailbox channel description
26 * @timeout_us: Timeout in microseconds for the mailbox transfer
28 struct scmi_mbox_channel {
30 struct mbox_chan mbox;
35 * struct scmi_channel - Channel instance referenced in SCMI drivers
36 * @ref: Reference to local channel instance
39 struct scmi_mbox_channel ref;
42 static int scmi_mbox_process_msg(struct udevice *dev,
43 struct scmi_channel *channel,
46 struct scmi_mbox_channel *chan = dev_get_plat(dev);
49 /* Support SCMI drivers upgraded to of_get_channel operator */
53 ret = scmi_write_msg_to_smt(dev, &chan->smt, msg);
57 /* Give shm addr to mbox in case it is meaningful */
58 ret = mbox_send(&chan->mbox, chan->smt.buf);
60 dev_err(dev, "Message send failed: %d\n", ret);
64 /* Receive the response */
65 ret = mbox_recv(&chan->mbox, chan->smt.buf, chan->timeout_us);
67 dev_err(dev, "Response failed: %d, abort\n", ret);
71 ret = scmi_read_resp_from_smt(dev, &chan->smt, msg);
74 scmi_clear_smt_channel(&chan->smt);
79 static int setup_channel(struct udevice *dev, struct scmi_mbox_channel *chan)
83 ret = mbox_get_by_index(dev, 0, &chan->mbox);
85 dev_err(dev, "Failed to find mailbox: %d\n", ret);
89 ret = scmi_dt_get_smt_buffer(dev, &chan->smt);
91 dev_err(dev, "Failed to get shm resources: %d\n", ret);
95 chan->timeout_us = TIMEOUT_US_10MS;
100 static int scmi_mbox_get_channel(struct udevice *dev,
101 struct scmi_channel **channel)
103 struct scmi_mbox_channel *base_chan = dev_get_plat(dev->parent);
104 struct scmi_mbox_channel *chan;
107 if (!dev_read_prop(dev, "shmem", NULL)) {
108 /* Uses agent base channel */
109 *channel = container_of(base_chan, struct scmi_channel, ref);
114 chan = calloc(1, sizeof(*chan));
118 /* Setup a dedicated channel for the protocol */
119 ret = setup_channel(dev, chan);
125 *channel = (void *)chan;
130 int scmi_mbox_of_to_plat(struct udevice *dev)
132 struct scmi_mbox_channel *chan = dev_get_plat(dev);
134 return setup_channel(dev, chan);
137 static const struct udevice_id scmi_mbox_ids[] = {
138 { .compatible = "arm,scmi" },
142 static const struct scmi_agent_ops scmi_mbox_ops = {
143 .of_get_channel = scmi_mbox_get_channel,
144 .process_msg = scmi_mbox_process_msg,
147 U_BOOT_DRIVER(scmi_mbox) = {
148 .name = "scmi-over-mailbox",
149 .id = UCLASS_SCMI_AGENT,
150 .of_match = scmi_mbox_ids,
151 .plat_auto = sizeof(struct scmi_mbox_channel),
152 .of_to_plat = scmi_mbox_of_to_plat,
153 .ops = &scmi_mbox_ops,