blob: 5d43f688032fd2a2c2d3dd64cc79a79d5d2e92f8 [file] [log] [blame]
Angel Ponsbbc99cf2020-04-04 18:51:23 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Liangfeng Wu76655cb2016-05-26 16:06:58 +08002
Kyösti Mälkki13f66502019-03-03 08:01:05 +02003#include <device/mmio.h>
Julius Werner785ff1b2016-08-03 19:18:39 -07004#include <assert.h>
Liangfeng Wu76655cb2016-05-26 16:06:58 +08005#include <console/console.h>
Liangfeng Wu737a7cc2016-09-15 17:16:54 +08006#include <soc/clock.h>
7#include <soc/grf.h>
8#include <soc/soc.h>
Liangfeng Wu76655cb2016-05-26 16:06:58 +08009#include <soc/usb.h>
10
Julius Werner785ff1b2016-08-03 19:18:39 -070011/* SuperSpeed over Type-C is hard. We don't care about speed in firmware: just
12 * gate off the SuperSpeed lines to have an unimpaired USB 2.0 connection. */
William wu801a8ef2016-10-01 20:58:21 +080013static void isolate_tcphy(struct rk3399_tcphy *tcphy)
Liangfeng Wu76655cb2016-05-26 16:06:58 +080014{
William wu801a8ef2016-10-01 20:58:21 +080015 write32(&tcphy->isolation_ctrl,
Julius Werner785ff1b2016-08-03 19:18:39 -070016 TCPHY_ISOLATION_CTRL_EN |
17 TCPHY_ISOLATION_CTRL_CMN_EN |
18 TCPHY_ISOLATION_CTRL_MODE_SEL |
19 TCPHY_ISOLATION_CTRL_LN_EN(7) |
20 TCPHY_ISOLATION_CTRL_LN_EN(6) |
21 TCPHY_ISOLATION_CTRL_LN_EN(5) |
22 TCPHY_ISOLATION_CTRL_LN_EN(4) |
23 TCPHY_ISOLATION_CTRL_LN_EN(3) |
24 TCPHY_ISOLATION_CTRL_LN_EN(2) |
25 TCPHY_ISOLATION_CTRL_LN_EN(1) |
26 TCPHY_ISOLATION_CTRL_LN_EN(0));
Liangfeng Wu76655cb2016-05-26 16:06:58 +080027}
28
William wu801a8ef2016-10-01 20:58:21 +080029static void tcphy_cfg_24m(struct rk3399_tcphy *tcphy)
30{
31 u32 i;
32
33 /* cmn_ref_clk_sel = 3, select the 24Mhz for clk parent
34 * cmn_psm_clk_dig_div = 2, set the clk division to 2 */
35 write32(&tcphy->pma_cmn_ctrl1, 2 << 10 | 3 << 4);
36 for (i = 0; i < 4; i++) {
37 /* The following PHY configuration assumes a
38 * 24 MHz reference clock */
39 write32(&tcphy->lane[i].xcvr_diag_lane_fcm_en_mgn, 0x90);
40 write32(&tcphy->lane[i].tx_rcvdet_en_tmr, 0x960);
41 write32(&tcphy->lane[i].tx_rcvdet_st_tmr, 0x30);
42 }
43
Julius Werner55009af2019-12-02 22:03:27 -080044 clrsetbits32(&tcphy->cmn_diag_hsclk_sel,
45 TCPHY_CMN_HSCLK_PLL_MASK, TCPHY_CMN_HSCLK_PLL_CONFIG);
William wu801a8ef2016-10-01 20:58:21 +080046}
47
48static void tcphy_phy_init(struct rk3399_tcphy *tcphy)
49{
50 u32 i;
51
52 tcphy_cfg_24m(tcphy);
53
54 for (i = 0; i < 4; i++) {
55 /* Enable transmitter reset pull down override for all lanes*/
56 write32(&tcphy->lane[i].tx_diag_tx_drv, 0x2000);
57 /* Disable transmitter low current mode, disable TX
58 * driver common mode, disable TX post-emphasis*/
59 write32(&tcphy->lane[i].tx_psc_a2, 0x0000);
60 }
61
62 isolate_tcphy(tcphy);
63}
64
Julius Werner785ff1b2016-08-03 19:18:39 -070065static void reset_dwc3(struct rockchip_usb_dwc3 *dwc3)
Liangfeng Wu76655cb2016-05-26 16:06:58 +080066{
Julius Werner785ff1b2016-08-03 19:18:39 -070067 /* Before Resetting PHY, put Core in Reset */
Julius Werner55009af2019-12-02 22:03:27 -080068 setbits32(&dwc3->ctl, DWC3_GCTL_CORESOFTRESET);
Julius Werner785ff1b2016-08-03 19:18:39 -070069 /* Assert USB3 PHY reset */
Julius Werner55009af2019-12-02 22:03:27 -080070 setbits32(&dwc3->usb3pipectl, DWC3_GUSB3PIPECTL_PHYSOFTRST);
Julius Werner785ff1b2016-08-03 19:18:39 -070071 /* Assert USB2 PHY reset */
Julius Werner55009af2019-12-02 22:03:27 -080072 setbits32(&dwc3->usb2phycfg, DWC3_GUSB2PHYCFG_PHYSOFTRST);
Julius Werner785ff1b2016-08-03 19:18:39 -070073}
Liangfeng Wu76655cb2016-05-26 16:06:58 +080074
Julius Werner785ff1b2016-08-03 19:18:39 -070075static void setup_dwc3(struct rockchip_usb_dwc3 *dwc3)
76{
77 u32 usb2phycfg = read32(&dwc3->usb2phycfg);
78 u32 ctl = read32(&dwc3->ctl);
Liangfeng Wu76655cb2016-05-26 16:06:58 +080079
Julius Werner785ff1b2016-08-03 19:18:39 -070080 /* Ensure reset_dwc3() has been called before this. */
81 assert(ctl & DWC3_GCTL_CORESOFTRESET);
Liangfeng Wu76655cb2016-05-26 16:06:58 +080082
Julius Werner785ff1b2016-08-03 19:18:39 -070083 /* Clear USB3 PHY reset (oddly enough, this is really necessary). */
Julius Werner55009af2019-12-02 22:03:27 -080084 clrbits32(&dwc3->usb3pipectl, DWC3_GUSB3PIPECTL_PHYSOFTRST);
Liangfeng Wu76655cb2016-05-26 16:06:58 +080085
Julius Werner785ff1b2016-08-03 19:18:39 -070086 /* Clear USB2 PHY and core reset. */
87 usb2phycfg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST;
88 ctl &= ~DWC3_GCTL_CORESOFTRESET;
Liangfeng Wu76655cb2016-05-26 16:06:58 +080089
90 /* We are hard-coding DWC3 core to Host Mode */
Julius Werner785ff1b2016-08-03 19:18:39 -070091 ctl &= ~DWC3_GCTL_PRTCAP_MASK;
92 ctl |= DWC3_GCTL_PRTCAP_HOST;
93
Liangfeng Wu76655cb2016-05-26 16:06:58 +080094 /*
95 * Configure USB phy interface of DWC3 core.
96 * For Rockchip rk3399 SOC DWC3 core:
97 * 1. Clear U2_FREECLK_EXITS.
98 * 2. Select UTMI+ PHY with 16-bit interface.
99 * 3. Set USBTRDTIM to the corresponding value
100 * according to the UTMI+ PHY interface.
101 */
Julius Werner785ff1b2016-08-03 19:18:39 -0700102 usb2phycfg &= ~(DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS |
103 DWC3_GUSB2PHYCFG_USB2TRDTIM_MASK |
104 DWC3_GUSB2PHYCFG_PHYIF_MASK);
105 usb2phycfg |= DWC3_GUSB2PHYCFG_PHYIF(1) |
106 DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_16_BIT);
107
108 write32(&dwc3->usb2phycfg, usb2phycfg);
109 write32(&dwc3->ctl, ctl);
Liangfeng Wu76655cb2016-05-26 16:06:58 +0800110}
111
Julius Werner785ff1b2016-08-03 19:18:39 -0700112void reset_usb_otg0(void)
Liangfeng Wu76655cb2016-05-26 16:06:58 +0800113{
William wu801a8ef2016-10-01 20:58:21 +0800114 printk(BIOS_DEBUG, "Starting DWC3 and TCPHY reset for USB OTG0\n");
115
Liangfeng Wu737a7cc2016-09-15 17:16:54 +0800116 /* Keep whole USB OTG0 controller in reset, then
117 * configure controller to work in USB 2.0 only mode. */
118 write32(&cru_ptr->softrst_con[18], RK_SETBITS(1 << 5));
119 write32(&rk3399_grf->usb3otg0_con1, RK_CLRSETBITS(0xf << 12, 1 << 0));
120 write32(&cru_ptr->softrst_con[18], RK_CLRBITS(1 << 5));
121
William wu801a8ef2016-10-01 20:58:21 +0800122 tcphy_phy_init(rockchip_usb_otg0_phy);
123
124 /* Clear TCPHY0 reset */
125 write32(&cru_ptr->softrst_con[9], RK_CLRBITS(1 << 5));
126
Julius Werner785ff1b2016-08-03 19:18:39 -0700127 reset_dwc3(rockchip_usb_otg0_dwc3);
Liangfeng Wu76655cb2016-05-26 16:06:58 +0800128}
129
Julius Werner785ff1b2016-08-03 19:18:39 -0700130void reset_usb_otg1(void)
Liangfeng Wu76655cb2016-05-26 16:06:58 +0800131{
William wu801a8ef2016-10-01 20:58:21 +0800132 printk(BIOS_DEBUG, "Starting DWC3 and TCPHY reset for USB OTG1\n");
133
Liangfeng Wu737a7cc2016-09-15 17:16:54 +0800134 /* Keep whole USB OTG1 controller in reset, then
135 * configure controller to work in USB 2.0 only mode. */
136 write32(&cru_ptr->softrst_con[18], RK_SETBITS(1 << 6));
137 write32(&rk3399_grf->usb3otg1_con1, RK_CLRSETBITS(0xf << 12, 1 << 0));
138 write32(&cru_ptr->softrst_con[18], RK_CLRBITS(1 << 6));
139
William wu801a8ef2016-10-01 20:58:21 +0800140 tcphy_phy_init(rockchip_usb_otg1_phy);
141
142 /* Clear TCPHY1 reset */
143 write32(&cru_ptr->softrst_con[9], RK_CLRBITS(1 << 13));
144
Julius Werner785ff1b2016-08-03 19:18:39 -0700145 reset_dwc3(rockchip_usb_otg1_dwc3);
Liangfeng Wu76655cb2016-05-26 16:06:58 +0800146}
147
Julius Werner785ff1b2016-08-03 19:18:39 -0700148void setup_usb_otg0(void)
Liangfeng Wu76655cb2016-05-26 16:06:58 +0800149{
William wu801a8ef2016-10-01 20:58:21 +0800150 /* Clear pipe reset */
151 write32(&cru_ptr->softrst_con[9], RK_CLRBITS(1 << 4));
152
Julius Werner785ff1b2016-08-03 19:18:39 -0700153 setup_dwc3(rockchip_usb_otg0_dwc3);
William wu801a8ef2016-10-01 20:58:21 +0800154 printk(BIOS_DEBUG, "DWC3 and TCPHY setup for USB OTG0 finished\n");
Liangfeng Wu76655cb2016-05-26 16:06:58 +0800155}
156
Julius Werner785ff1b2016-08-03 19:18:39 -0700157void setup_usb_otg1(void)
Liangfeng Wu76655cb2016-05-26 16:06:58 +0800158{
William wu801a8ef2016-10-01 20:58:21 +0800159 /* Clear pipe reset */
160 write32(&cru_ptr->softrst_con[9], RK_CLRBITS(1 << 12));
161
Julius Werner785ff1b2016-08-03 19:18:39 -0700162 setup_dwc3(rockchip_usb_otg1_dwc3);
William wu801a8ef2016-10-01 20:58:21 +0800163 printk(BIOS_DEBUG, "DWC3 and TCPHY setup for USB OTG1 finished\n");
Liangfeng Wu76655cb2016-05-26 16:06:58 +0800164}