diff --git a/src/mainboard/google/gru/mainboard.c b/src/mainboard/google/gru/mainboard.c index ca71dad902..a20103acd4 100644 --- a/src/mainboard/google/gru/mainboard.c +++ b/src/mainboard/google/gru/mainboard.c @@ -164,8 +164,8 @@ static void configure_display(void) static void setup_usb(void) { - setup_usb_drd0_dwc3(); - setup_usb_drd1_dwc3(); + setup_usb_otg0(); + setup_usb_otg1(); } static void setup_rtc(void) diff --git a/src/soc/rockchip/rk3399/include/soc/addressmap.h b/src/soc/rockchip/rk3399/include/soc/addressmap.h index e65674c77c..d316c3805d 100644 --- a/src/soc/rockchip/rk3399/include/soc/addressmap.h +++ b/src/soc/rockchip/rk3399/include/soc/addressmap.h @@ -70,8 +70,10 @@ #define DDRC1_BASE_ADDR 0xffa88000 #define SERVER_MSCH1_BASE_ADDR 0xffa8c000 -#define USB_DRD0_DWC3_BASE 0xfe80c100 -#define USB_DRD1_DWC3_BASE 0xfe90c100 +#define USB_OTG0_DWC3_BASE 0xfe80c100 +#define USB_OTG1_DWC3_BASE 0xfe90c100 +#define USB_OTG0_TCPHY_BASE 0xff7c0000 +#define USB_OTG1_TCPHY_BASE 0xff800000 #define IC_BASES { I2C0_BASE, I2C1_BASE, I2C2_BASE, I2C3_BASE, \ I2C4_BASE, I2C5_BASE, I2C6_BASE, I2C7_BASE, I2C8_BASE } diff --git a/src/soc/rockchip/rk3399/include/soc/usb.h b/src/soc/rockchip/rk3399/include/soc/usb.h index 4276a2b596..46d3752328 100644 --- a/src/soc/rockchip/rk3399/include/soc/usb.h +++ b/src/soc/rockchip/rk3399/include/soc/usb.h @@ -32,11 +32,10 @@ #define DWC3_GCTL_CLK_PIPE (1) #define DWC3_GCTL_CLK_PIPEHALF (2) #define DWC3_GCTL_CLK_MASK (3) -#define DWC3_GCTL_PRTCAP(n) (((n) & (3 << 12)) >> 12) -#define DWC3_GCTL_PRTCAPDIR(n) ((n) << 12) -#define DWC3_GCTL_PRTCAP_HOST 1 -#define DWC3_GCTL_PRTCAP_DEVICE 2 -#define DWC3_GCTL_PRTCAP_OTG 3 +#define DWC3_GCTL_PRTCAP_MASK (3 << 12) +#define DWC3_GCTL_PRTCAP_HOST (1 << 12) +#define DWC3_GCTL_PRTCAP_DEVICE (2 << 12) +#define DWC3_GCTL_PRTCAP_OTG (3 << 12) #define DWC3_GCTL_CORESOFTRESET (1 << 11) #define DWC3_GCTL_SCALEDOWN(n) ((n) << 4) #define DWC3_GCTL_SCALEDOWN_MASK DWC3_GCTL_SCALEDOWN(3) @@ -63,7 +62,7 @@ #define DWC3_GUSB3PIPECTL_PHYSOFTRST (1 << 31) #define DWC3_GUSB3PIPECTL_SUSPHY (1 << 17) -struct rockchip_usb_drd_dwc3 { +struct rockchip_usb_dwc3 { uint32_t sbuscfg0; uint32_t sbuscfg1; uint32_t txthrcfg; @@ -107,15 +106,22 @@ struct rockchip_usb_drd_dwc3 { uint8_t reserved6[60]; }; -static struct rockchip_usb_drd_dwc3 * const rockchip_usb_drd0_dwc3 = - (void *)USB_DRD0_DWC3_BASE; -static struct rockchip_usb_drd_dwc3 * const rockchip_usb_drd1_dwc3 = - (void *)USB_DRD1_DWC3_BASE; +static struct rockchip_usb_dwc3 * const rockchip_usb_otg0_dwc3 = + (void *)USB_OTG0_DWC3_BASE; +static struct rockchip_usb_dwc3 * const rockchip_usb_otg1_dwc3 = + (void *)USB_OTG1_DWC3_BASE; -/* Call reset _ before setup_ */ -void reset_usb_drd0_dwc3(void); -void reset_usb_drd1_dwc3(void); -void setup_usb_drd0_dwc3(void); -void setup_usb_drd1_dwc3(void); +/* 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)) + +/* Call reset_ before setup_ */ +void reset_usb_otg0(void); +void reset_usb_otg1(void); +void setup_usb_otg0(void); +void setup_usb_otg1(void); #endif /* __SOC_ROCKCHIP_RK3399_USB_H_ */ diff --git a/src/soc/rockchip/rk3399/romstage.c b/src/soc/rockchip/rk3399/romstage.c index 11454d3d04..8adaa7cef6 100644 --- a/src/soc/rockchip/rk3399/romstage.c +++ b/src/soc/rockchip/rk3399/romstage.c @@ -97,8 +97,8 @@ static void prepare_usb(void) * Do dwc3 core soft reset and phy reset. Kick these resets * off early so they get at least 100ms to settle. */ - reset_usb_drd0_dwc3(); - reset_usb_drd1_dwc3(); + reset_usb_otg0(); + reset_usb_otg1(); } void main(void) diff --git a/src/soc/rockchip/rk3399/usb.c b/src/soc/rockchip/rk3399/usb.c index df0305f8c3..f638a1ece2 100644 --- a/src/soc/rockchip/rk3399/usb.c +++ b/src/soc/rockchip/rk3399/usb.c @@ -14,57 +14,58 @@ */ #include +#include #include #include #include -static void reset_dwc3(struct rockchip_usb_drd_dwc3 *dwc3_reg) +/* 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) { - /* Before Resetting PHY, put Core in Reset */ - setbits_le32(&dwc3_reg->ctl, DWC3_GCTL_CORESOFTRESET); - /* Assert USB3 PHY reset */ - setbits_le32(&dwc3_reg->usb3pipectl, DWC3_GUSB3PIPECTL_PHYSOFTRST); - /* Assert USB2 PHY reset */ - setbits_le32(&dwc3_reg->usb2phycfg, DWC3_GUSB2PHYCFG_PHYSOFTRST); + write32((void *)(base + TCPHY_ISOLATION_CTRL_OFFSET), + TCPHY_ISOLATION_CTRL_EN | + TCPHY_ISOLATION_CTRL_CMN_EN | + TCPHY_ISOLATION_CTRL_MODE_SEL | + TCPHY_ISOLATION_CTRL_LN_EN(7) | + TCPHY_ISOLATION_CTRL_LN_EN(6) | + TCPHY_ISOLATION_CTRL_LN_EN(5) | + TCPHY_ISOLATION_CTRL_LN_EN(4) | + TCPHY_ISOLATION_CTRL_LN_EN(3) | + TCPHY_ISOLATION_CTRL_LN_EN(2) | + TCPHY_ISOLATION_CTRL_LN_EN(1) | + TCPHY_ISOLATION_CTRL_LN_EN(0)); } -static void setup_dwc3(struct rockchip_usb_drd_dwc3 *dwc3_reg) +static void reset_dwc3(struct rockchip_usb_dwc3 *dwc3) { - u32 reg; - u32 revision; - u32 dwc3_hwparams1; + /* Before Resetting PHY, put Core in Reset */ + setbits_le32(&dwc3->ctl, DWC3_GCTL_CORESOFTRESET); + /* Assert USB3 PHY reset */ + setbits_le32(&dwc3->usb3pipectl, DWC3_GUSB3PIPECTL_PHYSOFTRST); + /* Assert USB2 PHY reset */ + setbits_le32(&dwc3->usb2phycfg, DWC3_GUSB2PHYCFG_PHYSOFTRST); +} - /* Clear USB3 PHY reset */ - clrbits_le32(&dwc3_reg->usb3pipectl, DWC3_GUSB3PIPECTL_PHYSOFTRST); - /* Clear USB2 PHY reset */ - clrbits_le32(&dwc3_reg->usb2phycfg, DWC3_GUSB2PHYCFG_PHYSOFTRST); - /* After PHYs are stable we can take Core out of reset state */ - clrbits_le32(&dwc3_reg->ctl, DWC3_GCTL_CORESOFTRESET); +static void setup_dwc3(struct rockchip_usb_dwc3 *dwc3) +{ + u32 usb2phycfg = read32(&dwc3->usb2phycfg); + u32 ctl = read32(&dwc3->ctl); - revision = read32(&dwc3_reg->snpsid); - /* This should read as U3 followed by revision number */ - if ((revision & DWC3_GSNPSID_MASK) != 0x55330000) { - printk(BIOS_ERR, "ERROR: not a DesignWare USB3 DRD Core\n"); - return; - } + /* Ensure reset_dwc3() has been called before this. */ + assert(ctl & DWC3_GCTL_CORESOFTRESET); - dwc3_hwparams1 = read32(&dwc3_reg->hwparams1); + /* Clear USB3 PHY reset (oddly enough, this is really necessary). */ + clrbits_le32(&dwc3->usb3pipectl, DWC3_GUSB3PIPECTL_PHYSOFTRST); - reg = read32(&dwc3_reg->ctl); - reg &= ~DWC3_GCTL_SCALEDOWN_MASK; - reg &= ~DWC3_GCTL_DISSCRAMBLE; - if (DWC3_GHWPARAMS1_EN_PWROPT(dwc3_hwparams1) == - DWC3_GHWPARAMS1_EN_PWROPT_CLK) - reg &= ~DWC3_GCTL_DSBLCLKGTNG; - else - printk(BIOS_DEBUG, "No power optimization available\n"); - - write32(&dwc3_reg->ctl, reg); + /* Clear USB2 PHY and core reset. */ + usb2phycfg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; + ctl &= ~DWC3_GCTL_CORESOFTRESET; /* We are hard-coding DWC3 core to Host Mode */ - clrsetbits_le32(&dwc3_reg->ctl, - DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG), - DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_HOST)); + ctl &= ~DWC3_GCTL_PRTCAP_MASK; + ctl |= DWC3_GCTL_PRTCAP_HOST; + /* * Configure USB phy interface of DWC3 core. * For Rockchip rk3399 SOC DWC3 core: @@ -73,35 +74,38 @@ static void setup_dwc3(struct rockchip_usb_drd_dwc3 *dwc3_reg) * 3. Set USBTRDTIM to the corresponding value * according to the UTMI+ PHY interface. */ - reg = read32(&dwc3_reg->usb2phycfg); - reg &= ~(DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS | - DWC3_GUSB2PHYCFG_USB2TRDTIM_MASK | - DWC3_GUSB2PHYCFG_PHYIF_MASK); - reg |= DWC3_GUSB2PHYCFG_PHYIF(1) | - DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_16_BIT); - write32(&dwc3_reg->usb2phycfg, reg); + usb2phycfg &= ~(DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS | + DWC3_GUSB2PHYCFG_USB2TRDTIM_MASK | + DWC3_GUSB2PHYCFG_PHYIF_MASK); + usb2phycfg |= DWC3_GUSB2PHYCFG_PHYIF(1) | + DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_16_BIT); + + write32(&dwc3->usb2phycfg, usb2phycfg); + write32(&dwc3->ctl, ctl); } -void reset_usb_drd0_dwc3(void) +void reset_usb_otg0(void) { - printk(BIOS_DEBUG, "Starting DWC3 reset for USB DRD0\n"); - reset_dwc3(rockchip_usb_drd0_dwc3); + printk(BIOS_DEBUG, "Starting DWC3 reset for USB OTG0\n"); + reset_dwc3(rockchip_usb_otg0_dwc3); } -void reset_usb_drd1_dwc3(void) +void reset_usb_otg1(void) { - printk(BIOS_DEBUG, "Starting DWC3 reset for USB DRD1\n"); - reset_dwc3(rockchip_usb_drd1_dwc3); + printk(BIOS_DEBUG, "Starting DWC3 reset for USB OTG1\n"); + reset_dwc3(rockchip_usb_otg1_dwc3); } -void setup_usb_drd0_dwc3(void) +void setup_usb_otg0(void) { - setup_dwc3(rockchip_usb_drd0_dwc3); - printk(BIOS_DEBUG, "DWC3 setup for USB DRD0 finished\n"); + isolate_tcphy(USB_OTG0_TCPHY_BASE); + setup_dwc3(rockchip_usb_otg0_dwc3); + printk(BIOS_DEBUG, "DWC3 setup for USB OTG0 finished\n"); } -void setup_usb_drd1_dwc3(void) +void setup_usb_otg1(void) { - setup_dwc3(rockchip_usb_drd1_dwc3); - printk(BIOS_DEBUG, "DWC3 setup for USB DRD1 finished\n"); + isolate_tcphy(USB_OTG1_TCPHY_BASE); + setup_dwc3(rockchip_usb_otg1_dwc3); + printk(BIOS_DEBUG, "DWC3 setup for USB OTG1 finished\n"); }