In USB 3 mode the combo PHY's init only sets COMBO_PHY_SEL. Nothing programs or starts the PHY PLL, so the DWC3 controller gets no PIPE clock and its xHCI reset (USBCMD.HCRST) never completes.
Linux's k1_pcie_phy_init_usb() selects USB 3 mode and zeroes USB3_TEST_CTRL, its combo PHY probe leaves APP_HOLD_PHY_RST clear, and its PLL prepare for USB sets CFG_INTERNAL_TIMER_ADJ to the USB value, selects 5000 ppm spread spectrum and the 24 MHz reference without the 100 MHz SSC input, sets CFG_SW_PHY_INIT_DONE and waits for PLL_READY. Do the same, and also clear CFG_FORCE_RCV_RETRY, which is for PCIe only and may have been left set by an earlier stage. Return -ETIMEDOUT if the PLL does not lock. Do it at power-on rather than at init: the DWC3 glue initializes its USB 3 PHY before it enables the controller's clock and releases its resets, and powers it on afterwards, while Linux starts this PLL with the controller already running. PCIe mode is unchanged. Signed-off-by: Dave Klotz <[email protected]> --- drivers/phy/spacemit/phy-k1-pcie.c | 84 ++++++++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 4 deletions(-) diff --git a/drivers/phy/spacemit/phy-k1-pcie.c b/drivers/phy/spacemit/phy-k1-pcie.c index c3d29d6a2a..6ba8575ef6 100644 --- a/drivers/phy/spacemit/phy-k1-pcie.c +++ b/drivers/phy/spacemit/phy-k1-pcie.c @@ -39,6 +39,7 @@ #define PCIE_PU_ADDR_CLK_CFG 0x0008 #define PLL_READY BIT(0) #define CFG_INTERNAL_TIMER_ADJ GENMASK(10, 7) +#define TIMER_ADJ_USB 0x2 #define TIMER_ADJ_PCIE 0x6 #define CFG_SW_PHY_INIT_DONE BIT(11) @@ -58,6 +59,7 @@ #define FREF_24M 0x1 #define SSC_DEP_SEL GENMASK(19, 16) #define SSC_DEP_NONE 0x0 +#define SSC_DEP_5000PPM 0xa /* PCIe PHY configuration */ #define PCIE_PU_PLL_2 0x004c @@ -80,6 +82,9 @@ #define TX_RTERM_REG GENMASK(15, 12) #define TX_RTERM_SEL BIT(25) +/* Zeroed for the combo PHY operating in USB 3 mode */ +#define USB3_TEST_CTRL 0x0068 + /* PHY calibration values */ #define PCIE_RCAL_RESULT 0x0084 #define RTERM_VALUE_RX GENMASK(3, 0) @@ -216,11 +221,9 @@ static int k1_pcie_phy_init(struct phy *phy) u32 val; int i, lane; - /* If combo PHY is configured for USB 3 mode */ - if (k1_phy->is_combo && phy->id == PHY_TYPE_USB3) { - k1_combo_phy_sel(k1_phy, true); + /* USB 3 mode is set up at power-on, see k1_pcie_phy_power_on() */ + if (k1_phy->is_combo && phy->id == PHY_TYPE_USB3) return 0; - } /* For combo PHY, ensure it's in PCIe mode */ if (k1_phy->is_combo) @@ -364,6 +367,78 @@ static int k1_pcie_phy_init(struct phy *phy) return 0; } +/* Only called for the combo PHY */ +static int k1_combo_phy_usb3_power_on(struct phy *phy) +{ + struct k1_pcie_phy *k1_phy = dev_get_priv(phy->dev); + void __iomem *apmu = k1_phy->apmu_base; + void __iomem *regs = k1_phy->regs; + int ret; + u32 val; + + /* + * Point the lane at the USB 3 controller. Left in PCIe mode, the + * PHY PLL does not lock, the controller gets no PIPE clock and the + * xHCI reset never completes. + */ + k1_combo_phy_sel(k1_phy, true); + + /* Make sure the PHY is not held in reset by the PCIe port A logic */ + val = readl(apmu + PCIE_CLK_RES_CTRL); + val &= ~PCIE_APP_HOLD_PHY_RST; + writel(val, apmu + PCIE_CLK_RES_CTRL); + + /* We're not doing any testing */ + writel(0, regs + USB3_TEST_CTRL); + + /* Configure the PLL for USB 3 */ + val = readl(regs + PCIE_PU_ADDR_CLK_CFG); + val &= ~CFG_INTERNAL_TIMER_ADJ; + val |= FIELD_PREP(CFG_INTERNAL_TIMER_ADJ, TIMER_ADJ_USB); + writel(val, regs + PCIE_PU_ADDR_CLK_CFG); + + /* 5000 ppm spread spectrum, 24 MHz reference, no 100 MHz input */ + val = readl(regs + PCIE_PU_PLL_1); + val &= ~(SSC_DEP_SEL | REF_100_WSSC | FREF_SEL); + val |= FIELD_PREP(SSC_DEP_SEL, SSC_DEP_5000PPM); + val |= FIELD_PREP(FREF_SEL, FREF_24M); + writel(val, regs + PCIE_PU_PLL_1); + + /* Forcing receiver retry is for PCIe only */ + val = readl(regs + PCIE_RC_DONE_STATUS); + val &= ~CFG_FORCE_RCV_RETRY; + writel(val, regs + PCIE_RC_DONE_STATUS); + + /* PLL configuration is done; start the PLL */ + val = readl(regs + PCIE_PU_ADDR_CLK_CFG); + val |= CFG_SW_PHY_INIT_DONE; + writel(val, regs + PCIE_PU_ADDR_CLK_CFG); + + ret = readl_poll_timeout(regs + PCIE_PU_ADDR_CLK_CFG, val, + val & PLL_READY, PLL_TIMEOUT_US); + if (ret) + dev_err(phy->dev, "USB 3 PLL lock timeout, reg[0x08]=0x%08x\n", + val); + + return ret; +} + +/* + * The DWC3 glue initializes its USB 3 PHY before it enables the + * controller's clock and releases its resets, and powers the PHY on + * afterwards. Linux starts the PHY PLL with the controller already + * running, so for USB 3 the PHY is set up here rather than at init. + */ +static int k1_pcie_phy_power_on(struct phy *phy) +{ + struct k1_pcie_phy *k1_phy = dev_get_priv(phy->dev); + + if (k1_phy->is_combo && phy->id == PHY_TYPE_USB3) + return k1_combo_phy_usb3_power_on(phy); + + return 0; +} + static int k1_pcie_phy_exit(struct phy *phy) { return 0; @@ -393,6 +468,7 @@ static int k1_pcie_phy_of_xlate(struct phy *phy, static const struct phy_ops k1_pcie_phy_ops = { .of_xlate = k1_pcie_phy_of_xlate, .init = k1_pcie_phy_init, + .power_on = k1_pcie_phy_power_on, .exit = k1_pcie_phy_exit, }; -- 2.55.0
