]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
firmware: scmi: mailbox transport: implement multi-channel
authorEtienne Carriere <etienne.carriere@linaro.org>
Tue, 31 May 2022 16:09:22 +0000 (18:09 +0200)
committerTom Rini <trini@konsulko.com>
Thu, 23 Jun 2022 17:12:55 +0000 (13:12 -0400)
Updates SCMI mailbox transport driver to get SCMI channel reference
at initialization and use when posting SCMI messages.

Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
drivers/firmware/scmi/mailbox_agent.c

index aa4929aafaed7de3db260f56e9c39b7fe8c14e91..e63b67c5ee8ccc1751c4819468483dac067e8699 100644 (file)
@@ -31,6 +31,14 @@ struct scmi_mbox_channel {
        ulong timeout_us;
 };
 
+/**
+ * struct scmi_channel - Channel instance referenced in SCMI drivers
+ * @ref: Reference to local channel instance
+ **/
+struct scmi_channel {
+       struct scmi_mbox_channel ref;
+};
+
 static int scmi_mbox_process_msg(struct udevice *dev,
                                 struct scmi_channel *channel,
                                 struct scmi_msg *msg)
@@ -38,6 +46,10 @@ static int scmi_mbox_process_msg(struct udevice *dev,
        struct scmi_mbox_channel *chan = dev_get_plat(dev);
        int ret;
 
+       /* Support SCMI drivers upgraded to of_get_channel operator */
+       if (channel)
+               chan = &channel->ref;
+
        ret = scmi_write_msg_to_smt(dev, &chan->smt, msg);
        if (ret)
                return ret;
@@ -64,13 +76,10 @@ out:
        return ret;
 }
 
-int scmi_mbox_of_to_plat(struct udevice *dev)
+static int setup_channel(struct udevice *dev, struct scmi_mbox_channel *chan)
 {
-       struct scmi_mbox_channel *chan = dev_get_plat(dev);
        int ret;
 
-       chan->timeout_us = TIMEOUT_US_10MS;
-
        ret = mbox_get_by_index(dev, 0, &chan->mbox);
        if (ret) {
                dev_err(dev, "Failed to find mailbox: %d\n", ret);
@@ -78,10 +87,51 @@ int scmi_mbox_of_to_plat(struct udevice *dev)
        }
 
        ret = scmi_dt_get_smt_buffer(dev, &chan->smt);
-       if (ret)
+       if (ret) {
                dev_err(dev, "Failed to get shm resources: %d\n", ret);
+               return ret;
+       }
 
-       return ret;
+       chan->timeout_us = TIMEOUT_US_10MS;
+
+       return 0;
+}
+
+static int scmi_mbox_get_channel(struct udevice *dev,
+                                struct scmi_channel **channel)
+{
+       struct scmi_mbox_channel *base_chan = dev_get_plat(dev->parent);
+       struct scmi_mbox_channel *chan;
+       int ret;
+
+       if (!dev_read_prop(dev, "shmem", NULL)) {
+               /* Uses agent base channel */
+               *channel = container_of(base_chan, struct scmi_channel, ref);
+
+               return 0;
+       }
+
+       chan = calloc(1, sizeof(*chan));
+       if (!chan)
+               return -ENOMEM;
+
+       /* Setup a dedicated channel for the protocol */
+       ret = setup_channel(dev, chan);
+       if (ret) {
+               free(chan);
+               return ret;
+       }
+
+       *channel = (void *)chan;
+
+       return 0;
+}
+
+int scmi_mbox_of_to_plat(struct udevice *dev)
+{
+       struct scmi_mbox_channel *chan = dev_get_plat(dev);
+
+       return setup_channel(dev, chan);
 }
 
 static const struct udevice_id scmi_mbox_ids[] = {
@@ -90,6 +140,7 @@ static const struct udevice_id scmi_mbox_ids[] = {
 };
 
 static const struct scmi_agent_ops scmi_mbox_ops = {
+       .of_get_channel = scmi_mbox_get_channel,
        .process_msg = scmi_mbox_process_msg,
 };