This adds a minimum mailbox support. The code is based on the corresponding U-Boot code. It's currently enough to bring up the communication with the SCI on TI K3 SoCs. Signed-off-by: Sascha Hauer <s.hauer@xxxxxxxxxxxxxx> --- drivers/Kconfig | 1 + drivers/Makefile | 1 + drivers/mailbox/Kconfig | 10 +++++ drivers/mailbox/Makefile | 1 + drivers/mailbox/mailbox.c | 92 +++++++++++++++++++++++++++++++++++++++ include/mailbox.h | 36 +++++++++++++++ 6 files changed, 141 insertions(+) create mode 100644 drivers/mailbox/Kconfig create mode 100644 drivers/mailbox/Makefile create mode 100644 drivers/mailbox/mailbox.c create mode 100644 include/mailbox.h diff --git a/drivers/Kconfig b/drivers/Kconfig index 2636eed1a3..d9c0320556 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -46,5 +46,6 @@ source "drivers/nvme/Kconfig" source "drivers/ddr/Kconfig" source "drivers/power/Kconfig" source "drivers/virtio/Kconfig" +source "drivers/mailbox/Kconfig" endmenu diff --git a/drivers/Makefile b/drivers/Makefile index fa899a2ab8..3f60e1b9c7 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -48,3 +48,4 @@ obj-y += power/ obj-$(CONFIG_SOUND) += sound/ obj-y += virtio/ obj-$(CONFIG_HAVE_OPTEE) += tee/optee/of.o +obj-y += mailbox/ diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig new file mode 100644 index 0000000000..7839a44729 --- /dev/null +++ b/drivers/mailbox/Kconfig @@ -0,0 +1,10 @@ +menuconfig MAILBOX + bool "Mailbox Hardware Support" + help + Mailbox is a framework to control hardware communication between + on-chip processors through queued messages and interrupt driven + signals. Say Y if your platform supports hardware mailboxes. + +if MAILBOX + +endif diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile new file mode 100644 index 0000000000..9dec4e3b3b --- /dev/null +++ b/drivers/mailbox/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_MAILBOX) += mailbox.o diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c new file mode 100644 index 0000000000..edf9481aca --- /dev/null +++ b/drivers/mailbox/mailbox.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2016, NVIDIA CORPORATION. + */ + +#define LOG_CATEGORY UCLASS_MAILBOX + +#include <common.h> +#include <mailbox.h> +#include <deep-probe.h> + +int mbox_send(struct mbox_chan *chan, const void *data) +{ + const struct mbox_chan_ops *ops = chan->mbox->ops; + + return ops->send(chan, data); +} + +int mbox_recv(struct mbox_chan *chan, void *data, unsigned long timeout_us) +{ + const struct mbox_chan_ops *ops = chan->mbox->ops; + u64 start; + int ret; + + start = get_time_ns(); + + for (;;) { + ret = ops->recv(chan, data); + if (ret != -ENODATA) + return ret; + if (is_timeout(start, timeout_us * 1000)) + return -ETIMEDOUT; + } +} + +static LIST_HEAD(mbox_cons); + +int mbox_controller_register(struct mbox_controller *mbox) +{ + list_add_tail(&mbox->node, &mbox_cons); + + return 0; +} + + +struct mbox_chan *mbox_request_channel(struct device *dev, int index) +{ + struct of_phandle_args spec; + struct mbox_controller *mbox; + struct mbox_chan *chan = ERR_PTR(-ENODEV); + + if (of_parse_phandle_with_args(dev->of_node, "mboxes", + "#mbox-cells", index, &spec)) { + return ERR_PTR(-ENODEV); + } + + of_device_ensure_probed(spec.np); + + list_for_each_entry(mbox, &mbox_cons, node) { + if (mbox->dev->of_node != spec.np) + continue; + + chan = mbox->of_xlate(mbox, &spec); + if (!IS_ERR(chan)) + break; + } + + return chan; +} + +struct mbox_chan *mbox_request_channel_byname(struct device *dev, const char *name) +{ + struct device_node *np = dev->of_node; + struct property *prop; + const char *mbox_name; + int index = 0; + + if (!np) + return ERR_PTR(-EINVAL); + + if (!of_get_property(np, "mbox-names", NULL)) { + return ERR_PTR(-EINVAL); + } + + of_property_for_each_string(np, "mbox-names", prop, mbox_name) { + if (!strncmp(name, mbox_name, strlen(name))) + return mbox_request_channel(dev, index); + index++; + } + + return ERR_PTR(-ENODEV); +} diff --git a/include/mailbox.h b/include/mailbox.h new file mode 100644 index 0000000000..3be58ec103 --- /dev/null +++ b/include/mailbox.h @@ -0,0 +1,36 @@ +#ifndef __MAILBOX_H +#define __MAILBOX_H + +struct mbox_chan { + struct mbox_controller *mbox; + struct device *dev; + void *con_priv; +}; + +/** + * struct mbox_ops - The functions that a mailbox driver must implement. + */ +struct mbox_chan_ops { + int (*request)(struct mbox_chan *chan); + int (*rfree)(struct mbox_chan *chan); + int (*send)(struct mbox_chan *chan, const void *data); + int (*recv)(struct mbox_chan *chan, void *data); +}; + +struct mbox_controller { + struct device *dev; + const struct mbox_chan_ops *ops; + struct mbox_chan *chans; + int num_chans; + struct mbox_chan *(*of_xlate)(struct mbox_controller *mbox, + const struct of_phandle_args *sp); + struct list_head node; +}; + +int mbox_controller_register(struct mbox_controller *mbox); +struct mbox_chan *mbox_request_channel(struct device *dev, int index); +struct mbox_chan *mbox_request_channel_byname(struct device *dev, const char *name); +int mbox_send(struct mbox_chan *chan, const void *data); +int mbox_recv(struct mbox_chan *chan, void *data, unsigned long timeout_us); + +#endif /* __MAILBOX_H */ -- 2.39.2