[PATCH v3 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver

2014-09-02 Thread Andrew Bresticker
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

2014-09-02 Thread Andrew Bresticker
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)
+{
+