1 /* 2 * Copyright 2015 Freescale Semiconductor, Inc. 3 * 4 * FSL USB HOST xHCI Controller 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 <usb.h> 13 #include <asm-generic/errno.h> 14 #include <linux/compat.h> 15 #include <linux/usb/xhci-fsl.h> 16 #include <linux/usb/dwc3.h> 17 #include "xhci.h" 18 19 /* Declare global data pointer */ 20 DECLARE_GLOBAL_DATA_PTR; 21 22 static struct fsl_xhci fsl_xhci; 23 unsigned long ctr_addr[] = FSL_USB_XHCI_ADDR; 24 25 __weak int __board_usb_init(int index, enum usb_init_type init) 26 { 27 return 0; 28 } 29 30 void usb_phy_reset(struct dwc3 *dwc3_reg) 31 { 32 /* Assert USB3 PHY reset */ 33 setbits_le32(&dwc3_reg->g_usb3pipectl[0], DWC3_GUSB3PIPECTL_PHYSOFTRST); 34 35 /* Assert USB2 PHY reset */ 36 setbits_le32(&dwc3_reg->g_usb2phycfg, DWC3_GUSB2PHYCFG_PHYSOFTRST); 37 38 mdelay(200); 39 40 /* Clear USB3 PHY reset */ 41 clrbits_le32(&dwc3_reg->g_usb3pipectl[0], DWC3_GUSB3PIPECTL_PHYSOFTRST); 42 43 /* Clear USB2 PHY reset */ 44 clrbits_le32(&dwc3_reg->g_usb2phycfg, DWC3_GUSB2PHYCFG_PHYSOFTRST); 45 } 46 47 static int fsl_xhci_core_init(struct fsl_xhci *fsl_xhci) 48 { 49 int ret = 0; 50 51 ret = dwc3_core_init(fsl_xhci->dwc3_reg); 52 if (ret) { 53 debug("%s:failed to initialize core\n", __func__); 54 return ret; 55 } 56 57 /* We are hard-coding DWC3 core to Host Mode */ 58 dwc3_set_mode(fsl_xhci->dwc3_reg, DWC3_GCTL_PRTCAP_HOST); 59 60 /* Set GFLADJ_30MHZ as 20h as per XHCI spec default value */ 61 dwc3_set_fladj(fsl_xhci->dwc3_reg, GFLADJ_30MHZ_DEFAULT); 62 63 return ret; 64 } 65 66 static int fsl_xhci_core_exit(struct fsl_xhci *fsl_xhci) 67 { 68 /* 69 * Currently fsl socs do not support PHY shutdown from 70 * sw. But this support may be added in future socs. 71 */ 72 return 0; 73 } 74 75 int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor) 76 { 77 struct fsl_xhci *ctx = &fsl_xhci; 78 int ret = 0; 79 80 ctx->hcd = (struct xhci_hccr *)ctr_addr[index]; 81 ctx->dwc3_reg = (struct dwc3 *)((char *)(ctx->hcd) + DWC3_REG_OFFSET); 82 83 ret = board_usb_init(index, USB_INIT_HOST); 84 if (ret != 0) { 85 puts("Failed to initialize board for USB\n"); 86 return ret; 87 } 88 89 ret = fsl_xhci_core_init(ctx); 90 if (ret < 0) { 91 puts("Failed to initialize xhci\n"); 92 return ret; 93 } 94 95 *hccr = (struct xhci_hccr *)ctx->hcd; 96 *hcor = (struct xhci_hcor *)((uintptr_t) *hccr 97 + HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase))); 98 99 debug("fsl-xhci: init hccr %lx and hcor %lx hc_length %lx\n", 100 (uintptr_t)*hccr, (uintptr_t)*hcor, 101 (uintptr_t)HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase))); 102 103 return ret; 104 } 105 106 void xhci_hcd_stop(int index) 107 { 108 struct fsl_xhci *ctx = &fsl_xhci; 109 110 fsl_xhci_core_exit(ctx); 111 } 112