diff options
author | Ramneek Mehresh | 2015-05-29 14:47:19 +0530 |
---|---|---|
committer | Marek Vasut | 2015-07-22 08:55:45 +0200 |
commit | ba92ee06a5b792e5cbc144f95883cc54f4982255 (patch) | |
tree | ded0f7606686f7ccfc4e19bd8d5e1a880ec7d78d /drivers | |
parent | 792651f030a0b77961e484f8de36fa42add61900 (diff) |
usb: fsl: Add XHCI driver support
Add xhci driver support for all FSL socs
Signed-off-by: Ramneek Mehresh <ramneek.mehresh@freescale.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/host/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/host/xhci-fsl.c | 109 |
2 files changed, 110 insertions, 0 deletions
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 310d979ebdd..6cc3bbd870a 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -54,6 +54,7 @@ obj-$(CONFIG_USB_XHCI) += xhci.o xhci-mem.o xhci-ring.o obj-$(CONFIG_USB_XHCI_DWC3) += xhci-dwc3.o obj-$(CONFIG_USB_XHCI_KEYSTONE) += xhci-keystone.o obj-$(CONFIG_USB_XHCI_EXYNOS) += xhci-exynos5.o +obj-$(CONFIG_USB_XHCI_FSL) += xhci-fsl.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 diff --git a/drivers/usb/host/xhci-fsl.c b/drivers/usb/host/xhci-fsl.c new file mode 100644 index 00000000000..f624c901837 --- /dev/null +++ b/drivers/usb/host/xhci-fsl.c @@ -0,0 +1,109 @@ +/* + * Copyright 2015 Freescale Semiconductor, Inc. + * + * FSL USB HOST xHCI Controller + * + * Author: Ramneek Mehresh<ramneek.mehresh@freescale.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <usb.h> +#include <asm-generic/errno.h> +#include <asm/arch-ls102xa/immap_ls102xa.h> +#include <linux/compat.h> +#include <linux/usb/xhci-fsl.h> +#include <linux/usb/dwc3.h> +#include "xhci.h" + +/* Declare global data pointer */ +DECLARE_GLOBAL_DATA_PTR; + +static struct fsl_xhci fsl_xhci; +unsigned long ctr_addr[] = FSL_USB_XHCI_ADDR; + +__weak int __board_usb_init(int index, enum usb_init_type init) +{ + return 0; +} + +void usb_phy_reset(struct dwc3 *dwc3_reg) +{ + /* Assert USB3 PHY reset */ + setbits_le32(&dwc3_reg->g_usb3pipectl[0], DWC3_GUSB3PIPECTL_PHYSOFTRST); + + /* Assert USB2 PHY reset */ + setbits_le32(&dwc3_reg->g_usb2phycfg, DWC3_GUSB2PHYCFG_PHYSOFTRST); + + mdelay(200); + + /* Clear USB3 PHY reset */ + clrbits_le32(&dwc3_reg->g_usb3pipectl[0], DWC3_GUSB3PIPECTL_PHYSOFTRST); + + /* Clear USB2 PHY reset */ + clrbits_le32(&dwc3_reg->g_usb2phycfg, DWC3_GUSB2PHYCFG_PHYSOFTRST); +} + +static int fsl_xhci_core_init(struct fsl_xhci *fsl_xhci) +{ + int ret = 0; + + ret = dwc3_core_init(fsl_xhci->dwc3_reg); + if (ret) { + debug("%s:failed to initialize core\n", __func__); + return ret; + } + + /* We are hard-coding DWC3 core to Host Mode */ + dwc3_set_mode(fsl_xhci->dwc3_reg, DWC3_GCTL_PRTCAP_HOST); + + return ret; +} + +static int fsl_xhci_core_exit(struct fsl_xhci *fsl_xhci) +{ + /* + * Currently fsl socs do not support PHY shutdown from + * sw. But this support may be added in future socs. + */ + return 0; +} + +int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor) +{ + struct fsl_xhci *ctx = &fsl_xhci; + int ret = 0; + + ctx->hcd = (struct xhci_hccr *)ctr_addr[index]; + ctx->dwc3_reg = (struct dwc3 *)((char *)(ctx->hcd) + DWC3_REG_OFFSET); + + ret = board_usb_init(index, USB_INIT_HOST); + if (ret != 0) { + puts("Failed to initialize board for USB\n"); + return ret; + } + + ret = fsl_xhci_core_init(ctx); + if (ret < 0) { + puts("Failed to initialize xhci\n"); + return ret; + } + + *hccr = (struct xhci_hccr *)ctx->hcd; + *hcor = (struct xhci_hcor *)((uint32_t) *hccr + + HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase))); + + debug("fsl-xhci: init hccr %x and hcor %x hc_length %d\n", + (uint32_t)*hccr, (uint32_t)*hcor, + (uint32_t)HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase))); + + return ret; +} + +void xhci_hcd_stop(int index) +{ + struct fsl_xhci *ctx = &fsl_xhci; + + fsl_xhci_core_exit(ctx); +} |