1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <device/mmio.h>
4 #include <console/console.h>
10 #define CRPORT_TX_OVRD_DRV_LO 0x1002
11 #define CRPORT_RX_OVRD_IN_HI 0x1006
12 #define CRPORT_TX_ALT_BLOCK 0x102d
14 static u32
*const tcsr_usb_sel
= (void *)0x1a4000b0;
39 check_member(usb_qc_phy
, crport_ack_write
, 0x50);
41 static struct usb_qc_phy
* const usb_host1_phy
= (void *)USB_HOST1_PHY_BASE
;
42 static struct usb_qc_phy
* const usb_host2_phy
= (void *)USB_HOST2_PHY_BASE
;
80 check_member(usb_dwc3
, usb3pipectl
, 0x1c0);
82 static struct usb_dwc3
* const usb_host1_dwc3
= (void *)USB_HOST1_DWC3_BASE
;
83 static struct usb_dwc3
* const usb_host2_dwc3
= (void *)USB_HOST2_DWC3_BASE
;
85 static void setup_dwc3(struct usb_dwc3
*dwc3
)
87 write32(&dwc3
->usb3pipectl
,
88 0x1 << 31 | /* assert PHY soft reset */
89 0x1 << 25 | /* (default) U1/U2 exit fail -> recovery? */
90 0x1 << 24 | /* (default) activate PHY low power states */
91 0x1 << 19 | /* (default) PHY low power delay value */
92 0x1 << 18 | /* (default) activate PHY low power delay */
93 0x1 << 1 | /* (default) Tx deemphasis value */
94 0x1 << 0); /* (default) elastic buffer mode */
96 write32(&dwc3
->usb2phycfg
,
97 0x1 << 31 | /* assert PHY soft reset */
98 0x9 << 10 | /* (default) PHY clock turnaround 8-bit UTMI+ */
99 0x1 << 8 | /* (default) enable PHY sleep in L1 */
100 0x1 << 6); /* (default) enable PHY suspend */
103 0x2 << 19 | /* (default) suspend clock scaling */
104 0x1 << 16 | /* retry SS three times before HS downgrade */
105 0x1 << 12 | /* port capability HOST */
106 0x1 << 11 | /* assert core soft reset */
107 0x1 << 10 | /* (default) sync ITP to refclk */
108 0x1 << 2); /* U2 exit after 8us LFPS (instead of 248ns) */
111 0x32 << 22 | /* (default) reference clock period in ns */
112 0x1 << 15 | /* (default) XHCI compliant device addressing */
113 0x10 << 0); /* (default) devices time out after 32us */
117 clrbits32(&dwc3
->ctl
, 0x1 << 11); /* deassert core soft reset */
118 clrbits32(&dwc3
->usb2phycfg
, 0x1 << 31); /* PHY soft reset */
119 clrbits32(&dwc3
->usb3pipectl
, 0x1 << 31); /* PHY soft reset */
122 static void setup_phy(struct usb_qc_phy
*phy
)
124 write32(&phy
->ss_phy_ctrl
,
125 0x1 << 24 | /* Indicate VBUS power present */
126 0x1 << 8 | /* Enable USB3 ref clock to prescaler */
127 0x1 << 7 | /* assert SS PHY reset */
128 0x19 << 0); /* (default) reference clock multiplier */
130 write32(&phy
->hs_phy_ctrl
,
131 0x1 << 26 | /* (default) unclamp DPSE/DMSE VLS */
132 0x1 << 25 | /* (default) select freeclk for utmi_clk */
133 0x1 << 24 | /* (default) unclamp DMSE VLS */
134 0x1 << 21 | /* (default) enable UTMI clock */
135 0x1 << 20 | /* set OTG VBUS as valid */
136 0x1 << 18 | /* use ref clock from core */
137 0x1 << 17 | /* (default) unclamp DPSE VLS */
138 0x1 << 11 | /* force xo/bias/pll to stay on in suspend */
139 0x1 << 9 | /* (default) unclamp IDHV */
140 0x1 << 8 | /* (default) unclamp VLS (again???) */
141 0x1 << 7 | /* (default) unclamp HV VLS */
142 0x7 << 4 | /* select frequency (no idea which one) */
143 0x1 << 1); /* (default) "retention enable" */
145 write32(&phy
->ss_phy_param1
,
146 0x6e << 20 | /* full TX swing amplitude */
147 0x20 << 14 | /* (default) 6dB TX deemphasis */
148 0x17 << 8 | /* 3.5dB TX deemphasis */
149 0x9 << 3); /* (default) LoS detector level */
151 write32(&phy
->general_cfg
, 0x1 << 2); /* set XHCI 1.00 compliance */
154 clrbits32(&phy
->ss_phy_ctrl
, 0x1 << 7); /* deassert SS PHY reset */
157 static void crport_handshake(void *capture_reg
, void *acknowledge_bit
, u32 data
)
162 write32(capture_reg
, data
);
164 write32(acknowledge_bit
, 0x1 << 0);
165 while (read32(acknowledge_bit
) && --usec
)
169 printk(BIOS_ERR
, "CRPORT handshake timed out (0x%08x)\n", data
);
172 static void crport_write(struct usb_qc_phy
*phy
, u16 addr
, u16 data
)
174 crport_handshake(&phy
->crport_data_in
, &phy
->crport_cap_addr
, addr
);
175 crport_handshake(&phy
->crport_data_in
, &phy
->crport_cap_data
, data
);
176 crport_handshake(NULL
, &phy
->crport_ack_write
, 0);
179 static void tune_phy(struct usb_qc_phy
*phy
)
181 crport_write(phy
, CRPORT_RX_OVRD_IN_HI
,
182 0x1 << 11 | /* Set RX_EQ override? */
183 0x4 << 8 | /* Set RX_EQ to 4? */
184 0x1 << 7); /* Enable RX_EQ override */
185 crport_write(phy
, CRPORT_TX_OVRD_DRV_LO
,
186 0x1 << 14 | /* Enable amplitude (override?) */
187 0x17 << 7 | /* Set TX deemphasis to 23 */
188 0x6e << 0); /* Set amplitude to 110 */
189 crport_write(phy
, CRPORT_TX_ALT_BLOCK
,
190 0x1 << 7); /* ALT block? ("partial RX reset") */
193 void setup_usb_host1(void)
195 printk(BIOS_INFO
, "Setting up USB HOST1 controller...\n");
196 setbits32(tcsr_usb_sel
, 1 << 0); /* Select DWC3 controller */
197 setup_phy(usb_host1_phy
);
198 setup_dwc3(usb_host1_dwc3
);
199 tune_phy(usb_host1_phy
);
202 void setup_usb_host2(void)
204 printk(BIOS_INFO
, "Setting up USB HOST2 controller...\n");
205 setbits32(tcsr_usb_sel
, 1 << 1); /* Select DWC3 controller */
206 setup_phy(usb_host2_phy
);
207 setup_dwc3(usb_host2_dwc3
);
208 tune_phy(usb_host2_phy
);