usb: dwc3: Add DWC3 controller driver support
Add support for DWC3 XHCI controller driver Signed-off-by: Ramneek Mehresh <ramneek.mehresh@freescale.com>
This commit is contained in:
		
							parent
							
								
									b217c89e85
								
							
						
					
					
						commit
						dc9cdf859e
					
				|  | @ -51,6 +51,7 @@ obj-$(CONFIG_USB_EHCI_ZYNQ) += ehci-zynq.o | |||
| 
 | ||||
| # xhci
 | ||||
| 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_OMAP) += xhci-omap.o | ||||
|  |  | |||
|  | @ -0,0 +1,91 @@ | |||
| /*
 | ||||
|  * Copyright 2015 Freescale Semiconductor, Inc. | ||||
|  * | ||||
|  * DWC3 controller driver | ||||
|  * | ||||
|  * Author: Ramneek Mehresh<ramneek.mehresh@freescale.com> | ||||
|  * | ||||
|  * SPDX-License-Identifier:     GPL-2.0+ | ||||
|  */ | ||||
| 
 | ||||
| #include <common.h> | ||||
| #include <asm/io.h> | ||||
| #include <linux/usb/dwc3.h> | ||||
| 
 | ||||
| void dwc3_set_mode(struct dwc3 *dwc3_reg, u32 mode) | ||||
| { | ||||
| 	clrsetbits_le32(&dwc3_reg->g_ctl, | ||||
| 			DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG), | ||||
| 			DWC3_GCTL_PRTCAPDIR(mode)); | ||||
| } | ||||
| 
 | ||||
| void dwc3_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(100); | ||||
| 
 | ||||
| 	/* 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); | ||||
| } | ||||
| 
 | ||||
| void dwc3_core_soft_reset(struct dwc3 *dwc3_reg) | ||||
| { | ||||
| 	/* Before Resetting PHY, put Core in Reset */ | ||||
| 	setbits_le32(&dwc3_reg->g_ctl, DWC3_GCTL_CORESOFTRESET); | ||||
| 
 | ||||
| 	/* reset USB3 phy - if required */ | ||||
| 	dwc3_phy_reset(dwc3_reg); | ||||
| 
 | ||||
| 	/* After PHYs are stable we can take Core out of reset state */ | ||||
| 	clrbits_le32(&dwc3_reg->g_ctl, DWC3_GCTL_CORESOFTRESET); | ||||
| } | ||||
| 
 | ||||
| int dwc3_core_init(struct dwc3 *dwc3_reg) | ||||
| { | ||||
| 	u32 reg; | ||||
| 	u32 revision; | ||||
| 	unsigned int dwc3_hwparams1; | ||||
| 
 | ||||
| 	revision = readl(&dwc3_reg->g_snpsid); | ||||
| 	/* This should read as U3 followed by revision number */ | ||||
| 	if ((revision & DWC3_GSNPSID_MASK) != 0x55330000) { | ||||
| 		puts("this is not a DesignWare USB3 DRD Core\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	dwc3_core_soft_reset(dwc3_reg); | ||||
| 
 | ||||
| 	dwc3_hwparams1 = readl(&dwc3_reg->g_hwparams1); | ||||
| 
 | ||||
| 	reg = readl(&dwc3_reg->g_ctl); | ||||
| 	reg &= ~DWC3_GCTL_SCALEDOWN_MASK; | ||||
| 	reg &= ~DWC3_GCTL_DISSCRAMBLE; | ||||
| 	switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc3_hwparams1)) { | ||||
| 	case DWC3_GHWPARAMS1_EN_PWROPT_CLK: | ||||
| 		reg &= ~DWC3_GCTL_DSBLCLKGTNG; | ||||
| 		break; | ||||
| 	default: | ||||
| 		debug("No power optimization available\n"); | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * WORKAROUND: DWC3 revisions <1.90a have a bug | ||||
| 	 * where the device can fail to connect at SuperSpeed | ||||
| 	 * and falls back to high-speed mode which causes | ||||
| 	 * the device to enter a Connect/Disconnect loop | ||||
| 	 */ | ||||
| 	if ((revision & DWC3_REVISION_MASK) < 0x190a) | ||||
| 		reg |= DWC3_GCTL_U2RSTECN; | ||||
| 
 | ||||
| 	writel(reg, &dwc3_reg->g_ctl); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  | @ -191,4 +191,10 @@ struct dwc3 {					/* offset: 0xC100 */ | |||
| #define DWC3_DCTL_CSFTRST			(1 << 30) | ||||
| #define DWC3_DCTL_LSFTRST			(1 << 29) | ||||
| 
 | ||||
| #ifdef CONFIG_USB_XHCI_DWC3 | ||||
| void dwc3_set_mode(struct dwc3 *dwc3_reg, u32 mode); | ||||
| void dwc3_core_soft_reset(struct dwc3 *dwc3_reg); | ||||
| int dwc3_core_init(struct dwc3 *dwc3_reg); | ||||
| void usb_phy_reset(struct dwc3 *dwc3_reg); | ||||
| #endif | ||||
| #endif /* __DWC3_H_ */ | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue