]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
PCI: imx6: Add PLL lock check for i.MX95 SoC
authorRichard Zhu <hongxing.zhu@nxp.com>
Wed, 16 Apr 2025 08:13:13 +0000 (16:13 +0800)
committerManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Sun, 27 Apr 2025 11:46:32 +0000 (17:16 +0530)
PLL lock is required to ensure that the PLL clock is stable before enabling
the controller in i.MX95 SoC.

Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
[mani: subject and description rewording]
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Link: https://patch.msgid.link/20250416081314.3929794-7-hongxing.zhu@nxp.com
drivers/pci/controller/dwc/pci-imx6.c

index 7dcc9d88740d87cab9338fe20bd0b797cf76ddee..4cff667949902980268795681c6e3acf9fabb5f3 100644 (file)
@@ -45,6 +45,9 @@
 #define IMX95_PCIE_PHY_GEN_CTRL                        0x0
 #define IMX95_PCIE_REF_USE_PAD                 BIT(17)
 
+#define IMX95_PCIE_PHY_MPLLA_CTRL              0x10
+#define IMX95_PCIE_PHY_MPLL_STATE              BIT(30)
+
 #define IMX95_PCIE_SS_RW_REG_0                 0xf0
 #define IMX95_PCIE_REF_CLKEN                   BIT(23)
 #define IMX95_PCIE_PHY_CR_PARA_SEL             BIT(9)
@@ -132,6 +135,7 @@ struct imx_pcie_drvdata {
        int (*init_phy)(struct imx_pcie *pcie);
        int (*enable_ref_clk)(struct imx_pcie *pcie, bool enable);
        int (*core_reset)(struct imx_pcie *pcie, bool assert);
+       int (*wait_pll_lock)(struct imx_pcie *pcie);
        const struct dw_pcie_host_ops *ops;
 };
 
@@ -479,6 +483,23 @@ static void imx7d_pcie_wait_for_phy_pll_lock(struct imx_pcie *imx_pcie)
                dev_err(dev, "PCIe PLL lock timeout\n");
 }
 
+static int imx95_pcie_wait_for_phy_pll_lock(struct imx_pcie *imx_pcie)
+{
+       u32 val;
+       struct device *dev = imx_pcie->pci->dev;
+
+       if (regmap_read_poll_timeout(imx_pcie->iomuxc_gpr,
+                                    IMX95_PCIE_PHY_MPLLA_CTRL, val,
+                                    val & IMX95_PCIE_PHY_MPLL_STATE,
+                                    PHY_PLL_LOCK_WAIT_USLEEP_MAX,
+                                    PHY_PLL_LOCK_WAIT_TIMEOUT)) {
+               dev_err(dev, "PCIe PLL lock timeout\n");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
 static int imx_setup_phy_mpll(struct imx_pcie *imx_pcie)
 {
        unsigned long phy_rate = 0;
@@ -1225,6 +1246,12 @@ static int imx_pcie_host_init(struct dw_pcie_rp *pp)
                goto err_phy_off;
        }
 
+       if (imx_pcie->drvdata->wait_pll_lock) {
+               ret = imx_pcie->drvdata->wait_pll_lock(imx_pcie);
+               if (ret < 0)
+                       goto err_phy_off;
+       }
+
        imx_setup_phy_mpll(imx_pcie);
 
        return 0;
@@ -1826,6 +1853,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
                .mode_mask[0] = IMX95_PCIE_DEVICE_TYPE,
                .core_reset = imx95_pcie_core_reset,
                .init_phy = imx95_pcie_init_phy,
+               .wait_pll_lock = imx95_pcie_wait_for_phy_pll_lock,
        },
        [IMX8MQ_EP] = {
                .variant = IMX8MQ_EP,
@@ -1880,6 +1908,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
                .mode_mask[0] = IMX95_PCIE_DEVICE_TYPE,
                .init_phy = imx95_pcie_init_phy,
                .core_reset = imx95_pcie_core_reset,
+               .wait_pll_lock = imx95_pcie_wait_for_phy_pll_lock,
                .epc_features = &imx95_pcie_epc_features,
                .mode = DW_PCIE_EP_TYPE,
        },