[PATCH v3 2/8] firmware: scmi: mailbox/smt agent device

Simon Glass sjg at chromium.org
Tue Sep 8 17:20:54 CEST 2020


Hi Etienne,

On Mon, 7 Sep 2020 at 08:50, Etienne Carriere
<etienne.carriere at linaro.org> wrote:
>
> This change implements a mailbox transport using SMT format for SCMI
> exchanges. This implementation follows the Linux kernel and
> SCP-firmware [1] as references implementation for SCMI message
> processing using SMT format for communication channel meta-data.
>
> Use of mailboxes in SCMI FDT bindings are defined in the Linux kernel
> DT bindings since v4.17.
>
> Links: [1] https://github.com/ARM-software/SCP-firmware
> Signed-off-by: Etienne Carriere <etienne.carriere at linaro.org>
> Cc: Simon Glass <sjg at chromium.org>
> Cc: Peng Fan <peng.fan at nxp.com>
> Cc: Sudeep Holla <sudeep.holla at arm.com>
> ---
>
> Changes in v3:
> - This is a followup of the SCMI agent patches posted in
>   https://patchwork.ozlabs.org/project/uboot/list/?series=196253
>   The v3 splits commits and introduces a new uclass as requested.
> - This patch implements the same mailbox SCMI agent proposed in v2
>   but split over few source files.
> ---
>  drivers/firmware/scmi/Kconfig         |   6 +-
>  drivers/firmware/scmi/Makefile        |   2 +
>  drivers/firmware/scmi/mailbox_agent.c | 107 ++++++++++++++++++++
>  drivers/firmware/scmi/smt.c           | 139 ++++++++++++++++++++++++++
>  drivers/firmware/scmi/smt.h           |  86 ++++++++++++++++
>  5 files changed, 338 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/firmware/scmi/mailbox_agent.c
>  create mode 100644 drivers/firmware/scmi/smt.c
>  create mode 100644 drivers/firmware/scmi/smt.h

Reviewed-by: Simon Glass <sjg at chromium.org>

>
> diff --git a/drivers/firmware/scmi/Kconfig b/drivers/firmware/scmi/Kconfig
> index 57e2ebbe42..c501bf4943 100644
> --- a/drivers/firmware/scmi/Kconfig
> +++ b/drivers/firmware/scmi/Kconfig
> @@ -2,7 +2,7 @@ config SCMI_FIRMWARE
>         bool "Enable SCMI support"
>         select FIRMWARE
>         select OF_TRANSLATE
> -       depends on SANDBOX
> +       depends on SANDBOX || DM_MAILBOX
>         help
>           System Control and Management Interface (SCMI) is a communication
>           protocol that defines standard interfaces for power, performance
> @@ -14,4 +14,6 @@ config SCMI_FIRMWARE
>           or a companion host in the CPU system.
>
>           Communications between agent (client) and the SCMI server are
> -         based on message exchange.
> +         based on message exchange. Messages can be exchange over tranport
> +         channels as a mailbox device with some piece of identified shared
> +         memory.
> diff --git a/drivers/firmware/scmi/Makefile b/drivers/firmware/scmi/Makefile
> index 336ea1f2a3..d22f53efe7 100644
> --- a/drivers/firmware/scmi/Makefile
> +++ b/drivers/firmware/scmi/Makefile
> @@ -1,2 +1,4 @@
>  obj-y  += scmi_agent-uclass.o
> +obj-y  += smt.o
> +obj-$(CONFIG_DM_MAILBOX)       += mailbox_agent.o
>  obj-$(CONFIG_SANDBOX)          += sandbox-scmi_agent.o
> diff --git a/drivers/firmware/scmi/mailbox_agent.c b/drivers/firmware/scmi/mailbox_agent.c
> new file mode 100644
> index 0000000000..9a7b0a5858
> --- /dev/null
> +++ b/drivers/firmware/scmi/mailbox_agent.c
> @@ -0,0 +1,107 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2020 Linaro Limited.
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <mailbox.h>
> +#include <scmi_agent.h>
> +#include <scmi_agent-uclass.h>
> +#include <dm/devres.h>
> +#include <linux/compat.h>
> +
> +#include "smt.h"
> +
> +#define TIMEOUT_US_10MS                        10000
> +
> +/**
> + * struct scmi_mbox_channel - Description of an SCMI mailbox transport
> + * @smt:       Shared memory buffer
> + * @mbox:      Mailbox channel description
> + * @timeout_us:        Timeout in microseconds for the mailbox transfer
> + */
> +struct scmi_mbox_channel {
> +       struct scmi_smt smt;
> +       struct mbox_chan mbox;
> +       ulong timeout_us;
> +};
> +
> +static struct scmi_mbox_channel *scmi_mbox_get_priv(struct udevice *dev)
> +{
> +       return (struct scmi_mbox_channel *)dev_get_priv(dev);
> +}
> +
> +static int scmi_mbox_process_msg(struct udevice *dev, struct scmi_msg *msg)
> +{
> +       struct scmi_mbox_channel *chan = scmi_mbox_get_priv(dev);
> +       int ret;
> +
> +       ret = scmi_write_msg_to_smt(dev, &chan->smt, msg);
> +       if (ret)
> +               return ret;
> +
> +       /* Give shm addr to mbox in case it is meaningful */
> +       ret = mbox_send(&chan->mbox, chan->smt.buf);
> +       if (ret) {
> +               dev_err(dev, "Message send failed: %d\n", ret);
> +               goto out;
> +       }
> +
> +       /* Receive the response */
> +       ret = mbox_recv(&chan->mbox, chan->smt.buf, chan->timeout_us);
> +       if (ret) {
> +               dev_err(dev, "Response failed: %d, abort\n", ret);
> +               goto out;
> +       }
> +
> +       ret = scmi_read_resp_from_smt(dev, &chan->smt, msg);
> +
> +out:
> +       scmi_clear_smt_channel(&chan->smt);
> +
> +       return ret;
> +}
> +
> +int scmi_mbox_probe(struct udevice *dev)
> +{
> +       struct scmi_mbox_channel *chan = scmi_mbox_get_priv(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);
> +               goto out;
> +       }
> +
> +       ret = scmi_dt_get_smt_buffer(dev, &chan->smt);
> +       if (ret)
> +               dev_err(dev, "Failed to get shm resources: %d\n", ret);
> +
> +out:
> +       if (ret)
> +               devm_kfree(dev, chan);
> +
> +       return ret;
> +}
> +
> +static const struct udevice_id scmi_mbox_ids[] = {
> +       { .compatible = "arm,scmi" },
> +       { }
> +};
> +
> +static const struct scmi_agent_ops scmi_mbox_ops = {
> +       .process_msg = scmi_mbox_process_msg,
> +};
> +
> +U_BOOT_DRIVER(scmi_mbox) = {
> +       .name           = "scmi-over-mailbox",
> +       .id             = UCLASS_SCMI_AGENT,
> +       .of_match       = scmi_mbox_ids,
> +       .priv_auto_alloc_size = sizeof(struct scmi_mbox_channel),
> +       .probe          = scmi_mbox_probe,
> +       .ops            = &scmi_mbox_ops,
> +};
> diff --git a/drivers/firmware/scmi/smt.c b/drivers/firmware/scmi/smt.c
> new file mode 100644
> index 0000000000..afe95a4736
> --- /dev/null
> +++ b/drivers/firmware/scmi/smt.c
> @@ -0,0 +1,139 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.
> + * Copyright (C) 2019-2020 Linaro Limited.
> + */
> +
> +#include <common.h>
> +#include <cpu_func.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <scmi_agent.h>
> +#include <asm/cache.h>
> +#include <asm/system.h>
> +#include <dm/ofnode.h>
> +#include <linux/compat.h>
> +#include <linux/io.h>
> +#include <linux/ioport.h>
> +
> +#include "smt.h"
> +
> +/**
> + * Get shared memory configuration defined by the referred DT phandle
> + * Return with a errno compliant value.
> + */
> +int scmi_dt_get_smt_buffer(struct udevice *dev, struct scmi_smt *smt)
> +{
> +       int ret;
> +       struct ofnode_phandle_args args;
> +       struct resource resource;
> +       fdt32_t faddr;
> +       phys_addr_t paddr;
> +
> +       ret = dev_read_phandle_with_args(dev, "shmem", NULL, 0, 0, &args);
> +       if (ret)
> +               return ret;
> +
> +       ret = ofnode_read_resource(args.node, 0, &resource);
> +       if (ret)
> +               return ret;
> +
> +       faddr = cpu_to_fdt32(resource.start);
> +       paddr = ofnode_translate_address(args.node, &faddr);
> +
> +       smt->size = resource_size(&resource);
> +       if (smt->size < sizeof(struct scmi_smt_header)) {
> +               dev_err(dev, "Shared memory buffer too small\n");
> +               return -EINVAL;
> +       }
> +
> +       smt->buf = devm_ioremap(dev, paddr, smt->size);
> +       if (!smt->buf)
> +               return -ENOMEM;
> +
> +#ifdef __arm__

Should that be CONFIG_ARM ?

> +       if (dcache_status())
> +               mmu_set_region_dcache_behaviour((uintptr_t)smt->buf,
> +                                               smt->size, DCACHE_OFF);
> +#endif
> +
> +       return 0;
> +}
> +
[..]

Regards,
Simon


More information about the U-Boot mailing list