Hi Stephen, On 13 May 2016 at 15:52, Stephen Warren <swar...@wwwdotorg.org> wrote: > From: Stephen Warren <swar...@nvidia.com> > > Tegra186's HSP module implements doorbells, mailboxes, semaphores, and > shared interrupts. This patch provides a driver for HSP, and hooks it > into the mailbox API. Currently, only doorbells are supported. > > Signed-off-by: Stephen Warren <swar...@nvidia.com> > --- > This patch depends on: > 1) "Add a mailbox driver framework/uclass" > 2) "ARM: tegra: add core Tegra186 support" > > arch/arm/dts/tegra186.dtsi | 13 +++ > arch/arm/mach-tegra/Kconfig | 2 + > drivers/mailbox/Kconfig | 7 ++ > drivers/mailbox/Makefile | 1 + > drivers/mailbox/tegra-hsp.c | 163 > ++++++++++++++++++++++++++++++++ > include/dt-bindings/mailbox/tegra-hsp.h | 14 +++ > 6 files changed, 200 insertions(+) > create mode 100644 drivers/mailbox/tegra-hsp.c > create mode 100644 include/dt-bindings/mailbox/tegra-hsp.h
Reviewed-by: Simon Glass <s...@chromium.org> Comment below. > > diff --git a/arch/arm/dts/tegra186.dtsi b/arch/arm/dts/tegra186.dtsi > index 18b6a2664349..fce34fa6500e 100644 > --- a/arch/arm/dts/tegra186.dtsi > +++ b/arch/arm/dts/tegra186.dtsi > @@ -1,6 +1,7 @@ > #include "skeleton.dtsi" > #include <dt-bindings/gpio/tegra-gpio.h> > #include <dt-bindings/interrupt-controller/arm-gic.h> > +#include <dt-bindings/mailbox/tegra-hsp.h> > > / { > compatible = "nvidia,tegra186"; > @@ -40,6 +41,18 @@ > status = "disabled"; > }; > > + hsp: hsp@3c00000 { > + compatible = "nvidia,tegra186-hsp"; > + reg = <0x0 0x03c00000 0x0 0xa0000>; > + interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>; > + nvidia,num-SM = <0x8>; > + nvidia,num-AS = <0x2>; > + nvidia,num-SS = <0x2>; > + nvidia,num-DB = <0x7>; > + nvidia,num-SI = <0x8>; > + #mbox-cells = <1>; > + }; > + > gpio@c2f0000 { > compatible = "nvidia,tegra186-gpio-aon"; > reg-names = "security", "gpio"; > diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig > index b18a12e34203..f4affa5512bc 100644 > --- a/arch/arm/mach-tegra/Kconfig > +++ b/arch/arm/mach-tegra/Kconfig > @@ -56,8 +56,10 @@ config TEGRA210 > > config TEGRA186 > bool "Tegra186 family" > + select DM_MAILBOX > select TEGRA186_GPIO > select TEGRA_ARMV8_COMMON > + select TEGRA_HSP > > endchoice > > diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig > index 295e6db0f28c..8ae8edd28c52 100644 > --- a/drivers/mailbox/Kconfig > +++ b/drivers/mailbox/Kconfig > @@ -10,4 +10,11 @@ config DM_MAILBOX > the basis of a variety of inter-process/inter-CPU communication > protocols. > > +config TEGRA_HSP > + bool "Enable Tegra HSP controller support" > + depends on DM_MAILBOX && TEGRA > + help > + This enables support for the NVIDIA Tegra HSP Hw module, which > + implements doorbells, mailboxes, semaphores, and shared interrupts. > + > endmenu > diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile > index a2d96a4e3b98..b5bc84032573 100644 > --- a/drivers/mailbox/Makefile > +++ b/drivers/mailbox/Makefile > @@ -3,3 +3,4 @@ > # SPDX-License-Identifier: GPL-2.0 > > obj-$(CONFIG_DM_MAILBOX) += mailbox-uclass.o > +obj-$(CONFIG_TEGRA_HSP) += tegra-hsp.o > diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c > new file mode 100644 > index 000000000000..2d7aef21c036 > --- /dev/null > +++ b/drivers/mailbox/tegra-hsp.c > @@ -0,0 +1,163 @@ > +/* > + * Copyright (c) 2016, NVIDIA CORPORATION. > + * > + * SPDX-License-Identifier: GPL-2.0 > + */ > + > +#include <common.h> > +#include <asm/io.h> > +#include <dm.h> > +#include <mailbox_uclass.h> > +#include <dt-bindings/mailbox/tegra-hsp.h> > + > +#define TEGRA_HSP_DB_REG_TRIGGER 0x0 > +#define TEGRA_HSP_DB_REG_ENABLE 0x4 > +#define TEGRA_HSP_DB_REG_RAW 0x8 > +#define TEGRA_HSP_DB_REG_PENDING 0xc > + > +#define TEGRA_HSP_DB_ID_CCPLEX 1 > +#define TEGRA_HSP_DB_ID_BPMP 3 > +#define TEGRA_HSP_DB_ID_NUM 7 > + > +struct tegra_hsp { > + fdt_addr_t regs; > + uint32_t db_base; > +}; > + > +DECLARE_GLOBAL_DATA_PTR; > + > +static uint32_t *tegra_hsp_reg(struct tegra_hsp *thsp, uint32_t db_id, > + uint32_t reg) > +{ > + return (uint32_t *)(thsp->regs + thsp->db_base + (db_id * 0x100) + > reg); > +} > + > +static uint32_t tegra_hsp_readl(struct tegra_hsp *thsp, uint32_t db_id, > + uint32_t reg) > +{ > + uint32_t *r = tegra_hsp_reg(thsp, db_id, reg); > + return readl(r); > +} > + > +static void tegra_hsp_writel(struct tegra_hsp *thsp, uint32_t val, > + uint32_t db_id, uint32_t reg) > +{ > + uint32_t *r = tegra_hsp_reg(thsp, db_id, reg); I think it would be better to resolve the register set once in the caller and then access the different members. It does feel a bit obfuscated. But since this driver is so trivial I don't think it matters. > + > + writel(val, r); > + readl(r); > +} > + > +static int tegra_hsp_db_id(ulong chan_id) > +{ > + switch (chan_id) { > + case TEGRA_HSP_MASTER_BPMP: > + return TEGRA_HSP_DB_ID_BPMP; > + default: > + debug("Invalid channel ID\n"); > + return -EINVAL; > + } > +} > + > +static int tegra_hsp_request(struct mbox_chan *chan) > +{ > + int db_id; > + > + debug("%s(chan=%p)\n", __func__, chan); > + > + db_id = tegra_hsp_db_id(chan->id); > + if (db_id < 0) { > + debug("tegra_hsp_db_id() failed: %d\n", db_id); > + return -EINVAL; > + } > + > + return 0; > +} > + > +static int tegra_hsp_free(struct mbox_chan *chan) > +{ > + debug("%s(chan=%p)\n", __func__, chan); > + > + return 0; > +} > + > +static int tegra_hsp_send(struct mbox_chan *chan, const void *data) > +{ > + struct tegra_hsp *thsp = dev_get_priv(chan->dev); > + int db_id; > + > + debug("%s(chan=%p, data=%p)\n", __func__, chan, data); > + > + db_id = tegra_hsp_db_id(chan->id); > + tegra_hsp_writel(thsp, 1, db_id, TEGRA_HSP_DB_REG_TRIGGER); > + > + return 0; > +} > + > +static int tegra_hsp_recv(struct mbox_chan *chan, void *data) > +{ > + struct tegra_hsp *thsp = dev_get_priv(chan->dev); > + uint32_t db_id = TEGRA_HSP_DB_ID_CCPLEX; > + uint32_t val; > + > + debug("%s(chan=%p, data=%p)\n", __func__, chan, data); > + > + val = tegra_hsp_readl(thsp, db_id, TEGRA_HSP_DB_REG_RAW); > + if (!(val & BIT(chan->id))) > + return -ENODATA; > + > + tegra_hsp_writel(thsp, BIT(chan->id), db_id, TEGRA_HSP_DB_REG_RAW); > + > + return 0; > +} > + > +static int tegra_hsp_bind(struct udevice *dev) > +{ > + debug("%s(dev=%p)\n", __func__, dev); > + > + return 0; > +} > + > +static int tegra_hsp_probe(struct udevice *dev) > +{ > + struct tegra_hsp *thsp = dev_get_priv(dev); > + int nr_sm, nr_ss, nr_as; > + > + debug("%s(dev=%p)\n", __func__, dev); > + > + thsp->regs = dev_get_addr(dev); > + if (thsp->regs == FDT_ADDR_T_NONE) > + return -ENODEV; > + > + nr_sm = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "nvidia,num-SM", > + 0); > + nr_ss = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "nvidia,num-SS", > + 0); > + nr_as = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "nvidia,num-AS", > + 0); > + thsp->db_base = (1 + (nr_sm >> 1) + nr_ss + nr_as) << 16; > + > + return 0; > +} > + > +static const struct udevice_id tegra_hsp_ids[] = { > + { .compatible = "nvidia,tegra186-hsp" }, > + { } > +}; > + > +struct mbox_ops tegra_hsp_mbox_ops = { > + .request = tegra_hsp_request, > + .free = tegra_hsp_free, > + .send = tegra_hsp_send, > + .recv = tegra_hsp_recv, > +}; > + > +U_BOOT_DRIVER(tegra_hsp) = { > + .name = "tegra-hsp", > + .id = UCLASS_MAILBOX, > + .of_match = tegra_hsp_ids, > + .bind = tegra_hsp_bind, > + .probe = tegra_hsp_probe, > + .priv_auto_alloc_size = sizeof(struct tegra_hsp), > + .ops = &tegra_hsp_mbox_ops, > +}; > diff --git a/include/dt-bindings/mailbox/tegra-hsp.h > b/include/dt-bindings/mailbox/tegra-hsp.h > new file mode 100644 > index 000000000000..e8c23fa91d23 > --- /dev/null > +++ b/include/dt-bindings/mailbox/tegra-hsp.h > @@ -0,0 +1,14 @@ > +/* > + * This header provides constants for binding nvidia,tegra186-hsp. > + * > + * The number with TEGRA_HSP_MASTER prefix indicates the bit that is > + * associated with a master ID in the doorbell registers. > + */ > + > +#ifndef _DT_BINDINGS_MAILBOX_TEGRA186_HSP_H > +#define _DT_BINDINGS_MAILBOX_TEGRA186_HSP_H > + > +#define TEGRA_HSP_MASTER_CCPLEX 17 > +#define TEGRA_HSP_MASTER_BPMP 19 > + > +#endif > -- > 2.8.2 > Regards, Simon _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot