The driver gets the clocks and resets listed in the device tree with clk_get_bulk() and reset_get_bulk(), but never enables or deasserts any of them, and only warns if getting them fails. The combo PHY instead clears GLOBAL_PHY_RST by hand in the APMU before calibrating, and ports B and C rely on the PCIe controller driver to do the same for them.
Linux gets the "phy" reset of every K1 PCIe PHY deasserted at probe (devm_reset_control_get_exclusive_deasserted()) and leaves it that way; the "refclk" oscillator is the parent of the PHY PLL and is enabled with it. Do the same here: at probe, before any PHY register is accessed, enable "refclk" and deassert the "phy" reset, and fail the probe if either cannot be got or enabled. The combo PHY's PCIe port A application clocks and resets are not part of this: the calibration handles them, as it does in Linux. The calibration no longer needs to clear GLOBAL_PHY_RST itself, since that is the bit the "phy" reset controls. Signed-off-by: Dave Klotz <[email protected]> --- drivers/phy/spacemit/phy-k1-pcie.c | 69 ++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 19 deletions(-) diff --git a/drivers/phy/spacemit/phy-k1-pcie.c b/drivers/phy/spacemit/phy-k1-pcie.c index e54742a2a9..b445ee9d01 100644 --- a/drivers/phy/spacemit/phy-k1-pcie.c +++ b/drivers/phy/spacemit/phy-k1-pcie.c @@ -92,7 +92,6 @@ #define PCIE_CLK_RES_CTRL 0x03cc #define PCIE_APP_HOLD_PHY_RST BIT(30) #define DEVICE_TYPE_RC BIT(31) -#define GLOBAL_PHY_RST BIT(8) #define APMU_CLK_GATE_MASK 0x3f @@ -107,8 +106,8 @@ struct k1_pcie_phy { void __iomem *apmu_base; /* only for combo PHY */ u32 pcie_lanes; bool is_combo; - struct clk_bulk clks; - struct reset_ctl_bulk rst; + struct clk refclk; + struct reset_ctl phy_rst; }; static bool k1_phy_rterm_valid(void) @@ -155,13 +154,11 @@ int k1_pcie_combo_phy_calibrate(struct udevice *dev, struct k1_pcie_phy *k1_phy) /* * Initialize the APMU control register: set RC mode, enable - * clock gates (bits 0-5), deassert PHY global reset, then - * release the PHY hold. Without this the PHY registers are - * not accessible and reads will hang. + * clock gates (bits 0-5), then release the PHY hold. The PHY + * (global) reset was deasserted at probe. */ val = readl(k1_phy->apmu_base + PCIE_CLK_RES_CTRL); val |= DEVICE_TYPE_RC | PCIE_APP_HOLD_PHY_RST | APMU_CLK_GATE_MASK; - val &= ~GLOBAL_PHY_RST; writel(val, k1_phy->apmu_base + PCIE_CLK_RES_CTRL); val &= ~PCIE_APP_HOLD_PHY_RST; writel(val, k1_phy->apmu_base + PCIE_CLK_RES_CTRL); @@ -384,6 +381,48 @@ static const struct phy_ops k1_pcie_phy_ops = { .exit = k1_pcie_phy_exit, }; +/* + * Enable the 24 MHz reference clock that feeds the PHY PLL, and + * deassert the PHY (global) reset, leaving it deasserted. This must + * happen before any PHY register is accessed. + */ +static int k1_pcie_phy_enable_resources(struct udevice *dev, + struct k1_pcie_phy *k1_phy) +{ + int ret; + + ret = clk_get_by_name(dev, "refclk", &k1_phy->refclk); + if (ret) { + dev_err(dev, "failed to get refclk: %d\n", ret); + return ret; + } + + ret = clk_enable(&k1_phy->refclk); + if (ret) { + dev_err(dev, "failed to enable refclk: %d\n", ret); + return ret; + } + + ret = reset_get_by_name(dev, "phy", &k1_phy->phy_rst); + if (ret) { + dev_err(dev, "failed to get phy reset: %d\n", ret); + goto err_clk; + } + + ret = reset_deassert(&k1_phy->phy_rst); + if (ret) { + dev_err(dev, "failed to deassert phy reset: %d\n", ret); + goto err_clk; + } + + return 0; + +err_clk: + clk_disable(&k1_phy->refclk); + + return ret; +} + static int k1_pcie_phy_probe(struct udevice *dev) { struct k1_pcie_phy *k1_phy = dev_get_priv(dev); @@ -425,13 +464,9 @@ static int k1_pcie_phy_probe(struct udevice *dev) if (!k1_phy->apmu_base) return -EINVAL; - ret = clk_get_bulk(dev, &k1_phy->clks); - if (ret) - dev_warn(dev, "failed to get clocks: %d\n", ret); - - ret = reset_get_bulk(dev, &k1_phy->rst); + ret = k1_pcie_phy_enable_resources(dev, k1_phy); if (ret) - dev_warn(dev, "failed to get resets: %d\n", ret); + return ret; ret = k1_pcie_combo_phy_calibrate(dev, k1_phy); if (ret) @@ -461,13 +496,9 @@ static int k1_pcie_phy_probe(struct udevice *dev) return -ENOENT; } - ret = clk_get_bulk(dev, &k1_phy->clks); + ret = k1_pcie_phy_enable_resources(dev, k1_phy); if (ret) - dev_warn(dev, "failed to get clocks: %d\n", ret); - - ret = reset_get_bulk(dev, &k1_phy->rst); - if (ret) - dev_warn(dev, "failed to get resets: %d\n", ret); + return ret; } dev_dbg(dev, "probed (combo=%d lanes=%u rterm=0x%02x)\n", -- 2.55.0
