]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
PCI: imx6: Add CLKREQ# override to enable REFCLK for i.MX95 PCIe
authorRichard Zhu <hongxing.zhu@nxp.com>
Wed, 15 Oct 2025 03:04:27 +0000 (11:04 +0800)
committerManivannan Sadhasivam <mani@kernel.org>
Wed, 21 Jan 2026 07:39:35 +0000 (13:09 +0530)
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: Richard Zhu <hongxing.zhu@nxp.com>
[mani: reworded description]
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
Tested-by: Alexander Stein <alexander.stein@ew.tq-group.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Link: https://patch.msgid.link/20251015030428.2980427-11-hongxing.zhu@nxp.com
drivers/pci/controller/dwc/pci-imx6.c

index a6db1f0f73c3603bddc4fce248e82c7c9e599a83..e523cc08c6d9b42db64ace642e27f412ebfd0ddf 100644 (file)
@@ -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,
        },
 };