usb: UniPhier: add UniPhier on-chip xHCI host driver support
authorMasahiro Yamada <yamada.m@jp.panasonic.com>
Thu, 26 Feb 2015 17:27:00 +0000 (02:27 +0900)
committerMasahiro Yamada <yamada.m@jp.panasonic.com>
Sat, 28 Feb 2015 15:03:00 +0000 (00:03 +0900)
Support xHCI host driver used on Panasonic UniPhier platform.

Signed-off-by: Masahiro Yamada <yamada.m@jp.panasonic.com>
Acked-by: Marek Vasut <marex@denx.de>
doc/README.uniphier
drivers/usb/host/Kconfig
drivers/usb/host/Makefile
drivers/usb/host/xhci-uniphier.c [new file with mode: 0644]
include/fdtdec.h
lib/fdtdec.c

index aaeb50c4e6ad083bd6a1c4bc549d6dbdbe47ca5d..4902533544ff0a02679c0b614abaaf6441122c70 100644 (file)
@@ -73,7 +73,8 @@ Supported devices
 
  - UART (on-chip)
  - NAND
- - USB (2.0)
+ - USB 2.0 (EHCI)
+ - USB 3.0 (xHCI)
  - LAN (on-board SMSC9118)
  - I2C
  - EEPROM (connected to the on-board I2C bus)
index 0e005c2a1f69cccf53e15a8d7595511ebf6535b0..24a595fb42619aa3eced61402d14e4eb3c5d20b2 100644 (file)
@@ -17,6 +17,14 @@ config USB_XHCI
 
 if USB_XHCI_HCD
 
+config USB_XHCI_UNIPHIER
+       bool "Support for Panasonic UniPhier on-chip xHCI USB controller"
+       depends on ARCH_UNIPHIER
+       default y
+       ---help---
+         Enables support for the on-chip xHCI controller on Panasonic
+         UniPhier SoCs.
+
 endif
 
 config USB_EHCI_HCD
index 66d6e9a6d24662f085cb76bc2236629e51777a96..eb6f34b53cb686a6cbd093482661fb96c01ced6a 100644 (file)
@@ -48,6 +48,7 @@ obj-$(CONFIG_USB_XHCI_KEYSTONE) += xhci-keystone.o
 obj-$(CONFIG_USB_XHCI_EXYNOS) += xhci-exynos5.o
 obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o
 obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o
+obj-$(CONFIG_USB_XHCI_UNIPHIER) += xhci-uniphier.o
 
 # designware
 obj-$(CONFIG_USB_DWC2) += dwc2.o
diff --git a/drivers/usb/host/xhci-uniphier.c b/drivers/usb/host/xhci-uniphier.c
new file mode 100644 (file)
index 0000000..08b15e0
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2015 Panasonic Corporation
+ *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <linux/err.h>
+#include <usb.h>
+#include <fdtdec.h>
+#include "xhci.h"
+
+static int get_uniphier_xhci_base(int index, struct xhci_hccr **base)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+       int node_list[2];
+       fdt_addr_t addr;
+       int count;
+
+       count = fdtdec_find_aliases_for_id(gd->fdt_blob, "usb",
+                                          COMPAT_PANASONIC_XHCI, node_list,
+                                          ARRAY_SIZE(node_list));
+
+       if (index >= count)
+               return -ENODEV;
+
+       addr = fdtdec_get_addr(gd->fdt_blob, node_list[index], "reg");
+       if (addr == FDT_ADDR_T_NONE)
+               return -ENODEV;
+
+       *base = (struct xhci_hccr *)addr;
+
+       return 0;
+}
+
+#define USB3_RST_CTRL          0x00100040
+#define IOMMU_RST_N            (1 << 5)
+#define LINK_RST_N             (1 << 4)
+
+static void uniphier_xhci_reset(void __iomem *base, int on)
+{
+       u32 tmp;
+
+       tmp = readl(base + USB3_RST_CTRL);
+
+       if (on)
+               tmp &= ~(IOMMU_RST_N | LINK_RST_N);
+       else
+               tmp |= IOMMU_RST_N | LINK_RST_N;
+
+       writel(tmp, base + USB3_RST_CTRL);
+}
+
+int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor)
+{
+       int ret;
+       struct xhci_hccr *cr;
+       struct xhci_hcor *or;
+
+       ret = get_uniphier_xhci_base(index, &cr);
+       if (ret < 0)
+               return ret;
+
+       uniphier_xhci_reset(cr, 0);
+
+       or = (void *)cr + HC_LENGTH(xhci_readl(&cr->cr_capbase));
+
+       *hccr = cr;
+       *hcor = or;
+
+       return 0;
+}
+
+void xhci_hcd_stop(int index)
+{
+       int ret;
+       struct xhci_hccr *cr;
+
+       ret = get_uniphier_xhci_base(index, &cr);
+       if (ret < 0)
+               return;
+
+       uniphier_xhci_reset(cr, 1);
+}
index 1bc70dba213b603bfdd72cb266b151869b88d67b..1233dfb280b10efff3d2c395a728e50bef69a7a2 100644 (file)
@@ -168,6 +168,7 @@ enum fdt_compat_id {
        COMPAT_AMS_AS3722,              /* AMS AS3722 PMIC */
        COMPAT_INTEL_ICH_SPI,           /* Intel ICH7/9 SPI controller */
        COMPAT_INTEL_QRK_MRC,           /* Intel Quark MRC */
+       COMPAT_PANASONIC_XHCI,          /* Panasonic UniPhier xHCI */
 
        COMPAT_COUNT,
 };
index dd58bbb482fe996a9190c3e3c870e668fcc594ed..21933e4a47d4b8db69eb5c745ee3d69d4abd54e2 100644 (file)
@@ -76,6 +76,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
        COMPAT(AMS_AS3722, "ams,as3722"),
        COMPAT(INTEL_ICH_SPI, "intel,ich-spi"),
        COMPAT(INTEL_QRK_MRC, "intel,quark-mrc"),
+       COMPAT(PANASONIC_XHCI, "panasonic,uniphier-xhci"),
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)