[PATCH v3 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
The Tegra xHCI controller's firmware communicates requests to the host processor through a mailbox interface. While there is only a single physical channel, messages sent by the controller can be divided into two groups: those intended for the PHY driver and those intended for the host-controller driver. The requesting driver is assigned one of two virtual channels when the single physical channel is requested. All incoming messages are sent to both virtual channels. Signed-off-by: Andrew Bresticker --- Jassi: I've handled the sharing by making the channels in the Tegra driver 'virtual' channels. Having the mailbox core handle channel sharing would be a much more invasive change, but let me know if that's what you'd prefer. Changes from v2: - Fixed mailbox IRQ vs. channel alloc/free race. - Renamed defines to match TRM. - Dropped channel specifier and instead allocated virtual channels as they were requested. - Removed MODULE_ALIAS. Changes from v1: - Converted to common mailbox framework. - Removed useless polling sequences in TX path. - Moved xusb include from linux/ to soc/tegra/ --- drivers/mailbox/Kconfig | 3 + drivers/mailbox/Makefile | 2 + drivers/mailbox/tegra-xusb-mailbox.c | 290 +++ include/soc/tegra/xusb.h | 46 ++ 4 files changed, 341 insertions(+) create mode 100644 drivers/mailbox/tegra-xusb-mailbox.c create mode 100644 include/soc/tegra/xusb.h diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index 9fd9c67..97369c2 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -33,4 +33,7 @@ config OMAP_MBOX_KFIFO_SIZE Specify the default size of mailbox's kfifo buffers (bytes). This can also be changed at runtime (via the mbox_kfifo_size module parameter). + +config TEGRA_XUSB_MBOX + def_bool y if ARCH_TEGRA endif diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile index 94ed7ce..7f0af9c 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -5,3 +5,5 @@ obj-$(CONFIG_MAILBOX) += mailbox.o obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o obj-$(CONFIG_OMAP2PLUS_MBOX) += omap-mailbox.o + +obj-$(CONFIG_TEGRA_XUSB_MBOX) += tegra-xusb-mailbox.o diff --git a/drivers/mailbox/tegra-xusb-mailbox.c b/drivers/mailbox/tegra-xusb-mailbox.c new file mode 100644 index 000..2d87b8a --- /dev/null +++ b/drivers/mailbox/tegra-xusb-mailbox.c @@ -0,0 +1,290 @@ +/* + * NVIDIA Tegra XUSB mailbox driver + * + * Copyright (C) 2014 NVIDIA Corporation + * Copyright (C) 2014 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define XUSB_CFG_ARU_MBOX_CMD 0xe4 +#define MBOX_DEST_FALCBIT(27) +#define MBOX_DEST_PME BIT(28) +#define MBOX_DEST_SMI BIT(29) +#define MBOX_DEST_XHCIBIT(30) +#define MBOX_INT_EN BIT(31) +#define XUSB_CFG_ARU_MBOX_DATA_IN 0xe8 +#define CMD_DATA_SHIFT0 +#define CMD_DATA_MASK 0xff +#define CMD_TYPE_SHIFT24 +#define CMD_TYPE_MASK 0xff +#define XUSB_CFG_ARU_MBOX_DATA_OUT 0xec +#define XUSB_CFG_ARU_MBOX_OWNER0xf0 +#define MBOX_OWNER_NONE 0 +#define MBOX_OWNER_FW 1 +#define MBOX_OWNER_SW 2 +#define XUSB_CFG_ARU_SMI_INTR 0x428 +#define MBOX_SMI_INTR_FW_HANG BIT(1) +#define MBOX_SMI_INTR_EN BIT(3) + +struct tegra_xusb_mbox { + struct mbox_controller mbox; + int irq; + void __iomem *regs; + spinlock_t lock; + bool vchan_allocated[TEGRA_XUSB_MBOX_NUM_CHANS]; +}; + +static inline u32 mbox_readl(struct tegra_xusb_mbox *mbox, unsigned long offset) +{ + return readl(mbox->regs + offset); +} + +static inline void mbox_writel(struct tegra_xusb_mbox *mbox, u32 val, + unsigned long offset) +{ + writel(val, mbox->regs + offset); +} + +static inline u32 mbox_pack_msg(struct tegra_xusb_mbox_msg *msg) +{ + u32 val; + + val = (msg->cmd & CMD_TYPE_MASK) << CMD_TYPE_SHIFT; + val |= (msg->data & CMD_DATA_MASK) << CMD_DATA_SHIFT; + + return val; +} + +static inline void mbox_unpack_msg(u32 val, struct tegra_xusb_mbox_msg *msg) +{ + msg->cmd = (val >> CMD_TYPE_SHIFT) & CMD_TYPE_MASK; + msg->data = (val >> CMD_DATA_SHIFT) & CMD_DATA_MASK; +} + +static int tegra_xusb_mbox_send_data(struct
[PATCH v3 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
The Tegra xHCI controller's firmware communicates requests to the host processor through a mailbox interface. While there is only a single physical channel, messages sent by the controller can be divided into two groups: those intended for the PHY driver and those intended for the host-controller driver. The requesting driver is assigned one of two virtual channels when the single physical channel is requested. All incoming messages are sent to both virtual channels. Signed-off-by: Andrew Bresticker abres...@chromium.org --- Jassi: I've handled the sharing by making the channels in the Tegra driver 'virtual' channels. Having the mailbox core handle channel sharing would be a much more invasive change, but let me know if that's what you'd prefer. Changes from v2: - Fixed mailbox IRQ vs. channel alloc/free race. - Renamed defines to match TRM. - Dropped channel specifier and instead allocated virtual channels as they were requested. - Removed MODULE_ALIAS. Changes from v1: - Converted to common mailbox framework. - Removed useless polling sequences in TX path. - Moved xusb include from linux/ to soc/tegra/ --- drivers/mailbox/Kconfig | 3 + drivers/mailbox/Makefile | 2 + drivers/mailbox/tegra-xusb-mailbox.c | 290 +++ include/soc/tegra/xusb.h | 46 ++ 4 files changed, 341 insertions(+) create mode 100644 drivers/mailbox/tegra-xusb-mailbox.c create mode 100644 include/soc/tegra/xusb.h diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index 9fd9c67..97369c2 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -33,4 +33,7 @@ config OMAP_MBOX_KFIFO_SIZE Specify the default size of mailbox's kfifo buffers (bytes). This can also be changed at runtime (via the mbox_kfifo_size module parameter). + +config TEGRA_XUSB_MBOX + def_bool y if ARCH_TEGRA endif diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile index 94ed7ce..7f0af9c 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -5,3 +5,5 @@ obj-$(CONFIG_MAILBOX) += mailbox.o obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o obj-$(CONFIG_OMAP2PLUS_MBOX) += omap-mailbox.o + +obj-$(CONFIG_TEGRA_XUSB_MBOX) += tegra-xusb-mailbox.o diff --git a/drivers/mailbox/tegra-xusb-mailbox.c b/drivers/mailbox/tegra-xusb-mailbox.c new file mode 100644 index 000..2d87b8a --- /dev/null +++ b/drivers/mailbox/tegra-xusb-mailbox.c @@ -0,0 +1,290 @@ +/* + * NVIDIA Tegra XUSB mailbox driver + * + * Copyright (C) 2014 NVIDIA Corporation + * Copyright (C) 2014 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + */ + +#include linux/interrupt.h +#include linux/io.h +#include linux/kernel.h +#include linux/mailbox_controller.h +#include linux/module.h +#include linux/of_device.h +#include linux/platform_device.h +#include linux/slab.h + +#include soc/tegra/xusb.h + +#define XUSB_CFG_ARU_MBOX_CMD 0xe4 +#define MBOX_DEST_FALCBIT(27) +#define MBOX_DEST_PME BIT(28) +#define MBOX_DEST_SMI BIT(29) +#define MBOX_DEST_XHCIBIT(30) +#define MBOX_INT_EN BIT(31) +#define XUSB_CFG_ARU_MBOX_DATA_IN 0xe8 +#define CMD_DATA_SHIFT0 +#define CMD_DATA_MASK 0xff +#define CMD_TYPE_SHIFT24 +#define CMD_TYPE_MASK 0xff +#define XUSB_CFG_ARU_MBOX_DATA_OUT 0xec +#define XUSB_CFG_ARU_MBOX_OWNER0xf0 +#define MBOX_OWNER_NONE 0 +#define MBOX_OWNER_FW 1 +#define MBOX_OWNER_SW 2 +#define XUSB_CFG_ARU_SMI_INTR 0x428 +#define MBOX_SMI_INTR_FW_HANG BIT(1) +#define MBOX_SMI_INTR_EN BIT(3) + +struct tegra_xusb_mbox { + struct mbox_controller mbox; + int irq; + void __iomem *regs; + spinlock_t lock; + bool vchan_allocated[TEGRA_XUSB_MBOX_NUM_CHANS]; +}; + +static inline u32 mbox_readl(struct tegra_xusb_mbox *mbox, unsigned long offset) +{ + return readl(mbox-regs + offset); +} + +static inline void mbox_writel(struct tegra_xusb_mbox *mbox, u32 val, + unsigned long offset) +{ + writel(val, mbox-regs + offset); +} + +static inline u32 mbox_pack_msg(struct tegra_xusb_mbox_msg *msg) +{ + u32 val; + + val = (msg-cmd CMD_TYPE_MASK) CMD_TYPE_SHIFT; + val |= (msg-data CMD_DATA_MASK) CMD_DATA_SHIFT; + + return val; +} + +static inline void mbox_unpack_msg(u32 val, struct tegra_xusb_mbox_msg *msg) +{ +