1dc9cdf85SRamneek Mehresh /* 2dc9cdf85SRamneek Mehresh * Copyright 2015 Freescale Semiconductor, Inc. 3dc9cdf85SRamneek Mehresh * 4dc9cdf85SRamneek Mehresh * DWC3 controller driver 5dc9cdf85SRamneek Mehresh * 6dc9cdf85SRamneek Mehresh * Author: Ramneek Mehresh<ramneek.mehresh@freescale.com> 7dc9cdf85SRamneek Mehresh * 8dc9cdf85SRamneek Mehresh * SPDX-License-Identifier: GPL-2.0+ 9dc9cdf85SRamneek Mehresh */ 10dc9cdf85SRamneek Mehresh 11dc9cdf85SRamneek Mehresh #include <common.h> 12dc9cdf85SRamneek Mehresh #include <asm/io.h> 13dc9cdf85SRamneek Mehresh #include <linux/usb/dwc3.h> 14dc9cdf85SRamneek Mehresh 15dc9cdf85SRamneek Mehresh void dwc3_set_mode(struct dwc3 *dwc3_reg, u32 mode) 16dc9cdf85SRamneek Mehresh { 17dc9cdf85SRamneek Mehresh clrsetbits_le32(&dwc3_reg->g_ctl, 18dc9cdf85SRamneek Mehresh DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG), 19dc9cdf85SRamneek Mehresh DWC3_GCTL_PRTCAPDIR(mode)); 20dc9cdf85SRamneek Mehresh } 21dc9cdf85SRamneek Mehresh 22dc9cdf85SRamneek Mehresh void dwc3_phy_reset(struct dwc3 *dwc3_reg) 23dc9cdf85SRamneek Mehresh { 24dc9cdf85SRamneek Mehresh /* Assert USB3 PHY reset */ 25dc9cdf85SRamneek Mehresh setbits_le32(&dwc3_reg->g_usb3pipectl[0], DWC3_GUSB3PIPECTL_PHYSOFTRST); 26dc9cdf85SRamneek Mehresh 27dc9cdf85SRamneek Mehresh /* Assert USB2 PHY reset */ 28dc9cdf85SRamneek Mehresh setbits_le32(&dwc3_reg->g_usb2phycfg, DWC3_GUSB2PHYCFG_PHYSOFTRST); 29dc9cdf85SRamneek Mehresh 30dc9cdf85SRamneek Mehresh mdelay(100); 31dc9cdf85SRamneek Mehresh 32dc9cdf85SRamneek Mehresh /* Clear USB3 PHY reset */ 33dc9cdf85SRamneek Mehresh clrbits_le32(&dwc3_reg->g_usb3pipectl[0], DWC3_GUSB3PIPECTL_PHYSOFTRST); 34dc9cdf85SRamneek Mehresh 35dc9cdf85SRamneek Mehresh /* Clear USB2 PHY reset */ 36dc9cdf85SRamneek Mehresh clrbits_le32(&dwc3_reg->g_usb2phycfg, DWC3_GUSB2PHYCFG_PHYSOFTRST); 37dc9cdf85SRamneek Mehresh } 38dc9cdf85SRamneek Mehresh 39dc9cdf85SRamneek Mehresh void dwc3_core_soft_reset(struct dwc3 *dwc3_reg) 40dc9cdf85SRamneek Mehresh { 41dc9cdf85SRamneek Mehresh /* Before Resetting PHY, put Core in Reset */ 42dc9cdf85SRamneek Mehresh setbits_le32(&dwc3_reg->g_ctl, DWC3_GCTL_CORESOFTRESET); 43dc9cdf85SRamneek Mehresh 44dc9cdf85SRamneek Mehresh /* reset USB3 phy - if required */ 45dc9cdf85SRamneek Mehresh dwc3_phy_reset(dwc3_reg); 46dc9cdf85SRamneek Mehresh 47*5955bb93SRajesh Bhagat mdelay(100); 48*5955bb93SRajesh Bhagat 49dc9cdf85SRamneek Mehresh /* After PHYs are stable we can take Core out of reset state */ 50dc9cdf85SRamneek Mehresh clrbits_le32(&dwc3_reg->g_ctl, DWC3_GCTL_CORESOFTRESET); 51dc9cdf85SRamneek Mehresh } 52dc9cdf85SRamneek Mehresh 53dc9cdf85SRamneek Mehresh int dwc3_core_init(struct dwc3 *dwc3_reg) 54dc9cdf85SRamneek Mehresh { 55dc9cdf85SRamneek Mehresh u32 reg; 56dc9cdf85SRamneek Mehresh u32 revision; 57dc9cdf85SRamneek Mehresh unsigned int dwc3_hwparams1; 58dc9cdf85SRamneek Mehresh 59dc9cdf85SRamneek Mehresh revision = readl(&dwc3_reg->g_snpsid); 60dc9cdf85SRamneek Mehresh /* This should read as U3 followed by revision number */ 61dc9cdf85SRamneek Mehresh if ((revision & DWC3_GSNPSID_MASK) != 0x55330000) { 62dc9cdf85SRamneek Mehresh puts("this is not a DesignWare USB3 DRD Core\n"); 63dc9cdf85SRamneek Mehresh return -1; 64dc9cdf85SRamneek Mehresh } 65dc9cdf85SRamneek Mehresh 66dc9cdf85SRamneek Mehresh dwc3_core_soft_reset(dwc3_reg); 67dc9cdf85SRamneek Mehresh 68dc9cdf85SRamneek Mehresh dwc3_hwparams1 = readl(&dwc3_reg->g_hwparams1); 69dc9cdf85SRamneek Mehresh 70dc9cdf85SRamneek Mehresh reg = readl(&dwc3_reg->g_ctl); 71dc9cdf85SRamneek Mehresh reg &= ~DWC3_GCTL_SCALEDOWN_MASK; 72dc9cdf85SRamneek Mehresh reg &= ~DWC3_GCTL_DISSCRAMBLE; 73dc9cdf85SRamneek Mehresh switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc3_hwparams1)) { 74dc9cdf85SRamneek Mehresh case DWC3_GHWPARAMS1_EN_PWROPT_CLK: 75dc9cdf85SRamneek Mehresh reg &= ~DWC3_GCTL_DSBLCLKGTNG; 76dc9cdf85SRamneek Mehresh break; 77dc9cdf85SRamneek Mehresh default: 78dc9cdf85SRamneek Mehresh debug("No power optimization available\n"); 79dc9cdf85SRamneek Mehresh } 80dc9cdf85SRamneek Mehresh 81dc9cdf85SRamneek Mehresh /* 82dc9cdf85SRamneek Mehresh * WORKAROUND: DWC3 revisions <1.90a have a bug 83dc9cdf85SRamneek Mehresh * where the device can fail to connect at SuperSpeed 84dc9cdf85SRamneek Mehresh * and falls back to high-speed mode which causes 85dc9cdf85SRamneek Mehresh * the device to enter a Connect/Disconnect loop 86dc9cdf85SRamneek Mehresh */ 87dc9cdf85SRamneek Mehresh if ((revision & DWC3_REVISION_MASK) < 0x190a) 88dc9cdf85SRamneek Mehresh reg |= DWC3_GCTL_U2RSTECN; 89dc9cdf85SRamneek Mehresh 90dc9cdf85SRamneek Mehresh writel(reg, &dwc3_reg->g_ctl); 91dc9cdf85SRamneek Mehresh 92dc9cdf85SRamneek Mehresh return 0; 93dc9cdf85SRamneek Mehresh } 94667f4dd9SNikhil Badola 95667f4dd9SNikhil Badola void dwc3_set_fladj(struct dwc3 *dwc3_reg, u32 val) 96667f4dd9SNikhil Badola { 97667f4dd9SNikhil Badola setbits_le32(&dwc3_reg->g_fladj, GFLADJ_30MHZ_REG_SEL | 98667f4dd9SNikhil Badola GFLADJ_30MHZ(val)); 99667f4dd9SNikhil Badola } 100