1 /* 2 * Copyright 2015 Freescale Semiconductor, Inc. 3 * 4 * DWC3 controller driver 5 * 6 * Author: Ramneek Mehresh<ramneek.mehresh@freescale.com> 7 * 8 * SPDX-License-Identifier: GPL-2.0+ 9 */ 10 11 #include <common.h> 12 #include <dm.h> 13 #include <usb.h> 14 15 #include "xhci.h" 16 #include <asm/io.h> 17 #include <linux/usb/dwc3.h> 18 19 DECLARE_GLOBAL_DATA_PTR; 20 21 void dwc3_set_mode(struct dwc3 *dwc3_reg, u32 mode) 22 { 23 clrsetbits_le32(&dwc3_reg->g_ctl, 24 DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG), 25 DWC3_GCTL_PRTCAPDIR(mode)); 26 } 27 28 static void dwc3_phy_reset(struct dwc3 *dwc3_reg) 29 { 30 /* Assert USB3 PHY reset */ 31 setbits_le32(&dwc3_reg->g_usb3pipectl[0], DWC3_GUSB3PIPECTL_PHYSOFTRST); 32 33 /* Assert USB2 PHY reset */ 34 setbits_le32(&dwc3_reg->g_usb2phycfg, DWC3_GUSB2PHYCFG_PHYSOFTRST); 35 36 mdelay(100); 37 38 /* Clear USB3 PHY reset */ 39 clrbits_le32(&dwc3_reg->g_usb3pipectl[0], DWC3_GUSB3PIPECTL_PHYSOFTRST); 40 41 /* Clear USB2 PHY reset */ 42 clrbits_le32(&dwc3_reg->g_usb2phycfg, DWC3_GUSB2PHYCFG_PHYSOFTRST); 43 } 44 45 void dwc3_core_soft_reset(struct dwc3 *dwc3_reg) 46 { 47 /* Before Resetting PHY, put Core in Reset */ 48 setbits_le32(&dwc3_reg->g_ctl, DWC3_GCTL_CORESOFTRESET); 49 50 /* reset USB3 phy - if required */ 51 dwc3_phy_reset(dwc3_reg); 52 53 mdelay(100); 54 55 /* After PHYs are stable we can take Core out of reset state */ 56 clrbits_le32(&dwc3_reg->g_ctl, DWC3_GCTL_CORESOFTRESET); 57 } 58 59 int dwc3_core_init(struct dwc3 *dwc3_reg) 60 { 61 u32 reg; 62 u32 revision; 63 unsigned int dwc3_hwparams1; 64 65 revision = readl(&dwc3_reg->g_snpsid); 66 /* This should read as U3 followed by revision number */ 67 if ((revision & DWC3_GSNPSID_MASK) != 0x55330000) { 68 puts("this is not a DesignWare USB3 DRD Core\n"); 69 return -1; 70 } 71 72 dwc3_core_soft_reset(dwc3_reg); 73 74 dwc3_hwparams1 = readl(&dwc3_reg->g_hwparams1); 75 76 reg = readl(&dwc3_reg->g_ctl); 77 reg &= ~DWC3_GCTL_SCALEDOWN_MASK; 78 reg &= ~DWC3_GCTL_DISSCRAMBLE; 79 switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc3_hwparams1)) { 80 case DWC3_GHWPARAMS1_EN_PWROPT_CLK: 81 reg &= ~DWC3_GCTL_DSBLCLKGTNG; 82 break; 83 default: 84 debug("No power optimization available\n"); 85 } 86 87 /* 88 * WORKAROUND: DWC3 revisions <1.90a have a bug 89 * where the device can fail to connect at SuperSpeed 90 * and falls back to high-speed mode which causes 91 * the device to enter a Connect/Disconnect loop 92 */ 93 if ((revision & DWC3_REVISION_MASK) < 0x190a) 94 reg |= DWC3_GCTL_U2RSTECN; 95 96 writel(reg, &dwc3_reg->g_ctl); 97 98 return 0; 99 } 100 101 void dwc3_set_fladj(struct dwc3 *dwc3_reg, u32 val) 102 { 103 setbits_le32(&dwc3_reg->g_fladj, GFLADJ_30MHZ_REG_SEL | 104 GFLADJ_30MHZ(val)); 105 } 106 107 static int xhci_dwc3_probe(struct udevice *dev) 108 { 109 struct xhci_dwc3_platdata *plat = dev_get_platdata(dev); 110 struct xhci_hcor *hcor; 111 struct xhci_hccr *hccr; 112 struct dwc3 *dwc3_reg; 113 114 hccr = (struct xhci_hccr *)devfdt_get_addr(dev); 115 hcor = (struct xhci_hcor *)((phys_addr_t)hccr + 116 HC_LENGTH(xhci_readl(&(hccr)->cr_capbase))); 117 118 dwc3_reg = (struct dwc3 *)((char *)(hccr) + DWC3_REG_OFFSET); 119 120 dwc3_core_init(dwc3_reg); 121 122 return xhci_register(dev, hccr, hcor); 123 } 124 125 static int xhci_dwc3_remove(struct udevice *dev) 126 { 127 return xhci_deregister(dev); 128 } 129 130 static const struct udevice_id xhci_dwc3_ids[] = { 131 { .compatible = "snps,dwc3" }, 132 { } 133 }; 134 135 U_BOOT_DRIVER(xhci_dwc3) = { 136 .name = "xhci-dwc3", 137 .id = UCLASS_USB, 138 .of_match = xhci_dwc3_ids, 139 .probe = xhci_dwc3_probe, 140 .remove = xhci_dwc3_remove, 141 .ops = &xhci_usb_ops, 142 .priv_auto_alloc_size = sizeof(struct xhci_ctrl), 143 .platdata_auto_alloc_size = sizeof(struct xhci_dwc3_platdata), 144 .flags = DM_FLAG_ALLOC_PRIV_DMA, 145 }; 146