Commit 27a064ab authored by Richard Zhu's avatar Richard Zhu Committed by Manivannan Sadhasivam
Browse files

PCI: imx6: Add CLKREQ# override to enable REFCLK for i.MX95 PCIe



The CLKREQ# is an open drain, active low signal that is driven low by
the card to request reference clock. It's an optional signal added in
PCIe CEM r4.0, sec 2. Thus, this signal wouldn't be driven low if it's
not exposed on the slot.

On the i.MX95 EVK board, REFCLK to the host and endpoint is gated by this
CLKREQ# signal. So if the CLKREQ# signal is not driven by the endpoint, it
will gate the REFCLK to host too, leading to operational failure.

Hence, enable the REFCLK on this SoC by enabling the CLKREQ# override using
imx95_pcie_clkreq_override() helper during probe. This override should only
be cleared when the CLKREQ# signal is exposed on the slot.

Signed-off-by: default avatarRichard Zhu <hongxing.zhu@nxp.com>
[mani: reworded description]
Signed-off-by: default avatarManivannan Sadhasivam <mani@kernel.org>
Tested-by: default avatarAlexander Stein <alexander.stein@ew.tq-group.com>
Reviewed-by: default avatarFrank Li <Frank.Li@nxp.com>
Link: https://patch.msgid.link/20251015030428.2980427-11-hongxing.zhu@nxp.com
parent c577ce28
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -52,6 +52,8 @@
#define IMX95_PCIE_REF_CLKEN			BIT(23)
#define IMX95_PCIE_PHY_CR_PARA_SEL		BIT(9)
#define IMX95_PCIE_SS_RW_REG_1			0xf4
#define IMX95_PCIE_CLKREQ_OVERRIDE_EN		BIT(8)
#define IMX95_PCIE_CLKREQ_OVERRIDE_VAL		BIT(9)
#define IMX95_PCIE_SYS_AUX_PWR_DET		BIT(31)

#define IMX95_PE0_GEN_CTRL_1			0x1050
@@ -708,6 +710,22 @@ static int imx7d_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable)
	return 0;
}

static void imx95_pcie_clkreq_override(struct imx_pcie *imx_pcie, bool enable)
{
	regmap_update_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_SS_RW_REG_1,
			   IMX95_PCIE_CLKREQ_OVERRIDE_EN,
			   enable ? IMX95_PCIE_CLKREQ_OVERRIDE_EN : 0);
	regmap_update_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_SS_RW_REG_1,
			   IMX95_PCIE_CLKREQ_OVERRIDE_VAL,
			   enable ? IMX95_PCIE_CLKREQ_OVERRIDE_VAL : 0);
}

static int imx95_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable)
{
	imx95_pcie_clkreq_override(imx_pcie, enable);
	return 0;
}

static int imx_pcie_clk_enable(struct imx_pcie *imx_pcie)
{
	struct dw_pcie *pci = imx_pcie->pci;
@@ -1918,6 +1936,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
		.core_reset = imx95_pcie_core_reset,
		.init_phy = imx95_pcie_init_phy,
		.wait_pll_lock = imx95_pcie_wait_for_phy_pll_lock,
		.enable_ref_clk = imx95_pcie_enable_ref_clk,
	},
	[IMX8MQ_EP] = {
		.variant = IMX8MQ_EP,
@@ -1974,6 +1993,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
		.core_reset = imx95_pcie_core_reset,
		.wait_pll_lock = imx95_pcie_wait_for_phy_pll_lock,
		.epc_features = &imx95_pcie_epc_features,
		.enable_ref_clk = imx95_pcie_enable_ref_clk,
		.mode = DW_PCIE_EP_TYPE,
	},
};