1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright 2015,2016 Freescale Semiconductor, Inc. 4 * 5 * FSL USB HOST xHCI Controller 6 * 7 * Author: Ramneek Mehresh<ramneek.mehresh@freescale.com> 8 */ 9 10#include <common.h> 11#include <log.h> 12#include <usb.h> 13#include <linux/errno.h> 14#include <linux/compat.h> 15#include <linux/usb/xhci-fsl.h> 16#include <linux/usb/dwc3.h> 17#include <usb/xhci.h> 18#include <fsl_errata.h> 19#include <fsl_usb.h> 20#include <dm.h> 21 22/* Declare global data pointer */ 23struct xhci_fsl_priv { 24 struct xhci_ctrl xhci; 25 fdt_addr_t hcd_base; 26 struct fsl_xhci ctx; 27}; 28 29__weak int __board_usb_init(int index, enum usb_init_type init) 30{ 31 return 0; 32} 33 34static int erratum_a008751(void) 35{ 36#if defined(CONFIG_TARGET_LS2080AQDS) || defined(CONFIG_TARGET_LS2080ARDB) ||\ 37 defined(CONFIG_TARGET_LS2080AQDS) 38 u32 __iomem *scfg = (u32 __iomem *)SCFG_BASE; 39 writel(SCFG_USB3PRM1CR_INIT, scfg + SCFG_USB3PRM1CR / 4); 40 return 0; 41#endif 42 return 1; 43} 44 45static void fsl_apply_xhci_errata(void) 46{ 47 int ret; 48 if (has_erratum_a008751()) { 49 ret = erratum_a008751(); 50 if (ret != 0) 51 puts("Failed to apply erratum a008751\n"); 52 } 53} 54 55static void fsl_xhci_set_beat_burst_length(struct dwc3 *dwc3_reg) 56{ 57 clrsetbits_le32(&dwc3_reg->g_sbuscfg0, USB3_ENABLE_BEAT_BURST_MASK, 58 USB3_ENABLE_BEAT_BURST); 59 setbits_le32(&dwc3_reg->g_sbuscfg1, USB3_SET_BEAT_BURST_LIMIT); 60} 61 62static int fsl_xhci_core_init(struct fsl_xhci *fsl_xhci) 63{ 64 int ret = 0; 65 66 ret = dwc3_core_init(fsl_xhci->dwc3_reg); 67 if (ret) { 68 debug("%s:failed to initialize core\n", __func__); 69 return ret; 70 } 71 72 /* We are hard-coding DWC3 core to Host Mode */ 73 dwc3_set_mode(fsl_xhci->dwc3_reg, DWC3_GCTL_PRTCAP_HOST); 74 75 /* Set GFLADJ_30MHZ as 20h as per XHCI spec default value */ 76 dwc3_set_fladj(fsl_xhci->dwc3_reg, GFLADJ_30MHZ_DEFAULT); 77 78 /* Change beat burst and outstanding pipelined transfers requests */ 79 fsl_xhci_set_beat_burst_length(fsl_xhci->dwc3_reg); 80 81 /* 82 * A-010151: The dwc3 phy TSMC 28-nm HPM 0.9/1.8 V does not 83 * reliably support Rx Detect in P3 mode(P3 is the default 84 * setting). Therefore, some USB3.0 devices may not be detected 85 * reliably in Super Speed mode. So, USB controller to configure 86 * USB in P2 mode whenever the Receive Detect feature is required. 87 * whenever the Receive Detect feature is required. 88 */ 89 if (has_erratum_a010151()) 90 clrsetbits_le32(&fsl_xhci->dwc3_reg->g_usb3pipectl[0], 91 DWC3_GUSB3PIPECTL_DISRXDETP3, 92 DWC3_GUSB3PIPECTL_DISRXDETP3); 93 94 return ret; 95} 96 97static int fsl_xhci_core_exit(struct fsl_xhci *fsl_xhci) 98{ 99 /* 100 * Currently fsl socs do not support PHY shutdown from 101 * sw. But this support may be added in future socs. 102 */ 103 return 0; 104} 105 106static int xhci_fsl_probe(struct udevice *dev) 107{ 108 struct xhci_fsl_priv *priv = dev_get_priv(dev); 109 struct xhci_hccr *hccr; 110 struct xhci_hcor *hcor; 111 112 int ret = 0; 113 114 /* 115 * Get the base address for XHCI controller from the device node 116 */ 117 priv->hcd_base = dev_read_addr(dev); 118 if (priv->hcd_base == FDT_ADDR_T_NONE) { 119 debug("Can't get the XHCI register base address\n"); 120 return -ENXIO; 121 } 122 priv->ctx.hcd = (struct xhci_hccr *)priv->hcd_base; 123 priv->ctx.dwc3_reg = (struct dwc3 *)((char *)(priv->hcd_base) + 124 DWC3_REG_OFFSET); 125 126 fsl_apply_xhci_errata(); 127 128 ret = fsl_xhci_core_init(&priv->ctx); 129 if (ret < 0) { 130 puts("Failed to initialize xhci\n"); 131 return ret; 132 } 133 134 hccr = (struct xhci_hccr *)(priv->ctx.hcd); 135 hcor = (struct xhci_hcor *)((uintptr_t) hccr 136 + HC_LENGTH(xhci_readl(&hccr->cr_capbase))); 137 138 debug("xhci-fsl: init hccr %lx and hcor %lx hc_length %lx\n", 139 (uintptr_t)hccr, (uintptr_t)hcor, 140 (uintptr_t)HC_LENGTH(xhci_readl(&hccr->cr_capbase))); 141 142 return xhci_register(dev, hccr, hcor); 143} 144 145static int xhci_fsl_remove(struct udevice *dev) 146{ 147 struct xhci_fsl_priv *priv = dev_get_priv(dev); 148 149 fsl_xhci_core_exit(&priv->ctx); 150 151 return xhci_deregister(dev); 152} 153 154static const struct udevice_id xhci_usb_ids[] = { 155 { .compatible = "fsl,layerscape-dwc3", }, 156 { .compatible = "fsl,ls1028a-dwc3", }, 157 { } 158}; 159 160U_BOOT_DRIVER(xhci_fsl) = { 161 .name = "xhci_fsl", 162 .id = UCLASS_USB, 163 .of_match = xhci_usb_ids, 164 .probe = xhci_fsl_probe, 165 .remove = xhci_fsl_remove, 166 .ops = &xhci_usb_ops, 167 .plat_auto = sizeof(struct usb_plat), 168 .priv_auto = sizeof(struct xhci_fsl_priv), 169 .flags = DM_FLAG_ALLOC_PRIV_DMA, 170}; 171