summaryrefslogtreecommitdiff
path: root/src/soc/rockchip/rk3399/usb.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc/rockchip/rk3399/usb.c')
-rw-r--r--src/soc/rockchip/rk3399/usb.c68
1 files changed, 60 insertions, 8 deletions
diff --git a/src/soc/rockchip/rk3399/usb.c b/src/soc/rockchip/rk3399/usb.c
index 4c731bdf17..e6db1e0d6a 100644
--- a/src/soc/rockchip/rk3399/usb.c
+++ b/src/soc/rockchip/rk3399/usb.c
@@ -24,9 +24,9 @@
/* SuperSpeed over Type-C is hard. We don't care about speed in firmware: just
* gate off the SuperSpeed lines to have an unimpaired USB 2.0 connection. */
-static void isolate_tcphy(uintptr_t base)
+static void isolate_tcphy(struct rk3399_tcphy *tcphy)
{
- write32((void *)(base + TCPHY_ISOLATION_CTRL_OFFSET),
+ write32(&tcphy->isolation_ctrl,
TCPHY_ISOLATION_CTRL_EN |
TCPHY_ISOLATION_CTRL_CMN_EN |
TCPHY_ISOLATION_CTRL_MODE_SEL |
@@ -40,6 +40,42 @@ static void isolate_tcphy(uintptr_t base)
TCPHY_ISOLATION_CTRL_LN_EN(0));
}
+static void tcphy_cfg_24m(struct rk3399_tcphy *tcphy)
+{
+ u32 i;
+
+ /* cmn_ref_clk_sel = 3, select the 24Mhz for clk parent
+ * cmn_psm_clk_dig_div = 2, set the clk division to 2 */
+ write32(&tcphy->pma_cmn_ctrl1, 2 << 10 | 3 << 4);
+ for (i = 0; i < 4; i++) {
+ /* The following PHY configuration assumes a
+ * 24 MHz reference clock */
+ write32(&tcphy->lane[i].xcvr_diag_lane_fcm_en_mgn, 0x90);
+ write32(&tcphy->lane[i].tx_rcvdet_en_tmr, 0x960);
+ write32(&tcphy->lane[i].tx_rcvdet_st_tmr, 0x30);
+ }
+
+ clrsetbits_le32(&tcphy->cmn_diag_hsclk_sel,
+ TCPHY_CMN_HSCLK_PLL_MASK, TCPHY_CMN_HSCLK_PLL_CONFIG);
+}
+
+static void tcphy_phy_init(struct rk3399_tcphy *tcphy)
+{
+ u32 i;
+
+ tcphy_cfg_24m(tcphy);
+
+ for (i = 0; i < 4; i++) {
+ /* Enable transmitter reset pull down override for all lanes*/
+ write32(&tcphy->lane[i].tx_diag_tx_drv, 0x2000);
+ /* Disable transmitter low current mode, disable TX
+ * driver common mode, disable TX post-emphasis*/
+ write32(&tcphy->lane[i].tx_psc_a2, 0x0000);
+ }
+
+ isolate_tcphy(tcphy);
+}
+
static void reset_dwc3(struct rockchip_usb_dwc3 *dwc3)
{
/* Before Resetting PHY, put Core in Reset */
@@ -89,38 +125,54 @@ static void setup_dwc3(struct rockchip_usb_dwc3 *dwc3)
void reset_usb_otg0(void)
{
+ printk(BIOS_DEBUG, "Starting DWC3 and TCPHY reset for USB OTG0\n");
+
/* Keep whole USB OTG0 controller in reset, then
* configure controller to work in USB 2.0 only mode. */
write32(&cru_ptr->softrst_con[18], RK_SETBITS(1 << 5));
write32(&rk3399_grf->usb3otg0_con1, RK_CLRSETBITS(0xf << 12, 1 << 0));
write32(&cru_ptr->softrst_con[18], RK_CLRBITS(1 << 5));
- printk(BIOS_DEBUG, "Starting DWC3 reset for USB OTG0\n");
+ tcphy_phy_init(rockchip_usb_otg0_phy);
+
+ /* Clear TCPHY0 reset */
+ write32(&cru_ptr->softrst_con[9], RK_CLRBITS(1 << 5));
+
reset_dwc3(rockchip_usb_otg0_dwc3);
}
void reset_usb_otg1(void)
{
+ printk(BIOS_DEBUG, "Starting DWC3 and TCPHY reset for USB OTG1\n");
+
/* Keep whole USB OTG1 controller in reset, then
* configure controller to work in USB 2.0 only mode. */
write32(&cru_ptr->softrst_con[18], RK_SETBITS(1 << 6));
write32(&rk3399_grf->usb3otg1_con1, RK_CLRSETBITS(0xf << 12, 1 << 0));
write32(&cru_ptr->softrst_con[18], RK_CLRBITS(1 << 6));
- printk(BIOS_DEBUG, "Starting DWC3 reset for USB OTG1\n");
+ tcphy_phy_init(rockchip_usb_otg1_phy);
+
+ /* Clear TCPHY1 reset */
+ write32(&cru_ptr->softrst_con[9], RK_CLRBITS(1 << 13));
+
reset_dwc3(rockchip_usb_otg1_dwc3);
}
void setup_usb_otg0(void)
{
- isolate_tcphy(USB_OTG0_TCPHY_BASE);
+ /* Clear pipe reset */
+ write32(&cru_ptr->softrst_con[9], RK_CLRBITS(1 << 4));
+
setup_dwc3(rockchip_usb_otg0_dwc3);
- printk(BIOS_DEBUG, "DWC3 setup for USB OTG0 finished\n");
+ printk(BIOS_DEBUG, "DWC3 and TCPHY setup for USB OTG0 finished\n");
}
void setup_usb_otg1(void)
{
- isolate_tcphy(USB_OTG1_TCPHY_BASE);
+ /* Clear pipe reset */
+ write32(&cru_ptr->softrst_con[9], RK_CLRBITS(1 << 12));
+
setup_dwc3(rockchip_usb_otg1_dwc3);
- printk(BIOS_DEBUG, "DWC3 setup for USB OTG1 finished\n");
+ printk(BIOS_DEBUG, "DWC3 and TCPHY setup for USB OTG1 finished\n");
}