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