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 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 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