blob: f2286af4d2beaa685f71a521cb508d2e6f412594 [file] [log] [blame]
Googler15b35d92022-10-03 17:48:21 +08001/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
2/*
3 * drivers/usb/host/xhci-amlogic.c
4 *
5 * Copyright (C) 2020 Amlogic, Inc. All rights reserved.
6 *
7 */
8
9/*
10 * This file is a conglomeration for DWC3-init sequence and further
11 * exynos5 specific PHY-init sequence.
12 */
13
14#include <common.h>
15//#include <fdtdec.h>
16#include <libfdt.h>
17#include <malloc.h>
18#include <usb.h>
19#include <watchdog.h>
20#include <asm/arch/cpu.h>
21//#include <asm/arch/power.h>
22//#include <asm/gpio.h>
23#include <asm-generic/errno.h>
24#include <linux/compat.h>
25#include <linux/usb/dwc3.h>
26#include <asm/arch/usb.h>
27
28#include "xhci.h"
29
30/* Declare global data pointer */
31DECLARE_GLOBAL_DATA_PTR;
32
33/**
34 * Contains pointers to register base addresses
35 * for the usb controller.
36 */
37struct amlogic_xhci {
38 struct amlogic_usb2_phy *usb2_phy;
39 struct amlogic_usb3_phy *usb3_phy;
40 struct xhci_hccr *hcd;
41 struct dwc3 *dwc3_reg;
42};
43amlogic_usb3_phy *usb_aml_reg;
44
45static struct amlogic_xhci amlogic;
46
47
48static void amlogic_usb2_phy_init(struct amlogic_usb2_phy *phy)
49{
50 int time_dly = 500;
51 int i;
52
53 amlogic_usb2_phy *u2p_aml_reg;
54 u2p_r0_t reg0;
55
56 for (i=0; i<4; i++)
57 {
58 u2p_aml_reg = (amlogic_usb2_phy *)((ulong)phy+i*PHY_REGISTER_SIZE);
59
60 reg0.d32 = u2p_aml_reg->u2p_r0;
61 reg0.b.por = 1;
62 reg0.b.dmpulldown = 1;
63 reg0.b.dppulldown = 1;
64 u2p_aml_reg->u2p_r0 = reg0.d32;
65
66 udelay(time_dly);
67
68 reg0.d32 = u2p_aml_reg->u2p_r0;
69 reg0.b.por = 0;
70 u2p_aml_reg->u2p_r0 = reg0.d32;
71 }
72
73 return;
74
75}
76
77void cr_bus_addr (u32 addr)
78{
79 usb_r2_t usb_r2 = {.d32 = 0};
80 usb_r6_t usb_r6 = {.d32 = 0};
81
82 // prepare addr
83 usb_r2.b.p30_cr_data_in = addr;
84 usb_aml_reg->usb_r2 = usb_r2.d32;
85
86 // cap addr rising edge
87 usb_r2.b.p30_cr_cap_addr = 0;
88 usb_aml_reg->usb_r2 = usb_r2.d32;
89 usb_r2.b.p30_cr_cap_addr = 1;
90 usb_aml_reg->usb_r2 = usb_r2.d32;
91
92 // wait ack 1
93 do {
94 usb_r6.d32 = usb_aml_reg->usb_r6;
95 } while (usb_r6.b.p30_cr_ack == 0);
96
97 // clear cap addr
98 usb_r2.b.p30_cr_cap_addr = 0;
99 usb_aml_reg->usb_r2 = usb_r2.d32;
100
101 // wait ack 0
102 do {
103 usb_r6.d32 = usb_aml_reg->usb_r6;
104 } while (usb_r6.b.p30_cr_ack == 1);
105}
106
107int cr_bus_read (u32 addr)
108{
109 int data;
110 usb_r2_t usb_r2 = {.d32 = 0};
111 usb_r6_t usb_r6 = {.d32 = 0};
112
113 cr_bus_addr ( addr );
114
115 // read rising edge
116 usb_r2.b.p30_cr_read = 0;
117 usb_aml_reg->usb_r2 = usb_r2.d32;
118 usb_r2.b.p30_cr_read = 1;
119 usb_aml_reg->usb_r2 = usb_r2.d32;
120
121 // wait ack 1
122 do {
123 usb_r6.d32 = usb_aml_reg->usb_r6;
124 } while (usb_r6.b.p30_cr_ack == 0);
125
126 // save data
127 data = usb_r6.b.p30_cr_data_out;
128
129 // clear read
130 usb_r2.b.p30_cr_read = 0;
131 usb_aml_reg->usb_r2 = usb_r2.d32;
132
133 // wait ack 0
134 do {
135 usb_r6.d32 = usb_aml_reg->usb_r6;
136 } while (usb_r6.b.p30_cr_ack == 1);
137
138 return data;
139}
140
141void cr_bus_write (u32 addr, u32 data)
142{
143 usb_r2_t usb_r2 = {.d32 = 0};
144 usb_r6_t usb_r6 = {.d32 = 0};
145
146 cr_bus_addr ( addr );
147
148 // prepare data
149 usb_r2.b.p30_cr_data_in = data;
150 usb_aml_reg->usb_r2 = usb_r2.d32;
151
152 // cap data rising edge
153 usb_r2.b.p30_cr_cap_data = 0;
154 usb_aml_reg->usb_r2 = usb_r2.d32;
155 usb_r2.b.p30_cr_cap_data = 1;
156 usb_aml_reg->usb_r2 = usb_r2.d32;
157
158 // wait ack 1
159 do {
160 usb_r6.d32 = usb_aml_reg->usb_r6;
161 } while (usb_r6.b.p30_cr_ack == 0);
162
163 // clear cap data
164 usb_r2.b.p30_cr_cap_data = 0;
165 usb_aml_reg->usb_r2 = usb_r2.d32;
166
167 // wait ack 0
168 do {
169 usb_r6.d32 = usb_aml_reg->usb_r6;
170 } while (usb_r6.b.p30_cr_ack == 1);
171
172 // write rising edge
173 usb_r2.b.p30_cr_write = 0;
174 usb_aml_reg->usb_r2 = usb_r2.d32;
175 usb_r2.b.p30_cr_write = 1;
176 usb_aml_reg->usb_r2 = usb_r2.d32;
177
178 // wait ack 1
179 do {
180 usb_r6.d32 = usb_aml_reg->usb_r6;
181 } while (usb_r6.b.p30_cr_ack == 0);
182
183 // clear write
184 usb_r2.b.p30_cr_write = 0;
185 usb_aml_reg->usb_r2 = usb_r2.d32;
186
187 // wait ack 0
188 do {
189 usb_r6.d32 = usb_aml_reg->usb_r6;
190 } while (usb_r6.b.p30_cr_ack == 1);
191}
192
193
194static void amlogic_usb3_phy_init(struct amlogic_usb3_phy *phy)
195{
196 usb_r0_t r0 = {.d32 = 0};
197 usb_r1_t r1 = {.d32 = 0};
198 usb_r2_t r2 = {.d32 = 0};
199 usb_r3_t r3 = {.d32 = 0};
200 int i;
201 u32 data = 0;
202
203 for (i=0;i<1;i++)
204 {
205 usb_aml_reg = (amlogic_usb3_phy *)((ulong)phy+i*PHY_REGISTER_SIZE);
206
207 usb_aml_reg->usb_r3 = (1<<13) | (0x68<<24);
208 udelay(2);
209 r0.d32 = usb_aml_reg->usb_r0;
210 r0.b.p30_phy_reset = 1;
211 usb_aml_reg->usb_r0 = r0.d32;
212 udelay(2);
213 r0.b.p30_phy_reset = 0;
214 r0.b.p30_tx_vboost_lvl = 0x4;
215 usb_aml_reg->usb_r0 = r0.d32;
216
217
218 /*
219 * WORKAROUND: There is SSPHY suspend bug due to which USB enumerates
220 * in HS mode instead of SS mode. Workaround it by asserting
221 * LANE0.TX_ALT_BLOCK.EN_ALT_BUS to enable TX to use alt bus mode
222 */
223 data = cr_bus_read(0x102d);
224 data |= (1 << 7);
225 cr_bus_write(0x102D, data);
226
227 data = cr_bus_read(0x1010);
228 data &= ~0xff0;
229 data |= 0x20;
230 cr_bus_write(0x1010, data);
231
232 /*
233 * Fix RX Equalization setting as follows
234 * LANE0.RX_OVRD_IN_HI. RX_EQ_EN set to 0
235 * LANE0.RX_OVRD_IN_HI.RX_EQ_EN_OVRD set to 1
236 * LANE0.RX_OVRD_IN_HI.RX_EQ set to 3
237 * LANE0.RX_OVRD_IN_HI.RX_EQ_OVRD set to 1
238 */
239 data = cr_bus_read(0x1006);
240 data &= ~(1 << 6);
241 data |= (1 << 7);
242 data &= ~(0x7 << 8);
243 data |= (0x3 << 8);
244 data |= (0x1 << 11);
245 cr_bus_write(0x1006, data);
246
247 /*
248 * Set EQ and TX launch amplitudes as follows
249 * LANE0.TX_OVRD_DRV_LO.PREEMPH set to 22
250 * LANE0.TX_OVRD_DRV_LO.AMPLITUDE set to 127
251 * LANE0.TX_OVRD_DRV_LO.EN set to 1.
252 */
253 data = cr_bus_read(0x1002);
254 data &= ~0x3f80;
255 data |= (0x16 << 7);
256 data &= ~0x7f;
257 data |= (0x7f | (1 << 14));
258 cr_bus_write(0x1002, data);
259
260 /*
261 * TX_FULL_SWING to 127
262 */
263 data = cr_bus_read(0x30);
264 data &= ~(0xf << 4);
265 cr_bus_write(0x30, data);
266
267 /*
268 * TX_FULL_SWING to 127
269 */
270 r1.d32 = usb_aml_reg->usb_r1;
271 r1.b.p30_pcs_tx_swing_full = 127;
272 r1.b.u3h_fladj_30mhz_reg = 0x20;
273 usb_aml_reg->usb_r1 = r1.d32;
274 udelay(2);
275
276 /*
277 * TX_DEEMPH_3_5DB to 22
278 */
279 r2.d32 = usb_aml_reg->usb_r2;
280 r2.b.p30_pcs_tx_deemph_3p5db = 22;
281 usb_aml_reg->usb_r2 = r2.d32;
282
283 udelay(2);
284 /*
285 * LOS_BIAS to 0x5
286 * LOS_LEVEL to 0x9
287 */
288 r3.d32 = usb_aml_reg->usb_r3;
289 r3.b.p30_los_bias = 0x5;
290 r3.b.p30_los_level = 0x9;
291 r3.b.p30_ssc_en = 1;
292 r3.b.p30_ssc_range = 2;
293 usb_aml_reg->usb_r3 = r3.d32;
294 }
295
296}
297
298static void amlogic_usb2_phy_exit(struct amlogic_usb2_phy *phy)
299{
300 return;
301}
302
303static void amlogic_usb3_phy_exit(struct amlogic_usb3_phy *phy)
304{
305 return;
306}
307void dwc3_set_mode(struct dwc3 *dwc3_reg, u32 mode)
308{
309 u32 reg;
310
311 reg = xhci_readl(&dwc3_reg->g_ctl);
312 reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
313 reg |= DWC3_GCTL_PRTCAPDIR(mode);
314 xhci_writel(&dwc3_reg->g_ctl, reg);
315}
316
317static void dwc3_core_soft_reset(struct dwc3 *dwc3_reg)
318{
319 u32 reg;
320
321 /* Before Resetting PHY, put Core in Reset */
322 reg = xhci_readl(&dwc3_reg->g_ctl);
323 reg |= DWC3_GCTL_CORESOFTRESET;
324 xhci_writel(&dwc3_reg->g_ctl, reg);
325
326 /* Assert USB3 PHY reset */
327 reg = xhci_readl(&dwc3_reg->g_usb3pipectl[0]);
328 reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST;
329 xhci_writel(&dwc3_reg->g_usb3pipectl[0], reg);
330
331 /* Assert USB2 PHY reset */
332 reg = xhci_readl(&dwc3_reg->g_usb2phycfg[0]);
333 reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST;
334 xhci_writel(&dwc3_reg->g_usb2phycfg[0], reg);
335
336 reg = xhci_readl(&dwc3_reg->g_usb2phycfg[1]);
337 reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST;
338 xhci_writel(&dwc3_reg->g_usb2phycfg[1], reg);
339
340 reg = xhci_readl(&dwc3_reg->g_usb2phycfg[2]);
341 reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST;
342 xhci_writel(&dwc3_reg->g_usb2phycfg[2], reg);
343
344 reg = xhci_readl(&dwc3_reg->g_usb2phycfg[3]);
345 reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST;
346 xhci_writel(&dwc3_reg->g_usb2phycfg[3], reg);
347
348 amlogic_usb2_phy_init(amlogic.usb2_phy);
349 amlogic_usb3_phy_init(amlogic.usb3_phy);
350 mdelay(100);
351
352 /* Clear USB3 PHY reset */
353 reg = xhci_readl(&dwc3_reg->g_usb3pipectl[0]);
354 reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST;
355 xhci_writel(&dwc3_reg->g_usb3pipectl[0], reg);
356
357 /* Clear USB2 PHY reset */
358 reg = xhci_readl(&dwc3_reg->g_usb2phycfg[0]);
359 reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST;
360 reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
361 xhci_writel(&dwc3_reg->g_usb2phycfg[0], reg);
362
363 /* Clear USB2 PHY reset */
364 reg = xhci_readl(&dwc3_reg->g_usb2phycfg[1]);
365 reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST;
366 xhci_writel(&dwc3_reg->g_usb2phycfg[1], reg);
367
368 /* Clear USB2 PHY reset */
369 reg = xhci_readl(&dwc3_reg->g_usb2phycfg[2]);
370 reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST;
371 xhci_writel(&dwc3_reg->g_usb2phycfg[2], reg);
372
373 /* Clear USB2 PHY reset */
374 reg = xhci_readl(&dwc3_reg->g_usb2phycfg[3]);
375 reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST;
376 xhci_writel(&dwc3_reg->g_usb2phycfg[3], reg);
377
378 mdelay(100);
379
380 /* After PHYs are stable we can take Core out of reset state */
381 reg = xhci_readl(&dwc3_reg->g_ctl);
382 reg &= ~DWC3_GCTL_CORESOFTRESET;
383 xhci_writel(&dwc3_reg->g_ctl, reg);
384}
385
386static int dwc3_core_init(struct dwc3 *dwc3_reg)
387{
388 u32 reg;
389 u32 revision;
390 unsigned int dwc3_hwparams1;
391 unsigned long timeout;
392
393 revision = xhci_readl(&dwc3_reg->g_snpsid);
394 /* This should read as U3 followed by revision number */
395 if ((revision & DWC3_GSNPSID_MASK) != 0x55330000) {
396 printf("this is not a DesignWare USB3 DRD Core\n");
397 return -EINVAL;
398 }
399
400 /* issue device SoftReset too */
401 timeout = 500;
402 xhci_writel(&dwc3_reg->d_ctl, DWC3_DCTL_CSFTRST);
403 do {
404 reg = xhci_readl(&dwc3_reg->d_ctl);
405 if (!(reg & DWC3_DCTL_CSFTRST))
406 break;
407
408 timeout--;
409 mdelay(1);
410 } while (timeout);
411
412 if (!timeout) {
413 printf("device SoftReset fail!\n");
414 return -EINVAL;
415 }
416
417 dwc3_core_soft_reset(dwc3_reg);
418
419 dwc3_hwparams1 = xhci_readl(&dwc3_reg->g_hwparams1);
420
421 reg = xhci_readl(&dwc3_reg->g_ctl);
422 reg &= ~DWC3_GCTL_SCALEDOWN_MASK;
423 reg |= DWC3_GCTL_DISSCRAMBLE;
424 switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc3_hwparams1)) {
425 case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
426 reg &= ~DWC3_GCTL_DSBLCLKGTNG;
427 break;
428 default:
429 debug("No power optimization available\n");
430 }
431
432 /*
433 * WORKAROUND: DWC3 revisions <1.90a have a bug
434 * where the device can fail to connect at SuperSpeed
435 * and falls back to high-speed mode which causes
436 * the device to enter a Connect/Disconnect loop
437 */
438 if ((revision & DWC3_REVISION_MASK) < 0x190a)
439 reg |= DWC3_GCTL_U2RSTECN;
440
441 xhci_writel(&dwc3_reg->g_ctl, reg);
442
443 return 0;
444}
445
446static int amlogic_xhci_core_init(struct amlogic_xhci *amlogic)
447{
448 int ret;
449
450 ret = dwc3_core_init(amlogic->dwc3_reg);
451 if (ret) {
452 debug("failed to initialize core\n");
453 return -EINVAL;
454 }
455
456 /* We are hard-coding DWC3 core to Host Mode */
457 dwc3_set_mode(amlogic->dwc3_reg, DWC3_GCTL_PRTCAP_HOST);
458
459 return 0;
460}
461
462static void amlogic_xhci_core_exit(struct amlogic_xhci *amlogic)
463{
464 amlogic_usb2_phy_exit(amlogic->usb2_phy);
465
466 amlogic_usb3_phy_exit(amlogic->usb3_phy);
467}
468
469int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor)
470{
471 struct amlogic_xhci *ctx = &amlogic;
472 amlogic_usb_config_t * usb_config;
473 int ret;
474
475 usb_config = board_usb_start(BOARD_USB_MODE_HOST,index);
476
477 ctx->hcd = (struct xhci_hccr *)(ulong)(usb_config->base_addr);
478 ctx->dwc3_reg = (struct dwc3 *)((char *)(ctx->hcd) + DWC3_REG_OFFSET);
479 ctx->usb3_phy = (struct amlogic_usb3_phy *)(ulong)(usb_config->usb_phy3_base_addr);
480 ctx->usb2_phy = (struct amlogic_usb2_phy *)(ulong)(usb_config->usb_phy2_base_addr);
481
482 ret = amlogic_xhci_core_init(ctx);
483 if (ret) {
484 puts("XHCI: failed to initialize controller\n");
485 return -EINVAL;
486 }
487
488 *hccr = (ctx->hcd);
489 *hcor = (struct xhci_hcor *)((ulong) *hccr
490 + HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase)));
491
492 debug("amlogic-xhci: init hccr %lx and hcor %lx hc_length %d\n",
493 (ulong)*hccr, (ulong)*hcor,
494 (uint32_t)HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase)));
495
496 return 0;
497}
498
499void xhci_hcd_stop(int index)
500{
501 struct amlogic_xhci *ctx = &amlogic;
502
503 amlogic_xhci_core_exit(ctx);
504}
505