diff mbox series

[v6,7/8] PCI: imx6: Disable enabled clocks and regulators after link is down

Message ID 1644290735-3797-8-git-send-email-hongxing.zhu@nxp.com
State New
Headers show
Series PCI: imx6: refine codes and add compliance tests mode support | expand

Commit Message

Hongxing Zhu Feb. 8, 2022, 3:25 a.m. UTC
Since i.MX PCIe doesn't support the hot-plug, and to save power
consumption as much as possible. Return error and disable the enabled
clocks and regulators when link is down,.

Add a new host_exit() callback for i.MX PCIe driver to disable the
enabled clocks, regulators and so on in the error handling after
host_init is finished.

Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
---
 drivers/pci/controller/dwc/pci-imx6.c | 30 ++++++++++++++++++++++++---
 1 file changed, 27 insertions(+), 3 deletions(-)

Comments

Fabio Estevam Feb. 8, 2022, 10:09 a.m. UTC | #1
Hi Richard,

On Tue, Feb 8, 2022 at 12:57 AM Richard Zhu <hongxing.zhu@nxp.com> wrote:
>
> Since i.MX PCIe doesn't support the hot-plug, and to save power
> consumption as much as possible. Return error and disable the enabled
> clocks and regulators when link is down,.

It is OK to disable clocks and regulators, but I don't think we should
return an error on dw_pcie_wait_for_link() failure.

Please check:

https://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/pci.git/commit/?h=pci/imx6&id=f81f095e87715e198471f4653952fe5e3f824874

and

https://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/pci.git/commit/?h=pci/imx6&id=886a9c134755

as to why all the dwc PCI drivers should treat dw_pcie_wait_for_link()
uniformly.






>
> Add a new host_exit() callback for i.MX PCIe driver to disable the
> enabled clocks, regulators and so on in the error handling after
> host_init is finished.
>
> Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
> ---
>  drivers/pci/controller/dwc/pci-imx6.c | 30 ++++++++++++++++++++++++---
>  1 file changed, 27 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
> index e165ad00989c..7a7d9204c6bc 100644
> --- a/drivers/pci/controller/dwc/pci-imx6.c
> +++ b/drivers/pci/controller/dwc/pci-imx6.c
> @@ -848,7 +848,9 @@ static int imx6_pcie_start_link(struct dw_pcie *pci)
>         /* Start LTSSM. */
>         imx6_pcie_ltssm_enable(dev);
>
> -       dw_pcie_wait_for_link(pci);
> +       ret = dw_pcie_wait_for_link(pci);
> +       if (ret)
> +               goto err_reset_phy;
>
>         if (pci->link_gen == 2) {
>                 /* Allow Gen2 mode after the link is up. */
> @@ -884,7 +886,9 @@ static int imx6_pcie_start_link(struct dw_pcie *pci)
>                 }
>
>                 /* Make sure link training is finished as well! */
> -               dw_pcie_wait_for_link(pci);
> +               ret = dw_pcie_wait_for_link(pci);
> +               if (ret)
> +                       goto err_reset_phy;
>         } else {
>                 dev_info(dev, "Link: Gen2 disabled\n");
>         }
> @@ -897,7 +901,6 @@ static int imx6_pcie_start_link(struct dw_pcie *pci)
>         dev_dbg(dev, "PHY DEBUG_R0=0x%08x DEBUG_R1=0x%08x\n",
>                 dw_pcie_readl_dbi(pci, PCIE_PORT_DEBUG0),
>                 dw_pcie_readl_dbi(pci, PCIE_PORT_DEBUG1));
> -       imx6_pcie_reset_phy(imx6_pcie);
>         return ret;
>  }
>
> @@ -921,8 +924,29 @@ static int imx6_pcie_host_init(struct pcie_port *pp)
>         return 0;
>  }
>
> +static void imx6_pcie_host_exit(struct pcie_port *pp)
> +{
> +       struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> +       struct device *dev = pci->dev;
> +       struct imx6_pcie *imx6_pcie = to_imx6_pcie(pci);
> +
> +       imx6_pcie_reset_phy(imx6_pcie);
> +       imx6_pcie_clk_disable(imx6_pcie);
> +       switch (imx6_pcie->drvdata->variant) {
> +       case IMX8MM:
> +               if (phy_power_off(imx6_pcie->phy))
> +                       dev_err(dev, "unable to power off phy\n");
> +               break;
> +       default:
> +               break;
> +       }
> +       if (imx6_pcie->vpcie)
> +               regulator_disable(imx6_pcie->vpcie);
> +}
> +
>  static const struct dw_pcie_host_ops imx6_pcie_host_ops = {
>         .host_init = imx6_pcie_host_init,
> +       .host_exit = imx6_pcie_host_exit,
>  };
>
>  static const struct dw_pcie_ops dw_pcie_ops = {
> --
> 2.25.1
>
Hongxing Zhu Feb. 9, 2022, 1:56 a.m. UTC | #2
> -----Original Message-----
> From: Fabio Estevam <festevam@gmail.com>
> Sent: 2022年2月8日 18:10
> To: Hongxing Zhu <hongxing.zhu@nxp.com>
> Cc: Lucas Stach <l.stach@pengutronix.de>; Bjorn Helgaas
> <bhelgaas@google.com>; Mark Brown <broonie@kernel.org>; Lorenzo Pieralisi
> <lorenzo.pieralisi@arm.com>; Jingoo Han <jingoohan1@gmail.com>;
> linux-pci@vger.kernel.org; dl-linux-imx <linux-imx@nxp.com>; moderated
> list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
> <linux-arm-kernel@lists.infradead.org>; linux-kernel
> <linux-kernel@vger.kernel.org>; Sascha Hauer <kernel@pengutronix.de>
> Subject: Re: [PATCH v6 7/8] PCI: imx6: Disable enabled clocks and regulators
> after link is down
> 
> Hi Richard,
> 
> On Tue, Feb 8, 2022 at 12:57 AM Richard Zhu <hongxing.zhu@nxp.com>
> wrote:
> >
> > Since i.MX PCIe doesn't support the hot-plug, and to save power
> > consumption as much as possible. Return error and disable the enabled
> > clocks and regulators when link is down,.
> 
> It is OK to disable clocks and regulators, but I don't think we should return an
> error on dw_pcie_wait_for_link() failure.
Hi Fabio:
Thanks for your review.
How do we know there is a link down, if we don't return an error on the
 dw_pcie_wait_for_link() after host_init callback.

Do you mean that we should ignore the return of dw_pcie_host_init() and
finish the _probe without an error return?
Best Regards
Richard
> 
> Please check:
> 
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit.kern
> el.org%2Fpub%2Fscm%2Flinux%2Fkernel%2Fgit%2Flpieralisi%2Fpci.git%2Fco
> mmit%2F%3Fh%3Dpci%2Fimx6%26id%3Df81f095e87715e198471f4653952fe
> 5e3f824874&amp;data=04%7C01%7Chongxing.zhu%40nxp.com%7C3630184
> 5833b41f1f70a08d9eaeb2519%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C
> 0%7C0%7C637799117928160088%7CUnknown%7CTWFpbGZsb3d8eyJWIjoi
> MC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C300
> 0&amp;sdata=UUF%2FbZNUy7T4d89sJKnPvN6kNxEB%2FhnSUbIze7ilUOA%3D
> &amp;reserved=0
> 
> and
> 
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit.kern
> el.org%2Fpub%2Fscm%2Flinux%2Fkernel%2Fgit%2Flpieralisi%2Fpci.git%2Fco
> mmit%2F%3Fh%3Dpci%2Fimx6%26id%3D886a9c134755&amp;data=04%7C0
> 1%7Chongxing.zhu%40nxp.com%7C36301845833b41f1f70a08d9eaeb2519%7
> C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C63779911792816008
> 8%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiL
> CJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&amp;sdata=FO0wr4IE%2BA6YCu
> f0Lal2az8FRkK8ZvHkmLM%2F5zlosZY%3D&amp;reserved=0
> 
> as to why all the dwc PCI drivers should treat dw_pcie_wait_for_link()
> uniformly.
> 
> 
> 
> 
> 
> 
> >
> > Add a new host_exit() callback for i.MX PCIe driver to disable the
> > enabled clocks, regulators and so on in the error handling after
> > host_init is finished.
> >
> > Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
> > ---
> >  drivers/pci/controller/dwc/pci-imx6.c | 30
> > ++++++++++++++++++++++++---
> >  1 file changed, 27 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/pci/controller/dwc/pci-imx6.c
> > b/drivers/pci/controller/dwc/pci-imx6.c
> > index e165ad00989c..7a7d9204c6bc 100644
> > --- a/drivers/pci/controller/dwc/pci-imx6.c
> > +++ b/drivers/pci/controller/dwc/pci-imx6.c
> > @@ -848,7 +848,9 @@ static int imx6_pcie_start_link(struct dw_pcie *pci)
> >         /* Start LTSSM. */
> >         imx6_pcie_ltssm_enable(dev);
> >
> > -       dw_pcie_wait_for_link(pci);
> > +       ret = dw_pcie_wait_for_link(pci);
> > +       if (ret)
> > +               goto err_reset_phy;
> >
> >         if (pci->link_gen == 2) {
> >                 /* Allow Gen2 mode after the link is up. */ @@ -884,7
> > +886,9 @@ static int imx6_pcie_start_link(struct dw_pcie *pci)
> >                 }
> >
> >                 /* Make sure link training is finished as well! */
> > -               dw_pcie_wait_for_link(pci);
> > +               ret = dw_pcie_wait_for_link(pci);
> > +               if (ret)
> > +                       goto err_reset_phy;
> >         } else {
> >                 dev_info(dev, "Link: Gen2 disabled\n");
> >         }
> > @@ -897,7 +901,6 @@ static int imx6_pcie_start_link(struct dw_pcie *pci)
> >         dev_dbg(dev, "PHY DEBUG_R0=0x%08x DEBUG_R1=0x%08x\n",
> >                 dw_pcie_readl_dbi(pci, PCIE_PORT_DEBUG0),
> >                 dw_pcie_readl_dbi(pci, PCIE_PORT_DEBUG1));
> > -       imx6_pcie_reset_phy(imx6_pcie);
> >         return ret;
> >  }
> >
> > @@ -921,8 +924,29 @@ static int imx6_pcie_host_init(struct pcie_port *pp)
> >         return 0;
> >  }
> >
> > +static void imx6_pcie_host_exit(struct pcie_port *pp) {
> > +       struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > +       struct device *dev = pci->dev;
> > +       struct imx6_pcie *imx6_pcie = to_imx6_pcie(pci);
> > +
> > +       imx6_pcie_reset_phy(imx6_pcie);
> > +       imx6_pcie_clk_disable(imx6_pcie);
> > +       switch (imx6_pcie->drvdata->variant) {
> > +       case IMX8MM:
> > +               if (phy_power_off(imx6_pcie->phy))
> > +                       dev_err(dev, "unable to power off phy\n");
> > +               break;
> > +       default:
> > +               break;
> > +       }
> > +       if (imx6_pcie->vpcie)
> > +               regulator_disable(imx6_pcie->vpcie);
> > +}
> > +
> >  static const struct dw_pcie_host_ops imx6_pcie_host_ops = {
> >         .host_init = imx6_pcie_host_init,
> > +       .host_exit = imx6_pcie_host_exit,
> >  };
> >
> >  static const struct dw_pcie_ops dw_pcie_ops = {
> > --
> > 2.25.1
> >
Fabio Estevam Feb. 9, 2022, 2:01 a.m. UTC | #3
Hi Richard,

On Tue, Feb 8, 2022 at 10:56 PM Hongxing Zhu <hongxing.zhu@nxp.com> wrote:

> Do you mean that we should ignore the return of dw_pcie_host_init() and
> finish the _probe without an error return?

Yes, we should not return an error on probe if the link is down.

Thanks
Hongxing Zhu Feb. 9, 2022, 3:32 a.m. UTC | #4
> -----Original Message-----
> From: Fabio Estevam <festevam@gmail.com>
> Sent: 2022年2月9日 10:02
> To: Hongxing Zhu <hongxing.zhu@nxp.com>
> Cc: Lucas Stach <l.stach@pengutronix.de>; Bjorn Helgaas
> <bhelgaas@google.com>; Mark Brown <broonie@kernel.org>; Lorenzo Pieralisi
> <lorenzo.pieralisi@arm.com>; Jingoo Han <jingoohan1@gmail.com>;
> linux-pci@vger.kernel.org; dl-linux-imx <linux-imx@nxp.com>; moderated
> list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
> <linux-arm-kernel@lists.infradead.org>; linux-kernel
> <linux-kernel@vger.kernel.org>; Sascha Hauer <kernel@pengutronix.de>
> Subject: Re: [PATCH v6 7/8] PCI: imx6: Disable enabled clocks and regulators
> after link is down
> 
> Hi Richard,
> 
> On Tue, Feb 8, 2022 at 10:56 PM Hongxing Zhu <hongxing.zhu@nxp.com>
> wrote:
> 
> > Do you mean that we should ignore the return of dw_pcie_host_init()
> > and finish the _probe without an error return?
> 
> Yes, we should not return an error on probe if the link is down.
> 
> Thanks
Hi Fabio:
Regarding my understand, the suspend/resume callbacks would be hooked if the
 probe is complete successfully. There would be extra more than 100ms delay
 in every system resume operations.
I'm afraid that it would bring bad experience for the power management.

Is there a policy that we should obey, and let the probe complete without
an error return?
If yes, I can follow your suggestion, wouldn't return an error on probe when
link is down.

Thanks.
Best Regards
Richard Zhu
diff mbox series

Patch

diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index e165ad00989c..7a7d9204c6bc 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -848,7 +848,9 @@  static int imx6_pcie_start_link(struct dw_pcie *pci)
 	/* Start LTSSM. */
 	imx6_pcie_ltssm_enable(dev);
 
-	dw_pcie_wait_for_link(pci);
+	ret = dw_pcie_wait_for_link(pci);
+	if (ret)
+		goto err_reset_phy;
 
 	if (pci->link_gen == 2) {
 		/* Allow Gen2 mode after the link is up. */
@@ -884,7 +886,9 @@  static int imx6_pcie_start_link(struct dw_pcie *pci)
 		}
 
 		/* Make sure link training is finished as well! */
-		dw_pcie_wait_for_link(pci);
+		ret = dw_pcie_wait_for_link(pci);
+		if (ret)
+			goto err_reset_phy;
 	} else {
 		dev_info(dev, "Link: Gen2 disabled\n");
 	}
@@ -897,7 +901,6 @@  static int imx6_pcie_start_link(struct dw_pcie *pci)
 	dev_dbg(dev, "PHY DEBUG_R0=0x%08x DEBUG_R1=0x%08x\n",
 		dw_pcie_readl_dbi(pci, PCIE_PORT_DEBUG0),
 		dw_pcie_readl_dbi(pci, PCIE_PORT_DEBUG1));
-	imx6_pcie_reset_phy(imx6_pcie);
 	return ret;
 }
 
@@ -921,8 +924,29 @@  static int imx6_pcie_host_init(struct pcie_port *pp)
 	return 0;
 }
 
+static void imx6_pcie_host_exit(struct pcie_port *pp)
+{
+	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+	struct device *dev = pci->dev;
+	struct imx6_pcie *imx6_pcie = to_imx6_pcie(pci);
+
+	imx6_pcie_reset_phy(imx6_pcie);
+	imx6_pcie_clk_disable(imx6_pcie);
+	switch (imx6_pcie->drvdata->variant) {
+	case IMX8MM:
+		if (phy_power_off(imx6_pcie->phy))
+			dev_err(dev, "unable to power off phy\n");
+		break;
+	default:
+		break;
+	}
+	if (imx6_pcie->vpcie)
+		regulator_disable(imx6_pcie->vpcie);
+}
+
 static const struct dw_pcie_host_ops imx6_pcie_host_ops = {
 	.host_init = imx6_pcie_host_init,
+	.host_exit = imx6_pcie_host_exit,
 };
 
 static const struct dw_pcie_ops dw_pcie_ops = {