rockchip/rk3399: Add Type-C PHY init
Though we don't use Type-C PHY to support USB3 in firmware, we still need to initialize the Type-C PHY, and make sure the power state of pipe is always fixed to U2/P2. After this, we can force USB3 controller to work in USB2 only mode. BRANCH=none BUG=chrome-os-partner:56425 TEST=Go to recovery mode, plug a Type-C USB drive containing chrome OS image into both ports in all orientations, check if system can boot from USB. Change-Id: I95bb96ff27d4fecafb7b2b9e9dc2839b5c132654 Signed-off-by: Patrick Georgi <pgeorgi@chromium.org> Original-Commit-Id: 8ec98507845276119d8a9d5626934dedcb35f2dd Original-Change-Id: Ie3654cd1c1cb76b62aa9b247879b60cbecee0155 Original-Signed-off-by: William wu <wulf@rock-chips.com> Original-Reviewed-on: https://chromium-review.googlesource.com/391412 Original-Commit-Ready: Julius Werner <jwerner@chromium.org> Original-Tested-by: Julius Werner <jwerner@chromium.org> Original-Reviewed-by: Julius Werner <jwerner@chromium.org> Reviewed-on: https://review.coreboot.org/16910 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth <martinroth@google.com>
This commit is contained in:
parent
aa9df0f0de
commit
801a8ef2c3
|
@ -111,12 +111,41 @@ static struct rockchip_usb_dwc3 * const rockchip_usb_otg0_dwc3 =
|
|||
static struct rockchip_usb_dwc3 * const rockchip_usb_otg1_dwc3 =
|
||||
(void *)USB_OTG1_DWC3_BASE;
|
||||
|
||||
/* TODO: define struct overlay if we ever need more registers from this */
|
||||
#define TCPHY_ISOLATION_CTRL_OFFSET 0x3207c
|
||||
#define TCPHY_ISOLATION_CTRL_EN (1 << 15)
|
||||
#define TCPHY_ISOLATION_CTRL_CMN_EN (1 << 14)
|
||||
#define TCPHY_ISOLATION_CTRL_MODE_SEL (1 << 12)
|
||||
#define TCPHY_ISOLATION_CTRL_LN_EN(ln) (1 << (ln))
|
||||
#define TCPHY_CMN_HSCLK_PLL_CONFIG 0x30
|
||||
#define TCPHY_CMN_HSCLK_PLL_MASK 0x33
|
||||
|
||||
struct rk3399_tcphy {
|
||||
uint8_t _res0[0x780 - 0x0];
|
||||
uint32_t cmn_diag_hsclk_sel;
|
||||
uint8_t _res1[0x10000 - 0x784];
|
||||
struct {
|
||||
uint8_t _res2[0x3c8 - 0x0];
|
||||
uint32_t xcvr_diag_lane_fcm_en_mgn;
|
||||
uint8_t _res3[0x408 - 0x3cc];
|
||||
uint32_t tx_psc_a2;
|
||||
uint8_t _res4[0x488 - 0x40c];
|
||||
uint32_t tx_rcvdet_en_tmr;
|
||||
uint32_t tx_rcvdet_st_tmr;
|
||||
uint8_t _res5[0x784 - 0x490];
|
||||
uint32_t tx_diag_tx_drv;
|
||||
uint8_t _res6[0x800 - 0x788];
|
||||
} lane[4];
|
||||
uint8_t _res7[0x32000 - 0x12000];
|
||||
uint32_t pma_cmn_ctrl1;
|
||||
uint8_t _res8[0x3207c - 0x32004];
|
||||
uint32_t isolation_ctrl;
|
||||
};
|
||||
check_member(rk3399_tcphy, lane[2].tx_diag_tx_drv, 0x11784);
|
||||
check_member(rk3399_tcphy, isolation_ctrl, 0x3207c);
|
||||
|
||||
static struct rk3399_tcphy * const rockchip_usb_otg0_phy =
|
||||
(void *)USB_OTG0_TCPHY_BASE;
|
||||
static struct rk3399_tcphy * const rockchip_usb_otg1_phy =
|
||||
(void *)USB_OTG1_TCPHY_BASE;
|
||||
|
||||
/* Call reset_ before setup_ */
|
||||
void reset_usb_otg0(void);
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue