* [PATCH v5 0/2] PCI: imx6: Add a method to handle CLKREQ# override
@ 2025-09-23 7:39 Richard Zhu
2025-09-23 7:39 ` [PATCH v5 1/2] PCI: dwc: Invoke post_init in dw_pcie_resume_noirq() Richard Zhu
` (2 more replies)
0 siblings, 3 replies; 16+ messages in thread
From: Richard Zhu @ 2025-09-23 7:39 UTC (permalink / raw)
To: frank.li, jingoohan1, l.stach, lpieralisi, kwilczynski, mani,
robh, bhelgaas, shawnguo, s.hauer, kernel, festevam
Cc: linux-pci, linux-arm-kernel, imx, linux-kernel
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
reserved.
Since the reference clock controlled by CLKREQ# may be required by i.MX
PCIe host too. To make sure this clock is ready even when the CLKREQ#
isn't driven low by the card(e.x the scenario described above), force
CLKREQ# override active low for i.MX PCIe host during initialization.
The CLKREQ# override can be cleared safely when supports-clkreq is
present and PCIe link is up later. Because the CLKREQ# would be driven
low by the card at this time.
Main changes in v5:
- New create imx8mm_pcie_clkreq_override() and keep the original
enable_ref_clk callback function.
Main changes in v4:
- To align the function name when add the CLKREQ# override clear, rename
imx8mm_pcie_enable_ref_clk(), clean up codes refer to Mani' suggestions.
Main changes in v3:
- Rebase to v6.17-rc1.
- Update the commit message refer to Bjorn's suggestions.
Main changes in v2:
- Update the commit message, and collect the reviewed-by tag.
[PATCH v5 1/2] PCI: dwc: Invoke post_init in dw_pcie_resume_noirq()
[PATCH v5 2/2] PCI: imx6: Add a method to handle CLKREQ# override
drivers/pci/controller/dwc/pci-imx6.c | 43 ++++++++++++++++++++++++++++++++++++++++++-
drivers/pci/controller/dwc/pcie-designware-host.c | 3 +++
2 files changed, 45 insertions(+), 1 deletion(-)
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v5 1/2] PCI: dwc: Invoke post_init in dw_pcie_resume_noirq() 2025-09-23 7:39 [PATCH v5 0/2] PCI: imx6: Add a method to handle CLKREQ# override Richard Zhu @ 2025-09-23 7:39 ` Richard Zhu 2025-09-23 7:39 ` [PATCH v5 2/2] PCI: imx6: Add a method to handle CLKREQ# override active low Richard Zhu 2025-09-25 17:05 ` [PATCH v5 0/2] PCI: imx6: Add a method to handle CLKREQ# override Manivannan Sadhasivam 2 siblings, 0 replies; 16+ messages in thread From: Richard Zhu @ 2025-09-23 7:39 UTC (permalink / raw) To: frank.li, jingoohan1, l.stach, lpieralisi, kwilczynski, mani, robh, bhelgaas, shawnguo, s.hauer, kernel, festevam Cc: linux-pci, linux-arm-kernel, imx, linux-kernel, Richard Zhu, Frank Li If the ops has post_init callback, invoke it in dw_pcie_resume_noirq(). Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com> Reviewed-by: Frank Li <Frank.Li@nxp.com> --- drivers/pci/controller/dwc/pcie-designware-host.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index 952f8594b501..f24f4cd5c278 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -1079,6 +1079,9 @@ int dw_pcie_resume_noirq(struct dw_pcie *pci) if (ret) return ret; + if (pci->pp.ops->post_init) + pci->pp.ops->post_init(&pci->pp); + return ret; } EXPORT_SYMBOL_GPL(dw_pcie_resume_noirq); -- 2.37.1 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v5 2/2] PCI: imx6: Add a method to handle CLKREQ# override active low 2025-09-23 7:39 [PATCH v5 0/2] PCI: imx6: Add a method to handle CLKREQ# override Richard Zhu 2025-09-23 7:39 ` [PATCH v5 1/2] PCI: dwc: Invoke post_init in dw_pcie_resume_noirq() Richard Zhu @ 2025-09-23 7:39 ` Richard Zhu 2025-09-25 21:57 ` Bjorn Helgaas 2025-09-25 22:04 ` Bjorn Helgaas 2025-09-25 17:05 ` [PATCH v5 0/2] PCI: imx6: Add a method to handle CLKREQ# override Manivannan Sadhasivam 2 siblings, 2 replies; 16+ messages in thread From: Richard Zhu @ 2025-09-23 7:39 UTC (permalink / raw) To: frank.li, jingoohan1, l.stach, lpieralisi, kwilczynski, mani, robh, bhelgaas, shawnguo, s.hauer, kernel, festevam Cc: linux-pci, linux-arm-kernel, imx, linux-kernel, Richard Zhu, Frank Li 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 reserved. Since the reference clock controlled by CLKREQ# may be required by i.MX PCIe host too. To make sure this clock is ready even when the CLKREQ# isn't driven low by the card(e.x the scenario described above), force CLKREQ# override active low for i.MX PCIe host during initialization. The CLKREQ# override can be cleared safely when supports-clkreq is present and PCIe link is up later. Because the CLKREQ# would be driven low by the card at this time. Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com> Reviewed-by: Frank Li <Frank.Li@nxp.com> --- drivers/pci/controller/dwc/pci-imx6.c | 43 ++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c index 80e48746bbaf..6b03b1111d06 100644 --- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -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 @@ -136,6 +138,7 @@ struct imx_pcie_drvdata { 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); + void (*clr_clkreq_override)(struct imx_pcie *pcie); const struct dw_pcie_host_ops *ops; }; @@ -149,6 +152,7 @@ struct imx_pcie { struct gpio_desc *reset_gpiod; struct clk_bulk_data *clks; int num_clks; + bool supports_clkreq; struct regmap *iomuxc_gpr; u16 msi_ctrl; u32 controller_id; @@ -239,6 +243,16 @@ static unsigned int imx_pcie_grp_offset(const struct imx_pcie *imx_pcie) return imx_pcie->controller_id == 1 ? IOMUXC_GPR16 : IOMUXC_GPR14; } +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_init_phy(struct imx_pcie *imx_pcie) { /* @@ -685,7 +699,7 @@ static int imx6q_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable) return 0; } -static int imx8mm_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable) +static void imx8mm_pcie_clkreq_override(struct imx_pcie *imx_pcie, bool enable) { int offset = imx_pcie_grp_offset(imx_pcie); @@ -695,6 +709,11 @@ static int imx8mm_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable) regmap_update_bits(imx_pcie->iomuxc_gpr, offset, IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN, enable ? IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN : 0); +} + +static int imx8mm_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable) +{ + imx8mm_pcie_clkreq_override(imx_pcie, enable); return 0; } @@ -1298,6 +1317,16 @@ static void imx_pcie_host_exit(struct dw_pcie_rp *pp) regulator_disable(imx_pcie->vpcie); } +static void imx8mm_pcie_clr_clkreq_override(struct imx_pcie *imx_pcie) +{ + imx8mm_pcie_clkreq_override(imx_pcie, false); +} + +static void imx95_pcie_clr_clkreq_override(struct imx_pcie *imx_pcie) +{ + imx95_pcie_clkreq_override(imx_pcie, false); +} + static void imx_pcie_host_post_init(struct dw_pcie_rp *pp) { struct dw_pcie *pci = to_dw_pcie_from_pp(pp); @@ -1322,6 +1351,12 @@ static void imx_pcie_host_post_init(struct dw_pcie_rp *pp) dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val); dw_pcie_dbi_ro_wr_dis(pci); } + + /* Clear CLKREQ# override if supports_clkreq is true and link is up */ + if (dw_pcie_link_up(pci) && imx_pcie->supports_clkreq) { + if (imx_pcie->drvdata->clr_clkreq_override) + imx_pcie->drvdata->clr_clkreq_override(imx_pcie); + } } /* @@ -1745,6 +1780,8 @@ static int imx_pcie_probe(struct platform_device *pdev) pci->max_link_speed = 1; of_property_read_u32(node, "fsl,max-link-speed", &pci->max_link_speed); + imx_pcie->supports_clkreq = + of_property_read_bool(node, "supports-clkreq"); imx_pcie->vpcie = devm_regulator_get_optional(&pdev->dev, "vpcie"); if (IS_ERR(imx_pcie->vpcie)) { if (PTR_ERR(imx_pcie->vpcie) != -ENODEV) @@ -1873,6 +1910,7 @@ static const struct imx_pcie_drvdata drvdata[] = { .mode_mask[1] = IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE, .init_phy = imx8mq_pcie_init_phy, .enable_ref_clk = imx8mm_pcie_enable_ref_clk, + .clr_clkreq_override = imx8mm_pcie_clr_clkreq_override, }, [IMX8MM] = { .variant = IMX8MM, @@ -1883,6 +1921,7 @@ static const struct imx_pcie_drvdata drvdata[] = { .mode_off[0] = IOMUXC_GPR12, .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, .enable_ref_clk = imx8mm_pcie_enable_ref_clk, + .clr_clkreq_override = imx8mm_pcie_clr_clkreq_override, }, [IMX8MP] = { .variant = IMX8MP, @@ -1893,6 +1932,7 @@ static const struct imx_pcie_drvdata drvdata[] = { .mode_off[0] = IOMUXC_GPR12, .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, .enable_ref_clk = imx8mm_pcie_enable_ref_clk, + .clr_clkreq_override = imx8mm_pcie_clr_clkreq_override, }, [IMX8Q] = { .variant = IMX8Q, @@ -1913,6 +1953,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, + .clr_clkreq_override = imx95_pcie_clr_clkreq_override, }, [IMX8MQ_EP] = { .variant = IMX8MQ_EP, -- 2.37.1 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH v5 2/2] PCI: imx6: Add a method to handle CLKREQ# override active low 2025-09-23 7:39 ` [PATCH v5 2/2] PCI: imx6: Add a method to handle CLKREQ# override active low Richard Zhu @ 2025-09-25 21:57 ` Bjorn Helgaas 2025-09-26 2:19 ` Hongxing Zhu 2025-09-25 22:04 ` Bjorn Helgaas 1 sibling, 1 reply; 16+ messages in thread From: Bjorn Helgaas @ 2025-09-25 21:57 UTC (permalink / raw) To: Richard Zhu Cc: frank.li, jingoohan1, l.stach, lpieralisi, kwilczynski, mani, robh, bhelgaas, shawnguo, s.hauer, kernel, festevam, linux-pci, linux-arm-kernel, imx, linux-kernel On Tue, Sep 23, 2025 at 03:39:13PM +0800, Richard Zhu wrote: > 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 > reserved. > > Since the reference clock controlled by CLKREQ# may be required by i.MX > PCIe host too. To make sure this clock is ready even when the CLKREQ# > isn't driven low by the card(e.x the scenario described above), force > CLKREQ# override active low for i.MX PCIe host during initialization. > > The CLKREQ# override can be cleared safely when supports-clkreq is > present and PCIe link is up later. Because the CLKREQ# would be driven > low by the card at this time. > > Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com> > Reviewed-by: Frank Li <Frank.Li@nxp.com> > --- > drivers/pci/controller/dwc/pci-imx6.c | 43 ++++++++++++++++++++++++++- > 1 file changed, 42 insertions(+), 1 deletion(-) > > diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c > index 80e48746bbaf..6b03b1111d06 100644 > --- a/drivers/pci/controller/dwc/pci-imx6.c > +++ b/drivers/pci/controller/dwc/pci-imx6.c > @@ -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 > @@ -136,6 +138,7 @@ struct imx_pcie_drvdata { > 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); > + void (*clr_clkreq_override)(struct imx_pcie *pcie); > const struct dw_pcie_host_ops *ops; > }; > > @@ -149,6 +152,7 @@ struct imx_pcie { > struct gpio_desc *reset_gpiod; > struct clk_bulk_data *clks; > int num_clks; > + bool supports_clkreq; > struct regmap *iomuxc_gpr; > u16 msi_ctrl; > u32 controller_id; > @@ -239,6 +243,16 @@ static unsigned int imx_pcie_grp_offset(const struct imx_pcie *imx_pcie) > return imx_pcie->controller_id == 1 ? IOMUXC_GPR16 : IOMUXC_GPR14; > } > > +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_init_phy(struct imx_pcie *imx_pcie) > { > /* > @@ -685,7 +699,7 @@ static int imx6q_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable) > return 0; > } > > -static int imx8mm_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable) > +static void imx8mm_pcie_clkreq_override(struct imx_pcie *imx_pcie, bool enable) > { > int offset = imx_pcie_grp_offset(imx_pcie); > > @@ -695,6 +709,11 @@ static int imx8mm_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable) > regmap_update_bits(imx_pcie->iomuxc_gpr, offset, > IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN, > enable ? IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN : 0); > +} > + > +static int imx8mm_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable) > +{ > + imx8mm_pcie_clkreq_override(imx_pcie, enable); > return 0; > } > > @@ -1298,6 +1317,16 @@ static void imx_pcie_host_exit(struct dw_pcie_rp *pp) > regulator_disable(imx_pcie->vpcie); > } > > +static void imx8mm_pcie_clr_clkreq_override(struct imx_pcie *imx_pcie) > +{ > + imx8mm_pcie_clkreq_override(imx_pcie, false); > +} > + > +static void imx95_pcie_clr_clkreq_override(struct imx_pcie *imx_pcie) > +{ > + imx95_pcie_clkreq_override(imx_pcie, false); > +} > + > static void imx_pcie_host_post_init(struct dw_pcie_rp *pp) > { > struct dw_pcie *pci = to_dw_pcie_from_pp(pp); > @@ -1322,6 +1351,12 @@ static void imx_pcie_host_post_init(struct dw_pcie_rp *pp) > dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val); > dw_pcie_dbi_ro_wr_dis(pci); > } > + > + /* Clear CLKREQ# override if supports_clkreq is true and link is up */ > + if (dw_pcie_link_up(pci) && imx_pcie->supports_clkreq) { > + if (imx_pcie->drvdata->clr_clkreq_override) > + imx_pcie->drvdata->clr_clkreq_override(imx_pcie); > + } > } > > /* > @@ -1745,6 +1780,8 @@ static int imx_pcie_probe(struct platform_device *pdev) > pci->max_link_speed = 1; > of_property_read_u32(node, "fsl,max-link-speed", &pci->max_link_speed); > > + imx_pcie->supports_clkreq = > + of_property_read_bool(node, "supports-clkreq"); > imx_pcie->vpcie = devm_regulator_get_optional(&pdev->dev, "vpcie"); > if (IS_ERR(imx_pcie->vpcie)) { > if (PTR_ERR(imx_pcie->vpcie) != -ENODEV) > @@ -1873,6 +1910,7 @@ static const struct imx_pcie_drvdata drvdata[] = { > .mode_mask[1] = IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE, > .init_phy = imx8mq_pcie_init_phy, > .enable_ref_clk = imx8mm_pcie_enable_ref_clk, > + .clr_clkreq_override = imx8mm_pcie_clr_clkreq_override, > }, > [IMX8MM] = { > .variant = IMX8MM, > @@ -1883,6 +1921,7 @@ static const struct imx_pcie_drvdata drvdata[] = { > .mode_off[0] = IOMUXC_GPR12, > .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, > .enable_ref_clk = imx8mm_pcie_enable_ref_clk, > + .clr_clkreq_override = imx8mm_pcie_clr_clkreq_override, > }, > [IMX8MP] = { > .variant = IMX8MP, > @@ -1893,6 +1932,7 @@ static const struct imx_pcie_drvdata drvdata[] = { > .mode_off[0] = IOMUXC_GPR12, > .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, > .enable_ref_clk = imx8mm_pcie_enable_ref_clk, > + .clr_clkreq_override = imx8mm_pcie_clr_clkreq_override, imx8mm_pcie_enable_ref_clk() and imx8mm_pcie_clr_clkreq_override() both call imx8mm_pcie_clkreq_override(). All these devices that use imx8mm_pcie_clr_clkreq_override() also enable the refclk in .init() by overriding clkreq, so .post_init() clears that override. > }, > [IMX8Q] = { > .variant = IMX8Q, > @@ -1913,6 +1953,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, > + .clr_clkreq_override = imx95_pcie_clr_clkreq_override, But here there's no .enable_ref_clk() method, so I guess this device must override clkreq automatically and the driver doesn't have to enable that? > }, > [IMX8MQ_EP] = { > .variant = IMX8MQ_EP, > -- > 2.37.1 > ^ permalink raw reply [flat|nested] 16+ messages in thread
* RE: [PATCH v5 2/2] PCI: imx6: Add a method to handle CLKREQ# override active low 2025-09-25 21:57 ` Bjorn Helgaas @ 2025-09-26 2:19 ` Hongxing Zhu 0 siblings, 0 replies; 16+ messages in thread From: Hongxing Zhu @ 2025-09-26 2:19 UTC (permalink / raw) To: Bjorn Helgaas, mani@kernel.org Cc: Frank Li, jingoohan1@gmail.com, l.stach@pengutronix.de, lpieralisi@kernel.org, kwilczynski@kernel.org, robh@kernel.org, bhelgaas@google.com, shawnguo@kernel.org, s.hauer@pengutronix.de, kernel@pengutronix.de, festevam@gmail.com, linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org, imx@lists.linux.dev, linux-kernel@vger.kernel.org > -----Original Message----- > From: Bjorn Helgaas <helgaas@kernel.org> > Sent: 2025年9月26日 5:58 > To: Hongxing Zhu <hongxing.zhu@nxp.com> > Cc: Frank Li <frank.li@nxp.com>; jingoohan1@gmail.com; > l.stach@pengutronix.de; lpieralisi@kernel.org; kwilczynski@kernel.org; > mani@kernel.org; robh@kernel.org; bhelgaas@google.com; > shawnguo@kernel.org; s.hauer@pengutronix.de; kernel@pengutronix.de; > festevam@gmail.com; linux-pci@vger.kernel.org; > linux-arm-kernel@lists.infradead.org; imx@lists.linux.dev; > linux-kernel@vger.kernel.org > Subject: Re: [PATCH v5 2/2] PCI: imx6: Add a method to handle CLKREQ# > override active low > > On Tue, Sep 23, 2025 at 03:39:13PM +0800, Richard Zhu wrote: > > 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 > > reserved. > > > > Since the reference clock controlled by CLKREQ# may be required by > > i.MX PCIe host too. To make sure this clock is ready even when the > > CLKREQ# isn't driven low by the card(e.x the scenario described > > above), force CLKREQ# override active low for i.MX PCIe host during > initialization. > > > > The CLKREQ# override can be cleared safely when supports-clkreq is > > present and PCIe link is up later. Because the CLKREQ# would be driven > > low by the card at this time. > > > > Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com> > > Reviewed-by: Frank Li <Frank.Li@nxp.com> > > --- > > drivers/pci/controller/dwc/pci-imx6.c | 43 > > ++++++++++++++++++++++++++- > > 1 file changed, 42 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/pci/controller/dwc/pci-imx6.c > > b/drivers/pci/controller/dwc/pci-imx6.c > > index 80e48746bbaf..6b03b1111d06 100644 > > --- a/drivers/pci/controller/dwc/pci-imx6.c > > +++ b/drivers/pci/controller/dwc/pci-imx6.c > > @@ -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 > > @@ -136,6 +138,7 @@ struct imx_pcie_drvdata { > > 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); > > + void (*clr_clkreq_override)(struct imx_pcie *pcie); > > const struct dw_pcie_host_ops *ops; > > }; > > > > @@ -149,6 +152,7 @@ struct imx_pcie { > > struct gpio_desc *reset_gpiod; > > struct clk_bulk_data *clks; > > int num_clks; > > + bool supports_clkreq; > > struct regmap *iomuxc_gpr; > > u16 msi_ctrl; > > u32 controller_id; > > @@ -239,6 +243,16 @@ static unsigned int imx_pcie_grp_offset(const struct > imx_pcie *imx_pcie) > > return imx_pcie->controller_id == 1 ? IOMUXC_GPR16 : IOMUXC_GPR14; > > } > > > > +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_init_phy(struct imx_pcie *imx_pcie) { > > /* > > @@ -685,7 +699,7 @@ static int imx6q_pcie_enable_ref_clk(struct imx_pcie > *imx_pcie, bool enable) > > return 0; > > } > > > > -static int imx8mm_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool > > enable) > > +static void imx8mm_pcie_clkreq_override(struct imx_pcie *imx_pcie, > > +bool enable) > > { > > int offset = imx_pcie_grp_offset(imx_pcie); > > > > @@ -695,6 +709,11 @@ static int imx8mm_pcie_enable_ref_clk(struct > imx_pcie *imx_pcie, bool enable) > > regmap_update_bits(imx_pcie->iomuxc_gpr, offset, > > IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN, > > enable ? IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN : 0); > > +} > > + > > +static int imx8mm_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool > > +enable) { > > + imx8mm_pcie_clkreq_override(imx_pcie, enable); > > return 0; > > } > > > > @@ -1298,6 +1317,16 @@ static void imx_pcie_host_exit(struct dw_pcie_rp > *pp) > > regulator_disable(imx_pcie->vpcie); > > } > > > > +static void imx8mm_pcie_clr_clkreq_override(struct imx_pcie > > +*imx_pcie) { > > + imx8mm_pcie_clkreq_override(imx_pcie, false); } > > + > > +static void imx95_pcie_clr_clkreq_override(struct imx_pcie *imx_pcie) > > +{ > > + imx95_pcie_clkreq_override(imx_pcie, false); } > > + > > static void imx_pcie_host_post_init(struct dw_pcie_rp *pp) { > > struct dw_pcie *pci = to_dw_pcie_from_pp(pp); @@ -1322,6 +1351,12 > @@ > > static void imx_pcie_host_post_init(struct dw_pcie_rp *pp) > > dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val); > > dw_pcie_dbi_ro_wr_dis(pci); > > } > > + > > + /* Clear CLKREQ# override if supports_clkreq is true and link is up */ > > + if (dw_pcie_link_up(pci) && imx_pcie->supports_clkreq) { > > + if (imx_pcie->drvdata->clr_clkreq_override) > > + imx_pcie->drvdata->clr_clkreq_override(imx_pcie); > > + } > > } > > > > /* > > @@ -1745,6 +1780,8 @@ static int imx_pcie_probe(struct platform_device > *pdev) > > pci->max_link_speed = 1; > > of_property_read_u32(node, "fsl,max-link-speed", > > &pci->max_link_speed); > > > > + imx_pcie->supports_clkreq = > > + of_property_read_bool(node, "supports-clkreq"); > > imx_pcie->vpcie = devm_regulator_get_optional(&pdev->dev, "vpcie"); > > if (IS_ERR(imx_pcie->vpcie)) { > > if (PTR_ERR(imx_pcie->vpcie) != -ENODEV) @@ -1873,6 +1910,7 @@ > > static const struct imx_pcie_drvdata drvdata[] = { > > .mode_mask[1] = IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE, > > .init_phy = imx8mq_pcie_init_phy, > > .enable_ref_clk = imx8mm_pcie_enable_ref_clk, > > + .clr_clkreq_override = imx8mm_pcie_clr_clkreq_override, > > }, > > [IMX8MM] = { > > .variant = IMX8MM, > > @@ -1883,6 +1921,7 @@ static const struct imx_pcie_drvdata drvdata[] = { > > .mode_off[0] = IOMUXC_GPR12, > > .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, > > .enable_ref_clk = imx8mm_pcie_enable_ref_clk, > > + .clr_clkreq_override = imx8mm_pcie_clr_clkreq_override, > > }, > > [IMX8MP] = { > > .variant = IMX8MP, > > @@ -1893,6 +1932,7 @@ static const struct imx_pcie_drvdata drvdata[] = { > > .mode_off[0] = IOMUXC_GPR12, > > .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, > > .enable_ref_clk = imx8mm_pcie_enable_ref_clk, > > + .clr_clkreq_override = imx8mm_pcie_clr_clkreq_override, > > imx8mm_pcie_enable_ref_clk() and imx8mm_pcie_clr_clkreq_override() both > call imx8mm_pcie_clkreq_override(). > > All these devices that use imx8mm_pcie_clr_clkreq_override() also enable the > refclk in .init() by overriding clkreq, so .post_init() clears that override. > On i.MX8M, the override clkreq# operations are wrapped as .enable_ref_clk(). This would block L1ss feature enablement, if the override active low is not cleared. This patch-set paves the path to support L1ss feature on i.MX8M PCIes. > > }, > > [IMX8Q] = { > > .variant = IMX8Q, > > @@ -1913,6 +1953,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, > > + .clr_clkreq_override = imx95_pcie_clr_clkreq_override, > > But here there's no .enable_ref_clk() method, so I guess this device must > override clkreq automatically and the driver doesn't have to enable that? Wow, it's my fault that I made a mistake when sent out the v4 after v3 review around. "imx95_pcie_clkreq_override(imx_pcie, true);" should be added when I pack the codes into a new function in v4. https://lore.kernel.org/imx/hsmebnz6opoj45zztdd2svmdtrwwwrngjaidpltbunnkdvvdqz@lhyejtlwkkes/ --- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -281,6 +281,8 @@ static int imx95_pcie_init_phy(struct imx_pcie *imx_pcie) IMX95_PCIE_REF_CLKEN, IMX95_PCIE_REF_CLKEN); + imx95_pcie_clkreq_override(imx_pcie, true); + Thanks a lot for your carefully review here. Hi Mani: The v5 patch-set miss the changes listed above, please backout the applied v5 patch-set. Should I re-post next version? Sorry to bring inconvenience to you. Best Regards Richard Zhu > > > }, > > [IMX8MQ_EP] = { > > .variant = IMX8MQ_EP, > > -- > > 2.37.1 > > ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v5 2/2] PCI: imx6: Add a method to handle CLKREQ# override active low 2025-09-23 7:39 ` [PATCH v5 2/2] PCI: imx6: Add a method to handle CLKREQ# override active low Richard Zhu 2025-09-25 21:57 ` Bjorn Helgaas @ 2025-09-25 22:04 ` Bjorn Helgaas 2025-09-26 2:19 ` Hongxing Zhu 1 sibling, 1 reply; 16+ messages in thread From: Bjorn Helgaas @ 2025-09-25 22:04 UTC (permalink / raw) To: Richard Zhu Cc: frank.li, jingoohan1, l.stach, lpieralisi, kwilczynski, mani, robh, bhelgaas, shawnguo, s.hauer, kernel, festevam, linux-pci, linux-arm-kernel, imx, linux-kernel On Tue, Sep 23, 2025 at 03:39:13PM +0800, Richard Zhu wrote: > 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 > reserved. > > Since the reference clock controlled by CLKREQ# may be required by i.MX > PCIe host too. To make sure this clock is ready even when the CLKREQ# > isn't driven low by the card(e.x the scenario described above), force > CLKREQ# override active low for i.MX PCIe host during initialization. > > The CLKREQ# override can be cleared safely when supports-clkreq is > present and PCIe link is up later. Because the CLKREQ# would be driven > low by the card at this time. What happens if we clear the CLKREQ# override (so the host doesn't assert it), and the link is up but the card never asserts CLKREQ# (since it's an optional signal)? Does the i.MX host still work? > Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com> > Reviewed-by: Frank Li <Frank.Li@nxp.com> > --- > drivers/pci/controller/dwc/pci-imx6.c | 43 ++++++++++++++++++++++++++- > 1 file changed, 42 insertions(+), 1 deletion(-) > > diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c > index 80e48746bbaf..6b03b1111d06 100644 > --- a/drivers/pci/controller/dwc/pci-imx6.c > +++ b/drivers/pci/controller/dwc/pci-imx6.c > @@ -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 > @@ -136,6 +138,7 @@ struct imx_pcie_drvdata { > 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); > + void (*clr_clkreq_override)(struct imx_pcie *pcie); > const struct dw_pcie_host_ops *ops; > }; > > @@ -149,6 +152,7 @@ struct imx_pcie { > struct gpio_desc *reset_gpiod; > struct clk_bulk_data *clks; > int num_clks; > + bool supports_clkreq; > struct regmap *iomuxc_gpr; > u16 msi_ctrl; > u32 controller_id; > @@ -239,6 +243,16 @@ static unsigned int imx_pcie_grp_offset(const struct imx_pcie *imx_pcie) > return imx_pcie->controller_id == 1 ? IOMUXC_GPR16 : IOMUXC_GPR14; > } > > +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_init_phy(struct imx_pcie *imx_pcie) > { > /* > @@ -685,7 +699,7 @@ static int imx6q_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable) > return 0; > } > > -static int imx8mm_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable) > +static void imx8mm_pcie_clkreq_override(struct imx_pcie *imx_pcie, bool enable) > { > int offset = imx_pcie_grp_offset(imx_pcie); > > @@ -695,6 +709,11 @@ static int imx8mm_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable) > regmap_update_bits(imx_pcie->iomuxc_gpr, offset, > IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN, > enable ? IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN : 0); > +} > + > +static int imx8mm_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable) > +{ > + imx8mm_pcie_clkreq_override(imx_pcie, enable); > return 0; > } > > @@ -1298,6 +1317,16 @@ static void imx_pcie_host_exit(struct dw_pcie_rp *pp) > regulator_disable(imx_pcie->vpcie); > } > > +static void imx8mm_pcie_clr_clkreq_override(struct imx_pcie *imx_pcie) > +{ > + imx8mm_pcie_clkreq_override(imx_pcie, false); > +} > + > +static void imx95_pcie_clr_clkreq_override(struct imx_pcie *imx_pcie) > +{ > + imx95_pcie_clkreq_override(imx_pcie, false); > +} > + > static void imx_pcie_host_post_init(struct dw_pcie_rp *pp) > { > struct dw_pcie *pci = to_dw_pcie_from_pp(pp); > @@ -1322,6 +1351,12 @@ static void imx_pcie_host_post_init(struct dw_pcie_rp *pp) > dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val); > dw_pcie_dbi_ro_wr_dis(pci); > } > + > + /* Clear CLKREQ# override if supports_clkreq is true and link is up */ > + if (dw_pcie_link_up(pci) && imx_pcie->supports_clkreq) { > + if (imx_pcie->drvdata->clr_clkreq_override) > + imx_pcie->drvdata->clr_clkreq_override(imx_pcie); > + } > } > > /* > @@ -1745,6 +1780,8 @@ static int imx_pcie_probe(struct platform_device *pdev) > pci->max_link_speed = 1; > of_property_read_u32(node, "fsl,max-link-speed", &pci->max_link_speed); > > + imx_pcie->supports_clkreq = > + of_property_read_bool(node, "supports-clkreq"); > imx_pcie->vpcie = devm_regulator_get_optional(&pdev->dev, "vpcie"); > if (IS_ERR(imx_pcie->vpcie)) { > if (PTR_ERR(imx_pcie->vpcie) != -ENODEV) > @@ -1873,6 +1910,7 @@ static const struct imx_pcie_drvdata drvdata[] = { > .mode_mask[1] = IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE, > .init_phy = imx8mq_pcie_init_phy, > .enable_ref_clk = imx8mm_pcie_enable_ref_clk, > + .clr_clkreq_override = imx8mm_pcie_clr_clkreq_override, > }, > [IMX8MM] = { > .variant = IMX8MM, > @@ -1883,6 +1921,7 @@ static const struct imx_pcie_drvdata drvdata[] = { > .mode_off[0] = IOMUXC_GPR12, > .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, > .enable_ref_clk = imx8mm_pcie_enable_ref_clk, > + .clr_clkreq_override = imx8mm_pcie_clr_clkreq_override, > }, > [IMX8MP] = { > .variant = IMX8MP, > @@ -1893,6 +1932,7 @@ static const struct imx_pcie_drvdata drvdata[] = { > .mode_off[0] = IOMUXC_GPR12, > .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, > .enable_ref_clk = imx8mm_pcie_enable_ref_clk, > + .clr_clkreq_override = imx8mm_pcie_clr_clkreq_override, > }, > [IMX8Q] = { > .variant = IMX8Q, > @@ -1913,6 +1953,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, > + .clr_clkreq_override = imx95_pcie_clr_clkreq_override, > }, > [IMX8MQ_EP] = { > .variant = IMX8MQ_EP, > -- > 2.37.1 > ^ permalink raw reply [flat|nested] 16+ messages in thread
* RE: [PATCH v5 2/2] PCI: imx6: Add a method to handle CLKREQ# override active low 2025-09-25 22:04 ` Bjorn Helgaas @ 2025-09-26 2:19 ` Hongxing Zhu 2025-09-26 2:44 ` Bjorn Helgaas 0 siblings, 1 reply; 16+ messages in thread From: Hongxing Zhu @ 2025-09-26 2:19 UTC (permalink / raw) To: Bjorn Helgaas Cc: Frank Li, jingoohan1@gmail.com, l.stach@pengutronix.de, lpieralisi@kernel.org, kwilczynski@kernel.org, mani@kernel.org, robh@kernel.org, bhelgaas@google.com, shawnguo@kernel.org, s.hauer@pengutronix.de, kernel@pengutronix.de, festevam@gmail.com, linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org, imx@lists.linux.dev, linux-kernel@vger.kernel.org > -----Original Message----- > From: Bjorn Helgaas <helgaas@kernel.org> > Sent: 2025年9月26日 6:04 > To: Hongxing Zhu <hongxing.zhu@nxp.com> > Cc: Frank Li <frank.li@nxp.com>; jingoohan1@gmail.com; > l.stach@pengutronix.de; lpieralisi@kernel.org; kwilczynski@kernel.org; > mani@kernel.org; robh@kernel.org; bhelgaas@google.com; > shawnguo@kernel.org; s.hauer@pengutronix.de; kernel@pengutronix.de; > festevam@gmail.com; linux-pci@vger.kernel.org; > linux-arm-kernel@lists.infradead.org; imx@lists.linux.dev; > linux-kernel@vger.kernel.org > Subject: Re: [PATCH v5 2/2] PCI: imx6: Add a method to handle CLKREQ# > override active low > > On Tue, Sep 23, 2025 at 03:39:13PM +0800, Richard Zhu wrote: > > 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 > > reserved. > > > > Since the reference clock controlled by CLKREQ# may be required by > > i.MX PCIe host too. To make sure this clock is ready even when the > > CLKREQ# isn't driven low by the card(e.x the scenario described > > above), force CLKREQ# override active low for i.MX PCIe host during > initialization. > > > > The CLKREQ# override can be cleared safely when supports-clkreq is > > present and PCIe link is up later. Because the CLKREQ# would be driven > > low by the card at this time. > > What happens if we clear the CLKREQ# override (so the host doesn't assert > it), and the link is up but the card never asserts CLKREQ# (since it's an > optional signal)? > > Does the i.MX host still work? Hi Bjorn: Thanks for your kindly concerns. The CLKREQ# override active low only be cleared when link is up and supports-clkreq is present. In the other words, there is a remote endpoint device, and the CLKREQ# would be driven active low by this endpoint device. Best Regards Richard Zhu > > > Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com> > > Reviewed-by: Frank Li <Frank.Li@nxp.com> > > --- > > drivers/pci/controller/dwc/pci-imx6.c | 43 > > ++++++++++++++++++++++++++- > > 1 file changed, 42 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/pci/controller/dwc/pci-imx6.c > > b/drivers/pci/controller/dwc/pci-imx6.c > > index 80e48746bbaf..6b03b1111d06 100644 > > --- a/drivers/pci/controller/dwc/pci-imx6.c > > +++ b/drivers/pci/controller/dwc/pci-imx6.c > > @@ -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 > > @@ -136,6 +138,7 @@ struct imx_pcie_drvdata { > > 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); > > + void (*clr_clkreq_override)(struct imx_pcie *pcie); > > const struct dw_pcie_host_ops *ops; > > }; > > > > @@ -149,6 +152,7 @@ struct imx_pcie { > > struct gpio_desc *reset_gpiod; > > struct clk_bulk_data *clks; > > int num_clks; > > + bool supports_clkreq; > > struct regmap *iomuxc_gpr; > > u16 msi_ctrl; > > u32 controller_id; > > @@ -239,6 +243,16 @@ static unsigned int imx_pcie_grp_offset(const > struct imx_pcie *imx_pcie) > > return imx_pcie->controller_id == 1 ? IOMUXC_GPR16 : IOMUXC_GPR14; > > } > > > > +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_init_phy(struct imx_pcie *imx_pcie) { > > /* > > @@ -685,7 +699,7 @@ static int imx6q_pcie_enable_ref_clk(struct > imx_pcie *imx_pcie, bool enable) > > return 0; > > } > > > > -static int imx8mm_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool > > enable) > > +static void imx8mm_pcie_clkreq_override(struct imx_pcie *imx_pcie, > > +bool enable) > > { > > int offset = imx_pcie_grp_offset(imx_pcie); > > > > @@ -695,6 +709,11 @@ static int imx8mm_pcie_enable_ref_clk(struct > imx_pcie *imx_pcie, bool enable) > > regmap_update_bits(imx_pcie->iomuxc_gpr, offset, > > IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN, > > enable ? IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN : 0); > > +} > > + > > +static int imx8mm_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool > > +enable) { > > + imx8mm_pcie_clkreq_override(imx_pcie, enable); > > return 0; > > } > > > > @@ -1298,6 +1317,16 @@ static void imx_pcie_host_exit(struct > dw_pcie_rp *pp) > > regulator_disable(imx_pcie->vpcie); > > } > > > > +static void imx8mm_pcie_clr_clkreq_override(struct imx_pcie > > +*imx_pcie) { > > + imx8mm_pcie_clkreq_override(imx_pcie, false); } > > + > > +static void imx95_pcie_clr_clkreq_override(struct imx_pcie *imx_pcie) > > +{ > > + imx95_pcie_clkreq_override(imx_pcie, false); } > > + > > static void imx_pcie_host_post_init(struct dw_pcie_rp *pp) { > > struct dw_pcie *pci = to_dw_pcie_from_pp(pp); @@ -1322,6 +1351,12 > @@ > > static void imx_pcie_host_post_init(struct dw_pcie_rp *pp) > > dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val); > > dw_pcie_dbi_ro_wr_dis(pci); > > } > > + > > + /* Clear CLKREQ# override if supports_clkreq is true and link is up */ > > + if (dw_pcie_link_up(pci) && imx_pcie->supports_clkreq) { > > + if (imx_pcie->drvdata->clr_clkreq_override) > > + imx_pcie->drvdata->clr_clkreq_override(imx_pcie); > > + } > > } > > > > /* > > @@ -1745,6 +1780,8 @@ static int imx_pcie_probe(struct platform_device > *pdev) > > pci->max_link_speed = 1; > > of_property_read_u32(node, "fsl,max-link-speed", > > &pci->max_link_speed); > > > > + imx_pcie->supports_clkreq = > > + of_property_read_bool(node, "supports-clkreq"); > > imx_pcie->vpcie = devm_regulator_get_optional(&pdev->dev, "vpcie"); > > if (IS_ERR(imx_pcie->vpcie)) { > > if (PTR_ERR(imx_pcie->vpcie) != -ENODEV) @@ -1873,6 +1910,7 @@ > > static const struct imx_pcie_drvdata drvdata[] = { > > .mode_mask[1] = IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE, > > .init_phy = imx8mq_pcie_init_phy, > > .enable_ref_clk = imx8mm_pcie_enable_ref_clk, > > + .clr_clkreq_override = imx8mm_pcie_clr_clkreq_override, > > }, > > [IMX8MM] = { > > .variant = IMX8MM, > > @@ -1883,6 +1921,7 @@ static const struct imx_pcie_drvdata drvdata[] = { > > .mode_off[0] = IOMUXC_GPR12, > > .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, > > .enable_ref_clk = imx8mm_pcie_enable_ref_clk, > > + .clr_clkreq_override = imx8mm_pcie_clr_clkreq_override, > > }, > > [IMX8MP] = { > > .variant = IMX8MP, > > @@ -1893,6 +1932,7 @@ static const struct imx_pcie_drvdata drvdata[] = { > > .mode_off[0] = IOMUXC_GPR12, > > .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, > > .enable_ref_clk = imx8mm_pcie_enable_ref_clk, > > + .clr_clkreq_override = imx8mm_pcie_clr_clkreq_override, > > }, > > [IMX8Q] = { > > .variant = IMX8Q, > > @@ -1913,6 +1953,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, > > + .clr_clkreq_override = imx95_pcie_clr_clkreq_override, > > }, > > [IMX8MQ_EP] = { > > .variant = IMX8MQ_EP, > > -- > > 2.37.1 > > ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v5 2/2] PCI: imx6: Add a method to handle CLKREQ# override active low 2025-09-26 2:19 ` Hongxing Zhu @ 2025-09-26 2:44 ` Bjorn Helgaas 2025-09-26 3:08 ` Hongxing Zhu 2025-09-26 3:23 ` Hongxing Zhu 0 siblings, 2 replies; 16+ messages in thread From: Bjorn Helgaas @ 2025-09-26 2:44 UTC (permalink / raw) To: Hongxing Zhu Cc: Frank Li, jingoohan1@gmail.com, l.stach@pengutronix.de, lpieralisi@kernel.org, kwilczynski@kernel.org, mani@kernel.org, robh@kernel.org, bhelgaas@google.com, shawnguo@kernel.org, s.hauer@pengutronix.de, kernel@pengutronix.de, festevam@gmail.com, linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org, imx@lists.linux.dev, linux-kernel@vger.kernel.org On Fri, Sep 26, 2025 at 02:19:37AM +0000, Hongxing Zhu wrote: > > -----Original Message----- > > From: Bjorn Helgaas <helgaas@kernel.org> > > On Tue, Sep 23, 2025 at 03:39:13PM +0800, Richard Zhu wrote: > > > 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 > > > reserved. > > > > > > Since the reference clock controlled by CLKREQ# may be required by > > > i.MX PCIe host too. To make sure this clock is ready even when the > > > CLKREQ# isn't driven low by the card(e.x the scenario described > > > above), force CLKREQ# override active low for i.MX PCIe host during > > initialization. > > > > > > The CLKREQ# override can be cleared safely when supports-clkreq is > > > present and PCIe link is up later. Because the CLKREQ# would be driven > > > low by the card at this time. > > > > What happens if we clear the CLKREQ# override (so the host doesn't assert > > it), and the link is up but the card never asserts CLKREQ# (since it's an > > optional signal)? > > > > Does the i.MX host still work? > > The CLKREQ# override active low only be cleared when link is up and > supports-clkreq is present. In the other words, there is a remote endpoint > device, and the CLKREQ# would be driven active low by this endpoint device. Assume an endpoint designed to CEM r2.0. CLKREQ# doesn't exist in CEM r2.0, so even if the endpoint is present and the link is up, the endpoint will not assert CLKREQ#. Will the i.MX host still work? IIUC, CLKREQ# is required for ASPM L1 PM Substates. Maybe the CLKREQ# override should only be cleared if the endpoint advertises L1 PM Substates support? Sorry, I'm just really confused about this. Here's another question: Even if the endpoint is designed to CEM r4.0, it supports L1 PM Substates, and it asserts CLKREQ#, my understanding is that the endpoint won't assert CLKREQ# *all* the time. For example, when the link enters L1, the device deasserts CLKREQ# (CEM r5.0, sec 2.8.2). What happens to the i.MX host when the endpoint isn't asserting CLKREQ#? I guess i.MX doesn't need refclk in that situation? > > > Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com> > > > Reviewed-by: Frank Li <Frank.Li@nxp.com> > > > --- > > > drivers/pci/controller/dwc/pci-imx6.c | 43 > > > ++++++++++++++++++++++++++- > > > 1 file changed, 42 insertions(+), 1 deletion(-) > > > > > > diff --git a/drivers/pci/controller/dwc/pci-imx6.c > > > b/drivers/pci/controller/dwc/pci-imx6.c > > > index 80e48746bbaf..6b03b1111d06 100644 > > > --- a/drivers/pci/controller/dwc/pci-imx6.c > > > +++ b/drivers/pci/controller/dwc/pci-imx6.c > > > @@ -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 > > > @@ -136,6 +138,7 @@ struct imx_pcie_drvdata { > > > 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); > > > + void (*clr_clkreq_override)(struct imx_pcie *pcie); > > > const struct dw_pcie_host_ops *ops; > > > }; > > > > > > @@ -149,6 +152,7 @@ struct imx_pcie { > > > struct gpio_desc *reset_gpiod; > > > struct clk_bulk_data *clks; > > > int num_clks; > > > + bool supports_clkreq; > > > struct regmap *iomuxc_gpr; > > > u16 msi_ctrl; > > > u32 controller_id; > > > @@ -239,6 +243,16 @@ static unsigned int imx_pcie_grp_offset(const > > struct imx_pcie *imx_pcie) > > > return imx_pcie->controller_id == 1 ? IOMUXC_GPR16 : IOMUXC_GPR14; > > > } > > > > > > +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_init_phy(struct imx_pcie *imx_pcie) { > > > /* > > > @@ -685,7 +699,7 @@ static int imx6q_pcie_enable_ref_clk(struct > > imx_pcie *imx_pcie, bool enable) > > > return 0; > > > } > > > > > > -static int imx8mm_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool > > > enable) > > > +static void imx8mm_pcie_clkreq_override(struct imx_pcie *imx_pcie, > > > +bool enable) > > > { > > > int offset = imx_pcie_grp_offset(imx_pcie); > > > > > > @@ -695,6 +709,11 @@ static int imx8mm_pcie_enable_ref_clk(struct > > imx_pcie *imx_pcie, bool enable) > > > regmap_update_bits(imx_pcie->iomuxc_gpr, offset, > > > IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN, > > > enable ? IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN : 0); > > > +} > > > + > > > +static int imx8mm_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool > > > +enable) { > > > + imx8mm_pcie_clkreq_override(imx_pcie, enable); > > > return 0; > > > } > > > > > > @@ -1298,6 +1317,16 @@ static void imx_pcie_host_exit(struct > > dw_pcie_rp *pp) > > > regulator_disable(imx_pcie->vpcie); > > > } > > > > > > +static void imx8mm_pcie_clr_clkreq_override(struct imx_pcie > > > +*imx_pcie) { > > > + imx8mm_pcie_clkreq_override(imx_pcie, false); } > > > + > > > +static void imx95_pcie_clr_clkreq_override(struct imx_pcie *imx_pcie) > > > +{ > > > + imx95_pcie_clkreq_override(imx_pcie, false); } > > > + > > > static void imx_pcie_host_post_init(struct dw_pcie_rp *pp) { > > > struct dw_pcie *pci = to_dw_pcie_from_pp(pp); @@ -1322,6 +1351,12 > > @@ > > > static void imx_pcie_host_post_init(struct dw_pcie_rp *pp) > > > dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val); > > > dw_pcie_dbi_ro_wr_dis(pci); > > > } > > > + > > > + /* Clear CLKREQ# override if supports_clkreq is true and link is up */ > > > + if (dw_pcie_link_up(pci) && imx_pcie->supports_clkreq) { > > > + if (imx_pcie->drvdata->clr_clkreq_override) > > > + imx_pcie->drvdata->clr_clkreq_override(imx_pcie); > > > + } > > > } > > > > > > /* > > > @@ -1745,6 +1780,8 @@ static int imx_pcie_probe(struct platform_device > > *pdev) > > > pci->max_link_speed = 1; > > > of_property_read_u32(node, "fsl,max-link-speed", > > > &pci->max_link_speed); > > > > > > + imx_pcie->supports_clkreq = > > > + of_property_read_bool(node, "supports-clkreq"); > > > imx_pcie->vpcie = devm_regulator_get_optional(&pdev->dev, "vpcie"); > > > if (IS_ERR(imx_pcie->vpcie)) { > > > if (PTR_ERR(imx_pcie->vpcie) != -ENODEV) @@ -1873,6 +1910,7 @@ > > > static const struct imx_pcie_drvdata drvdata[] = { > > > .mode_mask[1] = IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE, > > > .init_phy = imx8mq_pcie_init_phy, > > > .enable_ref_clk = imx8mm_pcie_enable_ref_clk, > > > + .clr_clkreq_override = imx8mm_pcie_clr_clkreq_override, > > > }, > > > [IMX8MM] = { > > > .variant = IMX8MM, > > > @@ -1883,6 +1921,7 @@ static const struct imx_pcie_drvdata drvdata[] = { > > > .mode_off[0] = IOMUXC_GPR12, > > > .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, > > > .enable_ref_clk = imx8mm_pcie_enable_ref_clk, > > > + .clr_clkreq_override = imx8mm_pcie_clr_clkreq_override, > > > }, > > > [IMX8MP] = { > > > .variant = IMX8MP, > > > @@ -1893,6 +1932,7 @@ static const struct imx_pcie_drvdata drvdata[] = { > > > .mode_off[0] = IOMUXC_GPR12, > > > .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, > > > .enable_ref_clk = imx8mm_pcie_enable_ref_clk, > > > + .clr_clkreq_override = imx8mm_pcie_clr_clkreq_override, > > > }, > > > [IMX8Q] = { > > > .variant = IMX8Q, > > > @@ -1913,6 +1953,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, > > > + .clr_clkreq_override = imx95_pcie_clr_clkreq_override, > > > }, > > > [IMX8MQ_EP] = { > > > .variant = IMX8MQ_EP, > > > -- > > > 2.37.1 > > > ^ permalink raw reply [flat|nested] 16+ messages in thread
* RE: [PATCH v5 2/2] PCI: imx6: Add a method to handle CLKREQ# override active low 2025-09-26 2:44 ` Bjorn Helgaas @ 2025-09-26 3:08 ` Hongxing Zhu 2025-09-26 20:25 ` Bjorn Helgaas 2025-09-26 3:23 ` Hongxing Zhu 1 sibling, 1 reply; 16+ messages in thread From: Hongxing Zhu @ 2025-09-26 3:08 UTC (permalink / raw) To: Bjorn Helgaas Cc: Frank Li, jingoohan1@gmail.com, l.stach@pengutronix.de, lpieralisi@kernel.org, kwilczynski@kernel.org, mani@kernel.org, robh@kernel.org, bhelgaas@google.com, shawnguo@kernel.org, s.hauer@pengutronix.de, kernel@pengutronix.de, festevam@gmail.com, linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org, imx@lists.linux.dev, linux-kernel@vger.kernel.org > -----Original Message----- > From: Bjorn Helgaas <helgaas@kernel.org> > Sent: 2025年9月26日 10:45 > To: Hongxing Zhu <hongxing.zhu@nxp.com> > Cc: Frank Li <frank.li@nxp.com>; jingoohan1@gmail.com; > l.stach@pengutronix.de; lpieralisi@kernel.org; kwilczynski@kernel.org; > mani@kernel.org; robh@kernel.org; bhelgaas@google.com; > shawnguo@kernel.org; s.hauer@pengutronix.de; kernel@pengutronix.de; > festevam@gmail.com; linux-pci@vger.kernel.org; > linux-arm-kernel@lists.infradead.org; imx@lists.linux.dev; > linux-kernel@vger.kernel.org > Subject: Re: [PATCH v5 2/2] PCI: imx6: Add a method to handle CLKREQ# > override active low > > On Fri, Sep 26, 2025 at 02:19:37AM +0000, Hongxing Zhu wrote: > > > -----Original Message----- > > > From: Bjorn Helgaas <helgaas@kernel.org> On Tue, Sep 23, 2025 at > > > 03:39:13PM +0800, Richard Zhu wrote: > > > > 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 reserved. > > > > > > > > Since the reference clock controlled by CLKREQ# may be required by > > > > i.MX PCIe host too. To make sure this clock is ready even when the > > > > CLKREQ# isn't driven low by the card(e.x the scenario described > > > > above), force CLKREQ# override active low for i.MX PCIe host > > > > during > > > initialization. > > > > > > > > The CLKREQ# override can be cleared safely when supports-clkreq is > > > > present and PCIe link is up later. Because the CLKREQ# would be > > > > driven low by the card at this time. > > > > > > What happens if we clear the CLKREQ# override (so the host doesn't > > > assert it), and the link is up but the card never asserts CLKREQ# > > > (since it's an optional signal)? > > > > > > Does the i.MX host still work? > > > > The CLKREQ# override active low only be cleared when link is up and > > supports-clkreq is present. In the other words, there is a remote > > endpoint device, and the CLKREQ# would be driven active low by this > endpoint device. > > Assume an endpoint designed to CEM r2.0. CLKREQ# doesn't exist in CEM > r2.0, so even if the endpoint is present and the link is up, the endpoint will not > assert CLKREQ#. > > Will the i.MX host still work? Yes, i.MX hos still work. If the endpoint designed to CEM r2.0, and CLKREQ# is reserved. The property suppots-clkreq wouldn't present in this scenario. Thus, the CLKREQ# override active low set by host driver wouldn't be cleared later, although the link is up and an endpoint is present. > > IIUC, CLKREQ# is required for ASPM L1 PM Substates. Maybe the CLKREQ# > override should only be cleared if the endpoint advertises L1 PM Substates > support? > > Sorry, I'm just really confused about this. Here's another question: > Even if the endpoint is designed to CEM r4.0, it supports L1 PM Substates, and > it asserts CLKREQ#, my understanding is that the endpoint won't assert > CLKREQ# *all* the time. For example, when the link enters L1, the device > deasserts CLKREQ# (CEM r5.0, sec 2.8.2). > > What happens to the i.MX host when the endpoint isn't asserting CLKREQ#? I > guess i.MX doesn't need refclk in that situation? Yes, it is. When L1ss is entered, i.MX PCIe doesn't need refclk. In the other words, the REFCLK can be gated off when L1ss is entered. I had observed the toggling of CLKREQ# and REFCLK by the Oscilloscope when L1ss is enabled. CLKRQ# is high, and no REFCLK toggling, if there are no activities on the bus. CLKREQ# would be driven to active low and REFCLK start to toggle when any side try to issue the TLPs. Best Regards Richard Zhu > > > > > Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com> > > > > Reviewed-by: Frank Li <Frank.Li@nxp.com> > > > > --- > > > > drivers/pci/controller/dwc/pci-imx6.c | 43 > > > > ++++++++++++++++++++++++++- > > > > 1 file changed, 42 insertions(+), 1 deletion(-) > > > > > > > > diff --git a/drivers/pci/controller/dwc/pci-imx6.c > > > > b/drivers/pci/controller/dwc/pci-imx6.c > > > > index 80e48746bbaf..6b03b1111d06 100644 > > > > --- a/drivers/pci/controller/dwc/pci-imx6.c > > > > +++ b/drivers/pci/controller/dwc/pci-imx6.c > > > > @@ -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 > > > > @@ -136,6 +138,7 @@ struct imx_pcie_drvdata { > > > > 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); > > > > + void (*clr_clkreq_override)(struct imx_pcie *pcie); > > > > const struct dw_pcie_host_ops *ops; }; > > > > > > > > @@ -149,6 +152,7 @@ struct imx_pcie { > > > > struct gpio_desc *reset_gpiod; > > > > struct clk_bulk_data *clks; > > > > int num_clks; > > > > + bool supports_clkreq; > > > > struct regmap *iomuxc_gpr; > > > > u16 msi_ctrl; > > > > u32 controller_id; > > > > @@ -239,6 +243,16 @@ static unsigned int imx_pcie_grp_offset(const > > > struct imx_pcie *imx_pcie) > > > > return imx_pcie->controller_id == 1 ? IOMUXC_GPR16 : > > > > IOMUXC_GPR14; } > > > > > > > > +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_init_phy(struct imx_pcie *imx_pcie) { > > > > /* > > > > @@ -685,7 +699,7 @@ static int imx6q_pcie_enable_ref_clk(struct > > > imx_pcie *imx_pcie, bool enable) > > > > return 0; > > > > } > > > > > > > > -static int imx8mm_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, > > > > bool > > > > enable) > > > > +static void imx8mm_pcie_clkreq_override(struct imx_pcie > > > > +*imx_pcie, bool enable) > > > > { > > > > int offset = imx_pcie_grp_offset(imx_pcie); > > > > > > > > @@ -695,6 +709,11 @@ static int imx8mm_pcie_enable_ref_clk(struct > > > imx_pcie *imx_pcie, bool enable) > > > > regmap_update_bits(imx_pcie->iomuxc_gpr, offset, > > > > IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN, > > > > enable ? IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN : > 0); > > > > +} > > > > + > > > > +static int imx8mm_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, > > > > +bool > > > > +enable) { > > > > + imx8mm_pcie_clkreq_override(imx_pcie, enable); > > > > return 0; > > > > } > > > > > > > > @@ -1298,6 +1317,16 @@ static void imx_pcie_host_exit(struct > > > dw_pcie_rp *pp) > > > > regulator_disable(imx_pcie->vpcie); > > > > } > > > > > > > > +static void imx8mm_pcie_clr_clkreq_override(struct imx_pcie > > > > +*imx_pcie) { > > > > + imx8mm_pcie_clkreq_override(imx_pcie, false); } > > > > + > > > > +static void imx95_pcie_clr_clkreq_override(struct imx_pcie > > > > +*imx_pcie) { > > > > + imx95_pcie_clkreq_override(imx_pcie, false); } > > > > + > > > > static void imx_pcie_host_post_init(struct dw_pcie_rp *pp) { > > > > struct dw_pcie *pci = to_dw_pcie_from_pp(pp); @@ -1322,6 > > > > +1351,12 > > > @@ > > > > static void imx_pcie_host_post_init(struct dw_pcie_rp *pp) > > > > dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val); > > > > dw_pcie_dbi_ro_wr_dis(pci); > > > > } > > > > + > > > > + /* Clear CLKREQ# override if supports_clkreq is true and link is up */ > > > > + if (dw_pcie_link_up(pci) && imx_pcie->supports_clkreq) { > > > > + if (imx_pcie->drvdata->clr_clkreq_override) > > > > + imx_pcie->drvdata->clr_clkreq_override(imx_pcie); > > > > + } > > > > } > > > > > > > > /* > > > > @@ -1745,6 +1780,8 @@ static int imx_pcie_probe(struct > > > > platform_device > > > *pdev) > > > > pci->max_link_speed = 1; > > > > of_property_read_u32(node, "fsl,max-link-speed", > > > > &pci->max_link_speed); > > > > > > > > + imx_pcie->supports_clkreq = > > > > + of_property_read_bool(node, "supports-clkreq"); > > > > imx_pcie->vpcie = devm_regulator_get_optional(&pdev->dev, > "vpcie"); > > > > if (IS_ERR(imx_pcie->vpcie)) { > > > > if (PTR_ERR(imx_pcie->vpcie) != -ENODEV) @@ -1873,6 +1910,7 > @@ > > > > static const struct imx_pcie_drvdata drvdata[] = { > > > > .mode_mask[1] = IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE, > > > > .init_phy = imx8mq_pcie_init_phy, > > > > .enable_ref_clk = imx8mm_pcie_enable_ref_clk, > > > > + .clr_clkreq_override = imx8mm_pcie_clr_clkreq_override, > > > > }, > > > > [IMX8MM] = { > > > > .variant = IMX8MM, > > > > @@ -1883,6 +1921,7 @@ static const struct imx_pcie_drvdata drvdata[] > = { > > > > .mode_off[0] = IOMUXC_GPR12, > > > > .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, > > > > .enable_ref_clk = imx8mm_pcie_enable_ref_clk, > > > > + .clr_clkreq_override = imx8mm_pcie_clr_clkreq_override, > > > > }, > > > > [IMX8MP] = { > > > > .variant = IMX8MP, > > > > @@ -1893,6 +1932,7 @@ static const struct imx_pcie_drvdata drvdata[] > = { > > > > .mode_off[0] = IOMUXC_GPR12, > > > > .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, > > > > .enable_ref_clk = imx8mm_pcie_enable_ref_clk, > > > > + .clr_clkreq_override = imx8mm_pcie_clr_clkreq_override, > > > > }, > > > > [IMX8Q] = { > > > > .variant = IMX8Q, > > > > @@ -1913,6 +1953,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, > > > > + .clr_clkreq_override = imx95_pcie_clr_clkreq_override, > > > > }, > > > > [IMX8MQ_EP] = { > > > > .variant = IMX8MQ_EP, > > > > -- > > > > 2.37.1 > > > > ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v5 2/2] PCI: imx6: Add a method to handle CLKREQ# override active low 2025-09-26 3:08 ` Hongxing Zhu @ 2025-09-26 20:25 ` Bjorn Helgaas 2025-09-26 22:46 ` Frank Li 0 siblings, 1 reply; 16+ messages in thread From: Bjorn Helgaas @ 2025-09-26 20:25 UTC (permalink / raw) To: Hongxing Zhu Cc: Frank Li, jingoohan1@gmail.com, l.stach@pengutronix.de, lpieralisi@kernel.org, kwilczynski@kernel.org, mani@kernel.org, robh@kernel.org, bhelgaas@google.com, shawnguo@kernel.org, s.hauer@pengutronix.de, kernel@pengutronix.de, festevam@gmail.com, linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org, imx@lists.linux.dev, linux-kernel@vger.kernel.org On Fri, Sep 26, 2025 at 03:08:30AM +0000, Hongxing Zhu wrote: > > -----Original Message----- > > From: Bjorn Helgaas <helgaas@kernel.org> > > On Fri, Sep 26, 2025 at 02:19:37AM +0000, Hongxing Zhu wrote: > > > > -----Original Message----- > > > > From: Bjorn Helgaas <helgaas@kernel.org> On Tue, Sep 23, 2025 at > > > > 03:39:13PM +0800, Richard Zhu wrote: > > > > > 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 reserved. > > > > > > > > > > Since the reference clock controlled by CLKREQ# may be > > > > > required by i.MX PCIe host too. To make sure this clock is > > > > > ready even when the CLKREQ# isn't driven low by the card(e.x > > > > > the scenario described above), force CLKREQ# override active > > > > > low for i.MX PCIe host during initialization. > > > > > > > > > > The CLKREQ# override can be cleared safely when > > > > > supports-clkreq is present and PCIe link is up later. > > > > > Because the CLKREQ# would be driven low by the card at this > > > > > time. > > > > > > > > What happens if we clear the CLKREQ# override (so the host > > > > doesn't assert it), and the link is up but the card never > > > > asserts CLKREQ# (since it's an optional signal)? > > > > > > > > Does the i.MX host still work? > > > > > > The CLKREQ# override active low only be cleared when link is up > > > and supports-clkreq is present. In the other words, there is a > > > remote endpoint device, and the CLKREQ# would be driven active > > > low by this endpoint device. > > > > Assume an endpoint designed to CEM r2.0. CLKREQ# doesn't exist in > > CEM r2.0, so even if the endpoint is present and the link is up, > > the endpoint will not assert CLKREQ#. > > > > Will the i.MX host still work? > Yes, i.MX host still work. > If the endpoint designed to CEM r2.0, and CLKREQ# is reserved. The > property suppots-clkreq wouldn't present in this scenario. Thus, the > CLKREQ# override active low set by host driver wouldn't be cleared > later, although the link is up and an endpoint is present. Do you mean 'supports-clkreq' describes the *endpoint*, and you need to change the devicetree depending on which endpoint is connected? The schema says 'supports-clkreq' tells us whether CLKREQ# signal routing exists, not whether the downstream device actually supports CLKREQ#: https://github.com/devicetree-org/dt-schema/blob/4b28bc79fdc552f3e0b870ef1362bb711925f4f3/dtschema/schemas/pci/pci-bus-common.yaml#L155 I don't see 'supports-clkreq' in any devicetree related to imx6, so I'm not sure this patch is needed yet. Does it fix an existing problem? If it enables some future functionality, maybe we should defer it until we're actually ready to enable that functionality? Bjorn ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v5 2/2] PCI: imx6: Add a method to handle CLKREQ# override active low 2025-09-26 20:25 ` Bjorn Helgaas @ 2025-09-26 22:46 ` Frank Li 2025-10-03 17:21 ` Bjorn Helgaas 0 siblings, 1 reply; 16+ messages in thread From: Frank Li @ 2025-09-26 22:46 UTC (permalink / raw) To: Bjorn Helgaas Cc: Hongxing Zhu, jingoohan1@gmail.com, l.stach@pengutronix.de, lpieralisi@kernel.org, kwilczynski@kernel.org, mani@kernel.org, robh@kernel.org, bhelgaas@google.com, shawnguo@kernel.org, s.hauer@pengutronix.de, kernel@pengutronix.de, festevam@gmail.com, linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org, imx@lists.linux.dev, linux-kernel@vger.kernel.org On Fri, Sep 26, 2025 at 03:25:21PM -0500, Bjorn Helgaas wrote: > On Fri, Sep 26, 2025 at 03:08:30AM +0000, Hongxing Zhu wrote: > > > -----Original Message----- > > > From: Bjorn Helgaas <helgaas@kernel.org> > > > > On Fri, Sep 26, 2025 at 02:19:37AM +0000, Hongxing Zhu wrote: > > > > > -----Original Message----- > > > > > From: Bjorn Helgaas <helgaas@kernel.org> On Tue, Sep 23, 2025 at > > > > > 03:39:13PM +0800, Richard Zhu wrote: > > > > > > 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 reserved. > > > > > > > > > > > > Since the reference clock controlled by CLKREQ# may be > > > > > > required by i.MX PCIe host too. To make sure this clock is > > > > > > ready even when the CLKREQ# isn't driven low by the card(e.x > > > > > > the scenario described above), force CLKREQ# override active > > > > > > low for i.MX PCIe host during initialization. > > > > > > > > > > > > The CLKREQ# override can be cleared safely when > > > > > > supports-clkreq is present and PCIe link is up later. > > > > > > Because the CLKREQ# would be driven low by the card at this > > > > > > time. > > > > > > > > > > What happens if we clear the CLKREQ# override (so the host > > > > > doesn't assert it), and the link is up but the card never > > > > > asserts CLKREQ# (since it's an optional signal)? > > > > > > > > > > Does the i.MX host still work? > > > > > > > > The CLKREQ# override active low only be cleared when link is up > > > > and supports-clkreq is present. In the other words, there is a > > > > remote endpoint device, and the CLKREQ# would be driven active > > > > low by this endpoint device. > > > > > > Assume an endpoint designed to CEM r2.0. CLKREQ# doesn't exist in > > > CEM r2.0, so even if the endpoint is present and the link is up, > > > the endpoint will not assert CLKREQ#. > > > > > > Will the i.MX host still work? > > > Yes, i.MX host still work. > > If the endpoint designed to CEM r2.0, and CLKREQ# is reserved. The > > property suppots-clkreq wouldn't present in this scenario. Thus, the > > CLKREQ# override active low set by host driver wouldn't be cleared > > later, although the link is up and an endpoint is present. > > Do you mean 'supports-clkreq' describes the *endpoint*, and you need > to change the devicetree depending on which endpoint is connected? It is NOT descript *endpoint*. supports-clkreq descript the board design, which connect CLKREQ# signal. Because standard slot's CLKREQ# (PIN12) is reserved in beggin, so some old PCIe card have not pull down this signal as latest spec requirement. PCIe Standard slot with INTEL E2000 1G ethernet card, which is producted around 10 year ago, PIN12 is reserved. So we don't set supports-clkreq for stardard PCI slot, only set it for M.2 slot. So stardard PCI slot in imx95 evk can support most cards. We have not vendor card lists, which already connect/not connect CLKREQ#, so we have to fallback to disconnect CLKREQ# situation by clarm our evk board have not connect CLKREQ# to make all card works, eventhough it lost power save feature. work is more impantant then power saving. > > The schema says 'supports-clkreq' tells us whether CLKREQ# signal > routing exists, not whether the downstream device actually supports > CLKREQ#: > > https://github.com/devicetree-org/dt-schema/blob/4b28bc79fdc552f3e0b870ef1362bb711925f4f3/dtschema/schemas/pci/pci-bus-common.yaml#L155 > > I don't see 'supports-clkreq' in any devicetree related to imx6, so > I'm not sure this patch is needed yet. Does it fix an existing > problem? The patch adding 'supports-clkreq' in dts is on going. No funtional broken because it just impact l1ss power saving features. > > If it enables some future functionality, maybe we should defer it > until we're actually ready to enable that functionality? Actually, it fixes i.MX95 19x19 EVK second slot problem. At least INTEL E2000 1G ethernet card can't work at i.MX95 EVK boards at main stream kernel without this patch. Frank > > Bjorn ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v5 2/2] PCI: imx6: Add a method to handle CLKREQ# override active low 2025-09-26 22:46 ` Frank Li @ 2025-10-03 17:21 ` Bjorn Helgaas 0 siblings, 0 replies; 16+ messages in thread From: Bjorn Helgaas @ 2025-10-03 17:21 UTC (permalink / raw) To: Frank Li Cc: Hongxing Zhu, jingoohan1@gmail.com, l.stach@pengutronix.de, lpieralisi@kernel.org, kwilczynski@kernel.org, mani@kernel.org, robh@kernel.org, bhelgaas@google.com, shawnguo@kernel.org, s.hauer@pengutronix.de, kernel@pengutronix.de, festevam@gmail.com, linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org, imx@lists.linux.dev, linux-kernel@vger.kernel.org On Fri, Sep 26, 2025 at 06:46:28PM -0400, Frank Li wrote: > On Fri, Sep 26, 2025 at 03:25:21PM -0500, Bjorn Helgaas wrote: > > On Fri, Sep 26, 2025 at 03:08:30AM +0000, Hongxing Zhu wrote: > > > > -----Original Message----- > > > > From: Bjorn Helgaas <helgaas@kernel.org> > > > > > > On Fri, Sep 26, 2025 at 02:19:37AM +0000, Hongxing Zhu wrote: > > > > > > -----Original Message----- > > > > > > From: Bjorn Helgaas <helgaas@kernel.org> On Tue, Sep 23, 2025 at > > > > > > 03:39:13PM +0800, Richard Zhu wrote: > > > > > > > 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 reserved. > > > > > > > > > > > > > > Since the reference clock controlled by CLKREQ# may be > > > > > > > required by i.MX PCIe host too. To make sure this clock is > > > > > > > ready even when the CLKREQ# isn't driven low by the card(e.x > > > > > > > the scenario described above), force CLKREQ# override active > > > > > > > low for i.MX PCIe host during initialization. > > > > > > > > > > > > > > The CLKREQ# override can be cleared safely when > > > > > > > supports-clkreq is present and PCIe link is up later. > > > > > > > Because the CLKREQ# would be driven low by the card at this > > > > > > > time. > > > > > > > > > > > > What happens if we clear the CLKREQ# override (so the host > > > > > > doesn't assert it), and the link is up but the card never > > > > > > asserts CLKREQ# (since it's an optional signal)? > > > > > > > > > > > > Does the i.MX host still work? > > > > > > > > > > The CLKREQ# override active low only be cleared when link is up > > > > > and supports-clkreq is present. In the other words, there is a > > > > > remote endpoint device, and the CLKREQ# would be driven active > > > > > low by this endpoint device. > > > > > > > > Assume an endpoint designed to CEM r2.0. CLKREQ# doesn't exist in > > > > CEM r2.0, so even if the endpoint is present and the link is up, > > > > the endpoint will not assert CLKREQ#. > > > > > > > > Will the i.MX host still work? > > > > > Yes, i.MX host still work. > > > If the endpoint designed to CEM r2.0, and CLKREQ# is reserved. The > > > property suppots-clkreq wouldn't present in this scenario. Thus, the > > > CLKREQ# override active low set by host driver wouldn't be cleared > > > later, although the link is up and an endpoint is present. > > > > Do you mean 'supports-clkreq' describes the *endpoint*, and you need > > to change the devicetree depending on which endpoint is connected? > > It is NOT descript *endpoint*. supports-clkreq descript the board design, > which connect CLKREQ# signal. Because standard slot's CLKREQ# (PIN12) is > reserved in beggin, so some old PCIe card have not pull down this signal as > latest spec requirement. > > PCIe Standard slot with INTEL E2000 1G ethernet card, which is producted > around 10 year ago, PIN12 is reserved. > > So we don't set supports-clkreq for stardard PCI slot, only set it for > M.2 slot. So stardard PCI slot in imx95 evk can support most cards. We have > not vendor card lists, which already connect/not connect CLKREQ#, so we > have to fallback to disconnect CLKREQ# situation by clarm our evk board > have not connect CLKREQ# to make all card works, eventhough it lost power > save feature. work is more impantant then power saving. > > > The schema says 'supports-clkreq' tells us whether CLKREQ# signal > > routing exists, not whether the downstream device actually supports > > CLKREQ#: > > > > https://github.com/devicetree-org/dt-schema/blob/4b28bc79fdc552f3e0b870ef1362bb711925f4f3/dtschema/schemas/pci/pci-bus-common.yaml#L155 > > > > I don't see 'supports-clkreq' in any devicetree related to imx6, so > > I'm not sure this patch is needed yet. Does it fix an existing > > problem? > > The patch adding 'supports-clkreq' in dts is on going. No funtional broken > because it just impact l1ss power saving features. > > > If it enables some future functionality, maybe we should defer it > > until we're actually ready to enable that functionality? > > Actually, it fixes i.MX95 19x19 EVK second slot problem. At least > INTEL E2000 1G ethernet card can't work at i.MX95 EVK boards at main > stream kernel without this patch. I deferred these two patches so we have time to tidy these up: - Coordinate with adding 'supports-clkreq' in devicetrees. - Fix the imx95 refclk enable that was missed in the v5 series. - Consider making imx95 refclk enable parallel to the other versions, e.g., by using .enable_ref_clk() instead of doing it in imx95_pcie_init_phy(). - Describe the "i.MX95 19x19 EVK second slot problem" in the commit log. Possibly split that into a second patch if it can be separated from the CLKREQ# override. It sounds like this part doesn't depend on 'supports-clkreq' in a devicetree? Maybe we can also figure out how to explain why CLKREQ# override is an issue for imx6 but not for other DWC-based drivers. Bjorn ^ permalink raw reply [flat|nested] 16+ messages in thread
* RE: [PATCH v5 2/2] PCI: imx6: Add a method to handle CLKREQ# override active low 2025-09-26 2:44 ` Bjorn Helgaas 2025-09-26 3:08 ` Hongxing Zhu @ 2025-09-26 3:23 ` Hongxing Zhu 2025-09-26 20:24 ` Bjorn Helgaas 1 sibling, 1 reply; 16+ messages in thread From: Hongxing Zhu @ 2025-09-26 3:23 UTC (permalink / raw) To: Bjorn Helgaas Cc: Frank Li, jingoohan1@gmail.com, l.stach@pengutronix.de, lpieralisi@kernel.org, kwilczynski@kernel.org, mani@kernel.org, robh@kernel.org, bhelgaas@google.com, shawnguo@kernel.org, s.hauer@pengutronix.de, kernel@pengutronix.de, festevam@gmail.com, linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org, imx@lists.linux.dev, linux-kernel@vger.kernel.org > -----Original Message----- > From: Bjorn Helgaas <helgaas@kernel.org> > Sent: 2025年9月26日 10:45 > To: Hongxing Zhu <hongxing.zhu@nxp.com> > Cc: Frank Li <frank.li@nxp.com>; jingoohan1@gmail.com; > l.stach@pengutronix.de; lpieralisi@kernel.org; kwilczynski@kernel.org; > mani@kernel.org; robh@kernel.org; bhelgaas@google.com; > shawnguo@kernel.org; s.hauer@pengutronix.de; kernel@pengutronix.de; > festevam@gmail.com; linux-pci@vger.kernel.org; > linux-arm-kernel@lists.infradead.org; imx@lists.linux.dev; > linux-kernel@vger.kernel.org > Subject: Re: [PATCH v5 2/2] PCI: imx6: Add a method to handle CLKREQ# > override active low > > On Fri, Sep 26, 2025 at 02:19:37AM +0000, Hongxing Zhu wrote: > > > -----Original Message----- > > > From: Bjorn Helgaas <helgaas@kernel.org> On Tue, Sep 23, 2025 at > > > 03:39:13PM +0800, Richard Zhu wrote: > > > > 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 reserved. > > > > > > > > Since the reference clock controlled by CLKREQ# may be required by > > > > i.MX PCIe host too. To make sure this clock is ready even when the > > > > CLKREQ# isn't driven low by the card(e.x the scenario described > > > > above), force CLKREQ# override active low for i.MX PCIe host > > > > during > > > initialization. > > > > > > > > The CLKREQ# override can be cleared safely when supports-clkreq is > > > > present and PCIe link is up later. Because the CLKREQ# would be > > > > driven low by the card at this time. > > > > > > What happens if we clear the CLKREQ# override (so the host doesn't > > > assert it), and the link is up but the card never asserts CLKREQ# > > > (since it's an optional signal)? > > > > > > Does the i.MX host still work? > > > > The CLKREQ# override active low only be cleared when link is up and > > supports-clkreq is present. In the other words, there is a remote > > endpoint device, and the CLKREQ# would be driven active low by this > endpoint device. > > Assume an endpoint designed to CEM r2.0. CLKREQ# doesn't exist in CEM > r2.0, so even if the endpoint is present and the link is up, the endpoint will not > assert CLKREQ#. > > Will the i.MX host still work? > > IIUC, CLKREQ# is required for ASPM L1 PM Substates. Maybe the CLKREQ# > override should only be cleared if the endpoint advertises L1 PM Substates > support? CLKREQ# override active low only be cleared when the endpoint advertises that it has L1 PM Substates support or it always drives CLKREQ# low. Hope this explanation can resolve the confusion you have. Best Regards Richard Zhu > > Sorry, I'm just really confused about this. Here's another question: > Even if the endpoint is designed to CEM r4.0, it supports L1 PM Substates, and > it asserts CLKREQ#, my understanding is that the endpoint won't assert > CLKREQ# *all* the time. For example, when the link enters L1, the device > deasserts CLKREQ# (CEM r5.0, sec 2.8.2). > > What happens to the i.MX host when the endpoint isn't asserting CLKREQ#? I > guess i.MX doesn't need refclk in that situation? > > > > > Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com> > > > > Reviewed-by: Frank Li <Frank.Li@nxp.com> > > > > --- > > > > drivers/pci/controller/dwc/pci-imx6.c | 43 > > > > ++++++++++++++++++++++++++- > > > > 1 file changed, 42 insertions(+), 1 deletion(-) > > > > > > > > diff --git a/drivers/pci/controller/dwc/pci-imx6.c > > > > b/drivers/pci/controller/dwc/pci-imx6.c > > > > index 80e48746bbaf..6b03b1111d06 100644 > > > > --- a/drivers/pci/controller/dwc/pci-imx6.c > > > > +++ b/drivers/pci/controller/dwc/pci-imx6.c > > > > @@ -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 > > > > @@ -136,6 +138,7 @@ struct imx_pcie_drvdata { > > > > 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); > > > > + void (*clr_clkreq_override)(struct imx_pcie *pcie); > > > > const struct dw_pcie_host_ops *ops; }; > > > > > > > > @@ -149,6 +152,7 @@ struct imx_pcie { > > > > struct gpio_desc *reset_gpiod; > > > > struct clk_bulk_data *clks; > > > > int num_clks; > > > > + bool supports_clkreq; > > > > struct regmap *iomuxc_gpr; > > > > u16 msi_ctrl; > > > > u32 controller_id; > > > > @@ -239,6 +243,16 @@ static unsigned int imx_pcie_grp_offset(const > > > struct imx_pcie *imx_pcie) > > > > return imx_pcie->controller_id == 1 ? IOMUXC_GPR16 : > > > > IOMUXC_GPR14; } > > > > > > > > +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_init_phy(struct imx_pcie *imx_pcie) { > > > > /* > > > > @@ -685,7 +699,7 @@ static int imx6q_pcie_enable_ref_clk(struct > > > imx_pcie *imx_pcie, bool enable) > > > > return 0; > > > > } > > > > > > > > -static int imx8mm_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, > > > > bool > > > > enable) > > > > +static void imx8mm_pcie_clkreq_override(struct imx_pcie > > > > +*imx_pcie, bool enable) > > > > { > > > > int offset = imx_pcie_grp_offset(imx_pcie); > > > > > > > > @@ -695,6 +709,11 @@ static int imx8mm_pcie_enable_ref_clk(struct > > > imx_pcie *imx_pcie, bool enable) > > > > regmap_update_bits(imx_pcie->iomuxc_gpr, offset, > > > > IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN, > > > > enable ? IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN : > 0); > > > > +} > > > > + > > > > +static int imx8mm_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, > > > > +bool > > > > +enable) { > > > > + imx8mm_pcie_clkreq_override(imx_pcie, enable); > > > > return 0; > > > > } > > > > > > > > @@ -1298,6 +1317,16 @@ static void imx_pcie_host_exit(struct > > > dw_pcie_rp *pp) > > > > regulator_disable(imx_pcie->vpcie); > > > > } > > > > > > > > +static void imx8mm_pcie_clr_clkreq_override(struct imx_pcie > > > > +*imx_pcie) { > > > > + imx8mm_pcie_clkreq_override(imx_pcie, false); } > > > > + > > > > +static void imx95_pcie_clr_clkreq_override(struct imx_pcie > > > > +*imx_pcie) { > > > > + imx95_pcie_clkreq_override(imx_pcie, false); } > > > > + > > > > static void imx_pcie_host_post_init(struct dw_pcie_rp *pp) { > > > > struct dw_pcie *pci = to_dw_pcie_from_pp(pp); @@ -1322,6 > > > > +1351,12 > > > @@ > > > > static void imx_pcie_host_post_init(struct dw_pcie_rp *pp) > > > > dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val); > > > > dw_pcie_dbi_ro_wr_dis(pci); > > > > } > > > > + > > > > + /* Clear CLKREQ# override if supports_clkreq is true and link is up */ > > > > + if (dw_pcie_link_up(pci) && imx_pcie->supports_clkreq) { > > > > + if (imx_pcie->drvdata->clr_clkreq_override) > > > > + imx_pcie->drvdata->clr_clkreq_override(imx_pcie); > > > > + } > > > > } > > > > > > > > /* > > > > @@ -1745,6 +1780,8 @@ static int imx_pcie_probe(struct > > > > platform_device > > > *pdev) > > > > pci->max_link_speed = 1; > > > > of_property_read_u32(node, "fsl,max-link-speed", > > > > &pci->max_link_speed); > > > > > > > > + imx_pcie->supports_clkreq = > > > > + of_property_read_bool(node, "supports-clkreq"); > > > > imx_pcie->vpcie = devm_regulator_get_optional(&pdev->dev, > "vpcie"); > > > > if (IS_ERR(imx_pcie->vpcie)) { > > > > if (PTR_ERR(imx_pcie->vpcie) != -ENODEV) @@ -1873,6 +1910,7 > @@ > > > > static const struct imx_pcie_drvdata drvdata[] = { > > > > .mode_mask[1] = IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE, > > > > .init_phy = imx8mq_pcie_init_phy, > > > > .enable_ref_clk = imx8mm_pcie_enable_ref_clk, > > > > + .clr_clkreq_override = imx8mm_pcie_clr_clkreq_override, > > > > }, > > > > [IMX8MM] = { > > > > .variant = IMX8MM, > > > > @@ -1883,6 +1921,7 @@ static const struct imx_pcie_drvdata drvdata[] > = { > > > > .mode_off[0] = IOMUXC_GPR12, > > > > .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, > > > > .enable_ref_clk = imx8mm_pcie_enable_ref_clk, > > > > + .clr_clkreq_override = imx8mm_pcie_clr_clkreq_override, > > > > }, > > > > [IMX8MP] = { > > > > .variant = IMX8MP, > > > > @@ -1893,6 +1932,7 @@ static const struct imx_pcie_drvdata drvdata[] > = { > > > > .mode_off[0] = IOMUXC_GPR12, > > > > .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, > > > > .enable_ref_clk = imx8mm_pcie_enable_ref_clk, > > > > + .clr_clkreq_override = imx8mm_pcie_clr_clkreq_override, > > > > }, > > > > [IMX8Q] = { > > > > .variant = IMX8Q, > > > > @@ -1913,6 +1953,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, > > > > + .clr_clkreq_override = imx95_pcie_clr_clkreq_override, > > > > }, > > > > [IMX8MQ_EP] = { > > > > .variant = IMX8MQ_EP, > > > > -- > > > > 2.37.1 > > > > ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v5 2/2] PCI: imx6: Add a method to handle CLKREQ# override active low 2025-09-26 3:23 ` Hongxing Zhu @ 2025-09-26 20:24 ` Bjorn Helgaas 2025-09-26 22:58 ` Frank Li 0 siblings, 1 reply; 16+ messages in thread From: Bjorn Helgaas @ 2025-09-26 20:24 UTC (permalink / raw) To: Hongxing Zhu Cc: Frank Li, jingoohan1@gmail.com, l.stach@pengutronix.de, lpieralisi@kernel.org, kwilczynski@kernel.org, mani@kernel.org, robh@kernel.org, bhelgaas@google.com, shawnguo@kernel.org, s.hauer@pengutronix.de, kernel@pengutronix.de, festevam@gmail.com, linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org, imx@lists.linux.dev, linux-kernel@vger.kernel.org On Fri, Sep 26, 2025 at 03:23:43AM +0000, Hongxing Zhu wrote: > > -----Original Message----- > > From: Bjorn Helgaas <helgaas@kernel.org> > > On Fri, Sep 26, 2025 at 02:19:37AM +0000, Hongxing Zhu wrote: > > > > -----Original Message----- > > > > From: Bjorn Helgaas <helgaas@kernel.org> On Tue, Sep 23, 2025 at > > > > 03:39:13PM +0800, Richard Zhu wrote: > > > > > 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 reserved. > > > > > > > > > > Since the reference clock controlled by CLKREQ# may be required by > > > > > i.MX PCIe host too. To make sure this clock is ready even when the > > > > > CLKREQ# isn't driven low by the card(e.x the scenario described > > > > > above), force CLKREQ# override active low for i.MX PCIe host > > > > > during initialization. > > > > > > > > > > The CLKREQ# override can be cleared safely when supports-clkreq is > > > > > present and PCIe link is up later. Because the CLKREQ# would be > > > > > driven low by the card at this time. > > > > > > > > What happens if we clear the CLKREQ# override (so the host doesn't > > > > assert it), and the link is up but the card never asserts CLKREQ# > > > > (since it's an optional signal)? > > > > > > > > Does the i.MX host still work? > > > > > > The CLKREQ# override active low only be cleared when link is up > > > and supports-clkreq is present. In the other words, there is a > > > remote endpoint device, and the CLKREQ# would be driven active > > > low by this endpoint device. > > > > Assume an endpoint designed to CEM r2.0. CLKREQ# doesn't exist in > > CEM r2.0, so even if the endpoint is present and the link is up, > > the endpoint will not assert CLKREQ#. > > > > Will the i.MX host still work? > > > > IIUC, CLKREQ# is required for ASPM L1 PM Substates. Maybe the > > CLKREQ# override should only be cleared if the endpoint advertises > > L1 PM Substates support? > > CLKREQ# override active low only be cleared when the endpoint > advertises that it has L1 PM Substates support or it always drives > CLKREQ# low. What? That's not what the patch does. It calls .clr_clkreq_override() whenever the link is up and devicetree contains 'support-clkreq'. A device advertises L1 PM Substates support by putting the L1 PM Substates Capability in its config space. > > > > > static void imx_pcie_host_post_init(struct dw_pcie_rp *pp) > > > > > dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val); > > > > > dw_pcie_dbi_ro_wr_dis(pci); > > > > > } > > > > > + > > > > > + /* Clear CLKREQ# override if supports_clkreq is true and link is up */ > > > > > + if (dw_pcie_link_up(pci) && imx_pcie->supports_clkreq) { > > > > > + if (imx_pcie->drvdata->clr_clkreq_override) > > > > > + imx_pcie->drvdata->clr_clkreq_override(imx_pcie); > > > > > + } ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v5 2/2] PCI: imx6: Add a method to handle CLKREQ# override active low 2025-09-26 20:24 ` Bjorn Helgaas @ 2025-09-26 22:58 ` Frank Li 0 siblings, 0 replies; 16+ messages in thread From: Frank Li @ 2025-09-26 22:58 UTC (permalink / raw) To: Bjorn Helgaas Cc: Hongxing Zhu, jingoohan1@gmail.com, l.stach@pengutronix.de, lpieralisi@kernel.org, kwilczynski@kernel.org, mani@kernel.org, robh@kernel.org, bhelgaas@google.com, shawnguo@kernel.org, s.hauer@pengutronix.de, kernel@pengutronix.de, festevam@gmail.com, linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org, imx@lists.linux.dev, linux-kernel@vger.kernel.org On Fri, Sep 26, 2025 at 03:24:31PM -0500, Bjorn Helgaas wrote: > On Fri, Sep 26, 2025 at 03:23:43AM +0000, Hongxing Zhu wrote: > > > -----Original Message----- > > > From: Bjorn Helgaas <helgaas@kernel.org> > > > > On Fri, Sep 26, 2025 at 02:19:37AM +0000, Hongxing Zhu wrote: > > > > > -----Original Message----- > > > > > From: Bjorn Helgaas <helgaas@kernel.org> On Tue, Sep 23, 2025 at > > > > > 03:39:13PM +0800, Richard Zhu wrote: > > > > > > 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 reserved. > > > > > > > > > > > > Since the reference clock controlled by CLKREQ# may be required by > > > > > > i.MX PCIe host too. To make sure this clock is ready even when the > > > > > > CLKREQ# isn't driven low by the card(e.x the scenario described > > > > > > above), force CLKREQ# override active low for i.MX PCIe host > > > > > > during initialization. > > > > > > > > > > > > The CLKREQ# override can be cleared safely when supports-clkreq is > > > > > > present and PCIe link is up later. Because the CLKREQ# would be > > > > > > driven low by the card at this time. > > > > > > > > > > What happens if we clear the CLKREQ# override (so the host doesn't > > > > > assert it), and the link is up but the card never asserts CLKREQ# > > > > > (since it's an optional signal)? > > > > > > > > > > Does the i.MX host still work? > > > > > > > > The CLKREQ# override active low only be cleared when link is up > > > > and supports-clkreq is present. In the other words, there is a > > > > remote endpoint device, and the CLKREQ# would be driven active > > > > low by this endpoint device. > > > > > > Assume an endpoint designed to CEM r2.0. CLKREQ# doesn't exist in > > > CEM r2.0, so even if the endpoint is present and the link is up, > > > the endpoint will not assert CLKREQ#. > > > > > > Will the i.MX host still work? > > > > > > IIUC, CLKREQ# is required for ASPM L1 PM Substates. Maybe the > > > CLKREQ# override should only be cleared if the endpoint advertises > > > L1 PM Substates support? > > > > CLKREQ# override active low only be cleared when the endpoint > > advertises that it has L1 PM Substates support or it always drives > > CLKREQ# low. > > What? That's not what the patch does. It calls .clr_clkreq_override() > whenever the link is up and devicetree contains 'support-clkreq'. > > A device advertises L1 PM Substates support by putting the L1 PM > Substates Capability in its config space. Regardless L1SS state, EP will pull down CLKREQ# by spec requirement. 'support-clkreq' indicate board design connect this signal, so host needn't force it to low. Additional support-clkreq require use open drain to connect both EP and RC's CLKREQ#, some old board design use OR gate, which should not claim support-clkreq. The key point if CLKREQ# is connected. If clkreq# connected between EP and RC, we can release override. Frank > > > > > > > static void imx_pcie_host_post_init(struct dw_pcie_rp *pp) > > > > > > dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val); > > > > > > dw_pcie_dbi_ro_wr_dis(pci); > > > > > > } > > > > > > + > > > > > > + /* Clear CLKREQ# override if supports_clkreq is true and link is up */ > > > > > > + if (dw_pcie_link_up(pci) && imx_pcie->supports_clkreq) { > > > > > > + if (imx_pcie->drvdata->clr_clkreq_override) > > > > > > + imx_pcie->drvdata->clr_clkreq_override(imx_pcie); > > > > > > + } ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v5 0/2] PCI: imx6: Add a method to handle CLKREQ# override 2025-09-23 7:39 [PATCH v5 0/2] PCI: imx6: Add a method to handle CLKREQ# override Richard Zhu 2025-09-23 7:39 ` [PATCH v5 1/2] PCI: dwc: Invoke post_init in dw_pcie_resume_noirq() Richard Zhu 2025-09-23 7:39 ` [PATCH v5 2/2] PCI: imx6: Add a method to handle CLKREQ# override active low Richard Zhu @ 2025-09-25 17:05 ` Manivannan Sadhasivam 2 siblings, 0 replies; 16+ messages in thread From: Manivannan Sadhasivam @ 2025-09-25 17:05 UTC (permalink / raw) To: frank.li, jingoohan1, l.stach, lpieralisi, kwilczynski, robh, bhelgaas, shawnguo, s.hauer, kernel, festevam, Richard Zhu Cc: linux-pci, linux-arm-kernel, imx, linux-kernel On Tue, 23 Sep 2025 15:39:11 +0800, Richard Zhu wrote: > 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 > reserved. > > Since the reference clock controlled by CLKREQ# may be required by i.MX > PCIe host too. To make sure this clock is ready even when the CLKREQ# > isn't driven low by the card(e.x the scenario described above), force > CLKREQ# override active low for i.MX PCIe host during initialization. > > [...] Applied, thanks! [1/2] PCI: dwc: Invoke post_init in dw_pcie_resume_noirq() commit: 27afd094ea4be542594058d685c7af4654ab8de7 [2/2] PCI: imx6: Add a method to handle CLKREQ# override active low commit: dc853fb85d6b90e0805660c1dbb38ef7641af839 Best regards, -- Manivannan Sadhasivam <mani@kernel.org> ^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2025-10-03 17:21 UTC | newest] Thread overview: 16+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-09-23 7:39 [PATCH v5 0/2] PCI: imx6: Add a method to handle CLKREQ# override Richard Zhu 2025-09-23 7:39 ` [PATCH v5 1/2] PCI: dwc: Invoke post_init in dw_pcie_resume_noirq() Richard Zhu 2025-09-23 7:39 ` [PATCH v5 2/2] PCI: imx6: Add a method to handle CLKREQ# override active low Richard Zhu 2025-09-25 21:57 ` Bjorn Helgaas 2025-09-26 2:19 ` Hongxing Zhu 2025-09-25 22:04 ` Bjorn Helgaas 2025-09-26 2:19 ` Hongxing Zhu 2025-09-26 2:44 ` Bjorn Helgaas 2025-09-26 3:08 ` Hongxing Zhu 2025-09-26 20:25 ` Bjorn Helgaas 2025-09-26 22:46 ` Frank Li 2025-10-03 17:21 ` Bjorn Helgaas 2025-09-26 3:23 ` Hongxing Zhu 2025-09-26 20:24 ` Bjorn Helgaas 2025-09-26 22:58 ` Frank Li 2025-09-25 17:05 ` [PATCH v5 0/2] PCI: imx6: Add a method to handle CLKREQ# override Manivannan Sadhasivam
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).