blob: 27abe19fac8a1a5a8a480eb09030d2abf6566df0 [file] [log] [blame]
Angel Pons1ddb8942020-04-04 18:51:26 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Stefan Reinauer2ad63c22013-05-17 11:52:45 -07002
Kyösti Mälkki13f66502019-03-03 08:01:05 +02003#include <device/mmio.h>
Stefan Reinauer2ad63c22013-05-17 11:52:45 -07004#include <console/console.h>
Julius Werner1ed0c8c2014-10-20 13:16:29 -07005#include <delay.h>
Stefan Reinauer2ad63c22013-05-17 11:52:45 -07006#include <device/device.h>
Julius Werner1ed0c8c2014-10-20 13:16:29 -07007#include <soc/gpio.h>
8#include <soc/power.h>
9#include <soc/sysreg.h>
10#include <soc/usb.h>
Stefan Reinauer2ad63c22013-05-17 11:52:45 -070011
Julius Werner68aef112013-09-03 15:07:31 -070012static void reset_dwc3(struct exynos5_usb_drd_dwc3 *dwc3)
13{
Julius Werner55009af2019-12-02 22:03:27 -080014 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 */
Julius Werner68aef112013-09-03 15:07:31 -070017}
18
Elyes HAOUASbef4ec72022-01-30 11:33:15 +010019void reset_usb_drd_dwc3(void)
Julius Werner68aef112013-09-03 15:07:31 -070020{
21 printk(BIOS_DEBUG, "Starting DWC3 reset for USB DRD\n");
22 reset_dwc3(exynos_usb_drd_dwc3);
23}
24
25static void setup_dwc3(struct exynos5_usb_drd_dwc3 *dwc3)
26{
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);
32 }
33
34 /* Set relevant registers to default values (clearing all reset bits) */
35
Julius Werner2f37bd62015-02-19 14:51:15 -080036 write32(&dwc3->usb3pipectl,
Julius Werner94184762015-02-19 20:19:23 -080037 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 */
Julius Werner68aef112013-09-03 15:07:31 -070042
43 /* Configure PHY clock turnaround for 8-bit UTMI+, disable suspend */
Julius Werner94184762015-02-19 20:19:23 -080044 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 */
Julius Werner68aef112013-09-03 15:07:31 -070048
Julius Werner94184762015-02-19 20:19:23 -080049 write32(&dwc3->ctl,
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 */
Julius Werner68aef112013-09-03 15:07:31 -070053}
54
Elyes HAOUASbef4ec72022-01-30 11:33:15 +010055void setup_usb_drd_dwc3(void)
Julius Werner68aef112013-09-03 15:07:31 -070056{
57 setup_dwc3(exynos_usb_drd_dwc3);
58 printk(BIOS_DEBUG, "DWC3 setup for USB DRD finished\n");
59}
60
61static void setup_drd_phy(struct exynos5_usb_drd_phy *phy)
62{
63 /* Set all PHY registers to default values */
64
65 /* XHCI Version 1.0, Frame Length adjustment 30 MHz */
Julius Werner55009af2019-12-02 22:03:27 -080066 setbits32(&phy->linksystem, 0x1 << 27 | 0x20 << 1);
Julius Werner68aef112013-09-03 15:07:31 -070067
68 /* Disable OTG, ID0 and DRVVBUS, do not force sleep/suspend */
Julius Werner2f37bd62015-02-19 14:51:15 -080069 write32(&phy->utmi, 1 << 6);
Julius Werner68aef112013-09-03 15:07:31 -070070
Julius Werner2f37bd62015-02-19 14:51:15 -080071 write32(&phy->clkrst,
Julius Werner94184762015-02-19 20:19:23 -080072 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 */
Julius Werner68aef112013-09-03 15:07:31 -070081
Julius Werner2f37bd62015-02-19 14:51:15 -080082 write32(&phy->param0,
Julius Werner94184762015-02-19 20:19:23 -080083 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 */
Julius Werner68aef112013-09-03 15:07:31 -070092
Julius Werner2f37bd62015-02-19 14:51:15 -080093 write32(&phy->param1,
Julius Werner94184762015-02-19 20:19:23 -080094 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) */
Julius Werner68aef112013-09-03 15:07:31 -070098
99 /* disable all test features */
Julius Werner2f37bd62015-02-19 14:51:15 -0800100 write32(&phy->test, 0);
Julius Werner68aef112013-09-03 15:07:31 -0700101
102 /* UTMI clock select? ("must be 0x1") */
Julius Werner2f37bd62015-02-19 14:51:15 -0800103 write32(&phy->utmiclksel, 0x1 << 2);
Julius Werner68aef112013-09-03 15:07:31 -0700104
105 /* Samsung magic, undocumented (from U-Boot) */
Julius Werner2f37bd62015-02-19 14:51:15 -0800106 write32(&phy->resume, 0x0);
Julius Werner68aef112013-09-03 15:07:31 -0700107
108 udelay(10);
Julius Werner55009af2019-12-02 22:03:27 -0800109 clrbits32(&phy->clkrst, 0x1 << 1); /* deassert port reset */
Julius Werner68aef112013-09-03 15:07:31 -0700110}
111
Elyes HAOUASbef4ec72022-01-30 11:33:15 +0100112void setup_usb_drd_phy(void)
Julius Werner68aef112013-09-03 15:07:31 -0700113{
114 printk(BIOS_DEBUG, "Powering up USB DRD PHY\n");
Julius Werner55009af2019-12-02 22:03:27 -0800115 setbits32(&exynos_power->usb_drd_phy_ctrl, POWER_USB_PHY_CTRL_EN);
Julius Werner68aef112013-09-03 15:07:31 -0700116 setup_drd_phy(exynos_usb_drd_phy);
117}
118
Julius Werner79bff702013-08-15 17:34:45 -0700119void setup_usb_host_phy(int hsic_gpio)
Stefan Reinauer2ad63c22013-05-17 11:52:45 -0700120{
121 unsigned int hostphy_ctrl0;
122
Julius Werner55009af2019-12-02 22:03:27 -0800123 setbits32(&exynos_sysreg->usb20_phy_cfg, USB20_PHY_CFG_EN);
124 setbits32(&exynos_power->usb_host_phy_ctrl, POWER_USB_PHY_CTRL_EN);
Stefan Reinauer2ad63c22013-05-17 11:52:45 -0700125
Julius Werner79bff702013-08-15 17:34:45 -0700126 printk(BIOS_DEBUG, "Powering up USB HOST PHY (%s HSIC)\n",
127 hsic_gpio ? "with" : "without");
128
Julius Werner2f37bd62015-02-19 14:51:15 -0800129 hostphy_ctrl0 = read32(&exynos_usb_host_phy->usbphyctrl0);
Julius Werner79bff702013-08-15 17:34:45 -0700130 hostphy_ctrl0 &= ~(HOST_CTRL0_FSEL_MASK |
131 HOST_CTRL0_COMMONON_N |
Stefan Reinauer2ad63c22013-05-17 11:52:45 -0700132 /* HOST Phy setting */
133 HOST_CTRL0_PHYSWRST |
134 HOST_CTRL0_PHYSWRSTALL |
135 HOST_CTRL0_SIDDQ |
136 HOST_CTRL0_FORCESUSPEND |
137 HOST_CTRL0_FORCESLEEP);
Julius Werner79bff702013-08-15 17:34:45 -0700138 hostphy_ctrl0 |= (/* Setting up the ref freq */
139 CLK_24MHZ << 16 |
140 /* HOST Phy setting */
141 HOST_CTRL0_LINKSWRST |
142 HOST_CTRL0_UTMISWRST);
Julius Werner2f37bd62015-02-19 14:51:15 -0800143 write32(&exynos_usb_host_phy->usbphyctrl0, hostphy_ctrl0);
Stefan Reinauer2ad63c22013-05-17 11:52:45 -0700144 udelay(10);
Julius Werner55009af2019-12-02 22:03:27 -0800145 clrbits32(&exynos_usb_host_phy->usbphyctrl0,
146 HOST_CTRL0_LINKSWRST |
147 HOST_CTRL0_UTMISWRST);
Stefan Reinauer2ad63c22013-05-17 11:52:45 -0700148 udelay(20);
149
150 /* EHCI Ctrl setting */
Julius Werner55009af2019-12-02 22:03:27 -0800151 setbits32(&exynos_usb_host_phy->ehcictrl,
Stefan Reinauer2ad63c22013-05-17 11:52:45 -0700152 EHCICTRL_ENAINCRXALIGN |
153 EHCICTRL_ENAINCR4 |
Julius Werner79bff702013-08-15 17:34:45 -0700154 EHCICTRL_ENAINCR8 |
155 EHCICTRL_ENAINCR16);
Stefan Reinauer2ad63c22013-05-17 11:52:45 -0700156
157 /* HSIC USB Hub initialization. */
Julius Werner79bff702013-08-15 17:34:45 -0700158 if (hsic_gpio) {
159 gpio_direction_output(hsic_gpio, 0);
160 udelay(100);
161 gpio_direction_output(hsic_gpio, 1);
162 udelay(5000);
Stefan Reinauer2ad63c22013-05-17 11:52:45 -0700163
Julius Werner55009af2019-12-02 22:03:27 -0800164 clrbits32(&exynos_usb_host_phy->hsicphyctrl1,
165 HOST_CTRL0_SIDDQ |
166 HOST_CTRL0_FORCESLEEP |
167 HOST_CTRL0_FORCESUSPEND);
168 setbits32(&exynos_usb_host_phy->hsicphyctrl1,
169 HOST_CTRL0_PHYSWRST);
Julius Werner79bff702013-08-15 17:34:45 -0700170 udelay(10);
Julius Werner55009af2019-12-02 22:03:27 -0800171 clrbits32(&exynos_usb_host_phy->hsicphyctrl1,
172 HOST_CTRL0_PHYSWRST);
Julius Werner79bff702013-08-15 17:34:45 -0700173 }
Stefan Reinauer2ad63c22013-05-17 11:52:45 -0700174
Stefan Reinauer61fcd142013-08-14 17:14:39 -0700175 /* 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
178 * will have passed.
179 */
Stefan Reinauer2ad63c22013-05-17 11:52:45 -0700180}