Hi, On Fri, Jun 13, 2014 at 09:20:31PM +0900, Yoshihiro Shimoda wrote: > The R-Car H2 and M2 SoCs come with an xHCI controller that requires > some specific initializations related to the firmware downloading and > some specific registers. This patch adds the support for this special > configuration as an xHCI quirk executed during probe and start. > > Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@xxxxxxxxxxx> > --- > drivers/usb/host/Kconfig | 8 +++ > drivers/usb/host/Makefile | 3 + > drivers/usb/host/xhci-plat.c | 19 ++++++ > drivers/usb/host/xhci-rcar.c | 148 ++++++++++++++++++++++++++++++++++++++++++ > drivers/usb/host/xhci-rcar.h | 27 ++++++++ > 5 files changed, 205 insertions(+) > create mode 100644 drivers/usb/host/xhci-rcar.c > create mode 100644 drivers/usb/host/xhci-rcar.h > > diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig > index 61b7817..537d9e1 100644 > --- a/drivers/usb/host/Kconfig > +++ b/drivers/usb/host/Kconfig > @@ -37,6 +37,14 @@ config USB_XHCI_MVEBU > Say 'Y' to enable the support for the xHCI host controller > found in Marvell Armada 375/38x ARM SOCs. > > +config USB_XHCI_RCAR > + tristate "xHCI support for Renesas R-Car SoCs" > + select USB_XHCI_PLATFORM > + depends on ARCH_SHMOBILE || COMPILE_TEST > + ---help--- > + Say 'Y' to enable the support for the xHCI host controller > + found in Renesas R-Car ARM SoCs. > + > endif # USB_XHCI_HCD > > config USB_EHCI_HCD > diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile > index af89a90..144c038 100644 > --- a/drivers/usb/host/Makefile > +++ b/drivers/usb/host/Makefile > @@ -22,6 +22,9 @@ ifneq ($(CONFIG_USB_XHCI_PLATFORM), ) > ifneq ($(CONFIG_USB_XHCI_MVEBU), ) > xhci-hcd-y += xhci-mvebu.o > endif > +ifneq ($(CONFIG_USB_XHCI_RCAR), ) > + xhci-hcd-y += xhci-rcar.o > +endif > endif > > obj-$(CONFIG_USB_WHCI_HCD) += whci/ > diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c > index 29d8adb..b6f2b6b 100644 > --- a/drivers/usb/host/xhci-plat.c > +++ b/drivers/usb/host/xhci-plat.c > @@ -20,6 +20,7 @@ > > #include "xhci.h" > #include "xhci-mvebu.h" > +#include "xhci-rcar.h" > > static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci) > { > @@ -34,11 +35,27 @@ static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci) > /* called during probe() after chip reset completes */ > static int xhci_plat_setup(struct usb_hcd *hcd) > { > + struct device_node *of_node = hcd->self.controller->of_node; > + int ret; > + > + if (of_device_is_compatible(of_node, "renesas,xhci-r8a7790") || > + of_device_is_compatible(of_node, "renesas,xhci-r8a7791")) { > + ret = xhci_rcar_init_quirk(hcd); > + if (ret) > + return ret; > + } > + > return xhci_gen_setup(hcd, xhci_plat_quirks); > } > > static int xhci_plat_start(struct usb_hcd *hcd) > { > + struct device_node *of_node = hcd->self.controller->of_node; > + > + if (of_device_is_compatible(of_node, "renesas,xhci-r8a7790") || > + of_device_is_compatible(of_node, "renesas,xhci-r8a7791")) > + xhci_rcar_start(hcd); > + > return xhci_run(hcd); > } > > @@ -270,6 +287,8 @@ static const struct of_device_id usb_xhci_of_match[] = { > { .compatible = "xhci-platform" }, > { .compatible = "marvell,armada-375-xhci"}, > { .compatible = "marvell,armada-380-xhci"}, > + { .compatible = "renesas,xhci-r8a7790"}, > + { .compatible = "renesas,xhci-r8a7791"}, > { }, > }; > MODULE_DEVICE_TABLE(of, usb_xhci_of_match); > diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c > new file mode 100644 > index 0000000..ff0d1b4 > --- /dev/null > +++ b/drivers/usb/host/xhci-rcar.c > @@ -0,0 +1,148 @@ > +/* > + * xHCI host controller driver for R-Car SoCs > + * > + * Copyright (C) 2014 Renesas Electronics Corporation > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License > + * version 2 as published by the Free Software Foundation. > + */ > + > +#include <linux/firmware.h> > +#include <linux/module.h> > +#include <linux/platform_device.h> > +#include <linux/usb/phy.h> > + > +#include "xhci.h" > +#include "xhci-rcar.h" > + > +#define FIRMWARE_NAME "r8a779x_usb3_v1.dlmem" > +MODULE_FIRMWARE(FIRMWARE_NAME); > + > +/*** Register Offset ***/ > +#define RCAR_USB3_INT_ENA 0x224 /* Interrupt Enable */ > +#define RCAR_USB3_DL_CTRL 0x250 /* FW Download Control & Status */ > +#define RCAR_USB3_FW_DATA0 0x258 /* FW Data0 */ > + > +#define RCAR_USB3_LCLK 0xa44 /* LCLK Select */ > +#define RCAR_USB3_CONF1 0xa48 /* USB3.0 Configuration1 */ > +#define RCAR_USB3_CONF2 0xa5c /* USB3.0 Configuration2 */ > +#define RCAR_USB3_CONF3 0xaa8 /* USB3.0 Configuration3 */ > +#define RCAR_USB3_RX_POL 0xab0 /* USB3.0 RX Polarity */ > +#define RCAR_USB3_TX_POL 0xab8 /* USB3.0 TX Polarity */ > + > +/*** Register Settings ***/ > +/* Interrupt Enable */ > +#define RCAR_USB3_INT_XHC_ENA 0x00000001 > +#define RCAR_USB3_INT_PME_ENA 0x00000002 > +#define RCAR_USB3_INT_HSE_ENA 0x00000004 > +#define RCAR_USB3_INT_ENA_VAL (RCAR_USB3_INT_XHC_ENA | \ > + RCAR_USB3_INT_PME_ENA | RCAR_USB3_INT_HSE_ENA) > + > +/* FW Download Control & Status */ > +#define RCAR_USB3_DL_CTRL_ENABLE 0x00000001 > +#define RCAR_USB3_DL_CTRL_FW_SUCCESS 0x00000010 > +#define RCAR_USB3_DL_CTRL_FW_SET_DATA0 0x00000100 > + > +/* LCLK Select */ > +#define RCAR_USB3_LCLK_ENA_VAL 0x01030001 > + > +/* USB3.0 Configuration */ > +#define RCAR_USB3_CONF1_VAL 0x00030204 > +#define RCAR_USB3_CONF2_VAL 0x00030300 > +#define RCAR_USB3_CONF3_VAL 0x13802007 > + > +/* USB3.0 Polarity */ > +#define RCAR_USB3_RX_POL_VAL BIT(21) > +#define RCAR_USB3_TX_POL_VAL BIT(4) > + > +void xhci_rcar_start(struct usb_hcd *hcd) > +{ > + u32 temp; > + > + if (hcd->regs != NULL) { > + /* Interrupt Enable */ > + temp = readl(hcd->regs + RCAR_USB3_INT_ENA); > + temp |= RCAR_USB3_INT_ENA_VAL; > + writel(temp, hcd->regs + RCAR_USB3_INT_ENA); > + /* LCLK Select */ > + writel(RCAR_USB3_LCLK_ENA_VAL, hcd->regs + RCAR_USB3_LCLK); > + /* USB3.0 Configuration */ > + writel(RCAR_USB3_CONF1_VAL, hcd->regs + RCAR_USB3_CONF1); > + writel(RCAR_USB3_CONF2_VAL, hcd->regs + RCAR_USB3_CONF2); > + writel(RCAR_USB3_CONF3_VAL, hcd->regs + RCAR_USB3_CONF3); > + /* USB3.0 Polarity */ > + writel(RCAR_USB3_RX_POL_VAL, hcd->regs + RCAR_USB3_RX_POL); > + writel(RCAR_USB3_TX_POL_VAL, hcd->regs + RCAR_USB3_TX_POL); > + } > +} > + > +static int xhci_rcar_download_firmware(struct device *dev, void __iomem *regs) > +{ > + const struct firmware *fw; > + int retval, index, j, time; > + int timeout = 10000; > + u32 data, val, temp; > + > + /* request R-Car USB3.0 firmware */ > + retval = request_firmware(&fw, FIRMWARE_NAME, dev); > + if (retval) > + return retval; > + > + /* download R-Car USB3.0 firmware */ > + temp = readl(regs + RCAR_USB3_DL_CTRL); > + temp |= RCAR_USB3_DL_CTRL_ENABLE; > + writel(temp, regs + RCAR_USB3_DL_CTRL); > + > + for (index = 0; index < fw->size; index += 4) { > + /* to avoid reading beyond the end of the buffer */ > + for (data = 0, j = 3; j >= 0; j--) { > + if ((j + index) < fw->size) > + data |= fw->data[index + j] << (8 * j); > + } > + writel(data, regs + RCAR_USB3_FW_DATA0); > + temp = readl(regs + RCAR_USB3_DL_CTRL); > + temp |= RCAR_USB3_DL_CTRL_FW_SET_DATA0; > + writel(temp, regs + RCAR_USB3_DL_CTRL); > + > + for (time = 0; time < timeout; time++) { > + val = readl(regs + RCAR_USB3_DL_CTRL); > + if ((val & RCAR_USB3_DL_CTRL_FW_SET_DATA0) == 0) > + break; > + udelay(1); > + } > + if (time == timeout) { > + retval = -ETIMEDOUT; > + break; > + } > + } > + > + temp = readl(regs + RCAR_USB3_DL_CTRL); > + temp &= ~RCAR_USB3_DL_CTRL_ENABLE; > + writel(temp, regs + RCAR_USB3_DL_CTRL); > + > + for (time = 0; time < timeout; time++) { > + val = readl(regs + RCAR_USB3_DL_CTRL); > + if (val & RCAR_USB3_DL_CTRL_FW_SUCCESS) { > + retval = 0; > + break; > + } > + udelay(1); > + } > + if (time == timeout) > + retval = -ETIMEDOUT; > + > + release_firmware(fw); > + > + return retval; > +} > + > +/* This function needs to initialize a "phy" of usb before */ initializing a PHY looks like something that the PHY layer should do. Why don't you write a PHY driver and teach xhci-core about PHYs ? Then, more people would benefit. cheers -- balbi
Attachment:
signature.asc
Description: Digital signature