1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <device/mmio.h>
4 #include <console/console.h>
6 #include <device/device.h>
9 #include <soc/sysreg.h>
12 static void reset_dwc3(struct exynos5_usb_drd_dwc3
*dwc3
)
14 setbits32(&dwc3
->ctl
, 0x1 << 11); /* core soft reset */
15 setbits32(&dwc3
->usb3pipectl
, 0x1 << 31); /* PHY soft reset */
16 setbits32(&dwc3
->usb2phycfg
, 0x1 << 31); /* PHY soft reset */
19 void reset_usb_drd_dwc3(void)
21 printk(BIOS_DEBUG
, "Starting DWC3 reset for USB DRD\n");
22 reset_dwc3(exynos_usb_drd_dwc3
);
25 static void setup_dwc3(struct exynos5_usb_drd_dwc3
*dwc3
)
27 if (!(dwc3
->ctl
& 0x1 << 11) ||
28 !(dwc3
->usb3pipectl
& 0x1 << 31) ||
29 !(dwc3
->usb2phycfg
& 0x1 << 31)) {
30 printk(BIOS_ERR
, "DWC3 at %p not in reset (you need to call "
31 "reset_usb_drd_dwc3() first)!\n", dwc3
);
34 /* Set relevant registers to default values (clearing all reset bits) */
36 write32(&dwc3
->usb3pipectl
,
37 0x1 << 24 | /* activate PHY low power states */
38 0x4 << 19 | /* low power delay value */
39 0x1 << 18 | /* activate PHY low power delay */
40 0x1 << 17 | /* enable SuperSpeed PHY suspend */
41 0x1 << 1); /* default Tx deemphasis value */
43 /* Configure PHY clock turnaround for 8-bit UTMI+, disable suspend */
44 write32(&dwc3
->usb2phycfg
,
45 0x9 << 10 | /* PHY clock turnaround for 8-bit UTMI+ */
46 0x1 << 8 | /* enable PHY sleep in L1 */
47 0x1 << 6); /* enable PHY suspend */
50 0x5dc << 19 | /* suspend clock scale for 24MHz */
51 0x1 << 16 | /* retry SS three times (bugfix from U-Boot) */
52 0x1 << 12); /* port capability HOST */
55 void setup_usb_drd_dwc3(void)
57 setup_dwc3(exynos_usb_drd_dwc3
);
58 printk(BIOS_DEBUG
, "DWC3 setup for USB DRD finished\n");
61 static void setup_drd_phy(struct exynos5_usb_drd_phy
*phy
)
63 /* Set all PHY registers to default values */
65 /* XHCI Version 1.0, Frame Length adjustment 30 MHz */
66 setbits32(&phy
->linksystem
, 0x1 << 27 | 0x20 << 1);
68 /* Disable OTG, ID0 and DRVVBUS, do not force sleep/suspend */
69 write32(&phy
->utmi
, 1 << 6);
72 0x88 << 23 | /* spread spectrum refclk selector */
73 0x1 << 20 | /* enable spread spectrum */
74 0x1 << 19 | /* enable prescaler refclk */
75 0x68 << 11 | /* multiplier for 24MHz refclk */
76 0x5 << 5 | /* select 24MHz refclk (weird, from U-Boot) */
77 0x1 << 4 | /* power supply in normal operating mode */
78 0x3 << 2 | /* use external refclk (undocumented on 5420?)*/
79 0x1 << 1 | /* force port reset */
80 0x1 << 0); /* normal operating mode */
83 0x9 << 26 | /* LOS level */
84 0x3 << 22 | /* TX VREF tune */
85 0x1 << 20 | /* TX rise tune */
86 0x1 << 18 | /* TX res tune */
87 0x3 << 13 | /* TX HS X Vtune */
88 0x3 << 9 | /* TX FS/LS tune */
89 0x3 << 6 | /* SQRX tune */
90 0x4 << 3 | /* OTG tune */
91 0x4 << 0); /* comp disc tune */
94 0x7f << 19 | /* reserved */
95 0x7f << 12 | /* Tx launch amplitude */
96 0x20 << 6 | /* Tx deemphasis 6dB */
97 0x1c << 0); /* Tx deemphasis 3.5dB (value from U-Boot) */
99 /* disable all test features */
100 write32(&phy
->test
, 0);
102 /* UTMI clock select? ("must be 0x1") */
103 write32(&phy
->utmiclksel
, 0x1 << 2);
105 /* Samsung magic, undocumented (from U-Boot) */
106 write32(&phy
->resume
, 0x0);
109 clrbits32(&phy
->clkrst
, 0x1 << 1); /* deassert port reset */
112 void setup_usb_drd_phy(void)
114 printk(BIOS_DEBUG
, "Powering up USB DRD PHY\n");
115 setbits32(&exynos_power
->usb_drd_phy_ctrl
, POWER_USB_PHY_CTRL_EN
);
116 setup_drd_phy(exynos_usb_drd_phy
);
119 void setup_usb_host_phy(int hsic_gpio
)
121 unsigned int hostphy_ctrl0
;
123 setbits32(&exynos_sysreg
->usb20_phy_cfg
, USB20_PHY_CFG_EN
);
124 setbits32(&exynos_power
->usb_host_phy_ctrl
, POWER_USB_PHY_CTRL_EN
);
126 printk(BIOS_DEBUG
, "Powering up USB HOST PHY (%s HSIC)\n",
127 hsic_gpio
? "with" : "without");
129 hostphy_ctrl0
= read32(&exynos_usb_host_phy
->usbphyctrl0
);
130 hostphy_ctrl0
&= ~(HOST_CTRL0_FSEL_MASK
|
131 HOST_CTRL0_COMMONON_N
|
132 /* HOST Phy setting */
133 HOST_CTRL0_PHYSWRST
|
134 HOST_CTRL0_PHYSWRSTALL
|
136 HOST_CTRL0_FORCESUSPEND
|
137 HOST_CTRL0_FORCESLEEP
);
138 hostphy_ctrl0
|= (/* Setting up the ref freq */
140 /* HOST Phy setting */
141 HOST_CTRL0_LINKSWRST
|
142 HOST_CTRL0_UTMISWRST
);
143 write32(&exynos_usb_host_phy
->usbphyctrl0
, hostphy_ctrl0
);
145 clrbits32(&exynos_usb_host_phy
->usbphyctrl0
,
146 HOST_CTRL0_LINKSWRST
|
147 HOST_CTRL0_UTMISWRST
);
150 /* EHCI Ctrl setting */
151 setbits32(&exynos_usb_host_phy
->ehcictrl
,
152 EHCICTRL_ENAINCRXALIGN
|
157 /* HSIC USB Hub initialization. */
159 gpio_direction_output(hsic_gpio
, 0);
161 gpio_direction_output(hsic_gpio
, 1);
164 clrbits32(&exynos_usb_host_phy
->hsicphyctrl1
,
166 HOST_CTRL0_FORCESLEEP
|
167 HOST_CTRL0_FORCESUSPEND
);
168 setbits32(&exynos_usb_host_phy
->hsicphyctrl1
,
169 HOST_CTRL0_PHYSWRST
);
171 clrbits32(&exynos_usb_host_phy
->hsicphyctrl1
,
172 HOST_CTRL0_PHYSWRST
);
175 /* At this point we need to wait for 50ms before talking to
176 * the USB controller (PHY clock and power setup time)
177 * By the time we are actually in the payload, these 50ms