Commit 047e8b6b authored by Richard Zhu's avatar Richard Zhu Committed by Manivannan Sadhasivam
Browse files

PCI: imx6: Add PLL lock check for i.MX95 SoC



PLL lock is required to ensure that the PLL clock is stable before enabling
the controller in i.MX95 SoC.

Signed-off-by: default avatarRichard Zhu <hongxing.zhu@nxp.com>
[mani: subject and description rewording]
Signed-off-by: default avatarManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Reviewed-by: default avatarFrank Li <Frank.Li@nxp.com>
Reviewed-by: default avatarManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Link: https://patch.msgid.link/20250416081314.3929794-7-hongxing.zhu@nxp.com
parent 744a1c20
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -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,
	},