diff mbox series

[v5,6/7] PCI: imx6: Add PLL clock lock check for i.MX95 PCIe

Message ID 20250408025930.1863551-7-hongxing.zhu@nxp.com (mailing list archive)
State New
Headers show
Series Add some enhancements for i.MX95 PCIe | expand

Commit Message

Hongxing Zhu April 8, 2025, 2:59 a.m. UTC
Add PLL clock lock check for i.MX95 PCIe.

Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/pci/controller/dwc/pci-imx6.c | 28 +++++++++++++++++++++++++--
 1 file changed, 26 insertions(+), 2 deletions(-)

Comments

Manivannan Sadhasivam April 13, 2025, 3:33 p.m. UTC | #1
On Tue, Apr 08, 2025 at 10:59:29AM +0800, Richard Zhu wrote:
> Add PLL clock lock check for i.MX95 PCIe.
> 
> Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
> Reviewed-by: Frank Li <Frank.Li@nxp.com>
> ---
>  drivers/pci/controller/dwc/pci-imx6.c | 28 +++++++++++++++++++++++++--
>  1 file changed, 26 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
> index 7dcc9d88740d..c1d128ec255d 100644
> --- a/drivers/pci/controller/dwc/pci-imx6.c
> +++ b/drivers/pci/controller/dwc/pci-imx6.c
> @@ -45,6 +45,9 @@
>  #define IMX95_PCIE_PHY_GEN_CTRL			0x0
>  #define IMX95_PCIE_REF_USE_PAD			BIT(17)
>  
> +#define IMX95_PCIE_PHY_MPLLA_CTRL		0x10
> +#define IMX95_PCIE_PHY_MPLL_STATE		BIT(30)
> +
>  #define IMX95_PCIE_SS_RW_REG_0			0xf0
>  #define IMX95_PCIE_REF_CLKEN			BIT(23)
>  #define IMX95_PCIE_PHY_CR_PARA_SEL		BIT(9)
> @@ -479,6 +482,23 @@ static void imx7d_pcie_wait_for_phy_pll_lock(struct imx_pcie *imx_pcie)
>  		dev_err(dev, "PCIe PLL lock timeout\n");
>  }
>  
> +static int imx95_pcie_wait_for_phy_pll_lock(struct imx_pcie *imx_pcie)
> +{
> +	u32 val;
> +	struct device *dev = imx_pcie->pci->dev;
> +
> +	if (regmap_read_poll_timeout(imx_pcie->iomuxc_gpr,
> +				     IMX95_PCIE_PHY_MPLLA_CTRL, val,
> +				     val & IMX95_PCIE_PHY_MPLL_STATE,
> +				     PHY_PLL_LOCK_WAIT_USLEEP_MAX,
> +				     PHY_PLL_LOCK_WAIT_TIMEOUT)) {
> +		dev_err(dev, "PCIe PLL lock timeout\n");
> +		return -ETIMEDOUT;
> +	}
> +
> +	return 0;
> +}
> +
>  static int imx_setup_phy_mpll(struct imx_pcie *imx_pcie)
>  {
>  	unsigned long phy_rate = 0;
> @@ -824,6 +844,8 @@ static int imx95_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert)
>  		regmap_read_bypassed(imx_pcie->iomuxc_gpr, IMX95_PCIE_RST_CTRL,
>  				     &val);
>  		udelay(10);
> +	} else {
> +		return imx95_pcie_wait_for_phy_pll_lock(imx_pcie);

Is this PLL lock related to COLD_RESET? It doesn't look like it. If unrelated,
it should be called wherever required. imx95_pcie_core_reset() is supposed to
only assert/deassert the COLD_RESET.

If related, please explain how.

- Mani
Hongxing Zhu April 14, 2025, 3:16 a.m. UTC | #2
> -----Original Message-----
> From: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
> Sent: 2025年4月13日 23:33
> To: Hongxing Zhu <hongxing.zhu@nxp.com>
> Cc: Frank Li <frank.li@nxp.com>; l.stach@pengutronix.de;
> lpieralisi@kernel.org; kw@linux.com; 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 6/7] PCI: imx6: Add PLL clock lock check for i.MX95
> PCIe
> 
> On Tue, Apr 08, 2025 at 10:59:29AM +0800, Richard Zhu wrote:
> > Add PLL clock lock check for i.MX95 PCIe.
> >
> > Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
> > Reviewed-by: Frank Li <Frank.Li@nxp.com>
> > ---
> >  drivers/pci/controller/dwc/pci-imx6.c | 28
> > +++++++++++++++++++++++++--
> >  1 file changed, 26 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/pci/controller/dwc/pci-imx6.c
> > b/drivers/pci/controller/dwc/pci-imx6.c
> > index 7dcc9d88740d..c1d128ec255d 100644
> > --- a/drivers/pci/controller/dwc/pci-imx6.c
> > +++ b/drivers/pci/controller/dwc/pci-imx6.c
> > @@ -45,6 +45,9 @@
> >  #define IMX95_PCIE_PHY_GEN_CTRL			0x0
> >  #define IMX95_PCIE_REF_USE_PAD			BIT(17)
> >
> > +#define IMX95_PCIE_PHY_MPLLA_CTRL		0x10
> > +#define IMX95_PCIE_PHY_MPLL_STATE		BIT(30)
> > +
> >  #define IMX95_PCIE_SS_RW_REG_0			0xf0
> >  #define IMX95_PCIE_REF_CLKEN			BIT(23)
> >  #define IMX95_PCIE_PHY_CR_PARA_SEL		BIT(9)
> > @@ -479,6 +482,23 @@ static void
> imx7d_pcie_wait_for_phy_pll_lock(struct imx_pcie *imx_pcie)
> >  		dev_err(dev, "PCIe PLL lock timeout\n");  }
> >
> > +static int imx95_pcie_wait_for_phy_pll_lock(struct imx_pcie
> > +*imx_pcie) {
> > +	u32 val;
> > +	struct device *dev = imx_pcie->pci->dev;
> > +
> > +	if (regmap_read_poll_timeout(imx_pcie->iomuxc_gpr,
> > +				     IMX95_PCIE_PHY_MPLLA_CTRL, val,
> > +				     val & IMX95_PCIE_PHY_MPLL_STATE,
> > +				     PHY_PLL_LOCK_WAIT_USLEEP_MAX,
> > +				     PHY_PLL_LOCK_WAIT_TIMEOUT)) {
> > +		dev_err(dev, "PCIe PLL lock timeout\n");
> > +		return -ETIMEDOUT;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> >  static int imx_setup_phy_mpll(struct imx_pcie *imx_pcie)  {
> >  	unsigned long phy_rate = 0;
> > @@ -824,6 +844,8 @@ static int imx95_pcie_core_reset(struct imx_pcie
> *imx_pcie, bool assert)
> >  		regmap_read_bypassed(imx_pcie->iomuxc_gpr,
> IMX95_PCIE_RST_CTRL,
> >  				     &val);
> >  		udelay(10);
> > +	} else {
> > +		return imx95_pcie_wait_for_phy_pll_lock(imx_pcie);
> 
> Is this PLL lock related to COLD_RESET? It doesn't look like it. If unrelated, it
> should be called wherever required. imx95_pcie_core_reset() is supposed to
> only assert/deassert the COLD_RESET.
> 
> If related, please explain how.
Thanks for your kindly review.
To make sure the HW state is correct to continue the sequential initializations.
The PLL lock or not check would be kicked off after the COLD_RESET is
 de-asserted for i.MX95 PCIe.
So, the PLL lock check is added at the end of de-assertion in
 imx95_pcie_core_reset() function.

Best Regards
Richard Zhu
> 
> - Mani
> 
> --
> மணிவண்ணன் சதாசிவம்
Manivannan Sadhasivam April 15, 2025, 7:20 a.m. UTC | #3
On Mon, Apr 14, 2025 at 03:16:46AM +0000, Hongxing Zhu wrote:
> > -----Original Message-----
> > From: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
> > Sent: 2025年4月13日 23:33
> > To: Hongxing Zhu <hongxing.zhu@nxp.com>
> > Cc: Frank Li <frank.li@nxp.com>; l.stach@pengutronix.de;
> > lpieralisi@kernel.org; kw@linux.com; 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 6/7] PCI: imx6: Add PLL clock lock check for i.MX95
> > PCIe
> > 
> > On Tue, Apr 08, 2025 at 10:59:29AM +0800, Richard Zhu wrote:
> > > Add PLL clock lock check for i.MX95 PCIe.
> > >
> > > Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
> > > Reviewed-by: Frank Li <Frank.Li@nxp.com>
> > > ---
> > >  drivers/pci/controller/dwc/pci-imx6.c | 28
> > > +++++++++++++++++++++++++--
> > >  1 file changed, 26 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/pci/controller/dwc/pci-imx6.c
> > > b/drivers/pci/controller/dwc/pci-imx6.c
> > > index 7dcc9d88740d..c1d128ec255d 100644
> > > --- a/drivers/pci/controller/dwc/pci-imx6.c
> > > +++ b/drivers/pci/controller/dwc/pci-imx6.c
> > > @@ -45,6 +45,9 @@
> > >  #define IMX95_PCIE_PHY_GEN_CTRL			0x0
> > >  #define IMX95_PCIE_REF_USE_PAD			BIT(17)
> > >
> > > +#define IMX95_PCIE_PHY_MPLLA_CTRL		0x10
> > > +#define IMX95_PCIE_PHY_MPLL_STATE		BIT(30)
> > > +
> > >  #define IMX95_PCIE_SS_RW_REG_0			0xf0
> > >  #define IMX95_PCIE_REF_CLKEN			BIT(23)
> > >  #define IMX95_PCIE_PHY_CR_PARA_SEL		BIT(9)
> > > @@ -479,6 +482,23 @@ static void
> > imx7d_pcie_wait_for_phy_pll_lock(struct imx_pcie *imx_pcie)
> > >  		dev_err(dev, "PCIe PLL lock timeout\n");  }
> > >
> > > +static int imx95_pcie_wait_for_phy_pll_lock(struct imx_pcie
> > > +*imx_pcie) {
> > > +	u32 val;
> > > +	struct device *dev = imx_pcie->pci->dev;
> > > +
> > > +	if (regmap_read_poll_timeout(imx_pcie->iomuxc_gpr,
> > > +				     IMX95_PCIE_PHY_MPLLA_CTRL, val,
> > > +				     val & IMX95_PCIE_PHY_MPLL_STATE,
> > > +				     PHY_PLL_LOCK_WAIT_USLEEP_MAX,
> > > +				     PHY_PLL_LOCK_WAIT_TIMEOUT)) {
> > > +		dev_err(dev, "PCIe PLL lock timeout\n");
> > > +		return -ETIMEDOUT;
> > > +	}
> > > +
> > > +	return 0;
> > > +}
> > > +
> > >  static int imx_setup_phy_mpll(struct imx_pcie *imx_pcie)  {
> > >  	unsigned long phy_rate = 0;
> > > @@ -824,6 +844,8 @@ static int imx95_pcie_core_reset(struct imx_pcie
> > *imx_pcie, bool assert)
> > >  		regmap_read_bypassed(imx_pcie->iomuxc_gpr,
> > IMX95_PCIE_RST_CTRL,
> > >  				     &val);
> > >  		udelay(10);
> > > +	} else {
> > > +		return imx95_pcie_wait_for_phy_pll_lock(imx_pcie);
> > 
> > Is this PLL lock related to COLD_RESET? It doesn't look like it. If unrelated, it
> > should be called wherever required. imx95_pcie_core_reset() is supposed to
> > only assert/deassert the COLD_RESET.
> > 
> > If related, please explain how.
> Thanks for your kindly review.
> To make sure the HW state is correct to continue the sequential initializations.
> The PLL lock or not check would be kicked off after the COLD_RESET is
>  de-asserted for i.MX95 PCIe.
> So, the PLL lock check is added at the end of de-assertion in
>  imx95_pcie_core_reset() function.
> 

But imx95_pcie_core_reset() is not doing anything for deassert other than
waiting for PLL lock. Hence my question.

- Mani
diff mbox series

Patch

diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index 7dcc9d88740d..c1d128ec255d 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -45,6 +45,9 @@ 
 #define IMX95_PCIE_PHY_GEN_CTRL			0x0
 #define IMX95_PCIE_REF_USE_PAD			BIT(17)
 
+#define IMX95_PCIE_PHY_MPLLA_CTRL		0x10
+#define IMX95_PCIE_PHY_MPLL_STATE		BIT(30)
+
 #define IMX95_PCIE_SS_RW_REG_0			0xf0
 #define IMX95_PCIE_REF_CLKEN			BIT(23)
 #define IMX95_PCIE_PHY_CR_PARA_SEL		BIT(9)
@@ -479,6 +482,23 @@  static void imx7d_pcie_wait_for_phy_pll_lock(struct imx_pcie *imx_pcie)
 		dev_err(dev, "PCIe PLL lock timeout\n");
 }
 
+static int imx95_pcie_wait_for_phy_pll_lock(struct imx_pcie *imx_pcie)
+{
+	u32 val;
+	struct device *dev = imx_pcie->pci->dev;
+
+	if (regmap_read_poll_timeout(imx_pcie->iomuxc_gpr,
+				     IMX95_PCIE_PHY_MPLLA_CTRL, val,
+				     val & IMX95_PCIE_PHY_MPLL_STATE,
+				     PHY_PLL_LOCK_WAIT_USLEEP_MAX,
+				     PHY_PLL_LOCK_WAIT_TIMEOUT)) {
+		dev_err(dev, "PCIe PLL lock timeout\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
 static int imx_setup_phy_mpll(struct imx_pcie *imx_pcie)
 {
 	unsigned long phy_rate = 0;
@@ -824,6 +844,8 @@  static int imx95_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert)
 		regmap_read_bypassed(imx_pcie->iomuxc_gpr, IMX95_PCIE_RST_CTRL,
 				     &val);
 		udelay(10);
+	} else {
+		return imx95_pcie_wait_for_phy_pll_lock(imx_pcie);
 	}
 
 	return 0;
@@ -843,11 +865,13 @@  static void imx_pcie_assert_core_reset(struct imx_pcie *imx_pcie)
 
 static int imx_pcie_deassert_core_reset(struct imx_pcie *imx_pcie)
 {
+	int ret = 0;
+
 	reset_control_deassert(imx_pcie->pciephy_reset);
 	reset_control_deassert(imx_pcie->apps_reset);
 
 	if (imx_pcie->drvdata->core_reset)
-		imx_pcie->drvdata->core_reset(imx_pcie, false);
+		ret = imx_pcie->drvdata->core_reset(imx_pcie, false);
 
 	/* Some boards don't have PCIe reset GPIO. */
 	if (imx_pcie->reset_gpiod) {
@@ -857,7 +881,7 @@  static int imx_pcie_deassert_core_reset(struct imx_pcie *imx_pcie)
 		msleep(100);
 	}
 
-	return 0;
+	return ret;
 }
 
 static int imx_pcie_wait_for_speed_change(struct imx_pcie *imx_pcie)