1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #include <console/console.h>
4 #include <device/mmio.h>
5 #include <soc/usb/usb_common.h>
6 #include <soc/addressmap.h>
7 #include <soc/clock.h>
8
9 struct usb_dwc3 {
10 u32 sbuscfg0;
11 u32 sbuscfg1;
12 u32 txthrcfg;
13 u32 rxthrcfg;
14 u32 ctl;
15 u32 pmsts;
16 u32 sts;
17 u32 uctl1;
18 u32 snpsid;
19 u32 gpio;
20 u32 uid;
21 u32 uctl;
22 u64 buserraddr;
23 u64 prtbimap;
24 u8 reserved1[32];
25 u32 dbgfifospace;
26 u32 dbgltssm;
27 u32 dbglnmcc;
28 u32 dbgbmu;
29 u32 dbglspmux;
30 u32 dbglsp;
31 u32 dbgepinfo0;
32 u32 dbgepinfo1;
33 u64 prtbimap_hs;
34 u64 prtbimap_fs;
35 u8 reserved2[112];
36 u32 usb2phycfg;
37 u8 reserved3[124];
38 u32 usb2phyacc;
39 u8 reserved4[60];
40 u32 usb3pipectl;
41 u8 reserved5[60];
42 };
43 check_member(usb_dwc3, usb2phycfg, 0x100);
44 check_member(usb_dwc3, usb3pipectl, 0x1c0);
45
46 struct usb_dwc3_cfg {
47 struct usb_dwc3 *usb_host_dwc3;
48 u32 *usb3_bcr;
49 u32 *qusb2phy_bcr;
50 u32 *gcc_usb3phy_bcr_reg;
51 u32 *gcc_qmpphy_bcr_reg;
52 };
53
54 static struct usb_dwc3_cfg usb_port0 = {
55 .usb_host_dwc3 = (void *)USB_HOST_DWC3_BASE,
56 .usb3_bcr = &gcc->usb30_prim_bcr,
57 .qusb2phy_bcr = &gcc->qusb2phy_prim_bcr,
58 .gcc_usb3phy_bcr_reg = &gcc->usb3_dp_phy_prim_bcr,
59 .gcc_qmpphy_bcr_reg = &gcc->usb3_phy_prim_bcr,
60 };
61
reset_usb(struct usb_dwc3_cfg * dwc3)62 static void reset_usb(struct usb_dwc3_cfg *dwc3)
63 {
64 /* Assert Core reset */
65 clock_reset_bcr(dwc3->usb3_bcr, 1);
66
67 /* Assert HS PHY reset */
68 clock_reset_bcr(dwc3->qusb2phy_bcr, 1);
69
70 /* Assert QMP PHY reset */
71 clock_reset_bcr(dwc3->gcc_usb3phy_bcr_reg, 1);
72 clock_reset_bcr(dwc3->gcc_qmpphy_bcr_reg, 1);
73 }
74
reset_usb0(void)75 void reset_usb0(void)
76 {
77 /* Before Resetting PHY, put Core in Reset */
78 printk(BIOS_INFO, "Starting DWC3 and PHY resets for USB(0)\n");
79
80 reset_usb(&usb_port0);
81 }
82
setup_dwc3(struct usb_dwc3 * dwc3)83 static void setup_dwc3(struct usb_dwc3 *dwc3)
84 {
85 /* core exits U1/U2/U3 only in PHY power state P1/P2/P3 respectively */
86 clrsetbits32(&dwc3->usb3pipectl,
87 DWC3_GUSB3PIPECTL_DELAYP1TRANS,
88 DWC3_GUSB3PIPECTL_UX_EXIT_IN_PX);
89
90 /*
91 * Configure USB phy interface of DWC3 core.
92 * 1. Select UTMI+ PHY with 16-bit interface.
93 * 2. Set USBTRDTIM to the corresponding value
94 * according to the UTMI+ PHY interface.
95 */
96 clrsetbits32(&dwc3->usb2phycfg,
97 (DWC3_GUSB2PHYCFG_USB2TRDTIM_MASK |
98 DWC3_GUSB2PHYCFG_PHYIF_MASK),
99 (DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_8_BIT) |
100 DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_8_BIT)));
101
102 clrsetbits32(&dwc3->ctl, (DWC3_GCTL_SCALEDOWN_MASK |
103 DWC3_GCTL_DISSCRAMBLE),
104 DWC3_GCTL_U2EXIT_LFPS | DWC3_GCTL_DSBLCLKGTNG);
105
106 /* configure controller in Host mode */
107 clrsetbits32(&dwc3->ctl, (DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)),
108 DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_HOST));
109 printk(BIOS_SPEW, "Configure USB in Host mode\n");
110 }
111
112 /* Initialization of DWC3 Core and PHY */
113
setup_usb_host(struct usb_dwc3_cfg * dwc3,void * board_data)114 static void setup_usb_host(struct usb_dwc3_cfg *dwc3,
115 void *board_data)
116 {
117 /* Clear core reset. */
118 clock_reset_bcr(dwc3->usb3_bcr, 0);
119
120 /* Clear QUSB PHY reset. */
121 clock_reset_bcr(dwc3->qusb2phy_bcr, 0);
122
123 /* Initialize HS PHY */
124 hs_usb_phy_init(board_data);
125
126 /* Clear QMP PHY resets. */
127 clock_reset_bcr(dwc3->gcc_usb3phy_bcr_reg, 0);
128 clock_reset_bcr(dwc3->gcc_qmpphy_bcr_reg, 0);
129
130 /* Initialize QMP PHY */
131 ss_qmp_phy_init();
132
133 setup_dwc3(dwc3->usb_host_dwc3);
134
135 printk(BIOS_INFO, "DWC3 and PHY setup finished\n");
136 }
setup_usb_host0(void * board_data)137 void setup_usb_host0(void *board_data)
138 {
139 printk(BIOS_INFO, "Setting up USB HOST0 controller.\n");
140 setup_usb_host(&usb_port0, board_data);
141 }
142