xref: /OK3568_Linux_fs/u-boot/drivers/firmware/scmi/mailbox_agent.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2020 Linaro Limited.
4  */
5 
6 #include <common.h>
7 #include <dm.h>
8 #include <dm/device_compat.h>
9 #include <errno.h>
10 #include <mailbox.h>
11 #include <scmi_agent.h>
12 #include <scmi_agent-uclass.h>
13 #include <dm/devres.h>
14 #include <linux/compat.h>
15 
16 #include "smt.h"
17 
18 #define TIMEOUT_US_10MS			10000
19 
20 /**
21  * struct scmi_mbox_channel - Description of an SCMI mailbox transport
22  * @smt:	Shared memory buffer
23  * @mbox:	Mailbox channel description
24  * @timeout_us:	Timeout in microseconds for the mailbox transfer
25  */
26 struct scmi_mbox_channel {
27 	struct scmi_smt smt;
28 	struct mbox_chan mbox;
29 	ulong timeout_us;
30 };
31 
scmi_mbox_process_msg(struct udevice * dev,struct scmi_msg * msg)32 static int scmi_mbox_process_msg(struct udevice *dev, struct scmi_msg *msg)
33 {
34 	struct scmi_mbox_channel *chan = dev_get_priv(dev);
35 	int ret;
36 
37 	ret = scmi_write_msg_to_smt(dev, &chan->smt, msg);
38 	if (ret)
39 		return ret;
40 
41 	/* Give shm addr to mbox in case it is meaningful */
42 	ret = mbox_send(&chan->mbox, chan->smt.buf);
43 	if (ret) {
44 		dev_err(dev, "Message send failed: %d\n", ret);
45 		goto out;
46 	}
47 
48 	/* Receive the response */
49 	ret = mbox_recv(&chan->mbox, chan->smt.buf, chan->timeout_us);
50 	if (ret) {
51 		dev_err(dev, "Response failed: %d, abort\n", ret);
52 		goto out;
53 	}
54 
55 	ret = scmi_read_resp_from_smt(dev, &chan->smt, msg);
56 
57 out:
58 	scmi_clear_smt_channel(&chan->smt);
59 
60 	return ret;
61 }
62 
scmi_mbox_probe(struct udevice * dev)63 int scmi_mbox_probe(struct udevice *dev)
64 {
65 	struct scmi_mbox_channel *chan = dev_get_priv(dev);
66 	int ret;
67 
68 	chan->timeout_us = TIMEOUT_US_10MS;
69 
70 	ret = mbox_get_by_index(dev, 0, &chan->mbox);
71 	if (ret) {
72 		dev_err(dev, "Failed to find mailbox: %d\n", ret);
73 		goto out;
74 	}
75 
76 	ret = scmi_dt_get_smt_buffer(dev, &chan->smt);
77 	if (ret)
78 		dev_err(dev, "Failed to get shm resources: %d\n", ret);
79 
80 out:
81 	if (ret)
82 		devm_kfree(dev, chan);
83 
84 	return ret;
85 }
86 
87 static const struct udevice_id scmi_mbox_ids[] = {
88 	{ .compatible = "arm,scmi" },
89 	{ }
90 };
91 
92 static const struct scmi_agent_ops scmi_mbox_ops = {
93 	.process_msg = scmi_mbox_process_msg,
94 };
95 
96 U_BOOT_DRIVER(scmi_mbox) = {
97 	.name		= "scmi-over-mailbox",
98 	.id		= UCLASS_SCMI_AGENT,
99 	.of_match	= scmi_mbox_ids,
100 	.priv_auto_alloc_size = sizeof(struct scmi_mbox_channel),
101 	.probe		= scmi_mbox_probe,
102 	.ops		= &scmi_mbox_ops,
103 };
104