1 /* 2 * (C) Copyright 2014, Xilinx, Inc 3 * 4 * USB Low level initialization(Specific to zynq) 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 9 #include <common.h> 10 #include <asm/arch/hardware.h> 11 #include <asm/arch/sys_proto.h> 12 #include <asm/io.h> 13 #include <usb.h> 14 #include <usb/ehci-fsl.h> 15 #include <usb/ulpi.h> 16 17 #include "ehci.h" 18 19 #define ZYNQ_USB_USBCMD_RST 0x0000002 20 #define ZYNQ_USB_USBCMD_STOP 0x0000000 21 #define ZYNQ_USB_NUM_MIO 12 22 23 /* 24 * Create the appropriate control structures to manage 25 * a new EHCI host controller. 26 */ 27 int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, 28 struct ehci_hcor **hcor) 29 { 30 struct usb_ehci *ehci; 31 struct ulpi_viewport ulpi_vp; 32 int ret, mio_usb; 33 /* Used for writing the ULPI data address */ 34 struct ulpi_regs *ulpi = (struct ulpi_regs *)0; 35 36 if (!index) { 37 mio_usb = zynq_slcr_get_mio_pin_status("usb0"); 38 if (mio_usb != ZYNQ_USB_NUM_MIO) { 39 printf("usb0 wrong num MIO: %d, Index %d\n", mio_usb, 40 index); 41 return -1; 42 } 43 ehci = (struct usb_ehci *)ZYNQ_USB_BASEADDR0; 44 } else { 45 mio_usb = zynq_slcr_get_mio_pin_status("usb1"); 46 if (mio_usb != ZYNQ_USB_NUM_MIO) { 47 printf("usb1 wrong num MIO: %d, Index %d\n", mio_usb, 48 index); 49 return -1; 50 } 51 ehci = (struct usb_ehci *)ZYNQ_USB_BASEADDR1; 52 } 53 54 *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); 55 *hcor = (struct ehci_hcor *)((uint32_t) *hccr + 56 HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); 57 58 ulpi_vp.viewport_addr = (u32)&ehci->ulpi_viewpoint; 59 ulpi_vp.port_num = 0; 60 61 ret = ulpi_init(&ulpi_vp); 62 if (ret) { 63 puts("zynq ULPI viewport init failed\n"); 64 return -1; 65 } 66 67 /* ULPI set flags */ 68 ulpi_write(&ulpi_vp, &ulpi->otg_ctrl, 69 ULPI_OTG_DP_PULLDOWN | ULPI_OTG_DM_PULLDOWN | 70 ULPI_OTG_EXTVBUSIND); 71 ulpi_write(&ulpi_vp, &ulpi->function_ctrl, 72 ULPI_FC_FULL_SPEED | ULPI_FC_OPMODE_NORMAL | 73 ULPI_FC_SUSPENDM); 74 ulpi_write(&ulpi_vp, &ulpi->iface_ctrl, 0); 75 76 /* Set VBus */ 77 ulpi_write(&ulpi_vp, &ulpi->otg_ctrl_set, 78 ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT); 79 80 return 0; 81 } 82 83 /* 84 * Destroy the appropriate control structures corresponding 85 * the the EHCI host controller. 86 */ 87 int ehci_hcd_stop(int index) 88 { 89 struct usb_ehci *ehci; 90 91 if (!index) 92 ehci = (struct usb_ehci *)ZYNQ_USB_BASEADDR0; 93 else 94 ehci = (struct usb_ehci *)ZYNQ_USB_BASEADDR1; 95 96 /* Stop controller */ 97 writel(ZYNQ_USB_USBCMD_STOP, &ehci->usbcmd); 98 udelay(1000); 99 100 /* Initiate controller reset */ 101 writel(ZYNQ_USB_USBCMD_RST, &ehci->usbcmd); 102 103 return 0; 104 } 105