xref: /openbmc/u-boot/drivers/usb/host/ehci-zynq.c (revision ad5b5801)
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-ci.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