Re: [PATCH v12 8/8] PCI: endpoint: Remove "core_init_notifier" flag

2024-03-29 Thread Frank Li
On Wed, Mar 27, 2024 at 02:43:37PM +0530, Manivannan Sadhasivam wrote:
> "core_init_notifier" flag is set by the glue drivers requiring refclk from
> the host to complete the DWC core initialization. Also, those drivers will
> send a notification to the EPF drivers once the initialization is fully
> completed using the pci_epc_init_notify() API. Only then, the EPF drivers
> will start functioning.
> 
> For the rest of the drivers generating refclk locally, EPF drivers will
> start functioning post binding with them. EPF drivers rely on the
> 'core_init_notifier' flag to differentiate between the drivers.
> Unfortunately, this creates two different flows for the EPF drivers.
> 
> So to avoid that, let's get rid of the "core_init_notifier" flag and follow
> a single initialization flow for the EPF drivers. This is done by calling
> the dw_pcie_ep_init_notify() from all glue drivers after the completion of
> dw_pcie_ep_init_registers() API. This will allow all the glue drivers to
> send the notification to the EPF drivers once the initialization is fully
> completed.
> 
> Only difference here is that, the drivers requiring refclk from host will
> send the notification once refclk is received, while others will send it
> during probe time itself.
> 
> But this also requires the EPC core driver to deliver the notification
> after EPF driver bind. Because, the glue driver can send the notification
> before the EPF drivers bind() and in those cases the EPF drivers will miss
> the event. To accommodate this, EPC core is now caching the state of the
> EPC initialization in 'init_complete' flag and pci-ep-cfs driver sends the
> notification to EPF drivers based on that after each EPF driver bind.
> 
> Tested-by: Niklas Cassel 

Reviewed-by: Frank Li 

> Signed-off-by: Manivannan Sadhasivam 
> ---
>  drivers/pci/controller/cadence/pcie-cadence-ep.c  |  2 ++
>  drivers/pci/controller/dwc/pci-dra7xx.c   |  2 ++
>  drivers/pci/controller/dwc/pci-imx6.c |  2 ++
>  drivers/pci/controller/dwc/pci-keystone.c |  2 ++
>  drivers/pci/controller/dwc/pci-layerscape-ep.c|  2 ++
>  drivers/pci/controller/dwc/pcie-artpec6.c |  2 ++
>  drivers/pci/controller/dwc/pcie-designware-ep.c   |  1 +
>  drivers/pci/controller/dwc/pcie-designware-plat.c |  2 ++
>  drivers/pci/controller/dwc/pcie-keembay.c |  2 ++
>  drivers/pci/controller/dwc/pcie-qcom-ep.c |  1 -
>  drivers/pci/controller/dwc/pcie-rcar-gen4.c   |  2 ++
>  drivers/pci/controller/dwc/pcie-tegra194.c|  1 -
>  drivers/pci/controller/dwc/pcie-uniphier-ep.c |  2 ++
>  drivers/pci/controller/pcie-rcar-ep.c |  2 ++
>  drivers/pci/controller/pcie-rockchip-ep.c |  2 ++
>  drivers/pci/endpoint/functions/pci-epf-test.c | 18 +-
>  drivers/pci/endpoint/pci-ep-cfs.c |  9 +
>  drivers/pci/endpoint/pci-epc-core.c   | 22 ++
>  include/linux/pci-epc.h   |  7 ---
>  19 files changed, 65 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/pci/controller/cadence/pcie-cadence-ep.c 
> b/drivers/pci/controller/cadence/pcie-cadence-ep.c
> index 81c50dc64da9..55c42ca2b777 100644
> --- a/drivers/pci/controller/cadence/pcie-cadence-ep.c
> +++ b/drivers/pci/controller/cadence/pcie-cadence-ep.c
> @@ -746,6 +746,8 @@ int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep)
>  
>   spin_lock_init(>lock);
>  
> + pci_epc_init_notify(epc);
> +
>   return 0;
>  
>   free_epc_mem:
> diff --git a/drivers/pci/controller/dwc/pci-dra7xx.c 
> b/drivers/pci/controller/dwc/pci-dra7xx.c
> index 395042b29ffc..d2d17d37d3e0 100644
> --- a/drivers/pci/controller/dwc/pci-dra7xx.c
> +++ b/drivers/pci/controller/dwc/pci-dra7xx.c
> @@ -474,6 +474,8 @@ static int dra7xx_add_pcie_ep(struct dra7xx_pcie *dra7xx,
>   return ret;
>   }
>  
> + dw_pcie_ep_init_notify(ep);
> +
>   return 0;
>  }
>  
> diff --git a/drivers/pci/controller/dwc/pci-imx6.c 
> b/drivers/pci/controller/dwc/pci-imx6.c
> index 8d28ecc381bc..917c69edee1d 100644
> --- a/drivers/pci/controller/dwc/pci-imx6.c
> +++ b/drivers/pci/controller/dwc/pci-imx6.c
> @@ -1131,6 +1131,8 @@ static int imx6_add_pcie_ep(struct imx6_pcie *imx6_pcie,
>   return ret;
>   }
>  
> + dw_pcie_ep_init_notify(ep);
> +
>   /* Start LTSSM. */
>   imx6_pcie_ltssm_enable(dev);
>  
> diff --git a/drivers/pci/controller/dwc/pci-keystone.c 
> b/drivers/pci/controller/dwc/pci-keystone.c
> index 81ebac520650..d3a7d14ee685 100644
> --- a/drivers/pci/controller/dwc/pci-keystone.c
> +++ b/drivers/pci/controller/dwc/pci-keystone.c

Re: [PATCH v12 7/8] PCI: dwc: ep: Call dw_pcie_ep_init_registers() API directly from all glue drivers

2024-03-29 Thread Frank Li
On Wed, Mar 27, 2024 at 02:43:36PM +0530, Manivannan Sadhasivam wrote:
> Currently, dw_pcie_ep_init_registers() API is directly called by the glue
> drivers requiring active refclk from host. But for the other drivers, it is
> getting called implicitly by dw_pcie_ep_init(). This is due to the fact
> that this API initializes DWC EP specific registers and that requires an
> active refclk (either from host or generated locally by endpoint itsef).
> 
> But, this causes a discrepancy among the glue drivers. So to avoid this
> confusion, let's call this API directly from all glue drivers irrespective
> of refclk dependency. Only difference here is that the drivers requiring
> refclk from host will call this API only after the refclk is received and
> other drivers without refclk dependency will call this API right after
> dw_pcie_ep_init().
> 
> With this change, the check for 'core_init_notifier' flag can now be
> dropped from dw_pcie_ep_init() API. This will also allow us to remove the
> 'core_init_notifier' flag completely in the later commits.
> 
> Reviewed-by: Yoshihiro Shimoda 
> Reviewed-by: Niklas Cassel 

Reviewed-by: Frank Li 

> Signed-off-by: Manivannan Sadhasivam 
> ---
>  drivers/pci/controller/dwc/pci-dra7xx.c   |  7 +++
>  drivers/pci/controller/dwc/pci-imx6.c |  8 
>  drivers/pci/controller/dwc/pci-keystone.c |  9 +
>  drivers/pci/controller/dwc/pci-layerscape-ep.c|  7 +++
>  drivers/pci/controller/dwc/pcie-artpec6.c | 13 -
>  drivers/pci/controller/dwc/pcie-designware-ep.c   | 22 --
>  drivers/pci/controller/dwc/pcie-designware-plat.c |  9 +
>  drivers/pci/controller/dwc/pcie-keembay.c | 16 +++-
>  drivers/pci/controller/dwc/pcie-rcar-gen4.c   | 12 +++-
>  drivers/pci/controller/dwc/pcie-uniphier-ep.c | 13 -
>  10 files changed, 90 insertions(+), 26 deletions(-)
> 
> diff --git a/drivers/pci/controller/dwc/pci-dra7xx.c 
> b/drivers/pci/controller/dwc/pci-dra7xx.c
> index 0e406677060d..395042b29ffc 100644
> --- a/drivers/pci/controller/dwc/pci-dra7xx.c
> +++ b/drivers/pci/controller/dwc/pci-dra7xx.c
> @@ -467,6 +467,13 @@ static int dra7xx_add_pcie_ep(struct dra7xx_pcie *dra7xx,
>   return ret;
>   }
>  
> + ret = dw_pcie_ep_init_registers(ep);
> + if (ret) {
> + dev_err(dev, "Failed to initialize DWC endpoint registers\n");
> + dw_pcie_ep_deinit(ep);
> + return ret;
> + }
> +
>   return 0;
>  }
>  
> diff --git a/drivers/pci/controller/dwc/pci-imx6.c 
> b/drivers/pci/controller/dwc/pci-imx6.c
> index 99a60270b26c..8d28ecc381bc 100644
> --- a/drivers/pci/controller/dwc/pci-imx6.c
> +++ b/drivers/pci/controller/dwc/pci-imx6.c
> @@ -1123,6 +1123,14 @@ static int imx6_add_pcie_ep(struct imx6_pcie 
> *imx6_pcie,
>   dev_err(dev, "failed to initialize endpoint\n");
>   return ret;
>   }
> +
> + ret = dw_pcie_ep_init_registers(ep);
> + if (ret) {
> + dev_err(dev, "Failed to initialize DWC endpoint registers\n");
> + dw_pcie_ep_deinit(ep);
> + return ret;
> + }
> +
>   /* Start LTSSM. */
>   imx6_pcie_ltssm_enable(dev);
>  
> diff --git a/drivers/pci/controller/dwc/pci-keystone.c 
> b/drivers/pci/controller/dwc/pci-keystone.c
> index 844de4418724..81ebac520650 100644
> --- a/drivers/pci/controller/dwc/pci-keystone.c
> +++ b/drivers/pci/controller/dwc/pci-keystone.c
> @@ -1286,6 +1286,13 @@ static int ks_pcie_probe(struct platform_device *pdev)
>   ret = dw_pcie_ep_init(>ep);
>   if (ret < 0)
>   goto err_get_sync;
> +
> + ret = dw_pcie_ep_init_registers(>ep);
> + if (ret) {
> + dev_err(dev, "Failed to initialize DWC endpoint 
> registers\n");
> + goto err_ep_init;
> + }
> +
>   break;
>   default:
>   dev_err(dev, "INVALID device type %d\n", mode);
> @@ -1295,6 +1302,8 @@ static int ks_pcie_probe(struct platform_device *pdev)
>  
>   return 0;
>  
> +err_ep_init:
> + dw_pcie_ep_deinit(>ep);
>  err_get_sync:
>   pm_runtime_put(dev);
>   pm_runtime_disable(dev);
> diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
> b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> index 1f6ee1460ec2..9eb2233e3d7f 100644
> --- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
> +++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> @@ -279,6 +279,13 @@ static i

[PATCH 1/1] PCI: layerscape(ep): Implement common 'dbi' reg-names for dbi_base

2024-02-29 Thread Frank Li
Apply 'dbi' as the primary name for dbi_base register space in line with
Designware common binding. Attempt resource acquisition using 'dbi' first
via platform_get_resource_byname(). If encountering older device tree
files, gracefully fallback to 'regs', issuing a warning message.

Signed-off-by: Frank Li 
---
 drivers/pci/controller/dwc/pci-layerscape-ep.c | 7 ++-
 drivers/pci/controller/dwc/pci-layerscape.c| 7 ++-
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index 1f6ee1460ec2a..92d4750611d07 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -259,7 +259,12 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
pcie->pci = pci;
pcie->ls_epc = ls_epc;
 
-   dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
+   dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
+   if (!dbi_base) {
+   dev_warn(dev, "Please update your dtb, reg-names 'regs' should 
be 'dbi'");
+   dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, 
"regs");
+   }
+
pci->dbi_base = devm_pci_remap_cfg_resource(dev, dbi_base);
if (IS_ERR(pci->dbi_base))
return PTR_ERR(pci->dbi_base);
diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index ee6f525681337..1985086f6a1f3 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -345,7 +345,12 @@ static int ls_pcie_probe(struct platform_device *pdev)
pcie->pci = pci;
pci->pp.ops = pcie->drvdata->ops;
 
-   dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
+   dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
+   if (!dbi_base) {
+   dev_err(dev, "Please update your dtb, reg-names 'regs' should 
be 'dbi'");
+   dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, 
"regs");
+   }
+
pci->dbi_base = devm_pci_remap_cfg_resource(dev, dbi_base);
if (IS_ERR(pci->dbi_base))
return PTR_ERR(pci->dbi_base);
-- 
2.34.1



Re: [PATCH v8 09/10] PCI: qcom-ep: Use the generic dw_pcie_ep_linkdown() API to handle LINK_DOWN event

2024-02-27 Thread Frank Li
On Tue, Feb 27, 2024 at 06:02:30PM +0530, Manivannan Sadhasivam wrote:
> On Mon, Feb 26, 2024 at 12:20:41PM -0500, Frank Li wrote:
> > On Sat, Feb 24, 2024 at 12:24:15PM +0530, Manivannan Sadhasivam wrote:
> > > Now that the API is available, let's make use of it. It also handles the
> > > reinitialization of DWC non-sticky registers in addition to sending the
> > > notification to EPF drivers.
> > > 
> > > Signed-off-by: Manivannan Sadhasivam 
> > > ---
> > >  drivers/pci/controller/dwc/pcie-qcom-ep.c | 2 +-
> > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > 
> > > diff --git a/drivers/pci/controller/dwc/pcie-qcom-ep.c 
> > > b/drivers/pci/controller/dwc/pcie-qcom-ep.c
> > > index 2fb8c15e7a91..4e45bc4bca45 100644
> > > --- a/drivers/pci/controller/dwc/pcie-qcom-ep.c
> > > +++ b/drivers/pci/controller/dwc/pcie-qcom-ep.c
> > > @@ -640,7 +640,7 @@ static irqreturn_t qcom_pcie_ep_global_irq_thread(int 
> > > irq, void *data)
> > >   if (FIELD_GET(PARF_INT_ALL_LINK_DOWN, status)) {
> > >   dev_dbg(dev, "Received Linkdown event\n");
> > >   pcie_ep->link_status = QCOM_PCIE_EP_LINK_DOWN;
> > > - pci_epc_linkdown(pci->ep.epc);
> > > + dw_pcie_ep_linkdown(>ep);
> > 
> > Suppose pci_epc_linkdown() will call dw_pcie_ep_linkdown() ?
> > why need direct call dw_pcie_ep_linkdown() here?
> > 
> 
> I've already justified this in the commit message. Here is the excerpt:
> 
> "It also handles the reinitialization of DWC non-sticky registers in addition
> to sending the notification to EPF drivers."

API function name is too similar. It is hard to know difference from API
naming. It'd better to know what function do from function name.

Frank
> 
> - Mani
> 
> -- 
> மணிவண்ணன் சதாசிவம்


Re: [PATCH v8 06/10] PCI: dwc: ep: Call dw_pcie_ep_init_registers() API directly from all glue drivers

2024-02-27 Thread Frank Li
On Tue, Feb 27, 2024 at 05:51:41PM +0530, Manivannan Sadhasivam wrote:
> On Mon, Feb 26, 2024 at 12:04:33PM -0500, Frank Li wrote:
> > On Sat, Feb 24, 2024 at 12:24:12PM +0530, Manivannan Sadhasivam wrote:
> > > Currently, dw_pcie_ep_init_registers() API is directly called by the glue
> > > drivers requiring active refclk from host. But for the other drivers, it 
> > > is
> > > getting called implicitly by dw_pcie_ep_init(). This is due to the fact
> > > that this API initializes DWC EP specific registers and that requires an
> > > active refclk (either from host or generated locally by endpoint itsef).
> > > 
> > > But, this causes a discrepancy among the glue drivers. So to avoid this
> > > confusion, let's call this API directly from all glue drivers irrespective
> > > of refclk dependency. Only difference here is that the drivers requiring
> > > refclk from host will call this API only after the refclk is received and
> > > other drivers without refclk dependency will call this API right after
> > > dw_pcie_ep_init().
> > > 
> > > This change will also allow us to remove the "core_init_notifier" flag in
> > > the later commits.
> > > 
> > > Signed-off-by: Manivannan Sadhasivam 
> > > ---
> > >  drivers/pci/controller/dwc/pci-dra7xx.c   |  7 +++
> > >  drivers/pci/controller/dwc/pci-imx6.c |  8 
> > >  drivers/pci/controller/dwc/pci-keystone.c |  9 +
> > >  drivers/pci/controller/dwc/pci-layerscape-ep.c|  7 +++
> > >  drivers/pci/controller/dwc/pcie-designware-ep.c   | 22 
> > > --
> > >  drivers/pci/controller/dwc/pcie-designware-plat.c |  9 +
> > >  drivers/pci/controller/dwc/pcie-rcar-gen4.c   | 12 +++-
> > >  drivers/pci/controller/dwc/pcie-uniphier-ep.c | 13 -
> > >  8 files changed, 63 insertions(+), 24 deletions(-)
> 
> [...]
> 
> > > diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c 
> > > b/drivers/pci/controller/dwc/pcie-designware-ep.c
> > > index ed1f2afd830a..278bdc9b2269 100644
> > > --- a/drivers/pci/controller/dwc/pcie-designware-ep.c
> > > +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
> > > @@ -729,7 +729,6 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
> > >   struct device *dev = pci->dev;
> > >   struct platform_device *pdev = to_platform_device(dev);
> > >   struct device_node *np = dev->of_node;
> > > - const struct pci_epc_features *epc_features;
> > >  
> > >   INIT_LIST_HEAD(>func_list);
> > >  
> > > @@ -775,29 +774,8 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
> > >   goto err_exit_epc_mem;
> > >   }
> > >  
> > > - if (ep->ops->get_features) {
> > > - epc_features = ep->ops->get_features(ep);
> > > - if (epc_features->core_init_notifier)
> > > - return 0;
> > > - }
> > 
> > why remove this check?
> > 
> 
> There is no point in keeping this check since we are removing the call to
> dw_pcie_ep_init_registers() below. But I should've described this change in 
> the
> commit message.

Sperated patch will be helpful. This clean up does not related with other
change.

Frank

> 
> - Mani
> 
> -- 
> மணிவண்ணன் சதாசிவம்


Re: [PATCH v8 08/10] PCI: dwc: ep: Add a generic dw_pcie_ep_linkdown() API to handle LINK_DOWN event

2024-02-27 Thread Frank Li
On Tue, Feb 27, 2024 at 06:00:24PM +0530, Manivannan Sadhasivam wrote:
> On Mon, Feb 26, 2024 at 12:18:18PM -0500, Frank Li wrote:
> > On Sat, Feb 24, 2024 at 12:24:14PM +0530, Manivannan Sadhasivam wrote:
> > > The PCIe link can go to LINK_DOWN state in one of the following scenarios:
> > > 
> > > 1. Fundamental (PERST#)/hot/warm reset
> > > 2. Link transition from L2/L3 to L0
> > 
> > From L0 to L2/l3
> > 
> 
> I don't understand what you mean here. Link down won't happen while moving 
> from
> L0 to L2/L3, it is the opposite.

Strange, why there are not linkdown from L0 to L2/l3. But have linkdown
from L2/l3 to L0? when linkup happen? Any document show these?

Frank

> 
> > > 
> > > In those cases, LINK_DOWN causes some non-sticky DWC registers to loose 
> > > the
> > > state (like REBAR, PTM_CAP etc...). So the drivers need to reinitialize
> > > them to function properly once the link comes back again.
> > > 
> > > This is not a problem for drivers supporting PERST# IRQ, since they can
> > > reinitialize the registers in the PERST# IRQ callback. But for the drivers
> > > not supporting PERST#, there is no way they can reinitialize the registers
> > > other than relying on LINK_DOWN IRQ received when the link goes down. So
> > > let's add a DWC generic API dw_pcie_ep_linkdown() that reinitializes the
> > > non-sticky registers and also notifies the EPF drivers about link going
> > > down.
> > > 
> > > This API can also be used by the drivers supporting PERST# to handle the
> > > scenario (2) mentioned above.
> > > 
> > > Signed-off-by: Manivannan Sadhasivam 
> > > ---
> > >  drivers/pci/controller/dwc/pcie-designware-ep.c | 111 
> > > ++--
> > >  drivers/pci/controller/dwc/pcie-designware.h|   5 ++
> > >  2 files changed, 72 insertions(+), 44 deletions(-)
> > > 
> > > diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c 
> > > b/drivers/pci/controller/dwc/pcie-designware-ep.c
> > > index 278bdc9b2269..fed4c2936c78 100644
> > > --- a/drivers/pci/controller/dwc/pcie-designware-ep.c
> > > +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
> > > @@ -14,14 +14,6 @@
> > >  #include 
> > >  #include 
> > >  
> > > -void dw_pcie_ep_linkup(struct dw_pcie_ep *ep)
> > > -{
> > > - struct pci_epc *epc = ep->epc;
> > > -
> > > - pci_epc_linkup(epc);
> > > -}
> > > -EXPORT_SYMBOL_GPL(dw_pcie_ep_linkup);
> > > -
> > 
> > No sure why git remove this block and add these back.
> > 
> 
> Because, we are adding dw_pcie_ep_linkdown() API way below and it makes sense 
> to
> move this API also to keep it ordered. Maybe I should've described it in 
> commit
> message.
> 
> - Mani
> 
> > 
> > >  void dw_pcie_ep_init_notify(struct dw_pcie_ep *ep)
> > >  {
> > >   struct pci_epc *epc = ep->epc;
> > > @@ -603,19 +595,56 @@ static unsigned int 
> > > dw_pcie_ep_find_ext_capability(struct dw_pcie *pci, int cap)
> > >   return 0;
> > >  }
> > >  
> > > +static void dw_pcie_ep_init_non_sticky_registers(struct dw_pcie *pci)
> > > +{
> > > + unsigned int offset, ptm_cap_base;
> > > + unsigned int nbars;
> > > + u32 reg, i;
> > > +
> > > + offset = dw_pcie_ep_find_ext_capability(pci, PCI_EXT_CAP_ID_REBAR);
> > > + ptm_cap_base = dw_pcie_ep_find_ext_capability(pci, PCI_EXT_CAP_ID_PTM);
> > > +
> > > + dw_pcie_dbi_ro_wr_en(pci);
> > > +
> > > + if (offset) {
> > > + reg = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL);
> > > + nbars = (reg & PCI_REBAR_CTRL_NBAR_MASK) >>
> > > + PCI_REBAR_CTRL_NBAR_SHIFT;
> > > +
> > > + for (i = 0; i < nbars; i++, offset += PCI_REBAR_CTRL)
> > > + dw_pcie_writel_dbi(pci, offset + PCI_REBAR_CAP, 0x0);
> > > + }
> > > +
> > > + /*
> > > +  * PTM responder capability can be disabled only after disabling
> > > +  * PTM root capability.
> > > +  */
> > > + if (ptm_cap_base) {
> > > + dw_pcie_dbi_ro_wr_en(pci);
> > > + reg = dw_pcie_readl_dbi(pci, ptm_cap_base + PCI_PTM_CAP);
> > > + reg &= ~PCI_PTM_CAP_ROOT;
> > > + dw_pcie_writel_dbi(pci, ptm_cap_base + PCI_PTM_CAP, reg);
> > > +
> > > + reg = dw_pcie_readl_dbi(pci, ptm_c

Re: [PATCH v8 10/10] PCI: dwc: ep: Add Kernel-doc comments for APIs

2024-02-26 Thread Frank Li
On Sat, Feb 24, 2024 at 12:24:16PM +0530, Manivannan Sadhasivam wrote:
> All of the APIs are missing the Kernel-doc comments. Hence, add them.
> 
> Signed-off-by: Manivannan Sadhasivam 

Reviewed-by: Frank Li 

> ---
>  drivers/pci/controller/dwc/pcie-designware-ep.c | 92 
> +
>  1 file changed, 92 insertions(+)
> 
> diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c 
> b/drivers/pci/controller/dwc/pcie-designware-ep.c
> index fed4c2936c78..cdcb33a279db 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-ep.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
> @@ -14,6 +14,11 @@
>  #include 
>  #include 
>  
> +/**
> + * dw_pcie_ep_init_notify - Notify EPF drivers about EPC initialization
> + *   complete
> + * @ep: DWC EP device
> + */
>  void dw_pcie_ep_init_notify(struct dw_pcie_ep *ep)
>  {
>   struct pci_epc *epc = ep->epc;
> @@ -22,6 +27,14 @@ void dw_pcie_ep_init_notify(struct dw_pcie_ep *ep)
>  }
>  EXPORT_SYMBOL_GPL(dw_pcie_ep_init_notify);
>  
> +/**
> + * dw_pcie_ep_get_func_from_ep - Get the struct dw_pcie_ep_func 
> corresponding to
> + *the endpoint function
> + * @ep: DWC EP device
> + * @func_no: Function number of the endpoint device
> + *
> + * Return: struct dw_pcie_ep_func if success, NULL otherwise.
> + */
>  struct dw_pcie_ep_func *
>  dw_pcie_ep_get_func_from_ep(struct dw_pcie_ep *ep, u8 func_no)
>  {
> @@ -52,6 +65,11 @@ static void __dw_pcie_ep_reset_bar(struct dw_pcie *pci, u8 
> func_no,
>   dw_pcie_dbi_ro_wr_dis(pci);
>  }
>  
> +/**
> + * dw_pcie_ep_reset_bar - Reset endpoint BAR
> + * @pci: DWC PCI device
> + * @bar: BAR number of the endpoint
> + */
>  void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar)
>  {
>   u8 func_no, funcs;
> @@ -431,6 +449,13 @@ static const struct pci_epc_ops epc_ops = {
>   .get_features   = dw_pcie_ep_get_features,
>  };
>  
> +/**
> + * dw_pcie_ep_raise_intx_irq - Raise INTx IRQ to the host
> + * @ep: DWC EP device
> + * @func_no: Function number of the endpoint
> + *
> + * Return: 0 if success, errono otherwise.
> + */
>  int dw_pcie_ep_raise_intx_irq(struct dw_pcie_ep *ep, u8 func_no)
>  {
>   struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> @@ -442,6 +467,14 @@ int dw_pcie_ep_raise_intx_irq(struct dw_pcie_ep *ep, u8 
> func_no)
>  }
>  EXPORT_SYMBOL_GPL(dw_pcie_ep_raise_intx_irq);
>  
> +/**
> + * dw_pcie_ep_raise_msi_irq - Raise MSI IRQ to the host
> + * @ep: DWC EP device
> + * @func_no: Function number of the endpoint
> + * @interrupt_num: Interrupt number to be raised
> + *
> + * Return: 0 if success, errono otherwise.
> + */
>  int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
>u8 interrupt_num)
>  {
> @@ -490,6 +523,15 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 
> func_no,
>  }
>  EXPORT_SYMBOL_GPL(dw_pcie_ep_raise_msi_irq);
>  
> +/**
> + * dw_pcie_ep_raise_msix_irq_doorbell - Raise MSIX to the host using Doorbell
> + *   method
> + * @ep: DWC EP device
> + * @func_no: Function number of the endpoint device
> + * @interrupt_num: Interrupt number to be raised
> + *
> + * Return: 0 if success, errno otherwise.
> + */
>  int dw_pcie_ep_raise_msix_irq_doorbell(struct dw_pcie_ep *ep, u8 func_no,
>  u16 interrupt_num)
>  {
> @@ -509,6 +551,14 @@ int dw_pcie_ep_raise_msix_irq_doorbell(struct dw_pcie_ep 
> *ep, u8 func_no,
>   return 0;
>  }
>  
> +/**
> + * dw_pcie_ep_raise_msix_irq - Raise MSIX to the host
> + * @ep: DWC EP device
> + * @func_no: Function number of the endpoint device
> + * @interrupt_num: Interrupt number to be raised
> + *
> + * Return: 0 if success, errno otherwise.
> + */
>  int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
> u16 interrupt_num)
>  {
> @@ -556,6 +606,12 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 
> func_no,
>   return 0;
>  }
>  
> +/**
> + * dw_pcie_ep_cleanup - Cleanup DWC EP resources
> + * @ep: DWC EP device
> + *
> + * Cleans up the DWC EP specific resources like eDMA etc...
> + */
>  void dw_pcie_ep_cleanup(struct dw_pcie_ep *ep)
>  {
>   struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> @@ -564,6 +620,13 @@ void dw_pcie_ep_cleanup(struct dw_pcie_ep *ep)
>  }
>  EXPORT_SYMBOL_GPL(dw_pcie_ep_cleanup);
>  
> +/**
> + * dw_pcie_ep_deinit - Deinitialize the endpoint device
> + * @ep: DWC EP device
> + *
> + * Deinitialize the endpoint device. EPC device is not 

Re: [PATCH v8 09/10] PCI: qcom-ep: Use the generic dw_pcie_ep_linkdown() API to handle LINK_DOWN event

2024-02-26 Thread Frank Li
On Sat, Feb 24, 2024 at 12:24:15PM +0530, Manivannan Sadhasivam wrote:
> Now that the API is available, let's make use of it. It also handles the
> reinitialization of DWC non-sticky registers in addition to sending the
> notification to EPF drivers.
> 
> Signed-off-by: Manivannan Sadhasivam 
> ---
>  drivers/pci/controller/dwc/pcie-qcom-ep.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/pci/controller/dwc/pcie-qcom-ep.c 
> b/drivers/pci/controller/dwc/pcie-qcom-ep.c
> index 2fb8c15e7a91..4e45bc4bca45 100644
> --- a/drivers/pci/controller/dwc/pcie-qcom-ep.c
> +++ b/drivers/pci/controller/dwc/pcie-qcom-ep.c
> @@ -640,7 +640,7 @@ static irqreturn_t qcom_pcie_ep_global_irq_thread(int 
> irq, void *data)
>   if (FIELD_GET(PARF_INT_ALL_LINK_DOWN, status)) {
>   dev_dbg(dev, "Received Linkdown event\n");
>   pcie_ep->link_status = QCOM_PCIE_EP_LINK_DOWN;
> - pci_epc_linkdown(pci->ep.epc);
> + dw_pcie_ep_linkdown(>ep);

Suppose pci_epc_linkdown() will call dw_pcie_ep_linkdown() ?
why need direct call dw_pcie_ep_linkdown() here?

Frank

>   } else if (FIELD_GET(PARF_INT_ALL_BME, status)) {
>   dev_dbg(dev, "Received BME event. Link is enabled!\n");
>   pcie_ep->link_status = QCOM_PCIE_EP_LINK_ENABLED;
> 
> -- 
> 2.25.1
> 


Re: [PATCH v8 08/10] PCI: dwc: ep: Add a generic dw_pcie_ep_linkdown() API to handle LINK_DOWN event

2024-02-26 Thread Frank Li
On Sat, Feb 24, 2024 at 12:24:14PM +0530, Manivannan Sadhasivam wrote:
> The PCIe link can go to LINK_DOWN state in one of the following scenarios:
> 
> 1. Fundamental (PERST#)/hot/warm reset
> 2. Link transition from L2/L3 to L0

>From L0 to L2/l3

> 
> In those cases, LINK_DOWN causes some non-sticky DWC registers to loose the
> state (like REBAR, PTM_CAP etc...). So the drivers need to reinitialize
> them to function properly once the link comes back again.
> 
> This is not a problem for drivers supporting PERST# IRQ, since they can
> reinitialize the registers in the PERST# IRQ callback. But for the drivers
> not supporting PERST#, there is no way they can reinitialize the registers
> other than relying on LINK_DOWN IRQ received when the link goes down. So
> let's add a DWC generic API dw_pcie_ep_linkdown() that reinitializes the
> non-sticky registers and also notifies the EPF drivers about link going
> down.
> 
> This API can also be used by the drivers supporting PERST# to handle the
> scenario (2) mentioned above.
> 
> Signed-off-by: Manivannan Sadhasivam 
> ---
>  drivers/pci/controller/dwc/pcie-designware-ep.c | 111 
> ++--
>  drivers/pci/controller/dwc/pcie-designware.h|   5 ++
>  2 files changed, 72 insertions(+), 44 deletions(-)
> 
> diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c 
> b/drivers/pci/controller/dwc/pcie-designware-ep.c
> index 278bdc9b2269..fed4c2936c78 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-ep.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
> @@ -14,14 +14,6 @@
>  #include 
>  #include 
>  
> -void dw_pcie_ep_linkup(struct dw_pcie_ep *ep)
> -{
> - struct pci_epc *epc = ep->epc;
> -
> - pci_epc_linkup(epc);
> -}
> -EXPORT_SYMBOL_GPL(dw_pcie_ep_linkup);
> -

No sure why git remove this block and add these back.


>  void dw_pcie_ep_init_notify(struct dw_pcie_ep *ep)
>  {
>   struct pci_epc *epc = ep->epc;
> @@ -603,19 +595,56 @@ static unsigned int 
> dw_pcie_ep_find_ext_capability(struct dw_pcie *pci, int cap)
>   return 0;
>  }
>  
> +static void dw_pcie_ep_init_non_sticky_registers(struct dw_pcie *pci)
> +{
> + unsigned int offset, ptm_cap_base;
> + unsigned int nbars;
> + u32 reg, i;
> +
> + offset = dw_pcie_ep_find_ext_capability(pci, PCI_EXT_CAP_ID_REBAR);
> + ptm_cap_base = dw_pcie_ep_find_ext_capability(pci, PCI_EXT_CAP_ID_PTM);
> +
> + dw_pcie_dbi_ro_wr_en(pci);
> +
> + if (offset) {
> + reg = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL);
> + nbars = (reg & PCI_REBAR_CTRL_NBAR_MASK) >>
> + PCI_REBAR_CTRL_NBAR_SHIFT;
> +
> + for (i = 0; i < nbars; i++, offset += PCI_REBAR_CTRL)
> + dw_pcie_writel_dbi(pci, offset + PCI_REBAR_CAP, 0x0);
> + }
> +
> + /*
> +  * PTM responder capability can be disabled only after disabling
> +  * PTM root capability.
> +  */
> + if (ptm_cap_base) {
> + dw_pcie_dbi_ro_wr_en(pci);
> + reg = dw_pcie_readl_dbi(pci, ptm_cap_base + PCI_PTM_CAP);
> + reg &= ~PCI_PTM_CAP_ROOT;
> + dw_pcie_writel_dbi(pci, ptm_cap_base + PCI_PTM_CAP, reg);
> +
> + reg = dw_pcie_readl_dbi(pci, ptm_cap_base + PCI_PTM_CAP);
> + reg &= ~(PCI_PTM_CAP_RES | PCI_PTM_GRANULARITY_MASK);
> + dw_pcie_writel_dbi(pci, ptm_cap_base + PCI_PTM_CAP, reg);
> + dw_pcie_dbi_ro_wr_dis(pci);
> + }
> +
> + dw_pcie_setup(pci);
> + dw_pcie_dbi_ro_wr_dis(pci);
> +}
> +
>  int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep)
>  {
>   struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
>   struct dw_pcie_ep_func *ep_func;
>   struct device *dev = pci->dev;
>   struct pci_epc *epc = ep->epc;
> - unsigned int offset, ptm_cap_base;
> - unsigned int nbars;
>   u8 hdr_type;
>   u8 func_no;
> - int i, ret;
>   void *addr;
> - u32 reg;
> + int ret;
>  
>   hdr_type = dw_pcie_readb_dbi(pci, PCI_HEADER_TYPE) &
>  PCI_HEADER_TYPE_MASK;
> @@ -678,38 +707,7 @@ int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep)
>   if (ep->ops->init)
>   ep->ops->init(ep);
>  
> - offset = dw_pcie_ep_find_ext_capability(pci, PCI_EXT_CAP_ID_REBAR);
> - ptm_cap_base = dw_pcie_ep_find_ext_capability(pci, PCI_EXT_CAP_ID_PTM);
> -
> - dw_pcie_dbi_ro_wr_en(pci);
> -
> - if (offset) {
> - reg = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL);
> - nbars = (reg & PCI_REBAR_CTRL_NBAR_MASK) >>
> - PCI_REBAR_CTRL_NBAR_SHIFT;
> -
> - for (i = 0; i < nbars; i++, offset += PCI_REBAR_CTRL)
> - dw_pcie_writel_dbi(pci, offset + PCI_REBAR_CAP, 0x0);
> - }
> -
> - /*
> -  * PTM responder capability can be disabled only after disabling
> -  * PTM root capability.
> -  */
> - if (ptm_cap_base) {
> - dw_pcie_dbi_ro_wr_en(pci);
> 

Re: [PATCH v8 07/10] PCI: dwc: ep: Remove "core_init_notifier" flag

2024-02-26 Thread Frank Li
On Sat, Feb 24, 2024 at 12:24:13PM +0530, Manivannan Sadhasivam wrote:
> "core_init_notifier" flag is set by the glue drivers requiring refclk from
> the host to complete the DWC core initialization. Also, those drivers will
> send a notification to the EPF drivers once the initialization is fully
> completed using the pci_epc_init_notify() API. Only then, the EPF drivers
> will start functioning.
> 
> For the rest of the drivers generating refclk locally, EPF drivers will
> start functioning post binding with them. EPF drivers rely on the
> 'core_init_notifier' flag to differentiate between the drivers.
> Unfortunately, this creates two different flows for the EPF drivers.
> 
> So to avoid that, let's get rid of the "core_init_notifier" flag and follow
> a single initialization flow for the EPF drivers. This is done by calling
> the dw_pcie_ep_init_notify() from all glue drivers after the completion of
> dw_pcie_ep_init_registers() API. This will allow all the glue drivers to
> send the notification to the EPF drivers once the initialization is fully
> completed.
> 
> Only difference here is that, the drivers requiring refclk from host will
> send the notification once refclk is received, while others will send it
> during probe time itself.
> 
> Signed-off-by: Manivannan Sadhasivam 

Reviewed-by: Frank Li 

> ---
>  drivers/pci/controller/dwc/pci-dra7xx.c   |  2 ++
>  drivers/pci/controller/dwc/pci-imx6.c |  2 ++
>  drivers/pci/controller/dwc/pci-keystone.c |  2 ++
>  drivers/pci/controller/dwc/pci-layerscape-ep.c|  2 ++
>  drivers/pci/controller/dwc/pcie-designware-plat.c |  2 ++
>  drivers/pci/controller/dwc/pcie-qcom-ep.c |  1 -
>  drivers/pci/controller/dwc/pcie-rcar-gen4.c   |  2 ++
>  drivers/pci/controller/dwc/pcie-tegra194.c|  1 -
>  drivers/pci/controller/dwc/pcie-uniphier-ep.c |  2 ++
>  drivers/pci/endpoint/functions/pci-epf-test.c | 18 +-
>  include/linux/pci-epc.h   |  3 ---
>  11 files changed, 19 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/pci/controller/dwc/pci-dra7xx.c 
> b/drivers/pci/controller/dwc/pci-dra7xx.c
> index 395042b29ffc..d2d17d37d3e0 100644
> --- a/drivers/pci/controller/dwc/pci-dra7xx.c
> +++ b/drivers/pci/controller/dwc/pci-dra7xx.c
> @@ -474,6 +474,8 @@ static int dra7xx_add_pcie_ep(struct dra7xx_pcie *dra7xx,
>   return ret;
>   }
>  
> + dw_pcie_ep_init_notify(ep);
> +
>   return 0;
>  }
>  
> diff --git a/drivers/pci/controller/dwc/pci-imx6.c 
> b/drivers/pci/controller/dwc/pci-imx6.c
> index bfcafa440ddb..894b5de76e3a 100644
> --- a/drivers/pci/controller/dwc/pci-imx6.c
> +++ b/drivers/pci/controller/dwc/pci-imx6.c
> @@ -1144,6 +1144,8 @@ static int imx6_add_pcie_ep(struct imx6_pcie *imx6_pcie,
>   return ret;
>   }
>  
> + dw_pcie_ep_init_notify(ep);
> +
>   /* Start LTSSM. */
>   imx6_pcie_ltssm_enable(dev);
>  
> diff --git a/drivers/pci/controller/dwc/pci-keystone.c 
> b/drivers/pci/controller/dwc/pci-keystone.c
> index 8392894ed286..1d00c5fa14ce 100644
> --- a/drivers/pci/controller/dwc/pci-keystone.c
> +++ b/drivers/pci/controller/dwc/pci-keystone.c
> @@ -1293,6 +1293,8 @@ static int ks_pcie_probe(struct platform_device *pdev)
>   goto err_ep_init;
>   }
>  
> + dw_pcie_ep_init_notify(>ep);
> +
>   break;
>   default:
>   dev_err(dev, "INVALID device type %d\n", mode);
> diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
> b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> index b712fdd06549..c513598a46d7 100644
> --- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
> +++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> @@ -283,6 +283,8 @@ static int __init ls_pcie_ep_probe(struct platform_device 
> *pdev)
>   return ret;
>   }
>  
> + dw_pcie_ep_init_notify(>ep);
> +
>   return ls_pcie_ep_interrupt_init(pcie, pdev);
>  }
>  
> diff --git a/drivers/pci/controller/dwc/pcie-designware-plat.c 
> b/drivers/pci/controller/dwc/pcie-designware-plat.c
> index ca9b22e654cd..8490c5d6ff9f 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-plat.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-plat.c
> @@ -154,6 +154,8 @@ static int dw_plat_pcie_probe(struct platform_device 
> *pdev)
>   dw_pcie_ep_deinit(>ep);
>   }
>  
> + dw_pcie_ep_init_notify(>ep);
> +
>   break;
>   default:
>   dev_err(dev, "INVALID device type %d\n", dw_plat_pcie->mode);

Re: [PATCH v8 06/10] PCI: dwc: ep: Call dw_pcie_ep_init_registers() API directly from all glue drivers

2024-02-26 Thread Frank Li
On Sat, Feb 24, 2024 at 12:24:12PM +0530, Manivannan Sadhasivam wrote:
> Currently, dw_pcie_ep_init_registers() API is directly called by the glue
> drivers requiring active refclk from host. But for the other drivers, it is
> getting called implicitly by dw_pcie_ep_init(). This is due to the fact
> that this API initializes DWC EP specific registers and that requires an
> active refclk (either from host or generated locally by endpoint itsef).
> 
> But, this causes a discrepancy among the glue drivers. So to avoid this
> confusion, let's call this API directly from all glue drivers irrespective
> of refclk dependency. Only difference here is that the drivers requiring
> refclk from host will call this API only after the refclk is received and
> other drivers without refclk dependency will call this API right after
> dw_pcie_ep_init().
> 
> This change will also allow us to remove the "core_init_notifier" flag in
> the later commits.
> 
> Signed-off-by: Manivannan Sadhasivam 
> ---
>  drivers/pci/controller/dwc/pci-dra7xx.c   |  7 +++
>  drivers/pci/controller/dwc/pci-imx6.c |  8 
>  drivers/pci/controller/dwc/pci-keystone.c |  9 +
>  drivers/pci/controller/dwc/pci-layerscape-ep.c|  7 +++
>  drivers/pci/controller/dwc/pcie-designware-ep.c   | 22 --
>  drivers/pci/controller/dwc/pcie-designware-plat.c |  9 +
>  drivers/pci/controller/dwc/pcie-rcar-gen4.c   | 12 +++-
>  drivers/pci/controller/dwc/pcie-uniphier-ep.c | 13 -
>  8 files changed, 63 insertions(+), 24 deletions(-)
> 
> diff --git a/drivers/pci/controller/dwc/pci-dra7xx.c 
> b/drivers/pci/controller/dwc/pci-dra7xx.c
> index 0e406677060d..395042b29ffc 100644
> --- a/drivers/pci/controller/dwc/pci-dra7xx.c
> +++ b/drivers/pci/controller/dwc/pci-dra7xx.c
> @@ -467,6 +467,13 @@ static int dra7xx_add_pcie_ep(struct dra7xx_pcie *dra7xx,
>   return ret;
>   }
>  
> + ret = dw_pcie_ep_init_registers(ep);
> + if (ret) {
> + dev_err(dev, "Failed to initialize DWC endpoint registers\n");
> + dw_pcie_ep_deinit(ep);
> + return ret;
> + }
> +
>   return 0;
>  }
>  
> diff --git a/drivers/pci/controller/dwc/pci-imx6.c 
> b/drivers/pci/controller/dwc/pci-imx6.c
> index dc2c036ab28c..bfcafa440ddb 100644
> --- a/drivers/pci/controller/dwc/pci-imx6.c
> +++ b/drivers/pci/controller/dwc/pci-imx6.c
> @@ -1136,6 +1136,14 @@ static int imx6_add_pcie_ep(struct imx6_pcie 
> *imx6_pcie,
>   dev_err(dev, "failed to initialize endpoint\n");
>   return ret;
>   }
> +
> + ret = dw_pcie_ep_init_registers(ep);
> + if (ret) {
> + dev_err(dev, "Failed to initialize DWC endpoint registers\n");
> + dw_pcie_ep_deinit(ep);
> + return ret;
> + }
> +
>   /* Start LTSSM. */
>   imx6_pcie_ltssm_enable(dev);
>  
> diff --git a/drivers/pci/controller/dwc/pci-keystone.c 
> b/drivers/pci/controller/dwc/pci-keystone.c
> index c0c62533a3f1..8392894ed286 100644
> --- a/drivers/pci/controller/dwc/pci-keystone.c
> +++ b/drivers/pci/controller/dwc/pci-keystone.c
> @@ -1286,6 +1286,13 @@ static int ks_pcie_probe(struct platform_device *pdev)
>   ret = dw_pcie_ep_init(>ep);
>   if (ret < 0)
>   goto err_get_sync;
> +
> + ret = dw_pcie_ep_init_registers(>ep);
> + if (ret < 0) {
> + dev_err(dev, "Failed to initialize DWC endpoint 
> registers\n");
> + goto err_ep_init;
> + }
> +
>   break;
>   default:
>   dev_err(dev, "INVALID device type %d\n", mode);
> @@ -1295,6 +1302,8 @@ static int ks_pcie_probe(struct platform_device *pdev)
>  
>   return 0;
>  
> +err_ep_init:
> + dw_pcie_ep_deinit(>ep);
>  err_get_sync:
>   pm_runtime_put(dev);
>   pm_runtime_disable(dev);
> diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
> b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> index 2e398494e7c0..b712fdd06549 100644
> --- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
> +++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> @@ -276,6 +276,13 @@ static int __init ls_pcie_ep_probe(struct 
> platform_device *pdev)
>   if (ret)
>   return ret;
>  
> + ret = dw_pcie_ep_init_registers(>ep);
> + if (ret) {
> + dev_err(dev, "Failed to initialize DWC endpoint registers\n");
> + dw_pcie_ep_deinit(>ep);
> + return ret;
> + }
> +
>   return ls_pcie_ep_interrupt_init(pcie, pdev);
>  }
>  
> diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c 
> b/drivers/pci/controller/dwc/pcie-designware-ep.c
> index ed1f2afd830a..278bdc9b2269 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-ep.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
> @@ -729,7 +729,6 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
>   

Re: [PATCH v8 05/10] PCI: dwc: ep: Rename dw_pcie_ep_init_complete() to dw_pcie_ep_init_registers()

2024-02-26 Thread Frank Li
On Sat, Feb 24, 2024 at 12:24:11PM +0530, Manivannan Sadhasivam wrote:
> The goal of the dw_pcie_ep_init_complete() API is to initialize the DWC
> specific registers post registering the controller with the EP framework.
> 
> But the naming doesn't reflect its functionality and causes confusion. So,
> let's rename it to dw_pcie_ep_init_registers() to make it clear that it
> initializes the DWC specific registers.
> 
> Signed-off-by: Manivannan Sadhasivam 

Reviewed-by: Frank Li 

> ---
>  drivers/pci/controller/dwc/pcie-designware-ep.c | 6 +++---
>  drivers/pci/controller/dwc/pcie-designware.h| 4 ++--
>  drivers/pci/controller/dwc/pcie-qcom-ep.c   | 2 +-
>  drivers/pci/controller/dwc/pcie-tegra194.c  | 2 +-
>  4 files changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c 
> b/drivers/pci/controller/dwc/pcie-designware-ep.c
> index 99d66b0fa59b..ed1f2afd830a 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-ep.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
> @@ -603,7 +603,7 @@ static unsigned int dw_pcie_ep_find_ext_capability(struct 
> dw_pcie *pci, int cap)
>   return 0;
>  }
>  
> -int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep)
> +int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep)
>  {
>   struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
>   struct dw_pcie_ep_func *ep_func;
> @@ -718,7 +718,7 @@ int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep)
>  
>   return ret;
>  }
> -EXPORT_SYMBOL_GPL(dw_pcie_ep_init_complete);
> +EXPORT_SYMBOL_GPL(dw_pcie_ep_init_registers);
>  
>  int dw_pcie_ep_init(struct dw_pcie_ep *ep)
>  {
> @@ -788,7 +788,7 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
>* (Ex: tegra194). Any hardware access on such platforms result
>* in system hang.
>*/
> - ret = dw_pcie_ep_init_complete(ep);
> + ret = dw_pcie_ep_init_registers(ep);
>   if (ret)
>   goto err_free_epc_mem;
>  
> diff --git a/drivers/pci/controller/dwc/pcie-designware.h 
> b/drivers/pci/controller/dwc/pcie-designware.h
> index 351d2fe3ea4d..f8e5431a207b 100644
> --- a/drivers/pci/controller/dwc/pcie-designware.h
> +++ b/drivers/pci/controller/dwc/pcie-designware.h
> @@ -669,7 +669,7 @@ static inline void __iomem 
> *dw_pcie_own_conf_map_bus(struct pci_bus *bus,
>  #ifdef CONFIG_PCIE_DW_EP
>  void dw_pcie_ep_linkup(struct dw_pcie_ep *ep);
>  int dw_pcie_ep_init(struct dw_pcie_ep *ep);
> -int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep);
> +int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep);
>  void dw_pcie_ep_init_notify(struct dw_pcie_ep *ep);
>  void dw_pcie_ep_deinit(struct dw_pcie_ep *ep);
>  void dw_pcie_ep_cleanup(struct dw_pcie_ep *ep);
> @@ -693,7 +693,7 @@ static inline int dw_pcie_ep_init(struct dw_pcie_ep *ep)
>   return 0;
>  }
>  
> -static inline int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep)
> +static inline int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep)
>  {
>   return 0;
>  }
> diff --git a/drivers/pci/controller/dwc/pcie-qcom-ep.c 
> b/drivers/pci/controller/dwc/pcie-qcom-ep.c
> index 59b1c0110288..3697b4a944cc 100644
> --- a/drivers/pci/controller/dwc/pcie-qcom-ep.c
> +++ b/drivers/pci/controller/dwc/pcie-qcom-ep.c
> @@ -463,7 +463,7 @@ static int qcom_pcie_perst_deassert(struct dw_pcie *pci)
> PARF_INT_ALL_LINK_UP | PARF_INT_ALL_EDMA;
>   writel_relaxed(val, pcie_ep->parf + PARF_INT_ALL_MASK);
>  
> - ret = dw_pcie_ep_init_complete(_ep->pci.ep);
> + ret = dw_pcie_ep_init_registers(_ep->pci.ep);
>   if (ret) {
>   dev_err(dev, "Failed to complete initialization: %d\n", ret);
>   goto err_disable_resources;
> diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c 
> b/drivers/pci/controller/dwc/pcie-tegra194.c
> index 68bfeed3429b..264ee76bf008 100644
> --- a/drivers/pci/controller/dwc/pcie-tegra194.c
> +++ b/drivers/pci/controller/dwc/pcie-tegra194.c
> @@ -1897,7 +1897,7 @@ static void pex_ep_event_pex_rst_deassert(struct 
> tegra_pcie_dw *pcie)
>   val = (upper_32_bits(ep->msi_mem_phys) & MSIX_ADDR_MATCH_HIGH_OFF_MASK);
>   dw_pcie_writel_dbi(pci, MSIX_ADDR_MATCH_HIGH_OFF, val);
>  
> - ret = dw_pcie_ep_init_complete(ep);
> + ret = dw_pcie_ep_init_registers(ep);
>   if (ret) {
>   dev_err(dev, "Failed to complete initialization: %d\n", ret);
>   goto fail_init_complete;
> 
> -- 
> 2.25.1
> 


Re: [PATCH v8 04/10] PCI: dwc: ep: Fix DBI access failure for drivers requiring refclk from host

2024-02-26 Thread Frank Li
On Sat, Feb 24, 2024 at 12:24:10PM +0530, Manivannan Sadhasivam wrote:
> The DWC glue drivers requiring an active reference clock from the PCIe host
> for initializing their PCIe EP core, set a flag called 'core_init_notifier'
> to let DWC driver know that these drivers need a special attention during
> initialization. In these drivers, access to the hw registers (like DBI)
> before receiving the active refclk from host will result in access failure
> and also could cause a whole system hang.
> 
> But the current DWC EP driver doesn't honor the requirements of the drivers
> setting 'core_init_notifier' flag and tries to access the DBI registers
> during dw_pcie_ep_init(). This causes the system hang for glue drivers such
> as Tegra194 and Qcom EP as they depend on refclk from host and have set the
> above mentioned flag.
> 
> To workaround this issue, users of the affected platforms have to maintain
> the dependency with the PCIe host by booting the PCIe EP after host boot.
> But this won't provide a good user experience, since PCIe EP is _one_ of
> the features of those platforms and it doesn't make sense to delay the
> whole platform booting due to PCIe requiring active refclk.
> 
> So to fix this issue, let's move all the DBI access from
> dw_pcie_ep_init() in the DWC EP driver to the dw_pcie_ep_init_complete()
> API. This API will only be called by the drivers setting
> 'core_init_notifier' flag once refclk is received from host. For the rest
> of the drivers that gets the refclk locally, this API will be called
> within dw_pcie_ep_init().
> 
> Fixes: e966f7390da9 ("PCI: dwc: Refactor core initialization code for EP 
> mode")
> Co-developed-by: Vidya Sagar 
> Signed-off-by: Vidya Sagar 
> Signed-off-by: Manivannan Sadhasivam 

Reviewed-by: Frank Li 

> ---
>  drivers/pci/controller/dwc/pcie-designware-ep.c | 120 
> ++--
>  1 file changed, 71 insertions(+), 49 deletions(-)
> 
> diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c 
> b/drivers/pci/controller/dwc/pcie-designware-ep.c
> index 1205bfba8310..99d66b0fa59b 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-ep.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
> @@ -606,11 +606,16 @@ static unsigned int 
> dw_pcie_ep_find_ext_capability(struct dw_pcie *pci, int cap)
>  int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep)
>  {
>   struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> + struct dw_pcie_ep_func *ep_func;
> + struct device *dev = pci->dev;
> + struct pci_epc *epc = ep->epc;
>   unsigned int offset, ptm_cap_base;
>   unsigned int nbars;
>   u8 hdr_type;
> + u8 func_no;
> + int i, ret;
> + void *addr;
>   u32 reg;
> - int i;
>  
>   hdr_type = dw_pcie_readb_dbi(pci, PCI_HEADER_TYPE) &
>  PCI_HEADER_TYPE_MASK;
> @@ -621,6 +626,58 @@ int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep)
>   return -EIO;
>   }
>  
> + dw_pcie_version_detect(pci);
> +
> + dw_pcie_iatu_detect(pci);
> +
> + ret = dw_pcie_edma_detect(pci);
> + if (ret)
> + return ret;
> +
> + if (!ep->ib_window_map) {
> + ep->ib_window_map = devm_bitmap_zalloc(dev, pci->num_ib_windows,
> +GFP_KERNEL);
> + if (!ep->ib_window_map)
> + goto err_remove_edma;
> + }
> +
> + if (!ep->ob_window_map) {
> + ep->ob_window_map = devm_bitmap_zalloc(dev, pci->num_ob_windows,
> +GFP_KERNEL);
> + if (!ep->ob_window_map)
> + goto err_remove_edma;
> + }
> +
> + if (!ep->outbound_addr) {
> + addr = devm_kcalloc(dev, pci->num_ob_windows, 
> sizeof(phys_addr_t),
> + GFP_KERNEL);
> + if (!addr)
> + goto err_remove_edma;
> + ep->outbound_addr = addr;
> + }
> +
> + for (func_no = 0; func_no < epc->max_functions; func_no++) {
> +
> + ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
> + if (ep_func)
> + continue;
> +
> + ep_func = devm_kzalloc(dev, sizeof(*ep_func), GFP_KERNEL);
> + if (!ep_func)
> + goto err_remove_edma;
> +
> + ep_func->func_no = func_no;
> + ep_func->msi_cap = dw_pcie_ep_find_capability(ep, func_no,
> +   PCI_CAP_ID_MSI);
> + ep_func->msix_cap = dw_pcie_ep_find_cap

Re: [PATCH v8 03/10] PCI: dwc: ep: Introduce dw_pcie_ep_cleanup() API for drivers supporting PERST#

2024-02-26 Thread Frank Li
On Sat, Feb 24, 2024 at 12:24:09PM +0530, Manivannan Sadhasivam wrote:
> For DWC glue drivers supporting PERST# (currently Qcom and Tegra194), some
> of the DWC resources like eDMA should be cleaned up during the PERST#
> assert time.
> 
> So let's introduce a dw_pcie_ep_cleanup() API that could be called by these
> drivers to cleanup the DWC specific resources. Currently, it just removes
> eDMA.
> 
> Reported-by: Niklas Cassel 
> Closes: https://lore.kernel.org/linux-pci/ZWYmX8Y%2F7Q9WMxES@x1-carbon
> Signed-off-by: Manivannan Sadhasivam 

Reviewed-by: Frank Li 

> ---
>  drivers/pci/controller/dwc/pcie-designware-ep.c | 11 +--
>  drivers/pci/controller/dwc/pcie-designware.h|  5 +
>  drivers/pci/controller/dwc/pcie-qcom-ep.c   |  1 +
>  drivers/pci/controller/dwc/pcie-tegra194.c  |  2 ++
>  4 files changed, 17 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c 
> b/drivers/pci/controller/dwc/pcie-designware-ep.c
> index 2b11290aab4c..1205bfba8310 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-ep.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
> @@ -564,12 +564,19 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 
> func_no,
>   return 0;
>  }
>  
> -void dw_pcie_ep_deinit(struct dw_pcie_ep *ep)
> +void dw_pcie_ep_cleanup(struct dw_pcie_ep *ep)
>  {
>   struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> - struct pci_epc *epc = ep->epc;
>  
>   dw_pcie_edma_remove(pci);
> +}
> +EXPORT_SYMBOL_GPL(dw_pcie_ep_cleanup);
> +
> +void dw_pcie_ep_deinit(struct dw_pcie_ep *ep)
> +{
> + struct pci_epc *epc = ep->epc;
> +
> + dw_pcie_ep_cleanup(ep);
>  
>   pci_epc_mem_free_addr(epc, ep->msi_mem_phys, ep->msi_mem,
> epc->mem->window.page_size);
> diff --git a/drivers/pci/controller/dwc/pcie-designware.h 
> b/drivers/pci/controller/dwc/pcie-designware.h
> index 61465203bb60..351d2fe3ea4d 100644
> --- a/drivers/pci/controller/dwc/pcie-designware.h
> +++ b/drivers/pci/controller/dwc/pcie-designware.h
> @@ -672,6 +672,7 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep);
>  int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep);
>  void dw_pcie_ep_init_notify(struct dw_pcie_ep *ep);
>  void dw_pcie_ep_deinit(struct dw_pcie_ep *ep);
> +void dw_pcie_ep_cleanup(struct dw_pcie_ep *ep);
>  int dw_pcie_ep_raise_intx_irq(struct dw_pcie_ep *ep, u8 func_no);
>  int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
>u8 interrupt_num);
> @@ -705,6 +706,10 @@ static inline void dw_pcie_ep_deinit(struct dw_pcie_ep 
> *ep)
>  {
>  }
>  
> +static inline void dw_pcie_ep_cleanup(struct dw_pcie_ep *ep)
> +{
> +}
> +
>  static inline int dw_pcie_ep_raise_intx_irq(struct dw_pcie_ep *ep, u8 
> func_no)
>  {
>   return 0;
> diff --git a/drivers/pci/controller/dwc/pcie-qcom-ep.c 
> b/drivers/pci/controller/dwc/pcie-qcom-ep.c
> index 36e5e80cd22f..59b1c0110288 100644
> --- a/drivers/pci/controller/dwc/pcie-qcom-ep.c
> +++ b/drivers/pci/controller/dwc/pcie-qcom-ep.c
> @@ -507,6 +507,7 @@ static void qcom_pcie_perst_assert(struct dw_pcie *pci)
>   return;
>   }
>  
> + dw_pcie_ep_cleanup(>ep);
>   qcom_pcie_disable_resources(pcie_ep);
>   pcie_ep->link_status = QCOM_PCIE_EP_LINK_DISABLED;
>  }
> diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c 
> b/drivers/pci/controller/dwc/pcie-tegra194.c
> index 7afa9e9aabe2..68bfeed3429b 100644
> --- a/drivers/pci/controller/dwc/pcie-tegra194.c
> +++ b/drivers/pci/controller/dwc/pcie-tegra194.c
> @@ -1715,6 +1715,8 @@ static void pex_ep_event_pex_rst_assert(struct 
> tegra_pcie_dw *pcie)
>   if (ret)
>   dev_err(pcie->dev, "Failed to go Detect state: %d\n", ret);
>  
> + dw_pcie_ep_cleanup(>pci.ep);
> +
>   reset_control_assert(pcie->core_rst);
>  
>   tegra_pcie_disable_phy(pcie);
> 
> -- 
> 2.25.1
> 


Re: [PATCH v8 02/10] PCI: dwc: ep: Rename dw_pcie_ep_exit() to dw_pcie_ep_deinit()

2024-02-26 Thread Frank Li
On Sat, Feb 24, 2024 at 12:24:08PM +0530, Manivannan Sadhasivam wrote:
> dw_pcie_ep_exit() API is undoing what the dw_pcie_ep_init() API has done
> already (at least partly). But the API name dw_pcie_ep_exit() is not quite
> reflecting that. So let's rename it to dw_pcie_ep_deinit() to make the
> purpose of this API clear. This also aligns with the DWC host driver.
> 
> Signed-off-by: Manivannan Sadhasivam 

Reviewed-by: Frank Li 

> ---
>  drivers/pci/controller/dwc/pcie-designware-ep.c | 4 ++--
>  drivers/pci/controller/dwc/pcie-designware.h| 4 ++--
>  drivers/pci/controller/dwc/pcie-rcar-gen4.c | 2 +-
>  3 files changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c 
> b/drivers/pci/controller/dwc/pcie-designware-ep.c
> index d305f9b4cdfe..2b11290aab4c 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-ep.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
> @@ -564,7 +564,7 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 
> func_no,
>   return 0;
>  }
>  
> -void dw_pcie_ep_exit(struct dw_pcie_ep *ep)
> +void dw_pcie_ep_deinit(struct dw_pcie_ep *ep)
>  {
>   struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
>   struct pci_epc *epc = ep->epc;
> @@ -576,7 +576,7 @@ void dw_pcie_ep_exit(struct dw_pcie_ep *ep)
>  
>   pci_epc_mem_exit(epc);
>  }
> -EXPORT_SYMBOL_GPL(dw_pcie_ep_exit);
> +EXPORT_SYMBOL_GPL(dw_pcie_ep_deinit);
>  
>  static unsigned int dw_pcie_ep_find_ext_capability(struct dw_pcie *pci, int 
> cap)
>  {
> diff --git a/drivers/pci/controller/dwc/pcie-designware.h 
> b/drivers/pci/controller/dwc/pcie-designware.h
> index ab7431a37209..61465203bb60 100644
> --- a/drivers/pci/controller/dwc/pcie-designware.h
> +++ b/drivers/pci/controller/dwc/pcie-designware.h
> @@ -671,7 +671,7 @@ void dw_pcie_ep_linkup(struct dw_pcie_ep *ep);
>  int dw_pcie_ep_init(struct dw_pcie_ep *ep);
>  int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep);
>  void dw_pcie_ep_init_notify(struct dw_pcie_ep *ep);
> -void dw_pcie_ep_exit(struct dw_pcie_ep *ep);
> +void dw_pcie_ep_deinit(struct dw_pcie_ep *ep);
>  int dw_pcie_ep_raise_intx_irq(struct dw_pcie_ep *ep, u8 func_no);
>  int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
>u8 interrupt_num);
> @@ -701,7 +701,7 @@ static inline void dw_pcie_ep_init_notify(struct 
> dw_pcie_ep *ep)
>  {
>  }
>  
> -static inline void dw_pcie_ep_exit(struct dw_pcie_ep *ep)
> +static inline void dw_pcie_ep_deinit(struct dw_pcie_ep *ep)
>  {
>  }
>  
> diff --git a/drivers/pci/controller/dwc/pcie-rcar-gen4.c 
> b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
> index ac97d594ea47..9d9d22e367bb 100644
> --- a/drivers/pci/controller/dwc/pcie-rcar-gen4.c
> +++ b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
> @@ -430,7 +430,7 @@ static int rcar_gen4_add_dw_pcie_ep(struct rcar_gen4_pcie 
> *rcar)
>  
>  static void rcar_gen4_remove_dw_pcie_ep(struct rcar_gen4_pcie *rcar)
>  {
> - dw_pcie_ep_exit(>dw.ep);
> + dw_pcie_ep_deinit(>dw.ep);
>   rcar_gen4_pcie_ep_deinit(rcar);
>  }
>  
> 
> -- 
> 2.25.1
> 


Re: [PATCH v8 01/10] PCI: dwc: ep: Remove deinit() callback from struct dw_pcie_ep_ops

2024-02-26 Thread Frank Li
On Sat, Feb 24, 2024 at 12:24:07PM +0530, Manivannan Sadhasivam wrote:
> deinit() callback was solely introduced for the pcie-rcar-gen4 driver where
> it is used to do platform specific resource deallocation. And this callback
> is called right at the end of the dw_pcie_ep_exit() API. So it doesn't
> matter whether it is called within or outside of dw_pcie_ep_exit() API.
> 
> So let's remove this callback and directly call rcar_gen4_pcie_ep_deinit()
> in pcie-rcar-gen4 driver to do resource deallocation after the completion
> of dw_pcie_ep_exit() API in rcar_gen4_remove_dw_pcie_ep().
> 
> This simplifies the DWC layer.
> 
> Signed-off-by: Manivannan Sadhasivam 

Reviewed-by: Frank Li 

> ---
>  drivers/pci/controller/dwc/pcie-designware-ep.c |  9 +
>  drivers/pci/controller/dwc/pcie-designware.h|  1 -
>  drivers/pci/controller/dwc/pcie-rcar-gen4.c | 14 --
>  3 files changed, 9 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c 
> b/drivers/pci/controller/dwc/pcie-designware-ep.c
> index 5befed2dc02b..d305f9b4cdfe 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-ep.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
> @@ -575,9 +575,6 @@ void dw_pcie_ep_exit(struct dw_pcie_ep *ep)
> epc->mem->window.page_size);
>  
>   pci_epc_mem_exit(epc);
> -
> - if (ep->ops->deinit)
> - ep->ops->deinit(ep);
>  }
>  EXPORT_SYMBOL_GPL(dw_pcie_ep_exit);
>  
> @@ -738,7 +735,7 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
>  ep->page_size);
>   if (ret < 0) {
>   dev_err(dev, "Failed to initialize address space\n");
> - goto err_ep_deinit;
> + return ret;
>   }
>  
>   ep->msi_mem = pci_epc_mem_alloc_addr(epc, >msi_mem_phys,
> @@ -775,10 +772,6 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
>  err_exit_epc_mem:
>   pci_epc_mem_exit(epc);
>  
> -err_ep_deinit:
> - if (ep->ops->deinit)
> - ep->ops->deinit(ep);
> -
>   return ret;
>  }
>  EXPORT_SYMBOL_GPL(dw_pcie_ep_init);
> diff --git a/drivers/pci/controller/dwc/pcie-designware.h 
> b/drivers/pci/controller/dwc/pcie-designware.h
> index 26dae4837462..ab7431a37209 100644
> --- a/drivers/pci/controller/dwc/pcie-designware.h
> +++ b/drivers/pci/controller/dwc/pcie-designware.h
> @@ -333,7 +333,6 @@ struct dw_pcie_rp {
>  struct dw_pcie_ep_ops {
>   void(*pre_init)(struct dw_pcie_ep *ep);
>   void(*init)(struct dw_pcie_ep *ep);
> - void(*deinit)(struct dw_pcie_ep *ep);
>   int (*raise_irq)(struct dw_pcie_ep *ep, u8 func_no,
>unsigned int type, u16 interrupt_num);
>   const struct pci_epc_features* (*get_features)(struct dw_pcie_ep *ep);
> diff --git a/drivers/pci/controller/dwc/pcie-rcar-gen4.c 
> b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
> index e9166619b1f9..ac97d594ea47 100644
> --- a/drivers/pci/controller/dwc/pcie-rcar-gen4.c
> +++ b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
> @@ -352,11 +352,8 @@ static void rcar_gen4_pcie_ep_init(struct dw_pcie_ep *ep)
>   dw_pcie_ep_reset_bar(pci, bar);
>  }
>  
> -static void rcar_gen4_pcie_ep_deinit(struct dw_pcie_ep *ep)
> +static void rcar_gen4_pcie_ep_deinit(struct rcar_gen4_pcie *rcar)
>  {
> - struct dw_pcie *dw = to_dw_pcie_from_ep(ep);
> - struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw);
> -
>   writel(0, rcar->base + PCIEDMAINTSTSEN);
>   rcar_gen4_pcie_common_deinit(rcar);
>  }
> @@ -408,7 +405,6 @@ static unsigned int 
> rcar_gen4_pcie_ep_get_dbi2_offset(struct dw_pcie_ep *ep,
>  static const struct dw_pcie_ep_ops pcie_ep_ops = {
>   .pre_init = rcar_gen4_pcie_ep_pre_init,
>   .init = rcar_gen4_pcie_ep_init,
> - .deinit = rcar_gen4_pcie_ep_deinit,
>   .raise_irq = rcar_gen4_pcie_ep_raise_irq,
>   .get_features = rcar_gen4_pcie_ep_get_features,
>   .get_dbi_offset = rcar_gen4_pcie_ep_get_dbi_offset,
> @@ -418,18 +414,24 @@ static const struct dw_pcie_ep_ops pcie_ep_ops = {
>  static int rcar_gen4_add_dw_pcie_ep(struct rcar_gen4_pcie *rcar)
>  {
>   struct dw_pcie_ep *ep = >dw.ep;
> + int ret;
>  
>   if (!IS_ENABLED(CONFIG_PCIE_RCAR_GEN4_EP))
>   return -ENODEV;
>  
>   ep->ops = _ep_ops;
>  
> - return dw_pcie_ep_init(ep);
> + ret = dw_pcie_ep_init(ep);
> + if (ret)
> + rcar_gen4_pcie_ep_deinit(rcar);
> +
> + return ret;
>  }
>  
>  static void rcar_gen4_remove_dw_pcie_ep(struct rcar_gen4_pcie *rcar)
>  {
>   dw_pcie_ep_exit(>dw.ep);
> + rcar_gen4_pcie_ep_deinit(rcar);
>  }
>  
>  /* Common */
> 
> -- 
> 2.25.1
> 


[PATCH 4/4] powerpc: dts: fsl: rename ifc node name to be memory-controller

2024-01-19 Thread Frank Li
From: Li Yang 

Update the node name to be align with binding document.

Signed-off-by: Li Yang 
Signed-off-by: Frank Li 
---
 arch/powerpc/boot/dts/fsl/bsc9131rdb.dts| 2 +-
 arch/powerpc/boot/dts/fsl/bsc9132qds.dts| 2 +-
 arch/powerpc/boot/dts/fsl/c293pcie.dts  | 2 +-
 arch/powerpc/boot/dts/fsl/p1010rdb_32b.dtsi | 2 +-
 arch/powerpc/boot/dts/fsl/p1010rdb_36b.dtsi | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/boot/dts/fsl/bsc9131rdb.dts 
b/arch/powerpc/boot/dts/fsl/bsc9131rdb.dts
index 8da984251abc8..0ba86a6dce1b6 100644
--- a/arch/powerpc/boot/dts/fsl/bsc9131rdb.dts
+++ b/arch/powerpc/boot/dts/fsl/bsc9131rdb.dts
@@ -15,7 +15,7 @@ memory {
device_type = "memory";
};
 
-   board_ifc: ifc: ifc@ff71e000 {
+   board_ifc: ifc: memory-controller@ff71e000 {
/* NAND Flash on board */
ranges = <0x0 0x0 0x0 0xff80 0x4000>;
reg = <0x0 0xff71e000 0x0 0x2000>;
diff --git a/arch/powerpc/boot/dts/fsl/bsc9132qds.dts 
b/arch/powerpc/boot/dts/fsl/bsc9132qds.dts
index 7cb2158dfe583..ce642e879a1b8 100644
--- a/arch/powerpc/boot/dts/fsl/bsc9132qds.dts
+++ b/arch/powerpc/boot/dts/fsl/bsc9132qds.dts
@@ -15,7 +15,7 @@ memory {
device_type = "memory";
};
 
-   ifc: ifc@ff71e000 {
+   ifc: memory-controller@ff71e000 {
/* NOR, NAND Flash on board */
ranges = <0x0 0x0 0x0 0x8800 0x0800
  0x1 0x0 0x0 0xff80 0x0001>;
diff --git a/arch/powerpc/boot/dts/fsl/c293pcie.dts 
b/arch/powerpc/boot/dts/fsl/c293pcie.dts
index 5e905e0857cf9..e2fdac2ed4205 100644
--- a/arch/powerpc/boot/dts/fsl/c293pcie.dts
+++ b/arch/powerpc/boot/dts/fsl/c293pcie.dts
@@ -42,7 +42,7 @@ memory {
device_type = "memory";
};
 
-   ifc: ifc@fffe1e000 {
+   ifc: memory-controller@fffe1e000 {
reg = <0xf 0xffe1e000 0 0x2000>;
ranges = <0x0 0x0 0xf 0xec00 0x0400
  0x1 0x0 0xf 0xff80 0x0001
diff --git a/arch/powerpc/boot/dts/fsl/p1010rdb_32b.dtsi 
b/arch/powerpc/boot/dts/fsl/p1010rdb_32b.dtsi
index fdc19aab2f706..583a6cd050793 100644
--- a/arch/powerpc/boot/dts/fsl/p1010rdb_32b.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p1010rdb_32b.dtsi
@@ -36,7 +36,7 @@ memory {
device_type = "memory";
 };
 
-board_ifc: ifc: ifc@ffe1e000 {
+board_ifc: ifc: memory-controller@ffe1e000 {
/* NOR, NAND Flashes and CPLD on board */
ranges = <0x0 0x0 0x0 0xee00 0x0200
  0x1 0x0 0x0 0xff80 0x0001
diff --git a/arch/powerpc/boot/dts/fsl/p1010rdb_36b.dtsi 
b/arch/powerpc/boot/dts/fsl/p1010rdb_36b.dtsi
index de2fceed4f799..4d41efe0038f2 100644
--- a/arch/powerpc/boot/dts/fsl/p1010rdb_36b.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p1010rdb_36b.dtsi
@@ -36,7 +36,7 @@ memory {
device_type = "memory";
 };
 
-board_ifc: ifc: ifc@fffe1e000 {
+board_ifc: ifc: memory-controller@fffe1e000 {
/* NOR, NAND Flashes and CPLD on board */
ranges = <0x0 0x0 0xf 0xee00 0x0200
  0x1 0x0 0xf 0xff80 0x0001
-- 
2.34.1



[PATCH 3/4] powerpc: dts: mpc85xx: remove "simple-bus" compatible from ifc node

2024-01-19 Thread Frank Li
From: Li Yang 

Update dts to match dts binding document.

Signed-off-by: Li Yang 
Signed-off-by: Frank Li 
---
 arch/powerpc/boot/dts/fsl/b4si-post.dtsi  | 2 +-
 arch/powerpc/boot/dts/fsl/bsc9131si-post.dtsi | 2 +-
 arch/powerpc/boot/dts/fsl/bsc9132si-post.dtsi | 2 +-
 arch/powerpc/boot/dts/fsl/c293si-post.dtsi| 2 +-
 arch/powerpc/boot/dts/fsl/p1010si-post.dtsi   | 2 +-
 arch/powerpc/boot/dts/fsl/t1023si-post.dtsi   | 2 +-
 arch/powerpc/boot/dts/fsl/t1040si-post.dtsi   | 2 +-
 arch/powerpc/boot/dts/fsl/t2081si-post.dtsi   | 2 +-
 arch/powerpc/boot/dts/fsl/t4240si-post.dtsi   | 2 +-
 9 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/boot/dts/fsl/b4si-post.dtsi 
b/arch/powerpc/boot/dts/fsl/b4si-post.dtsi
index 4f044b41a776b..fb3200b006ade 100644
--- a/arch/powerpc/boot/dts/fsl/b4si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/b4si-post.dtsi
@@ -50,7 +50,7 @@ _pfdr {
  {
#address-cells = <2>;
#size-cells = <1>;
-   compatible = "fsl,ifc", "simple-bus";
+   compatible = "fsl,ifc";
interrupts = <25 2 0 0>;
 };
 
diff --git a/arch/powerpc/boot/dts/fsl/bsc9131si-post.dtsi 
b/arch/powerpc/boot/dts/fsl/bsc9131si-post.dtsi
index 2a677fd323ebe..5c53cee8755f9 100644
--- a/arch/powerpc/boot/dts/fsl/bsc9131si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/bsc9131si-post.dtsi
@@ -35,7 +35,7 @@
  {
#address-cells = <2>;
#size-cells = <1>;
-   compatible = "fsl,ifc", "simple-bus";
+   compatible = "fsl,ifc";
interrupts = <16 2 0 0 20 2 0 0>;
 };
 
diff --git a/arch/powerpc/boot/dts/fsl/bsc9132si-post.dtsi 
b/arch/powerpc/boot/dts/fsl/bsc9132si-post.dtsi
index b8e0edd1ac69a..4da451e000d90 100644
--- a/arch/powerpc/boot/dts/fsl/bsc9132si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/bsc9132si-post.dtsi
@@ -35,7 +35,7 @@
  {
#address-cells = <2>;
#size-cells = <1>;
-   compatible = "fsl,ifc", "simple-bus";
+   compatible = "fsl,ifc";
/* FIXME: Test whether interrupts are split */
interrupts = <16 2 0 0 20 2 0 0>;
 };
diff --git a/arch/powerpc/boot/dts/fsl/c293si-post.dtsi 
b/arch/powerpc/boot/dts/fsl/c293si-post.dtsi
index f208fb8f64b37..2d443d5192749 100644
--- a/arch/powerpc/boot/dts/fsl/c293si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/c293si-post.dtsi
@@ -35,7 +35,7 @@
  {
#address-cells = <2>;
#size-cells = <1>;
-   compatible = "fsl,ifc", "simple-bus";
+   compatible = "fsl,ifc";
interrupts = <19 2 0 0>;
 };
 
diff --git a/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi 
b/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi
index b540e58ff79e7..2d2550729dcc2 100644
--- a/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi
@@ -35,7 +35,7 @@
  {
#address-cells = <2>;
#size-cells = <1>;
-   compatible = "fsl,ifc", "simple-bus";
+   compatible = "fsl,ifc";
interrupts = <16 2 0 0 19 2 0 0>;
 };
 
diff --git a/arch/powerpc/boot/dts/fsl/t1023si-post.dtsi 
b/arch/powerpc/boot/dts/fsl/t1023si-post.dtsi
index aa5152ca81201..8ef0c020206b9 100644
--- a/arch/powerpc/boot/dts/fsl/t1023si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/t1023si-post.dtsi
@@ -52,7 +52,7 @@ _pfdr {
  {
#address-cells = <2>;
#size-cells = <1>;
-   compatible = "fsl,ifc", "simple-bus";
+   compatible = "fsl,ifc";
interrupts = <25 2 0 0>;
 };
 
diff --git a/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi 
b/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi
index 7767886232040..c9542b73bd7f1 100644
--- a/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi
@@ -52,7 +52,7 @@ _pfdr {
  {
#address-cells = <2>;
#size-cells = <1>;
-   compatible = "fsl,ifc", "simple-bus";
+   compatible = "fsl,ifc";
interrupts = <25 2 0 0>;
 };
 
diff --git a/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi 
b/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi
index 27714dc2f04a5..6bb95878d39d3 100644
--- a/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi
@@ -50,7 +50,7 @@ _pfdr {
  {
#address-cells = <2>;
#size-cells = <1>;
-   compatible = "fsl,ifc", "simple-bus";
+   compatible = "fsl,ifc";
interrupts = <25 2 0 0>;
 };
 
diff --git a/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi 
b/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi
index fcac73486d487..65f3e17c0d413 100644
--- a/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi
@@ -50,7 +50,7 @@ _pfdr {
  {
#address-cells = <2>;
#size-cells = <1>;
-   compatible = "fsl,ifc", "simple-bus";
+   compatible = "fsl,ifc";
interrupts = <25 2 0 0>;
 };
 
-- 
2.34.1



[PATCH 2/4] powerpc: dts: p1010rdb: fix INTx interrupt issue on P1010RDB-PB

2024-01-19 Thread Frank Li
From: Xiaowei Bao 

Due to the INTA is shared with the active-low PHY2 interrupt on
P1010RDB-PA board, so configure P1010RDB-PA's INTA with polarity as
active-low, the P1010RDB-PB board is used separately, so configure
P1010RDB-PB's INTA with polarity as active-high.  The INTX in
P1010RDB-PB do not work because of the pcie@0 node fixup will be
overwrited by p1010si-post.dtsi file, so we move the pcie@0 node fixup
to p1010rdb-pb.dts and p1010rdb-pb_36b.dts.

Signed-off-by: Xiaowei Bao 
Signed-off-by: Li Yang 
Signed-off-by: Frank Li 
---
 arch/powerpc/boot/dts/fsl/p1010rdb-pb.dts | 16 
 arch/powerpc/boot/dts/fsl/p1010rdb-pb_36b.dts | 16 
 arch/powerpc/boot/dts/fsl/p1010rdb.dtsi   | 16 
 3 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/boot/dts/fsl/p1010rdb-pb.dts 
b/arch/powerpc/boot/dts/fsl/p1010rdb-pb.dts
index 3a94acbb3c033..ce3346d77858f 100644
--- a/arch/powerpc/boot/dts/fsl/p1010rdb-pb.dts
+++ b/arch/powerpc/boot/dts/fsl/p1010rdb-pb.dts
@@ -29,3 +29,19 @@  {
 };
 
 /include/ "p1010si-post.dtsi"
+
+ {
+   pcie@0 {
+   interrupt-map = <
+   /* IDSEL 0x0 */
+   /*
+*irq[4:5] are active-high
+*irq[6:7] are active-low
+*/
+    0x0 0x0 0x1  0x4 0x2 0x0 0x0
+    0x0 0x0 0x2  0x5 0x2 0x0 0x0
+    0x0 0x0 0x3  0x6 0x1 0x0 0x0
+    0x0 0x0 0x4  0x7 0x1 0x0 0x0
+   >;
+   };
+};
diff --git a/arch/powerpc/boot/dts/fsl/p1010rdb-pb_36b.dts 
b/arch/powerpc/boot/dts/fsl/p1010rdb-pb_36b.dts
index 4cf255fedc96e..83590354f9a09 100644
--- a/arch/powerpc/boot/dts/fsl/p1010rdb-pb_36b.dts
+++ b/arch/powerpc/boot/dts/fsl/p1010rdb-pb_36b.dts
@@ -56,3 +56,19 @@  {
 };
 
 /include/ "p1010si-post.dtsi"
+
+ {
+   pcie@0 {
+   interrupt-map = <
+   /* IDSEL 0x0 */
+   /*
+*irq[4:5] are active-high
+*irq[6:7] are active-low
+*/
+    0x0 0x0 0x1  0x4 0x2 0x0 0x0
+    0x0 0x0 0x2  0x5 0x2 0x0 0x0
+    0x0 0x0 0x3  0x6 0x1 0x0 0x0
+    0x0 0x0 0x4  0x7 0x1 0x0 0x0
+   >;
+   };
+};
diff --git a/arch/powerpc/boot/dts/fsl/p1010rdb.dtsi 
b/arch/powerpc/boot/dts/fsl/p1010rdb.dtsi
index 2ca9cee2ddeb2..ef49a7d6c69dd 100644
--- a/arch/powerpc/boot/dts/fsl/p1010rdb.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p1010rdb.dtsi
@@ -215,19 +215,3 @@ enet2: ethernet@b2000 {
phy-connection-type = "sgmii";
};
 };
-
- {
-   pcie@0 {
-   interrupt-map = <
-   /* IDSEL 0x0 */
-   /*
-*irq[4:5] are active-high
-*irq[6:7] are active-low
-*/
-    0x0 0x0 0x1  0x4 0x2 0x0 0x0
-    0x0 0x0 0x2  0x5 0x2 0x0 0x0
-    0x0 0x0 0x3  0x6 0x1 0x0 0x0
-    0x0 0x0 0x4  0x7 0x1 0x0 0x0
-   >;
-   };
-};
-- 
2.34.1



[PATCH 1/4] powerpc: dts: add power management nodes to FSL chips

2024-01-19 Thread Frank Li
From: Ran Wang 

Enable Power Management feature on device tree, including MPC8536,
MPC8544, MPC8548, MPC8572, P1010, P1020, P1021, P1022, P2020, P2041,
P3041, T104X, T1024.

Signed-off-by: Zhao Chenhui 
Signed-off-by: Ran Wang 
Signed-off-by: Frank Li 
---
 arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi | 14 --
 arch/powerpc/boot/dts/fsl/mpc8544si-post.dtsi |  2 ++
 arch/powerpc/boot/dts/fsl/mpc8548si-post.dtsi |  2 ++
 arch/powerpc/boot/dts/fsl/mpc8572si-post.dtsi |  2 ++
 arch/powerpc/boot/dts/fsl/p1010si-post.dtsi   | 14 ++
 arch/powerpc/boot/dts/fsl/p1020si-post.dtsi   |  5 +
 arch/powerpc/boot/dts/fsl/p1021si-post.dtsi   |  5 +
 arch/powerpc/boot/dts/fsl/p1022si-post.dtsi   |  7 +--
 arch/powerpc/boot/dts/fsl/p2020si-post.dtsi   | 17 +
 arch/powerpc/boot/dts/fsl/pq3-power.dtsi  | 19 +++
 arch/powerpc/boot/dts/fsl/t1024rdb.dts|  2 +-
 arch/powerpc/boot/dts/fsl/t1040rdb.dts|  2 +-
 arch/powerpc/boot/dts/fsl/t1042rdb.dts|  2 +-
 arch/powerpc/boot/dts/fsl/t1042rdb_pi.dts |  2 +-
 14 files changed, 83 insertions(+), 12 deletions(-)
 create mode 100644 arch/powerpc/boot/dts/fsl/pq3-power.dtsi

diff --git a/arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi 
b/arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi
index 41935709ebe87..fba40a1bccc04 100644
--- a/arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi
@@ -199,6 +199,10 @@ L2: l2-cache-controller@2 {
 
 /include/ "pq3-dma-0.dtsi"
 /include/ "pq3-etsec1-0.dtsi"
+   enet0: ethernet@24000 {
+   fsl,wake-on-filer;
+   fsl,pmc-handle = <_clk>;
+   };
 /include/ "pq3-etsec1-timer-0.dtsi"
 
usb@22000 {
@@ -222,9 +226,10 @@ ptp_clock@24e00 {
};
 
 /include/ "pq3-etsec1-2.dtsi"
-
-   ethernet@26000 {
+   enet2: ethernet@26000 {
cell-index = <1>;
+   fsl,wake-on-filer;
+   fsl,pmc-handle = <_clk>;
};
 
usb@2b000 {
@@ -249,4 +254,9 @@ global-utilities@e {
reg = <0xe 0x1000>;
fsl,has-rstcr;
};
+
+/include/ "pq3-power.dtsi"
+   power@e0070 {
+   compatible = "fsl,mpc8536-pmc", "fsl,mpc8548-pmc";
+   };
 };
diff --git a/arch/powerpc/boot/dts/fsl/mpc8544si-post.dtsi 
b/arch/powerpc/boot/dts/fsl/mpc8544si-post.dtsi
index b68eb119faef3..ea7416af7ee3e 100644
--- a/arch/powerpc/boot/dts/fsl/mpc8544si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/mpc8544si-post.dtsi
@@ -188,4 +188,6 @@ global-utilities@e {
reg = <0xe 0x1000>;
fsl,has-rstcr;
};
+
+/include/ "pq3-power.dtsi"
 };
diff --git a/arch/powerpc/boot/dts/fsl/mpc8548si-post.dtsi 
b/arch/powerpc/boot/dts/fsl/mpc8548si-post.dtsi
index 579d76cb8e329..dddb7374508d6 100644
--- a/arch/powerpc/boot/dts/fsl/mpc8548si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/mpc8548si-post.dtsi
@@ -156,4 +156,6 @@ global-utilities@e {
reg = <0xe 0x1000>;
fsl,has-rstcr;
};
+
+/include/ "pq3-power.dtsi"
 };
diff --git a/arch/powerpc/boot/dts/fsl/mpc8572si-post.dtsi 
b/arch/powerpc/boot/dts/fsl/mpc8572si-post.dtsi
index 49294cf36b4e6..40a6cff770327 100644
--- a/arch/powerpc/boot/dts/fsl/mpc8572si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/mpc8572si-post.dtsi
@@ -193,4 +193,6 @@ global-utilities@e {
reg = <0xe 0x1000>;
fsl,has-rstcr;
};
+
+/include/ "pq3-power.dtsi"
 };
diff --git a/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi 
b/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi
index ccda0a91abf00..b540e58ff79e7 100644
--- a/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi
@@ -183,9 +183,23 @@ sdhc@2e000 {
 /include/ "pq3-etsec2-1.dtsi"
 /include/ "pq3-etsec2-2.dtsi"
 
+   enet0: ethernet@b {
+   fsl,pmc-handle = <_clk>;
+   };
+
+   enet1: ethernet@b1000 {
+   fsl,pmc-handle = <_clk>;
+   };
+
+   enet2: ethernet@b2000 {
+   fsl,pmc-handle = <_clk>;
+   };
+
global-utilities@e {
compatible = "fsl,p1010-guts";
reg = <0xe 0x1000>;
fsl,has-rstcr;
};
+
+/include/ "pq3-power.dtsi"
 };
diff --git a/arch/powerpc/boot/dts/fsl/p1020si-post.dtsi 
b/arch/powerpc/boot/dts/fsl/p1020si-post.dtsi
index 642dc3a83d0e3..cc4c7461003bb 100644
--- a/arch/powerpc/boot/dts/fsl/p1020si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p1020si-post.dtsi
@@ -163,14 +163,17 @@ sdhc@2e000 {
 
 /include/ "pq3-etsec2-0.dtsi"
enet0: enet0_grp2: ethernet@b {
+   fsl,pmc-handle = <_clk>;
};
 
 /include/ &

Re: [PATCH v6 4/4] PCI: layerscape: Add suspend/resume for ls1043a

2023-12-11 Thread Frank Li
On Mon, Dec 04, 2023 at 11:08:29AM -0500, Frank Li wrote:
> Add suspend/resume support for Layerscape LS1043a.
> 
> In the suspend path, PME_Turn_Off message is sent to the endpoint to
> transition the link to L2/L3_Ready state. In this SoC, there is no way to
> check if the controller has received the PME_To_Ack from the endpoint or
> not. So to be on the safer side, the driver just waits for
> PCIE_PME_TO_L2_TIMEOUT_US before asserting the SoC specific PMXMTTURNOFF
> bit to complete the PME_Turn_Off handshake. Then the link would enter L2/L3
> state depending on the VAUX supply.
> 
> In the resume path, the link is brought back from L2 to L0 by doing a
> software reset.
> 
> Acked-by: Roy Zang 
> Reviewed-by: Manivannan Sadhasivam 
> Signed-off-by: Frank Li 

@Lorenzo:

   Could you please pick up these patches? Mani already reviewed and only
impact layerscape platform.

Frank

> ---
> 
> Notes:
> Chagne from v5 to v6
> - none
> Change from v4 to v5
> - update commit message
> - use comments
> /* Reset the PEX wrapper to bring the link out of L2 */
> 
> Change from v3 to v4
> - Call scfg_pcie_send_turnoff_msg() shared with ls1021a
> - update commit message
> 
> Change from v2 to v3
> - Remove ls_pcie_lut_readl(writel) function
> 
> Change from v1 to v2
> - Update subject 'a' to 'A'
> 
>  drivers/pci/controller/dwc/pci-layerscape.c | 63 -
>  1 file changed, 62 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
> b/drivers/pci/controller/dwc/pci-layerscape.c
> index f3dfb70066fb7..7cdada200de7e 100644
> --- a/drivers/pci/controller/dwc/pci-layerscape.c
> +++ b/drivers/pci/controller/dwc/pci-layerscape.c
> @@ -41,6 +41,15 @@
>  #define SCFG_PEXSFTRSTCR 0x190
>  #define PEXSR(idx)   BIT(idx)
>  
> +/* LS1043A PEX PME control register */
> +#define SCFG_PEXPMECR0x144
> +#define PEXPME(idx)  BIT(31 - (idx) * 4)
> +
> +/* LS1043A PEX LUT debug register */
> +#define LS_PCIE_LDBG 0x7fc
> +#define LDBG_SR  BIT(30)
> +#define LDBG_WE  BIT(31)
> +
>  #define PCIE_IATU_NUM6
>  
>  struct ls_pcie_drvdata {
> @@ -224,6 +233,45 @@ static int ls1021a_pcie_exit_from_l2(struct dw_pcie_rp 
> *pp)
>   return scfg_pcie_exit_from_l2(pcie->scfg, SCFG_PEXSFTRSTCR, 
> PEXSR(pcie->index));
>  }
>  
> +static void ls1043a_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
> +{
> + struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> + struct ls_pcie *pcie = to_ls_pcie(pci);
> +
> + scfg_pcie_send_turnoff_msg(pcie->scfg, SCFG_PEXPMECR, 
> PEXPME(pcie->index));
> +}
> +
> +static int ls1043a_pcie_exit_from_l2(struct dw_pcie_rp *pp)
> +{
> + struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> + struct ls_pcie *pcie = to_ls_pcie(pci);
> + u32 val;
> +
> + /*
> +  * Reset the PEX wrapper to bring the link out of L2.
> +  * LDBG_WE: allows the user to have write access to the PEXDBG[SR] for 
> both setting and
> +  *  clearing the soft reset on the PEX module.
> +  * LDBG_SR: When SR is set to 1, the PEX module enters soft reset.
> +  */
> + val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
> + val |= LDBG_WE;
> + ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
> +
> + val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
> + val |= LDBG_SR;
> + ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
> +
> + val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
> + val &= ~LDBG_SR;
> + ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
> +
> + val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
> + val &= ~LDBG_WE;
> + ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
> +
> + return 0;
> +}
> +
>  static const struct dw_pcie_host_ops ls_pcie_host_ops = {
>   .host_init = ls_pcie_host_init,
>   .pme_turn_off = ls_pcie_send_turnoff_msg,
> @@ -241,6 +289,19 @@ static const struct ls_pcie_drvdata ls1021a_drvdata = {
>   .exit_from_l2 = ls1021a_pcie_exit_from_l2,
>  };
>  
> +static const struct dw_pcie_host_ops ls1043a_pcie_host_ops = {
> + .host_init = ls_pcie_host_init,
> + .pme_turn_off = ls1043a_pcie_send_turnoff_msg,
> +};
> +
> +static const struct ls_pcie_drvdata ls1043a_drvdata = {
> + .pf_lut_off = 0x1,
> + .pm_support = true,
> + .scfg_support = true,
> + .ops = _pcie_host_ops,
> + .exit_from_l2 = ls1043a_pcie_exit_from_l2,
> +};
> +
>  static const struct ls_pcie_drvdata layerscape_drvdata = {
>   .pf_lut_off = 0xc00

[PATCH v6 4/4] PCI: layerscape: Add suspend/resume for ls1043a

2023-12-04 Thread Frank Li
Add suspend/resume support for Layerscape LS1043a.

In the suspend path, PME_Turn_Off message is sent to the endpoint to
transition the link to L2/L3_Ready state. In this SoC, there is no way to
check if the controller has received the PME_To_Ack from the endpoint or
not. So to be on the safer side, the driver just waits for
PCIE_PME_TO_L2_TIMEOUT_US before asserting the SoC specific PMXMTTURNOFF
bit to complete the PME_Turn_Off handshake. Then the link would enter L2/L3
state depending on the VAUX supply.

In the resume path, the link is brought back from L2 to L0 by doing a
software reset.

Acked-by: Roy Zang 
Reviewed-by: Manivannan Sadhasivam 
Signed-off-by: Frank Li 
---

Notes:
Chagne from v5 to v6
- none
Change from v4 to v5
- update commit message
- use comments
/* Reset the PEX wrapper to bring the link out of L2 */

Change from v3 to v4
- Call scfg_pcie_send_turnoff_msg() shared with ls1021a
- update commit message

Change from v2 to v3
- Remove ls_pcie_lut_readl(writel) function

Change from v1 to v2
- Update subject 'a' to 'A'

 drivers/pci/controller/dwc/pci-layerscape.c | 63 -
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index f3dfb70066fb7..7cdada200de7e 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -41,6 +41,15 @@
 #define SCFG_PEXSFTRSTCR   0x190
 #define PEXSR(idx) BIT(idx)
 
+/* LS1043A PEX PME control register */
+#define SCFG_PEXPMECR  0x144
+#define PEXPME(idx)BIT(31 - (idx) * 4)
+
+/* LS1043A PEX LUT debug register */
+#define LS_PCIE_LDBG   0x7fc
+#define LDBG_SRBIT(30)
+#define LDBG_WEBIT(31)
+
 #define PCIE_IATU_NUM  6
 
 struct ls_pcie_drvdata {
@@ -224,6 +233,45 @@ static int ls1021a_pcie_exit_from_l2(struct dw_pcie_rp *pp)
return scfg_pcie_exit_from_l2(pcie->scfg, SCFG_PEXSFTRSTCR, 
PEXSR(pcie->index));
 }
 
+static void ls1043a_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+   struct ls_pcie *pcie = to_ls_pcie(pci);
+
+   scfg_pcie_send_turnoff_msg(pcie->scfg, SCFG_PEXPMECR, 
PEXPME(pcie->index));
+}
+
+static int ls1043a_pcie_exit_from_l2(struct dw_pcie_rp *pp)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+   struct ls_pcie *pcie = to_ls_pcie(pci);
+   u32 val;
+
+   /*
+* Reset the PEX wrapper to bring the link out of L2.
+* LDBG_WE: allows the user to have write access to the PEXDBG[SR] for 
both setting and
+*  clearing the soft reset on the PEX module.
+* LDBG_SR: When SR is set to 1, the PEX module enters soft reset.
+*/
+   val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
+   val |= LDBG_WE;
+   ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
+
+   val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
+   val |= LDBG_SR;
+   ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
+
+   val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
+   val &= ~LDBG_SR;
+   ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
+
+   val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
+   val &= ~LDBG_WE;
+   ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
+
+   return 0;
+}
+
 static const struct dw_pcie_host_ops ls_pcie_host_ops = {
.host_init = ls_pcie_host_init,
.pme_turn_off = ls_pcie_send_turnoff_msg,
@@ -241,6 +289,19 @@ static const struct ls_pcie_drvdata ls1021a_drvdata = {
.exit_from_l2 = ls1021a_pcie_exit_from_l2,
 };
 
+static const struct dw_pcie_host_ops ls1043a_pcie_host_ops = {
+   .host_init = ls_pcie_host_init,
+   .pme_turn_off = ls1043a_pcie_send_turnoff_msg,
+};
+
+static const struct ls_pcie_drvdata ls1043a_drvdata = {
+   .pf_lut_off = 0x1,
+   .pm_support = true,
+   .scfg_support = true,
+   .ops = _pcie_host_ops,
+   .exit_from_l2 = ls1043a_pcie_exit_from_l2,
+};
+
 static const struct ls_pcie_drvdata layerscape_drvdata = {
.pf_lut_off = 0xc,
.pm_support = true,
@@ -252,7 +313,7 @@ static const struct of_device_id ls_pcie_of_match[] = {
{ .compatible = "fsl,ls1012a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls1021a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls1028a-pcie", .data = _drvdata },
-   { .compatible = "fsl,ls1043a-pcie", .data = _drvdata },
+   { .compatible = "fsl,ls1043a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls1046a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls2080a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls2085a-pcie", .data = _drvdata },
-- 
2.34.1



[PATCH v6 3/4] PCI: layerscape(ep): Rename pf_* as pf_lut_*

2023-12-04 Thread Frank Li
'pf' and 'lut' is just difference name in difference chips, but basic it is
a MMIO base address plus an offset.

Rename it to avoid duplicate pf_* and lut_* in driver.

Reviewed-by: Manivannan Sadhasivam 
Acked-by: Roy Zang 
Signed-off-by: Frank Li 
---

Notes:
pf_lut is better than pf_* or lut* because some chip use 'pf', some chip
use 'lut'.

Change from v5 to v6
move to previous patch
-> -.ops = _pcie_host_ops;
> + .ops = _pcie_host_ops,

Change from v4 to v5
- rename layerscape-ep code also
change from v1 to v4
- new patch at v3

 .../pci/controller/dwc/pci-layerscape-ep.c| 16 -
 drivers/pci/controller/dwc/pci-layerscape.c   | 34 +--
 2 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index 3d3c50ef4b6ff..2ca339f938a86 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -49,7 +49,7 @@ struct ls_pcie_ep {
boolbig_endian;
 };
 
-static u32 ls_lut_readl(struct ls_pcie_ep *pcie, u32 offset)
+static u32 ls_pcie_pf_lut_readl(struct ls_pcie_ep *pcie, u32 offset)
 {
struct dw_pcie *pci = pcie->pci;
 
@@ -59,7 +59,7 @@ static u32 ls_lut_readl(struct ls_pcie_ep *pcie, u32 offset)
return ioread32(pci->dbi_base + offset);
 }
 
-static void ls_lut_writel(struct ls_pcie_ep *pcie, u32 offset, u32 value)
+static void ls_pcie_pf_lut_writel(struct ls_pcie_ep *pcie, u32 offset, u32 
value)
 {
struct dw_pcie *pci = pcie->pci;
 
@@ -76,8 +76,8 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, void 
*dev_id)
u32 val, cfg;
u8 offset;
 
-   val = ls_lut_readl(pcie, PEX_PF0_PME_MES_DR);
-   ls_lut_writel(pcie, PEX_PF0_PME_MES_DR, val);
+   val = ls_pcie_pf_lut_readl(pcie, PEX_PF0_PME_MES_DR);
+   ls_pcie_pf_lut_writel(pcie, PEX_PF0_PME_MES_DR, val);
 
if (!val)
return IRQ_NONE;
@@ -96,9 +96,9 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, void 
*dev_id)
dw_pcie_writel_dbi(pci, offset + PCI_EXP_LNKCAP, pcie->lnkcap);
dw_pcie_dbi_ro_wr_dis(pci);
 
-   cfg = ls_lut_readl(pcie, PEX_PF0_CONFIG);
+   cfg = ls_pcie_pf_lut_readl(pcie, PEX_PF0_CONFIG);
cfg |= PEX_PF0_CFG_READY;
-   ls_lut_writel(pcie, PEX_PF0_CONFIG, cfg);
+   ls_pcie_pf_lut_writel(pcie, PEX_PF0_CONFIG, cfg);
dw_pcie_ep_linkup(>ep);
 
dev_dbg(pci->dev, "Link up\n");
@@ -130,10 +130,10 @@ static int ls_pcie_ep_interrupt_init(struct ls_pcie_ep 
*pcie,
}
 
/* Enable interrupts */
-   val = ls_lut_readl(pcie, PEX_PF0_PME_MES_IER);
+   val = ls_pcie_pf_lut_readl(pcie, PEX_PF0_PME_MES_IER);
val |=  PEX_PF0_PME_MES_IER_LDDIE | PEX_PF0_PME_MES_IER_HRDIE |
PEX_PF0_PME_MES_IER_LUDIE;
-   ls_lut_writel(pcie, PEX_PF0_PME_MES_IER, val);
+   ls_pcie_pf_lut_writel(pcie, PEX_PF0_PME_MES_IER, val);
 
return 0;
 }
diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index 711563777aeba..f3dfb70066fb7 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -44,7 +44,7 @@
 #define PCIE_IATU_NUM  6
 
 struct ls_pcie_drvdata {
-   const u32 pf_off;
+   const u32 pf_lut_off;
const struct dw_pcie_host_ops *ops;
int (*exit_from_l2)(struct dw_pcie_rp *pp);
bool scfg_support;
@@ -54,13 +54,13 @@ struct ls_pcie_drvdata {
 struct ls_pcie {
struct dw_pcie *pci;
const struct ls_pcie_drvdata *drvdata;
-   void __iomem *pf_base;
+   void __iomem *pf_lut_base;
struct regmap *scfg;
int index;
bool big_endian;
 };
 
-#define ls_pcie_pf_readl_addr(addr)ls_pcie_pf_readl(pcie, addr)
+#define ls_pcie_pf_lut_readl_addr(addr)ls_pcie_pf_lut_readl(pcie, addr)
 #define to_ls_pcie(x)  dev_get_drvdata((x)->dev)
 
 static bool ls_pcie_is_bridge(struct ls_pcie *pcie)
@@ -101,20 +101,20 @@ static void ls_pcie_fix_error_response(struct ls_pcie 
*pcie)
iowrite32(PCIE_ABSERR_SETTING, pci->dbi_base + PCIE_ABSERR);
 }
 
-static u32 ls_pcie_pf_readl(struct ls_pcie *pcie, u32 off)
+static u32 ls_pcie_pf_lut_readl(struct ls_pcie *pcie, u32 off)
 {
if (pcie->big_endian)
-   return ioread32be(pcie->pf_base + off);
+   return ioread32be(pcie->pf_lut_base + off);
 
-   return ioread32(pcie->pf_base + off);
+   return ioread32(pcie->pf_lut_base + off);
 }
 
-static void ls_pcie_pf_writel(struct ls_pcie *pcie, u32 off, u32 val)
+static void ls_pcie_pf_lut_writel(struct ls_pcie *pcie, u32 off, u32 val)
 {
if (pcie->big_en

[PATCH v6 2/4] PCI: layerscape: Add suspend/resume for ls1021a

2023-12-04 Thread Frank Li
Add suspend/resume support for Layerscape LS1021a.

In the suspend path, PME_Turn_Off message is sent to the endpoint to
transition the link to L2/L3_Ready state. In this SoC, there is no way to
check if the controller has received the PME_To_Ack from the endpoint or
not. So to be on the safer side, the driver just waits for
PCIE_PME_TO_L2_TIMEOUT_US before asserting the SoC specific PMXMTTURNOFF
bit to complete the PME_Turn_Off handshake. Then the link would enter L2/L3
state depending on the VAUX supply.

In the resume path, the link is brought back from L2 to L0 by doing a
software reset.

Acked-by: Roy Zang 
Reviewed-by: Manivannan Sadhasivam 
Signed-off-by: Frank Li 
---

Notes:
Change from v5 to v6
- remove reduntant pci->pp.ops = _pcie_host_ops;
Change from v4 to v5
- update comit message
- remove a empty line
- use comments
/* Reset the PEX wrapper to bring the link out of L2 */
- pci->pp.ops = pcie->drvdata->ops,
ls_pcie_host_ops to the "ops" member of layerscape_drvdata.
- don't set pcie->scfg = NULL at error path

Change from v3 to v4
- update commit message.
- it is reset a glue logic part for PCI controller.
- use regmap_write_bits() to reduce code change.

Change from v2 to v3
- update according to mani's feedback
change from v1 to v2
- change subject 'a' to 'A'

 drivers/pci/controller/dwc/pci-layerscape.c | 83 -
 1 file changed, 80 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index aea89926bcc4f..711563777aeba 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -35,11 +35,19 @@
 #define PF_MCR_PTOMR   BIT(0)
 #define PF_MCR_EXL2S   BIT(1)
 
+/* LS1021A PEXn PM Write Control Register */
+#define SCFG_PEXPMWRCR(idx)(0x5c + (idx) * 0x64)
+#define PMXMTTURNOFF   BIT(31)
+#define SCFG_PEXSFTRSTCR   0x190
+#define PEXSR(idx) BIT(idx)
+
 #define PCIE_IATU_NUM  6
 
 struct ls_pcie_drvdata {
const u32 pf_off;
+   const struct dw_pcie_host_ops *ops;
int (*exit_from_l2)(struct dw_pcie_rp *pp);
+   bool scfg_support;
bool pm_support;
 };
 
@@ -47,6 +55,8 @@ struct ls_pcie {
struct dw_pcie *pci;
const struct ls_pcie_drvdata *drvdata;
void __iomem *pf_base;
+   struct regmap *scfg;
+   int index;
bool big_endian;
 };
 
@@ -171,18 +181,70 @@ static int ls_pcie_host_init(struct dw_pcie_rp *pp)
return 0;
 }
 
+static void scfg_pcie_send_turnoff_msg(struct regmap *scfg, u32 reg, u32 mask)
+{
+   /* Send PME_Turn_Off message */
+   regmap_write_bits(scfg, reg, mask, mask);
+
+   /*
+* There is no specific register to check for PME_To_Ack from endpoint.
+* So on the safe side, wait for PCIE_PME_TO_L2_TIMEOUT_US.
+*/
+   mdelay(PCIE_PME_TO_L2_TIMEOUT_US/1000);
+
+   /*
+* Layerscape hardware reference manual recommends clearing the 
PMXMTTURNOFF bit
+* to complete the PME_Turn_Off handshake.
+*/
+   regmap_write_bits(scfg, reg, mask, 0);
+}
+
+static void ls1021a_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+   struct ls_pcie *pcie = to_ls_pcie(pci);
+
+   scfg_pcie_send_turnoff_msg(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), 
PMXMTTURNOFF);
+}
+
+static int scfg_pcie_exit_from_l2(struct regmap *scfg, u32 reg, u32 mask)
+{
+   /* Reset the PEX wrapper to bring the link out of L2 */
+   regmap_write_bits(scfg, reg, mask, mask);
+   regmap_write_bits(scfg, reg, mask, 0);
+
+   return 0;
+}
+
+static int ls1021a_pcie_exit_from_l2(struct dw_pcie_rp *pp)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+   struct ls_pcie *pcie = to_ls_pcie(pci);
+
+   return scfg_pcie_exit_from_l2(pcie->scfg, SCFG_PEXSFTRSTCR, 
PEXSR(pcie->index));
+}
+
 static const struct dw_pcie_host_ops ls_pcie_host_ops = {
.host_init = ls_pcie_host_init,
.pme_turn_off = ls_pcie_send_turnoff_msg,
 };
 
+static const struct dw_pcie_host_ops ls1021a_pcie_host_ops = {
+   .host_init = ls_pcie_host_init,
+   .pme_turn_off = ls1021a_pcie_send_turnoff_msg,
+};
+
 static const struct ls_pcie_drvdata ls1021a_drvdata = {
-   .pm_support = false,
+   .pm_support = true,
+   .scfg_support = true,
+   .ops = _pcie_host_ops,
+   .exit_from_l2 = ls1021a_pcie_exit_from_l2,
 };
 
 static const struct ls_pcie_drvdata layerscape_drvdata = {
.pf_off = 0xc,
.pm_support = true,
+   .ops = _pcie_host_ops,
.exit_from_l2 = ls_pcie_exit_from_l2,
 };
 
@@ -205,6 +267,8 @@ static int ls_pcie_probe(struct platform_device *pdev)
struct dw_pcie *pci;
struct ls_pcie *pcie;
struct resource *dbi_base;

[PATCH v6 1/4] PCI: layerscape: Add function pointer for exit_from_l2()

2023-12-04 Thread Frank Li
Since difference SoCs require different sequence for exiting L2, let's add
a separate "exit_from_l2()" callback. This callback can be used to execute
SoC specific sequence.

Change ls_pcie_exit_from_l2() return value from void to int. Return error
if exit_from_l2() failure at exit resume flow.

Acked-by: Roy Zang 
Reviewed-by: Manivannan Sadhasivam 
Signed-off-by: Frank Li 
---

Notes:
Change from v4 to v6
- none
Change from v3 to v4
- update commit message
  Add mani's review by tag
Change from v2 to v3
- fixed according to mani's feedback
  1. update commit message
  2. move dw_pcie_host_ops to next patch
  3. check return value from exit_from_l2()
Change from v1 to v2
- change subject 'a' to 'A'

Change from v1 to v2
- change subject 'a' to 'A'

 drivers/pci/controller/dwc/pci-layerscape.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index 37956e09c65bd..aea89926bcc4f 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -39,6 +39,7 @@
 
 struct ls_pcie_drvdata {
const u32 pf_off;
+   int (*exit_from_l2)(struct dw_pcie_rp *pp);
bool pm_support;
 };
 
@@ -125,7 +126,7 @@ static void ls_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
dev_err(pcie->pci->dev, "PME_Turn_off timeout\n");
 }
 
-static void ls_pcie_exit_from_l2(struct dw_pcie_rp *pp)
+static int ls_pcie_exit_from_l2(struct dw_pcie_rp *pp)
 {
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct ls_pcie *pcie = to_ls_pcie(pci);
@@ -150,6 +151,8 @@ static void ls_pcie_exit_from_l2(struct dw_pcie_rp *pp)
 1);
if (ret)
dev_err(pcie->pci->dev, "L2 exit timeout\n");
+
+   return ret;
 }
 
 static int ls_pcie_host_init(struct dw_pcie_rp *pp)
@@ -180,6 +183,7 @@ static const struct ls_pcie_drvdata ls1021a_drvdata = {
 static const struct ls_pcie_drvdata layerscape_drvdata = {
.pf_off = 0xc,
.pm_support = true,
+   .exit_from_l2 = ls_pcie_exit_from_l2,
 };
 
 static const struct of_device_id ls_pcie_of_match[] = {
@@ -247,11 +251,14 @@ static int ls_pcie_suspend_noirq(struct device *dev)
 static int ls_pcie_resume_noirq(struct device *dev)
 {
struct ls_pcie *pcie = dev_get_drvdata(dev);
+   int ret;
 
if (!pcie->drvdata->pm_support)
return 0;
 
-   ls_pcie_exit_from_l2(>pci->pp);
+   ret = pcie->drvdata->exit_from_l2(>pci->pp);
+   if (ret)
+   return ret;
 
return dw_pcie_resume_noirq(pcie->pci);
 }
-- 
2.34.1



[PATCH v6 0/4] PCI: layerscape: Add suspend/resume support for ls1043 and ls1021

2023-12-04 Thread Frank Li
Add suspend/resume support for ls1043 and ls1021.

Change log see each patch

Frank Li (4):
  PCI: layerscape: Add function pointer for exit_from_l2()
  PCI: layerscape: Add suspend/resume for ls1021a
  PCI: layerscape(ep): Rename pf_* as pf_lut_*
  PCI: layerscape: Add suspend/resume for ls1043a

 .../pci/controller/dwc/pci-layerscape-ep.c|  16 +-
 drivers/pci/controller/dwc/pci-layerscape.c   | 191 +++---
 2 files changed, 176 insertions(+), 31 deletions(-)

-- 
2.34.1



[PATCH v5 4/4] PCI: layerscape: Add suspend/resume for ls1043a

2023-12-01 Thread Frank Li
Add suspend/resume support for Layerscape LS1043a.

In the suspend path, PME_Turn_Off message is sent to the endpoint to
transition the link to L2/L3_Ready state. In this SoC, there is no way to
check if the controller has received the PME_To_Ack from the endpoint or
not. So to be on the safer side, the driver just waits for
PCIE_PME_TO_L2_TIMEOUT_US before asserting the SoC specific PMXMTTURNOFF
bit to complete the PME_Turn_Off handshake. Then the link would enter L2/L3
state depending on the VAUX supply.

In the resume path, the link is brought back from L2 to L0 by doing a
software reset.

Signed-off-by: Frank Li 
---

Notes:
Change from v4 to v5
- update commit message
- use comments
/* Reset the PEX wrapper to bring the link out of L2 */

Change from v3 to v4
- Call scfg_pcie_send_turnoff_msg() shared with ls1021a
- update commit message

Change from v2 to v3
- Remove ls_pcie_lut_readl(writel) function

Change from v1 to v2
- Update subject 'a' to 'A'

 drivers/pci/controller/dwc/pci-layerscape.c | 63 -
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index a9151e98fde6f..715365e91f8ef 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -41,6 +41,15 @@
 #define SCFG_PEXSFTRSTCR   0x190
 #define PEXSR(idx) BIT(idx)
 
+/* LS1043A PEX PME control register */
+#define SCFG_PEXPMECR  0x144
+#define PEXPME(idx)BIT(31 - (idx) * 4)
+
+/* LS1043A PEX LUT debug register */
+#define LS_PCIE_LDBG   0x7fc
+#define LDBG_SRBIT(30)
+#define LDBG_WEBIT(31)
+
 #define PCIE_IATU_NUM  6
 
 struct ls_pcie_drvdata {
@@ -224,6 +233,45 @@ static int ls1021a_pcie_exit_from_l2(struct dw_pcie_rp *pp)
return scfg_pcie_exit_from_l2(pcie->scfg, SCFG_PEXSFTRSTCR, 
PEXSR(pcie->index));
 }
 
+static void ls1043a_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+   struct ls_pcie *pcie = to_ls_pcie(pci);
+
+   scfg_pcie_send_turnoff_msg(pcie->scfg, SCFG_PEXPMECR, 
PEXPME(pcie->index));
+}
+
+static int ls1043a_pcie_exit_from_l2(struct dw_pcie_rp *pp)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+   struct ls_pcie *pcie = to_ls_pcie(pci);
+   u32 val;
+
+   /*
+* Reset the PEX wrapper to bring the link out of L2.
+* LDBG_WE: allows the user to have write access to the PEXDBG[SR] for 
both setting and
+*  clearing the soft reset on the PEX module.
+* LDBG_SR: When SR is set to 1, the PEX module enters soft reset.
+*/
+   val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
+   val |= LDBG_WE;
+   ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
+
+   val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
+   val |= LDBG_SR;
+   ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
+
+   val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
+   val &= ~LDBG_SR;
+   ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
+
+   val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
+   val &= ~LDBG_WE;
+   ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
+
+   return 0;
+}
+
 static const struct dw_pcie_host_ops ls_pcie_host_ops = {
.host_init = ls_pcie_host_init,
.pme_turn_off = ls_pcie_send_turnoff_msg,
@@ -241,6 +289,19 @@ static const struct ls_pcie_drvdata ls1021a_drvdata = {
.exit_from_l2 = ls1021a_pcie_exit_from_l2,
 };
 
+static const struct dw_pcie_host_ops ls1043a_pcie_host_ops = {
+   .host_init = ls_pcie_host_init,
+   .pme_turn_off = ls1043a_pcie_send_turnoff_msg,
+};
+
+static const struct ls_pcie_drvdata ls1043a_drvdata = {
+   .pf_lut_off = 0x1,
+   .pm_support = true,
+   .scfg_support = true,
+   .ops = _pcie_host_ops,
+   .exit_from_l2 = ls1043a_pcie_exit_from_l2,
+};
+
 static const struct ls_pcie_drvdata layerscape_drvdata = {
.pf_lut_off = 0xc,
.pm_support = true,
@@ -252,7 +313,7 @@ static const struct of_device_id ls_pcie_of_match[] = {
{ .compatible = "fsl,ls1012a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls1021a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls1028a-pcie", .data = _drvdata },
-   { .compatible = "fsl,ls1043a-pcie", .data = _drvdata },
+   { .compatible = "fsl,ls1043a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls1046a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls2080a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls2085a-pcie", .data = _drvdata },
-- 
2.34.1



[PATCH v5 3/4] PCI: layerscape(ep): Rename pf_* as pf_lut_*

2023-12-01 Thread Frank Li
'pf' and 'lut' is just difference name in difference chips, but basic it is
a MMIO base address plus an offset.

Rename it to avoid duplicate pf_* and lut_* in driver.

Signed-off-by: Frank Li 
---

Notes:
pf_lut is better than pf_* or lut* because some chip use 'pf', some chip
use 'lut'.

Change from v4 to v5
- rename layerscape-ep code also
change from v1 to v4
- new patch at v3

 .../pci/controller/dwc/pci-layerscape-ep.c| 16 -
 drivers/pci/controller/dwc/pci-layerscape.c   | 36 +--
 2 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index 3d3c50ef4b6ff..2ca339f938a86 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -49,7 +49,7 @@ struct ls_pcie_ep {
boolbig_endian;
 };
 
-static u32 ls_lut_readl(struct ls_pcie_ep *pcie, u32 offset)
+static u32 ls_pcie_pf_lut_readl(struct ls_pcie_ep *pcie, u32 offset)
 {
struct dw_pcie *pci = pcie->pci;
 
@@ -59,7 +59,7 @@ static u32 ls_lut_readl(struct ls_pcie_ep *pcie, u32 offset)
return ioread32(pci->dbi_base + offset);
 }
 
-static void ls_lut_writel(struct ls_pcie_ep *pcie, u32 offset, u32 value)
+static void ls_pcie_pf_lut_writel(struct ls_pcie_ep *pcie, u32 offset, u32 
value)
 {
struct dw_pcie *pci = pcie->pci;
 
@@ -76,8 +76,8 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, void 
*dev_id)
u32 val, cfg;
u8 offset;
 
-   val = ls_lut_readl(pcie, PEX_PF0_PME_MES_DR);
-   ls_lut_writel(pcie, PEX_PF0_PME_MES_DR, val);
+   val = ls_pcie_pf_lut_readl(pcie, PEX_PF0_PME_MES_DR);
+   ls_pcie_pf_lut_writel(pcie, PEX_PF0_PME_MES_DR, val);
 
if (!val)
return IRQ_NONE;
@@ -96,9 +96,9 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, void 
*dev_id)
dw_pcie_writel_dbi(pci, offset + PCI_EXP_LNKCAP, pcie->lnkcap);
dw_pcie_dbi_ro_wr_dis(pci);
 
-   cfg = ls_lut_readl(pcie, PEX_PF0_CONFIG);
+   cfg = ls_pcie_pf_lut_readl(pcie, PEX_PF0_CONFIG);
cfg |= PEX_PF0_CFG_READY;
-   ls_lut_writel(pcie, PEX_PF0_CONFIG, cfg);
+   ls_pcie_pf_lut_writel(pcie, PEX_PF0_CONFIG, cfg);
dw_pcie_ep_linkup(>ep);
 
dev_dbg(pci->dev, "Link up\n");
@@ -130,10 +130,10 @@ static int ls_pcie_ep_interrupt_init(struct ls_pcie_ep 
*pcie,
}
 
/* Enable interrupts */
-   val = ls_lut_readl(pcie, PEX_PF0_PME_MES_IER);
+   val = ls_pcie_pf_lut_readl(pcie, PEX_PF0_PME_MES_IER);
val |=  PEX_PF0_PME_MES_IER_LDDIE | PEX_PF0_PME_MES_IER_HRDIE |
PEX_PF0_PME_MES_IER_LUDIE;
-   ls_lut_writel(pcie, PEX_PF0_PME_MES_IER, val);
+   ls_pcie_pf_lut_writel(pcie, PEX_PF0_PME_MES_IER, val);
 
return 0;
 }
diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index 8bdaae9be7d56..a9151e98fde6f 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -44,7 +44,7 @@
 #define PCIE_IATU_NUM  6
 
 struct ls_pcie_drvdata {
-   const u32 pf_off;
+   const u32 pf_lut_off;
const struct dw_pcie_host_ops *ops;
int (*exit_from_l2)(struct dw_pcie_rp *pp);
bool scfg_support;
@@ -54,13 +54,13 @@ struct ls_pcie_drvdata {
 struct ls_pcie {
struct dw_pcie *pci;
const struct ls_pcie_drvdata *drvdata;
-   void __iomem *pf_base;
+   void __iomem *pf_lut_base;
struct regmap *scfg;
int index;
bool big_endian;
 };
 
-#define ls_pcie_pf_readl_addr(addr)ls_pcie_pf_readl(pcie, addr)
+#define ls_pcie_pf_lut_readl_addr(addr)ls_pcie_pf_lut_readl(pcie, addr)
 #define to_ls_pcie(x)  dev_get_drvdata((x)->dev)
 
 static bool ls_pcie_is_bridge(struct ls_pcie *pcie)
@@ -101,20 +101,20 @@ static void ls_pcie_fix_error_response(struct ls_pcie 
*pcie)
iowrite32(PCIE_ABSERR_SETTING, pci->dbi_base + PCIE_ABSERR);
 }
 
-static u32 ls_pcie_pf_readl(struct ls_pcie *pcie, u32 off)
+static u32 ls_pcie_pf_lut_readl(struct ls_pcie *pcie, u32 off)
 {
if (pcie->big_endian)
-   return ioread32be(pcie->pf_base + off);
+   return ioread32be(pcie->pf_lut_base + off);
 
-   return ioread32(pcie->pf_base + off);
+   return ioread32(pcie->pf_lut_base + off);
 }
 
-static void ls_pcie_pf_writel(struct ls_pcie *pcie, u32 off, u32 val)
+static void ls_pcie_pf_lut_writel(struct ls_pcie *pcie, u32 off, u32 val)
 {
if (pcie->big_endian)
-   iowrite32be(val, pcie->pf_base + off);
+   iowrite32be(val, pcie->pf_lut_base + off);
else
-   iowrite32(val, pcie->pf_base + off);
+

[PATCH v5 2/4] PCI: layerscape: Add suspend/resume for ls1021a

2023-12-01 Thread Frank Li
Add suspend/resume support for Layerscape LS1021a.

In the suspend path, PME_Turn_Off message is sent to the endpoint to
transition the link to L2/L3_Ready state. In this SoC, there is no way to
check if the controller has received the PME_To_Ack from the endpoint or
not. So to be on the safer side, the driver just waits for
PCIE_PME_TO_L2_TIMEOUT_US before asserting the SoC specific PMXMTTURNOFF
bit to complete the PME_Turn_Off handshake. Then the link would enter L2/L3
state depending on the VAUX supply.

In the resume path, the link is brought back from L2 to L0 by doing a
software reset.

Signed-off-by: Frank Li 
---

Notes:
Change from v4 to v5
- update comit message
- remove a empty line
- use comments
/* Reset the PEX wrapper to bring the link out of L2 */
- pci->pp.ops = pcie->drvdata->ops,
ls_pcie_host_ops to the "ops" member of layerscape_drvdata.
- don't set pcie->scfg = NULL at error path

Change from v3 to v4
- update commit message.
- it is reset a glue logic part for PCI controller.
- use regmap_write_bits() to reduce code change.

Change from v2 to v3
- update according to mani's feedback
change from v1 to v2
- change subject 'a' to 'A'

 drivers/pci/controller/dwc/pci-layerscape.c | 81 -
 1 file changed, 80 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index aea89926bcc4f..8bdaae9be7d56 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -35,11 +35,19 @@
 #define PF_MCR_PTOMR   BIT(0)
 #define PF_MCR_EXL2S   BIT(1)
 
+/* LS1021A PEXn PM Write Control Register */
+#define SCFG_PEXPMWRCR(idx)(0x5c + (idx) * 0x64)
+#define PMXMTTURNOFF   BIT(31)
+#define SCFG_PEXSFTRSTCR   0x190
+#define PEXSR(idx) BIT(idx)
+
 #define PCIE_IATU_NUM  6
 
 struct ls_pcie_drvdata {
const u32 pf_off;
+   const struct dw_pcie_host_ops *ops;
int (*exit_from_l2)(struct dw_pcie_rp *pp);
+   bool scfg_support;
bool pm_support;
 };
 
@@ -47,6 +55,8 @@ struct ls_pcie {
struct dw_pcie *pci;
const struct ls_pcie_drvdata *drvdata;
void __iomem *pf_base;
+   struct regmap *scfg;
+   int index;
bool big_endian;
 };
 
@@ -171,18 +181,70 @@ static int ls_pcie_host_init(struct dw_pcie_rp *pp)
return 0;
 }
 
+static void scfg_pcie_send_turnoff_msg(struct regmap *scfg, u32 reg, u32 mask)
+{
+   /* Send PME_Turn_Off message */
+   regmap_write_bits(scfg, reg, mask, mask);
+
+   /*
+* There is no specific register to check for PME_To_Ack from endpoint.
+* So on the safe side, wait for PCIE_PME_TO_L2_TIMEOUT_US.
+*/
+   mdelay(PCIE_PME_TO_L2_TIMEOUT_US/1000);
+
+   /*
+* Layerscape hardware reference manual recommends clearing the 
PMXMTTURNOFF bit
+* to complete the PME_Turn_Off handshake.
+*/
+   regmap_write_bits(scfg, reg, mask, 0);
+}
+
+static void ls1021a_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+   struct ls_pcie *pcie = to_ls_pcie(pci);
+
+   scfg_pcie_send_turnoff_msg(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), 
PMXMTTURNOFF);
+}
+
+static int scfg_pcie_exit_from_l2(struct regmap *scfg, u32 reg, u32 mask)
+{
+   /* Reset the PEX wrapper to bring the link out of L2 */
+   regmap_write_bits(scfg, reg, mask, mask);
+   regmap_write_bits(scfg, reg, mask, 0);
+
+   return 0;
+}
+
+static int ls1021a_pcie_exit_from_l2(struct dw_pcie_rp *pp)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+   struct ls_pcie *pcie = to_ls_pcie(pci);
+
+   return scfg_pcie_exit_from_l2(pcie->scfg, SCFG_PEXSFTRSTCR, 
PEXSR(pcie->index));
+}
+
 static const struct dw_pcie_host_ops ls_pcie_host_ops = {
.host_init = ls_pcie_host_init,
.pme_turn_off = ls_pcie_send_turnoff_msg,
 };
 
+static const struct dw_pcie_host_ops ls1021a_pcie_host_ops = {
+   .host_init = ls_pcie_host_init,
+   .pme_turn_off = ls1021a_pcie_send_turnoff_msg,
+};
+
 static const struct ls_pcie_drvdata ls1021a_drvdata = {
-   .pm_support = false,
+   .pm_support = true,
+   .scfg_support = true,
+   .ops = _pcie_host_ops,
+   .exit_from_l2 = ls1021a_pcie_exit_from_l2,
 };
 
 static const struct ls_pcie_drvdata layerscape_drvdata = {
.pf_off = 0xc,
.pm_support = true,
+   .ops = _pcie_host_ops;
.exit_from_l2 = ls_pcie_exit_from_l2,
 };
 
@@ -205,6 +267,8 @@ static int ls_pcie_probe(struct platform_device *pdev)
struct dw_pcie *pci;
struct ls_pcie *pcie;
struct resource *dbi_base;
+   u32 index[2];
+   int ret;
 
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
if (!pcie)
@@ -220,6 +284,7 

[PATCH v5 1/4] PCI: layerscape: Add function pointer for exit_from_l2()

2023-12-01 Thread Frank Li
Since difference SoCs require different sequence for exiting L2, let's add
a separate "exit_from_l2()" callback. This callback can be used to execute
SoC specific sequence.

Change ls_pcie_exit_from_l2() return value from void to int. Return error
if exit_from_l2() failure at exit resume flow.

Reviewed-by: Manivannan Sadhasivam 
Signed-off-by: Frank Li 
---

Notes:
Change from v4 to v5
- none
Change from v3 to v4
- update commit message
  Add mani's review by tag
Change from v2 to v3
- fixed according to mani's feedback
  1. update commit message
  2. move dw_pcie_host_ops to next patch
  3. check return value from exit_from_l2()
Change from v1 to v2
- change subject 'a' to 'A'

Change from v1 to v2
- change subject 'a' to 'A'

 drivers/pci/controller/dwc/pci-layerscape.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index 37956e09c65bd..aea89926bcc4f 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -39,6 +39,7 @@
 
 struct ls_pcie_drvdata {
const u32 pf_off;
+   int (*exit_from_l2)(struct dw_pcie_rp *pp);
bool pm_support;
 };
 
@@ -125,7 +126,7 @@ static void ls_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
dev_err(pcie->pci->dev, "PME_Turn_off timeout\n");
 }
 
-static void ls_pcie_exit_from_l2(struct dw_pcie_rp *pp)
+static int ls_pcie_exit_from_l2(struct dw_pcie_rp *pp)
 {
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct ls_pcie *pcie = to_ls_pcie(pci);
@@ -150,6 +151,8 @@ static void ls_pcie_exit_from_l2(struct dw_pcie_rp *pp)
 1);
if (ret)
dev_err(pcie->pci->dev, "L2 exit timeout\n");
+
+   return ret;
 }
 
 static int ls_pcie_host_init(struct dw_pcie_rp *pp)
@@ -180,6 +183,7 @@ static const struct ls_pcie_drvdata ls1021a_drvdata = {
 static const struct ls_pcie_drvdata layerscape_drvdata = {
.pf_off = 0xc,
.pm_support = true,
+   .exit_from_l2 = ls_pcie_exit_from_l2,
 };
 
 static const struct of_device_id ls_pcie_of_match[] = {
@@ -247,11 +251,14 @@ static int ls_pcie_suspend_noirq(struct device *dev)
 static int ls_pcie_resume_noirq(struct device *dev)
 {
struct ls_pcie *pcie = dev_get_drvdata(dev);
+   int ret;
 
if (!pcie->drvdata->pm_support)
return 0;
 
-   ls_pcie_exit_from_l2(>pci->pp);
+   ret = pcie->drvdata->exit_from_l2(>pci->pp);
+   if (ret)
+   return ret;
 
return dw_pcie_resume_noirq(pcie->pci);
 }
-- 
2.34.1



[PATCH v5 0/4] PCI: layerscape: Add suspend/resume support for ls1043 and ls1021

2023-12-01 Thread Frank Li
Add suspend/resume support for ls1043 and ls1021.

Change log see each patch

Frank Li (4):
  PCI: layerscape: Add function pointer for exit_from_l2()
  PCI: layerscape: Add suspend/resume for ls1021a
  PCI: layerscape(ep): Rename pf_* as pf_lut_*
  PCI: layerscape: Add suspend/resume for ls1043a

 .../pci/controller/dwc/pci-layerscape-ep.c|  16 +-
 drivers/pci/controller/dwc/pci-layerscape.c   | 189 --
 2 files changed, 176 insertions(+), 29 deletions(-)

-- 
2.34.1



Re: [PATCH v4 4/4] PCI: layerscape: Add suspend/resume for ls1043a

2023-11-30 Thread Frank Li
On Thu, Nov 30, 2023 at 03:17:39PM -0500, Frank Li wrote:
> On Thu, Nov 30, 2023 at 10:21:00PM +0530, Manivannan Sadhasivam wrote:
> > On Wed, Nov 29, 2023 at 04:44:12PM -0500, Frank Li wrote:
> > > In the suspend path, PME_Turn_Off message is sent to the endpoint to
> > > transition the link to L2/L3_Ready state. In this SoC, there is no way to
> > > check if the controller has received the PME_To_Ack from the endpoint or
> > > not. So to be on the safer side, the driver just waits for
> > > PCIE_PME_TO_L2_TIMEOUT_US before asserting the SoC specific PMXMTTURNOFF
> > > bit to complete the PME_Turn_Off handshake. This link would then enter
> > > L2/L3 state depending on the VAUX supply.
> > > 
> > > In the resume path, the link is brought back from L2 to L0 by doing a
> > > software reset.
> > > 
> > 
> > Same comment on the patch description as on patch 2/4.
> > 
> > > Signed-off-by: Frank Li 
> > > ---
> > > 
> > > Notes:
> > > Change from v3 to v4
> > > - Call scfg_pcie_send_turnoff_msg() shared with ls1021a
> > > - update commit message
> > > 
> > > Change from v2 to v3
> > > - Remove ls_pcie_lut_readl(writel) function
> > > 
> > > Change from v1 to v2
> > > - Update subject 'a' to 'A'
> > > 
> > >  drivers/pci/controller/dwc/pci-layerscape.c | 63 -
> > >  1 file changed, 62 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
> > > b/drivers/pci/controller/dwc/pci-layerscape.c
> > > index 590e07bb27002..d39700b3afaaa 100644
> > > --- a/drivers/pci/controller/dwc/pci-layerscape.c
> > > +++ b/drivers/pci/controller/dwc/pci-layerscape.c
> > > @@ -41,6 +41,15 @@
> > >  #define SCFG_PEXSFTRSTCR 0x190
> > >  #define PEXSR(idx)   BIT(idx)
> > >  
> > > +/* LS1043A PEX PME control register */
> > > +#define SCFG_PEXPMECR0x144
> > > +#define PEXPME(idx)  BIT(31 - (idx) * 4)
> > > +
> > > +/* LS1043A PEX LUT debug register */
> > > +#define LS_PCIE_LDBG 0x7fc
> > > +#define LDBG_SR  BIT(30)
> > > +#define LDBG_WE  BIT(31)
> > > +
> > >  #define PCIE_IATU_NUM6
> > >  
> > >  struct ls_pcie_drvdata {
> > > @@ -225,6 +234,45 @@ static int ls1021a_pcie_exit_from_l2(struct 
> > > dw_pcie_rp *pp)
> > >   return scfg_pcie_exit_from_l2(pcie->scfg, SCFG_PEXSFTRSTCR, 
> > > PEXSR(pcie->index));
> > >  }
> > >  
> > > +static void ls1043a_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
> > > +{
> > > + struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > > + struct ls_pcie *pcie = to_ls_pcie(pci);
> > > +
> > > + scfg_pcie_send_turnoff_msg(pcie->scfg, SCFG_PEXPMECR, 
> > > PEXPME(pcie->index));
> > > +}
> > > +
> > > +static int ls1043a_pcie_exit_from_l2(struct dw_pcie_rp *pp)
> > > +{
> > > + struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > > + struct ls_pcie *pcie = to_ls_pcie(pci);
> > > + u32 val;
> > > +
> > > + /*
> > > +  * Only way let PEX module exit L2 is do a software reset.
> > 
> > Can you expand PEX? What is it used for?
> > 
> > Also if the reset is only for the PEX module, please use the same comment in
> > both patches 2 and 4. Patch 2 doesn't mention PEX in the comment.
> 
> After read spec again, I think PEX is pci express. So it should software
> reset controller. I don't know what exactly did in the chip. But without
> below code, PCIe can't exit L2/L3.
> 
> Any harmful if dwc controller reset? Anyway these code works well with
> intel network card.

Sorry, sent too quick. It is PCIe express wrapper

Copy from spec: 

"PEXLDBG[SR]. Once set the
PEXLDBG[SR] will enable the soft reset to the PEX wrapper."

Frank

> 
> Frank
> 
> > 
> > - Mani
> > 
> > > +  * LDBG_WE: allows the user to have write access to the PEXDBG[SR] for 
> > > both setting and
> > > +  *  clearing the soft reset on the PEX module.
> > > +  * LDBG_SR: When SR is set to 1, the PEX module enters soft reset.
> > > +  */
> > > + val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
> > > + val |= LDBG_WE;
> > > + ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
> > > +
> > > + val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_

Re: [PATCH v4 4/4] PCI: layerscape: Add suspend/resume for ls1043a

2023-11-30 Thread Frank Li
On Thu, Nov 30, 2023 at 10:21:00PM +0530, Manivannan Sadhasivam wrote:
> On Wed, Nov 29, 2023 at 04:44:12PM -0500, Frank Li wrote:
> > In the suspend path, PME_Turn_Off message is sent to the endpoint to
> > transition the link to L2/L3_Ready state. In this SoC, there is no way to
> > check if the controller has received the PME_To_Ack from the endpoint or
> > not. So to be on the safer side, the driver just waits for
> > PCIE_PME_TO_L2_TIMEOUT_US before asserting the SoC specific PMXMTTURNOFF
> > bit to complete the PME_Turn_Off handshake. This link would then enter
> > L2/L3 state depending on the VAUX supply.
> > 
> > In the resume path, the link is brought back from L2 to L0 by doing a
> > software reset.
> > 
> 
> Same comment on the patch description as on patch 2/4.
> 
> > Signed-off-by: Frank Li 
> > ---
> > 
> > Notes:
> > Change from v3 to v4
> > - Call scfg_pcie_send_turnoff_msg() shared with ls1021a
> > - update commit message
> > 
> > Change from v2 to v3
> > - Remove ls_pcie_lut_readl(writel) function
> > 
> > Change from v1 to v2
> > - Update subject 'a' to 'A'
> > 
> >  drivers/pci/controller/dwc/pci-layerscape.c | 63 -
> >  1 file changed, 62 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
> > b/drivers/pci/controller/dwc/pci-layerscape.c
> > index 590e07bb27002..d39700b3afaaa 100644
> > --- a/drivers/pci/controller/dwc/pci-layerscape.c
> > +++ b/drivers/pci/controller/dwc/pci-layerscape.c
> > @@ -41,6 +41,15 @@
> >  #define SCFG_PEXSFTRSTCR   0x190
> >  #define PEXSR(idx) BIT(idx)
> >  
> > +/* LS1043A PEX PME control register */
> > +#define SCFG_PEXPMECR  0x144
> > +#define PEXPME(idx)BIT(31 - (idx) * 4)
> > +
> > +/* LS1043A PEX LUT debug register */
> > +#define LS_PCIE_LDBG   0x7fc
> > +#define LDBG_SRBIT(30)
> > +#define LDBG_WEBIT(31)
> > +
> >  #define PCIE_IATU_NUM  6
> >  
> >  struct ls_pcie_drvdata {
> > @@ -225,6 +234,45 @@ static int ls1021a_pcie_exit_from_l2(struct dw_pcie_rp 
> > *pp)
> > return scfg_pcie_exit_from_l2(pcie->scfg, SCFG_PEXSFTRSTCR, 
> > PEXSR(pcie->index));
> >  }
> >  
> > +static void ls1043a_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
> > +{
> > +   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > +   struct ls_pcie *pcie = to_ls_pcie(pci);
> > +
> > +   scfg_pcie_send_turnoff_msg(pcie->scfg, SCFG_PEXPMECR, 
> > PEXPME(pcie->index));
> > +}
> > +
> > +static int ls1043a_pcie_exit_from_l2(struct dw_pcie_rp *pp)
> > +{
> > +   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > +   struct ls_pcie *pcie = to_ls_pcie(pci);
> > +   u32 val;
> > +
> > +   /*
> > +* Only way let PEX module exit L2 is do a software reset.
> 
> Can you expand PEX? What is it used for?
> 
> Also if the reset is only for the PEX module, please use the same comment in
> both patches 2 and 4. Patch 2 doesn't mention PEX in the comment.

After read spec again, I think PEX is pci express. So it should software
reset controller. I don't know what exactly did in the chip. But without
below code, PCIe can't exit L2/L3.

Any harmful if dwc controller reset? Anyway these code works well with
intel network card.

Frank

> 
> - Mani
> 
> > +* LDBG_WE: allows the user to have write access to the PEXDBG[SR] for 
> > both setting and
> > +*  clearing the soft reset on the PEX module.
> > +* LDBG_SR: When SR is set to 1, the PEX module enters soft reset.
> > +*/
> > +   val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
> > +   val |= LDBG_WE;
> > +   ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
> > +
> > +   val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
> > +   val |= LDBG_SR;
> > +   ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
> > +
> > +   val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
> > +   val &= ~LDBG_SR;
> > +   ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
> > +
> > +   val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
> > +   val &= ~LDBG_WE;
> > +   ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
> > +
> > +   return 0;
> > +}
> > +
> >  static const struct dw_pcie_host_ops ls_pcie_host_ops = {
> > .host_init = ls_pcie_host_init,
> > .pme_turn_off = ls_pcie_send_turnoff_msg,
> > @@ -242,6 +290,19 @@ static co

[PATCH v4 4/4] PCI: layerscape: Add suspend/resume for ls1043a

2023-11-29 Thread Frank Li
In the suspend path, PME_Turn_Off message is sent to the endpoint to
transition the link to L2/L3_Ready state. In this SoC, there is no way to
check if the controller has received the PME_To_Ack from the endpoint or
not. So to be on the safer side, the driver just waits for
PCIE_PME_TO_L2_TIMEOUT_US before asserting the SoC specific PMXMTTURNOFF
bit to complete the PME_Turn_Off handshake. This link would then enter
L2/L3 state depending on the VAUX supply.

In the resume path, the link is brought back from L2 to L0 by doing a
software reset.

Signed-off-by: Frank Li 
---

Notes:
Change from v3 to v4
- Call scfg_pcie_send_turnoff_msg() shared with ls1021a
- update commit message

Change from v2 to v3
- Remove ls_pcie_lut_readl(writel) function

Change from v1 to v2
- Update subject 'a' to 'A'

 drivers/pci/controller/dwc/pci-layerscape.c | 63 -
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index 590e07bb27002..d39700b3afaaa 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -41,6 +41,15 @@
 #define SCFG_PEXSFTRSTCR   0x190
 #define PEXSR(idx) BIT(idx)
 
+/* LS1043A PEX PME control register */
+#define SCFG_PEXPMECR  0x144
+#define PEXPME(idx)BIT(31 - (idx) * 4)
+
+/* LS1043A PEX LUT debug register */
+#define LS_PCIE_LDBG   0x7fc
+#define LDBG_SRBIT(30)
+#define LDBG_WEBIT(31)
+
 #define PCIE_IATU_NUM  6
 
 struct ls_pcie_drvdata {
@@ -225,6 +234,45 @@ static int ls1021a_pcie_exit_from_l2(struct dw_pcie_rp *pp)
return scfg_pcie_exit_from_l2(pcie->scfg, SCFG_PEXSFTRSTCR, 
PEXSR(pcie->index));
 }
 
+static void ls1043a_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+   struct ls_pcie *pcie = to_ls_pcie(pci);
+
+   scfg_pcie_send_turnoff_msg(pcie->scfg, SCFG_PEXPMECR, 
PEXPME(pcie->index));
+}
+
+static int ls1043a_pcie_exit_from_l2(struct dw_pcie_rp *pp)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+   struct ls_pcie *pcie = to_ls_pcie(pci);
+   u32 val;
+
+   /*
+* Only way let PEX module exit L2 is do a software reset.
+* LDBG_WE: allows the user to have write access to the PEXDBG[SR] for 
both setting and
+*  clearing the soft reset on the PEX module.
+* LDBG_SR: When SR is set to 1, the PEX module enters soft reset.
+*/
+   val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
+   val |= LDBG_WE;
+   ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
+
+   val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
+   val |= LDBG_SR;
+   ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
+
+   val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
+   val &= ~LDBG_SR;
+   ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
+
+   val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
+   val &= ~LDBG_WE;
+   ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
+
+   return 0;
+}
+
 static const struct dw_pcie_host_ops ls_pcie_host_ops = {
.host_init = ls_pcie_host_init,
.pme_turn_off = ls_pcie_send_turnoff_msg,
@@ -242,6 +290,19 @@ static const struct ls_pcie_drvdata ls1021a_drvdata = {
.exit_from_l2 = ls1021a_pcie_exit_from_l2,
 };
 
+static const struct dw_pcie_host_ops ls1043a_pcie_host_ops = {
+   .host_init = ls_pcie_host_init,
+   .pme_turn_off = ls1043a_pcie_send_turnoff_msg,
+};
+
+static const struct ls_pcie_drvdata ls1043a_drvdata = {
+   .pf_lut_off = 0x1,
+   .pm_support = true,
+   .scfg_support = true,
+   .ops = _pcie_host_ops,
+   .exit_from_l2 = ls1043a_pcie_exit_from_l2,
+};
+
 static const struct ls_pcie_drvdata layerscape_drvdata = {
.pf_lut_off = 0xc,
.pm_support = true,
@@ -252,7 +313,7 @@ static const struct of_device_id ls_pcie_of_match[] = {
{ .compatible = "fsl,ls1012a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls1021a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls1028a-pcie", .data = _drvdata },
-   { .compatible = "fsl,ls1043a-pcie", .data = _drvdata },
+   { .compatible = "fsl,ls1043a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls1046a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls2080a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls2085a-pcie", .data = _drvdata },
-- 
2.34.1



[PATCH v4 3/4] PCI: layerscape: Rename pf_* as pf_lut_*

2023-11-29 Thread Frank Li
'pf' and 'lut' is just difference name in difference chips, but basic it is
a MMIO base address plus an offset.

Rename it to avoid duplicate pf_* and lut_* in driver.

Signed-off-by: Frank Li 
---

Notes:
pf_lut is better than pf_* or lut* because some chip use 'pf', some chip
use 'lut'.

change from v1 to v4
- new patch at v3

 drivers/pci/controller/dwc/pci-layerscape.c | 34 ++---
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index 42bca2c3b5c3e..590e07bb27002 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -44,7 +44,7 @@
 #define PCIE_IATU_NUM  6
 
 struct ls_pcie_drvdata {
-   const u32 pf_off;
+   const u32 pf_lut_off;
const struct dw_pcie_host_ops *ops;
int (*exit_from_l2)(struct dw_pcie_rp *pp);
bool scfg_support;
@@ -54,13 +54,13 @@ struct ls_pcie_drvdata {
 struct ls_pcie {
struct dw_pcie *pci;
const struct ls_pcie_drvdata *drvdata;
-   void __iomem *pf_base;
+   void __iomem *pf_lut_base;
struct regmap *scfg;
int index;
bool big_endian;
 };
 
-#define ls_pcie_pf_readl_addr(addr)ls_pcie_pf_readl(pcie, addr)
+#define ls_pcie_pf_lut_readl_addr(addr)ls_pcie_pf_lut_readl(pcie, addr)
 #define to_ls_pcie(x)  dev_get_drvdata((x)->dev)
 
 static bool ls_pcie_is_bridge(struct ls_pcie *pcie)
@@ -101,20 +101,20 @@ static void ls_pcie_fix_error_response(struct ls_pcie 
*pcie)
iowrite32(PCIE_ABSERR_SETTING, pci->dbi_base + PCIE_ABSERR);
 }
 
-static u32 ls_pcie_pf_readl(struct ls_pcie *pcie, u32 off)
+static u32 ls_pcie_pf_lut_readl(struct ls_pcie *pcie, u32 off)
 {
if (pcie->big_endian)
-   return ioread32be(pcie->pf_base + off);
+   return ioread32be(pcie->pf_lut_base + off);
 
-   return ioread32(pcie->pf_base + off);
+   return ioread32(pcie->pf_lut_base + off);
 }
 
-static void ls_pcie_pf_writel(struct ls_pcie *pcie, u32 off, u32 val)
+static void ls_pcie_pf_lut_writel(struct ls_pcie *pcie, u32 off, u32 val)
 {
if (pcie->big_endian)
-   iowrite32be(val, pcie->pf_base + off);
+   iowrite32be(val, pcie->pf_lut_base + off);
else
-   iowrite32(val, pcie->pf_base + off);
+   iowrite32(val, pcie->pf_lut_base + off);
 }
 
 static void ls_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
@@ -124,11 +124,11 @@ static void ls_pcie_send_turnoff_msg(struct dw_pcie_rp 
*pp)
u32 val;
int ret;
 
-   val = ls_pcie_pf_readl(pcie, LS_PCIE_PF_MCR);
+   val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_PF_MCR);
val |= PF_MCR_PTOMR;
-   ls_pcie_pf_writel(pcie, LS_PCIE_PF_MCR, val);
+   ls_pcie_pf_lut_writel(pcie, LS_PCIE_PF_MCR, val);
 
-   ret = readx_poll_timeout(ls_pcie_pf_readl_addr, LS_PCIE_PF_MCR,
+   ret = readx_poll_timeout(ls_pcie_pf_lut_readl_addr, LS_PCIE_PF_MCR,
 val, !(val & PF_MCR_PTOMR),
 PCIE_PME_TO_L2_TIMEOUT_US/10,
 PCIE_PME_TO_L2_TIMEOUT_US);
@@ -147,15 +147,15 @@ static int ls_pcie_exit_from_l2(struct dw_pcie_rp *pp)
 * Set PF_MCR_EXL2S bit in LS_PCIE_PF_MCR register for the link
 * to exit L2 state.
 */
-   val = ls_pcie_pf_readl(pcie, LS_PCIE_PF_MCR);
+   val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_PF_MCR);
val |= PF_MCR_EXL2S;
-   ls_pcie_pf_writel(pcie, LS_PCIE_PF_MCR, val);
+   ls_pcie_pf_lut_writel(pcie, LS_PCIE_PF_MCR, val);
 
/*
 * L2 exit timeout of 10ms is not defined in the specifications,
 * it was chosen based on empirical observations.
 */
-   ret = readx_poll_timeout(ls_pcie_pf_readl_addr, LS_PCIE_PF_MCR,
+   ret = readx_poll_timeout(ls_pcie_pf_lut_readl_addr, LS_PCIE_PF_MCR,
 val, !(val & PF_MCR_EXL2S),
 1000,
 1);
@@ -243,7 +243,7 @@ static const struct ls_pcie_drvdata ls1021a_drvdata = {
 };
 
 static const struct ls_pcie_drvdata layerscape_drvdata = {
-   .pf_off = 0xc,
+   .pf_lut_off = 0xc,
.pm_support = true,
.exit_from_l2 = ls_pcie_exit_from_l2,
 };
@@ -293,7 +293,7 @@ static int ls_pcie_probe(struct platform_device *pdev)
 
pcie->big_endian = of_property_read_bool(dev->of_node, "big-endian");
 
-   pcie->pf_base = pci->dbi_base + pcie->drvdata->pf_off;
+   pcie->pf_lut_base = pci->dbi_base + pcie->drvdata->pf_lut_off;
 
if (pcie->drvdata->scfg_support) {
pcie->scfg = syscon_regmap_lookup_by_phandle(dev->of_node, 
"fsl,pcie-scfg");
-- 
2.34.1



[PATCH v4 2/4] PCI: layerscape: Add suspend/resume for ls1021a

2023-11-29 Thread Frank Li
ls1021a add suspend/resume support.

In the suspend path, PME_Turn_Off message is sent to the endpoint to
transition the link to L2/L3_Ready state. In this SoC, there is no way to
check if the controller has received the PME_To_Ack from the endpoint or
not. So to be on the safer side, the driver just waits for
PCIE_PME_TO_L2_TIMEOUT_US before asserting the SoC specific PMXMTTURNOFF
bit to complete the PME_Turn_Off handshake. This link would then enter
L2/L3 state depending on the VAUX supply.

In the resume path, the link is brought back from L2 to L0 by doing a
software reset.

Signed-off-by: Frank Li 
---

Notes:
Change from v3 to v4
- update commit message.
- it is reset a glue logic part for PCI controller.
- use regmap_write_bits() to reduce code change.

Change from v2 to v3
- update according to mani's feedback
change from v1 to v2
- change subject 'a' to 'A'

 drivers/pci/controller/dwc/pci-layerscape.c | 83 -
 1 file changed, 82 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index aea89926bcc4f..42bca2c3b5c3e 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -35,11 +35,19 @@
 #define PF_MCR_PTOMR   BIT(0)
 #define PF_MCR_EXL2S   BIT(1)
 
+/* LS1021A PEXn PM Write Control Register */
+#define SCFG_PEXPMWRCR(idx)(0x5c + (idx) * 0x64)
+#define PMXMTTURNOFF   BIT(31)
+#define SCFG_PEXSFTRSTCR   0x190
+#define PEXSR(idx) BIT(idx)
+
 #define PCIE_IATU_NUM  6
 
 struct ls_pcie_drvdata {
const u32 pf_off;
+   const struct dw_pcie_host_ops *ops;
int (*exit_from_l2)(struct dw_pcie_rp *pp);
+   bool scfg_support;
bool pm_support;
 };
 
@@ -47,6 +55,8 @@ struct ls_pcie {
struct dw_pcie *pci;
const struct ls_pcie_drvdata *drvdata;
void __iomem *pf_base;
+   struct regmap *scfg;
+   int index;
bool big_endian;
 };
 
@@ -171,13 +181,65 @@ static int ls_pcie_host_init(struct dw_pcie_rp *pp)
return 0;
 }
 
+static void scfg_pcie_send_turnoff_msg(struct regmap *scfg, u32 reg, u32 mask)
+{
+   /* Send PME_Turn_Off message */
+   regmap_write_bits(scfg, reg, mask, mask);
+
+   /*
+* There is no specific register to check for PME_To_Ack from endpoint.
+* So on the safe side, wait for PCIE_PME_TO_L2_TIMEOUT_US.
+*/
+   mdelay(PCIE_PME_TO_L2_TIMEOUT_US/1000);
+
+   /*
+* Layerscape hardware reference manual recommends clearing the 
PMXMTTURNOFF bit
+* to complete the PME_Turn_Off handshake.
+*/
+   regmap_write_bits(scfg, reg, mask, 0);
+}
+
+static void ls1021a_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+   struct ls_pcie *pcie = to_ls_pcie(pci);
+
+   scfg_pcie_send_turnoff_msg(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), 
PMXMTTURNOFF);
+}
+
+static int scfg_pcie_exit_from_l2(struct regmap *scfg, u32 reg, u32 mask)
+{
+   /* Only way exit from l2 is that do software reset */
+   regmap_write_bits(scfg, reg, mask, mask);
+
+   regmap_write_bits(scfg, reg, mask, 0);
+
+   return 0;
+}
+
+static int ls1021a_pcie_exit_from_l2(struct dw_pcie_rp *pp)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+   struct ls_pcie *pcie = to_ls_pcie(pci);
+
+   return scfg_pcie_exit_from_l2(pcie->scfg, SCFG_PEXSFTRSTCR, 
PEXSR(pcie->index));
+}
+
 static const struct dw_pcie_host_ops ls_pcie_host_ops = {
.host_init = ls_pcie_host_init,
.pme_turn_off = ls_pcie_send_turnoff_msg,
 };
 
+static const struct dw_pcie_host_ops ls1021a_pcie_host_ops = {
+   .host_init = ls_pcie_host_init,
+   .pme_turn_off = ls1021a_pcie_send_turnoff_msg,
+};
+
 static const struct ls_pcie_drvdata ls1021a_drvdata = {
-   .pm_support = false,
+   .pm_support = true,
+   .scfg_support = true,
+   .ops = _pcie_host_ops,
+   .exit_from_l2 = ls1021a_pcie_exit_from_l2,
 };
 
 static const struct ls_pcie_drvdata layerscape_drvdata = {
@@ -205,6 +267,8 @@ static int ls_pcie_probe(struct platform_device *pdev)
struct dw_pcie *pci;
struct ls_pcie *pcie;
struct resource *dbi_base;
+   u32 index[2];
+   int ret;
 
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
if (!pcie)
@@ -220,6 +284,7 @@ static int ls_pcie_probe(struct platform_device *pdev)
pci->pp.ops = _pcie_host_ops;
 
pcie->pci = pci;
+   pci->pp.ops = pcie->drvdata->ops ? pcie->drvdata->ops : 
_pcie_host_ops;
 
dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
pci->dbi_base = devm_pci_remap_cfg_resource(dev, dbi_base);
@@ -230,6 +295,22 @@ static int ls_pcie_probe(struct platform_device *pdev)
 
pcie-&g

[PATCH v4 1/4] PCI: layerscape: Add function pointer for exit_from_l2()

2023-11-29 Thread Frank Li
Since difference SoCs require different sequence for exiting L2, let's add
a separate "exit_from_l2()" callback. This callback can be used to execute
SoC specific sequence.

Change ls_pcie_exit_from_l2() return value from void to int. Return error
if exit_from_l2() failure at exit resume flow.

Reviewed-by: Manivannan Sadhasivam 
Signed-off-by: Frank Li 
---

Notes:
Change from v3 to v4
- update commit message
  Add mani's review by tag
Change from v2 to v3
- fixed according to mani's feedback
  1. update commit message
  2. move dw_pcie_host_ops to next patch
  3. check return value from exit_from_l2()
Change from v1 to v2
- change subject 'a' to 'A'

Change from v1 to v2
- change subject 'a' to 'A'

 drivers/pci/controller/dwc/pci-layerscape.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index 37956e09c65bd..aea89926bcc4f 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -39,6 +39,7 @@
 
 struct ls_pcie_drvdata {
const u32 pf_off;
+   int (*exit_from_l2)(struct dw_pcie_rp *pp);
bool pm_support;
 };
 
@@ -125,7 +126,7 @@ static void ls_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
dev_err(pcie->pci->dev, "PME_Turn_off timeout\n");
 }
 
-static void ls_pcie_exit_from_l2(struct dw_pcie_rp *pp)
+static int ls_pcie_exit_from_l2(struct dw_pcie_rp *pp)
 {
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct ls_pcie *pcie = to_ls_pcie(pci);
@@ -150,6 +151,8 @@ static void ls_pcie_exit_from_l2(struct dw_pcie_rp *pp)
 1);
if (ret)
dev_err(pcie->pci->dev, "L2 exit timeout\n");
+
+   return ret;
 }
 
 static int ls_pcie_host_init(struct dw_pcie_rp *pp)
@@ -180,6 +183,7 @@ static const struct ls_pcie_drvdata ls1021a_drvdata = {
 static const struct ls_pcie_drvdata layerscape_drvdata = {
.pf_off = 0xc,
.pm_support = true,
+   .exit_from_l2 = ls_pcie_exit_from_l2,
 };
 
 static const struct of_device_id ls_pcie_of_match[] = {
@@ -247,11 +251,14 @@ static int ls_pcie_suspend_noirq(struct device *dev)
 static int ls_pcie_resume_noirq(struct device *dev)
 {
struct ls_pcie *pcie = dev_get_drvdata(dev);
+   int ret;
 
if (!pcie->drvdata->pm_support)
return 0;
 
-   ls_pcie_exit_from_l2(>pci->pp);
+   ret = pcie->drvdata->exit_from_l2(>pci->pp);
+   if (ret)
+   return ret;
 
return dw_pcie_resume_noirq(pcie->pci);
 }
-- 
2.34.1



[PATCH v4 0/4] dwc general suspend/resume functionality

2023-11-29 Thread Frank Li
Add a API for dwc suspend/resume.
In layerscape platform call this api.

Frank Li (4):
  PCI: layerscape: Add function pointer for exit_from_l2()
  PCI: layerscape: Add suspend/resume for ls1021a
  PCI: layerscape: Rename pf_* as pf_lut_*
  PCI: layerscape: Add suspend/resume for ls1043a

 drivers/pci/controller/dwc/pci-layerscape.c | 191 +---
 1 file changed, 170 insertions(+), 21 deletions(-)

-- 
2.34.1



Re: [PATCH v3 4/4] PCI: layerscape: Add suspend/resume for ls1043a

2023-11-02 Thread Frank Li
On Thu, Nov 02, 2023 at 11:09:00PM +0530, Manivannan Sadhasivam wrote:
> On Tue, Oct 17, 2023 at 03:31:45PM -0400, Frank Li wrote:
> > ls1043a add suspend/resume support.
> > Implement ls1043a_pcie_send_turnoff_msg() to send PME_Turn_Off message.
> > Implement ls1043a_pcie_exit_from_l2() to exit from L2 state.
> > 
> 
> Please use the suggestion I gave in patch 2/4.
> 
> > Signed-off-by: Frank Li 
> > ---
> > 
> > Notes:
> > Change from v2 to v3
> > - Remove ls_pcie_lut_readl(writel) function
> > 
> > Change from v1 to v2
> > - Update subject 'a' to 'A'
> > 
> >  drivers/pci/controller/dwc/pci-layerscape.c | 86 -
> >  1 file changed, 85 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
> > b/drivers/pci/controller/dwc/pci-layerscape.c
> > index 4b663b20d8612..9656224960b0c 100644
> > --- a/drivers/pci/controller/dwc/pci-layerscape.c
> > +++ b/drivers/pci/controller/dwc/pci-layerscape.c
> > @@ -41,6 +41,15 @@
> >  #define SCFG_PEXSFTRSTCR   0x190
> >  #define PEXSR(idx) BIT(idx)
> >  
> > +/* LS1043A PEX PME control register */
> > +#define SCFG_PEXPMECR  0x144
> > +#define PEXPME(idx)BIT(31 - (idx) * 4)
> > +
> > +/* LS1043A PEX LUT debug register */
> > +#define LS_PCIE_LDBG   0x7fc
> > +#define LDBG_SRBIT(30)
> > +#define LDBG_WEBIT(31)
> > +
> >  #define PCIE_IATU_NUM  6
> >  
> >  #define LS_PCIE_DRV_SCFG   BIT(0)
> > @@ -227,6 +236,68 @@ static int ls1021a_pcie_exit_from_l2(struct dw_pcie_rp 
> > *pp)
> > return 0;
> >  }
> >  
> > +static void ls1043a_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
> > +{
> > +   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > +   struct ls_pcie *pcie = to_ls_pcie(pci);
> > +   u32 val;
> > +
> > +   if (!pcie->scfg) {
> > +   dev_dbg(pcie->pci->dev, "SYSCFG is NULL\n");
> > +   return;
> > +   }
> 
> Why scfg is optional for this SoC and not for the other one added in patch 
> 2/4?

No, it is not optional for this SoC. This check can be removed as your
previous comments about 2/4.

> 
> > +
> > +   /* Send Turn_off message */
> > +   regmap_read(pcie->scfg, SCFG_PEXPMECR, );
> > +   val |= PEXPME(pcie->index);
> > +   regmap_write(pcie->scfg, SCFG_PEXPMECR, val);
> > +
> 
> In my previous review, I asked you to use a common function and just pass the
> offsets, as the sequence is same for both the SoCs. But you ignored it :/
> 

Sorry, I will fixed it at next version. 

> > +   /*
> > +* There is no specific register to check for PME_To_Ack from endpoint.
> > +* So on the safe side, wait for PCIE_PME_TO_L2_TIMEOUT_US.
> > +*/
> > +   mdelay(PCIE_PME_TO_L2_TIMEOUT_US/1000);
> > +
> > +   /*
> > +* Layerscape hardware reference manual recommends clearing the 
> > PMXMTTURNOFF bit
> > +* to complete the PME_Turn_Off handshake.
> > +*/
> > +   regmap_read(pcie->scfg, SCFG_PEXPMECR, );
> > +   val &= ~PEXPME(pcie->index);
> > +   regmap_write(pcie->scfg, SCFG_PEXPMECR, val);
> > +}
> > +
> > +static int ls1043a_pcie_exit_from_l2(struct dw_pcie_rp *pp)
> > +{
> > +   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > +   struct ls_pcie *pcie = to_ls_pcie(pci);
> > +   u32 val;
> > +
> > +   /*
> > +* Only way let PEX module exit L2 is do a software reset.
> 
> Same comment applies as patch 2/4.
> 
> - Mani
> 
> -- 
> மணிவண்ணன் சதாசிவம்


Re: [PATCH v3 3/4] PCI: layerscape: Rename pf_* as pf_lut_*

2023-11-02 Thread Frank Li
On Thu, Nov 02, 2023 at 11:03:14PM +0530, Manivannan Sadhasivam wrote:
> On Tue, Oct 17, 2023 at 03:31:44PM -0400, Frank Li wrote:
> > 'pf' and 'lut' is just difference name in difference chips, but basic it is
> > a MMIO base address plus an offset.
> > 
> > Rename it to avoid duplicate pf_* and lut_* in driver.
> > 
> 
> "pci-layerscape-ep.c" uses "ls_lut_" prefix and now you are using "pf_lut_". 
> May
> I know the difference between these two? Can we just use a common name?

Some chip use name lut, some chip use name pf. I think ls_pcie_pf_lut_*()
is better name then 'ls_lut_' in pci-layerscape-ep.c to align with spec. 

If need, I can rename "ls_lut_" in "pci-layerscape-ep.c" later.

Frank

> 
> - Mani
> 
> > Signed-off-by: Frank Li 
> > ---
> > 
> > Notes:
> > change from v1 to v3
> > - new patch at v3
> > 
> >  drivers/pci/controller/dwc/pci-layerscape.c | 34 ++---
> >  1 file changed, 17 insertions(+), 17 deletions(-)
> > 
> > diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
> > b/drivers/pci/controller/dwc/pci-layerscape.c
> > index 6f47cfe146c44..4b663b20d8612 100644
> > --- a/drivers/pci/controller/dwc/pci-layerscape.c
> > +++ b/drivers/pci/controller/dwc/pci-layerscape.c
> > @@ -46,7 +46,7 @@
> >  #define LS_PCIE_DRV_SCFG   BIT(0)
> >  
> >  struct ls_pcie_drvdata {
> > -   const u32 pf_off;
> > +   const u32 pf_lut_off;
> > const struct dw_pcie_host_ops *ops;
> > int (*exit_from_l2)(struct dw_pcie_rp *pp);
> > int flags;
> > @@ -56,13 +56,13 @@ struct ls_pcie_drvdata {
> >  struct ls_pcie {
> > struct dw_pcie *pci;
> > const struct ls_pcie_drvdata *drvdata;
> > -   void __iomem *pf_base;
> > +   void __iomem *pf_lut_base;
> > struct regmap *scfg;
> > int index;
> > bool big_endian;
> >  };
> >  
> > -#define ls_pcie_pf_readl_addr(addr)ls_pcie_pf_readl(pcie, addr)
> > +#define ls_pcie_pf_lut_readl_addr(addr)ls_pcie_pf_lut_readl(pcie, addr)
> >  #define to_ls_pcie(x)  dev_get_drvdata((x)->dev)
> >  
> >  static bool ls_pcie_is_bridge(struct ls_pcie *pcie)
> > @@ -103,20 +103,20 @@ static void ls_pcie_fix_error_response(struct ls_pcie 
> > *pcie)
> > iowrite32(PCIE_ABSERR_SETTING, pci->dbi_base + PCIE_ABSERR);
> >  }
> >  
> > -static u32 ls_pcie_pf_readl(struct ls_pcie *pcie, u32 off)
> > +static u32 ls_pcie_pf_lut_readl(struct ls_pcie *pcie, u32 off)
> >  {
> > if (pcie->big_endian)
> > -   return ioread32be(pcie->pf_base + off);
> > +   return ioread32be(pcie->pf_lut_base + off);
> >  
> > -   return ioread32(pcie->pf_base + off);
> > +   return ioread32(pcie->pf_lut_base + off);
> >  }
> >  
> > -static void ls_pcie_pf_writel(struct ls_pcie *pcie, u32 off, u32 val)
> > +static void ls_pcie_pf_lut_writel(struct ls_pcie *pcie, u32 off, u32 val)
> >  {
> > if (pcie->big_endian)
> > -   iowrite32be(val, pcie->pf_base + off);
> > +   iowrite32be(val, pcie->pf_lut_base + off);
> > else
> > -   iowrite32(val, pcie->pf_base + off);
> > +   iowrite32(val, pcie->pf_lut_base + off);
> >  }
> >  
> >  static void ls_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
> > @@ -126,11 +126,11 @@ static void ls_pcie_send_turnoff_msg(struct 
> > dw_pcie_rp *pp)
> > u32 val;
> > int ret;
> >  
> > -   val = ls_pcie_pf_readl(pcie, LS_PCIE_PF_MCR);
> > +   val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_PF_MCR);
> > val |= PF_MCR_PTOMR;
> > -   ls_pcie_pf_writel(pcie, LS_PCIE_PF_MCR, val);
> > +   ls_pcie_pf_lut_writel(pcie, LS_PCIE_PF_MCR, val);
> >  
> > -   ret = readx_poll_timeout(ls_pcie_pf_readl_addr, LS_PCIE_PF_MCR,
> > +   ret = readx_poll_timeout(ls_pcie_pf_lut_readl_addr, LS_PCIE_PF_MCR,
> >  val, !(val & PF_MCR_PTOMR),
> >  PCIE_PME_TO_L2_TIMEOUT_US/10,
> >  PCIE_PME_TO_L2_TIMEOUT_US);
> > @@ -149,15 +149,15 @@ static int ls_pcie_exit_from_l2(struct dw_pcie_rp *pp)
> >  * Set PF_MCR_EXL2S bit in LS_PCIE_PF_MCR register for the link
> >  * to exit L2 state.
> >  */
> > -   val = ls_pcie_pf_readl(pcie, LS_PCIE_PF_MCR);
> > +   val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_PF_MCR);
> > val |= PF_MCR_EXL2S;
> > -   ls_pcie_pf_writel(pcie, LS_PCIE_PF_MCR, val);
> > +   ls_pcie_pf_

Re: [PATCH v3 2/4] PCI: layerscape: Add suspend/resume for ls1021a

2023-11-02 Thread Frank Li
On Thu, Nov 02, 2023 at 10:58:09PM +0530, Manivannan Sadhasivam wrote:
> On Tue, Oct 17, 2023 at 03:31:43PM -0400, Frank Li wrote:
> > ls1021a add suspend/resume support.
> > 
> > Implement callback ls1021a_pcie_send_turnoff_msg(), which write scfg's
> > SCFG_PEXPMWRCR to issue PME_Turn_off message.
> > 
> > Implement ls1021a_pcie_exit_from_l2() to let controller exit L2 state.
> > 
> 
> I'd like to reword it to better reflect what the patch does:
> 
> "In the suspend path, PME_Turn_Off message is sent to the endpoint to 
> transition
> the link to L2/L3_Ready state. In this SoC, there is no way to check if the
> controller has received the PME_To_Ack from the endpoint or not. So to be on 
> the
> safer side, the driver just waits for PCIE_PME_TO_L2_TIMEOUT_US before 
> asserting
> the SoC specific PMXMTTURNOFF bit to complete the PME_Turn_Off handshake. This
> link would then enter L2/L3 state depending on the VAUX supply.
> 
> In the resume path, the link is brought back from L2 to L0 by doing a software
> reset."
> 
> Although I do have questions on the resume behavior below.
> 
> > Signed-off-by: Frank Li 
> > ---
> > 
> > Notes:
> > Change from v2 to v3
> > - update according to mani's feedback
> > change from v1 to v2
> > - change subject 'a' to 'A'
> > 
> >  drivers/pci/controller/dwc/pci-layerscape.c | 86 -
> >  1 file changed, 85 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
> > b/drivers/pci/controller/dwc/pci-layerscape.c
> > index aea89926bcc4f..6f47cfe146c44 100644
> > --- a/drivers/pci/controller/dwc/pci-layerscape.c
> > +++ b/drivers/pci/controller/dwc/pci-layerscape.c
> > @@ -35,11 +35,21 @@
> >  #define PF_MCR_PTOMR   BIT(0)
> >  #define PF_MCR_EXL2S   BIT(1)
> >  
> > +/* LS1021A PEXn PM Write Control Register */
> > +#define SCFG_PEXPMWRCR(idx)(0x5c + (idx) * 0x64)
> > +#define PMXMTTURNOFF   BIT(31)
> > +#define SCFG_PEXSFTRSTCR   0x190
> > +#define PEXSR(idx) BIT(idx)
> > +
> >  #define PCIE_IATU_NUM  6
> >  
> > +#define LS_PCIE_DRV_SCFG   BIT(0)
> > +
> >  struct ls_pcie_drvdata {
> > const u32 pf_off;
> > +   const struct dw_pcie_host_ops *ops;
> > int (*exit_from_l2)(struct dw_pcie_rp *pp);
> > +   int flags;
> 
> Why not "bool scfg_support"?

It will be easy to add new flag if need in future.

> 
> > bool pm_support;
> >  };
> >  
> > @@ -47,6 +57,8 @@ struct ls_pcie {
> > struct dw_pcie *pci;
> > const struct ls_pcie_drvdata *drvdata;
> > void __iomem *pf_base;
> > +   struct regmap *scfg;
> > +   int index;
> > bool big_endian;
> >  };
> >  
> > @@ -171,13 +183,65 @@ static int ls_pcie_host_init(struct dw_pcie_rp *pp)
> > return 0;
> >  }
> >  
> > +static void ls1021a_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
> > +{
> > +   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > +   struct ls_pcie *pcie = to_ls_pcie(pci);
> > +   u32 val;
> > +
> > +   /* Send PME_Turn_Off message */
> > +   regmap_read(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), );
> > +   val |= PMXMTTURNOFF;
> > +   regmap_write(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), val);
> > +
> > +   /*
> > +* There is no specific register to check for PME_To_Ack from endpoint.
> > +* So on the safe side, wait for PCIE_PME_TO_L2_TIMEOUT_US.
> > +*/
> > +   mdelay(PCIE_PME_TO_L2_TIMEOUT_US/1000);
> > +
> > +   /*
> > +* Layerscape hardware reference manual recommends clearing the 
> > PMXMTTURNOFF bit
> > +* to complete the PME_Turn_Off handshake.
> > +*/
> > +   regmap_read(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), );
> > +   val &= ~PMXMTTURNOFF;
> > +   regmap_write(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), val);
> > +}
> > +
> > +static int ls1021a_pcie_exit_from_l2(struct dw_pcie_rp *pp)
> > +{
> > +   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > +   struct ls_pcie *pcie = to_ls_pcie(pci);
> > +   u32 val;
> > +
> > +   /* Only way exit from l2 is that do software reset */
> 
> So, what does exactly "software reset" mean? Are you resetting the endpoint or
> some specific registers/blocks in the controlleri?

No, it is PCIe controller reset. Not touch endpoint.

> 
> Also, what if the link goes to L3 in the case of no VAUX?


Re: [PATCH v3 1/4] PCI: layerscape: Add function pointer for exit_from_l2()

2023-11-02 Thread Frank Li
On Thu, Nov 02, 2023 at 10:28:08PM +0530, Manivannan Sadhasivam wrote:
> On Tue, Oct 17, 2023 at 03:31:42PM -0400, Frank Li wrote:
> > Since difference SoCs require different sequence for exiting L2, let's add
> > a separate "exit_from_l2()" callback. This callback can be used to execute
> > SoC specific sequence.
> > 
> 
> I missed the fact that this patch honors the return value of the callback 
> (which
> was ignored previously). So this should be added to the description as well.

How about add below?

"Change ls_pcie_exit_from_l2() return value from void to int. Return error
when exit_from_l2() failure to exit suspend flow."

Frank


> 
> > Signed-off-by: Frank Li 
> 
> With that,
> 
> Reviewed-by: Manivannan Sadhasivam 
> 
> - Mani
> 
> > ---
> > 
> > Notes:
> > Change from v2 to v3
> > - fixed according to mani's feedback
> >   1. update commit message
> >   2. move dw_pcie_host_ops to next patch
> >   3. check return value from exit_from_l2()
> > Change from v1 to v2
> > - change subject 'a' to 'A'
> > 
> > Change from v1 to v2
> > - change subject 'a' to 'A'
> > 
> >  drivers/pci/controller/dwc/pci-layerscape.c | 11 +--
> >  1 file changed, 9 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
> > b/drivers/pci/controller/dwc/pci-layerscape.c
> > index 37956e09c65bd..aea89926bcc4f 100644
> > --- a/drivers/pci/controller/dwc/pci-layerscape.c
> > +++ b/drivers/pci/controller/dwc/pci-layerscape.c
> > @@ -39,6 +39,7 @@
> >  
> >  struct ls_pcie_drvdata {
> > const u32 pf_off;
> > +   int (*exit_from_l2)(struct dw_pcie_rp *pp);
> > bool pm_support;
> >  };
> >  
> > @@ -125,7 +126,7 @@ static void ls_pcie_send_turnoff_msg(struct dw_pcie_rp 
> > *pp)
> > dev_err(pcie->pci->dev, "PME_Turn_off timeout\n");
> >  }
> >  
> > -static void ls_pcie_exit_from_l2(struct dw_pcie_rp *pp)
> > +static int ls_pcie_exit_from_l2(struct dw_pcie_rp *pp)
> >  {
> > struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > struct ls_pcie *pcie = to_ls_pcie(pci);
> > @@ -150,6 +151,8 @@ static void ls_pcie_exit_from_l2(struct dw_pcie_rp *pp)
> >  1);
> > if (ret)
> > dev_err(pcie->pci->dev, "L2 exit timeout\n");
> > +
> > +   return ret;
> >  }
> >  
> >  static int ls_pcie_host_init(struct dw_pcie_rp *pp)
> > @@ -180,6 +183,7 @@ static const struct ls_pcie_drvdata ls1021a_drvdata = {
> >  static const struct ls_pcie_drvdata layerscape_drvdata = {
> > .pf_off = 0xc,
> > .pm_support = true,
> > +   .exit_from_l2 = ls_pcie_exit_from_l2,
> >  };
> >  
> >  static const struct of_device_id ls_pcie_of_match[] = {
> > @@ -247,11 +251,14 @@ static int ls_pcie_suspend_noirq(struct device *dev)
> >  static int ls_pcie_resume_noirq(struct device *dev)
> >  {
> > struct ls_pcie *pcie = dev_get_drvdata(dev);
> > +   int ret;
> >  
> > if (!pcie->drvdata->pm_support)
> > return 0;
> >  
> > -   ls_pcie_exit_from_l2(>pci->pp);
> > +   ret = pcie->drvdata->exit_from_l2(>pci->pp);
> > +   if (ret)
> > +   return ret;
> >  
> > return dw_pcie_resume_noirq(pcie->pci);
> >  }
> > -- 
> > 2.34.1
> > 
> 
> -- 
> மணிவண்ணன் சதாசிவம்


Re: [PATCH v3 0/4] PCI: layerscape: Add suspend/resume support for ls1043 and ls1021

2023-10-27 Thread Frank Li
On Tue, Oct 17, 2023 at 03:31:41PM -0400, Frank Li wrote:
> Add suspend/resume support for ls1043 and ls1021.
> Change log see each patch
> 
> Frank Li (4):
>   PCI: layerscape: Add function pointer for exit_from_l2()
>   PCI: layerscape: Add suspend/resume for ls1021a
>   PCI: layerscape: Rename pf_* as pf_lut_*
>   PCI: layerscape: Add suspend/resume for ls1043a
> 

@mani:
Do you have any additional comments for these?

Frank

>  drivers/pci/controller/dwc/pci-layerscape.c | 217 ++--
>  1 file changed, 196 insertions(+), 21 deletions(-)
> 
> -- 
> 2.34.1
> 


[PATCH v3 4/4] PCI: layerscape: Add suspend/resume for ls1043a

2023-10-17 Thread Frank Li
ls1043a add suspend/resume support.
Implement ls1043a_pcie_send_turnoff_msg() to send PME_Turn_Off message.
Implement ls1043a_pcie_exit_from_l2() to exit from L2 state.

Signed-off-by: Frank Li 
---

Notes:
Change from v2 to v3
- Remove ls_pcie_lut_readl(writel) function

Change from v1 to v2
- Update subject 'a' to 'A'

 drivers/pci/controller/dwc/pci-layerscape.c | 86 -
 1 file changed, 85 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index 4b663b20d8612..9656224960b0c 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -41,6 +41,15 @@
 #define SCFG_PEXSFTRSTCR   0x190
 #define PEXSR(idx) BIT(idx)
 
+/* LS1043A PEX PME control register */
+#define SCFG_PEXPMECR  0x144
+#define PEXPME(idx)BIT(31 - (idx) * 4)
+
+/* LS1043A PEX LUT debug register */
+#define LS_PCIE_LDBG   0x7fc
+#define LDBG_SRBIT(30)
+#define LDBG_WEBIT(31)
+
 #define PCIE_IATU_NUM  6
 
 #define LS_PCIE_DRV_SCFG   BIT(0)
@@ -227,6 +236,68 @@ static int ls1021a_pcie_exit_from_l2(struct dw_pcie_rp *pp)
return 0;
 }
 
+static void ls1043a_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+   struct ls_pcie *pcie = to_ls_pcie(pci);
+   u32 val;
+
+   if (!pcie->scfg) {
+   dev_dbg(pcie->pci->dev, "SYSCFG is NULL\n");
+   return;
+   }
+
+   /* Send Turn_off message */
+   regmap_read(pcie->scfg, SCFG_PEXPMECR, );
+   val |= PEXPME(pcie->index);
+   regmap_write(pcie->scfg, SCFG_PEXPMECR, val);
+
+   /*
+* There is no specific register to check for PME_To_Ack from endpoint.
+* So on the safe side, wait for PCIE_PME_TO_L2_TIMEOUT_US.
+*/
+   mdelay(PCIE_PME_TO_L2_TIMEOUT_US/1000);
+
+   /*
+* Layerscape hardware reference manual recommends clearing the 
PMXMTTURNOFF bit
+* to complete the PME_Turn_Off handshake.
+*/
+   regmap_read(pcie->scfg, SCFG_PEXPMECR, );
+   val &= ~PEXPME(pcie->index);
+   regmap_write(pcie->scfg, SCFG_PEXPMECR, val);
+}
+
+static int ls1043a_pcie_exit_from_l2(struct dw_pcie_rp *pp)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+   struct ls_pcie *pcie = to_ls_pcie(pci);
+   u32 val;
+
+   /*
+* Only way let PEX module exit L2 is do a software reset.
+* LDBG_WE: allows the user to have write access to the PEXDBG[SR] for 
both setting and
+*  clearing the soft reset on the PEX module.
+* LDBG_SR: When SR is set to 1, the PEX module enters soft reset.
+*/
+   val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
+   val |= LDBG_WE;
+   ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
+
+   val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
+   val |= LDBG_SR;
+   ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
+
+   val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
+   val &= ~LDBG_SR;
+   ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
+
+   val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
+   val &= ~LDBG_WE;
+   ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
+
+   return 0;
+}
+
 static const struct dw_pcie_host_ops ls_pcie_host_ops = {
.host_init = ls_pcie_host_init,
.pme_turn_off = ls_pcie_send_turnoff_msg,
@@ -244,6 +315,19 @@ static const struct ls_pcie_drvdata ls1021a_drvdata = {
.flags = LS_PCIE_DRV_SCFG,
 };
 
+static const struct dw_pcie_host_ops ls1043a_pcie_host_ops = {
+   .host_init = ls_pcie_host_init,
+   .pme_turn_off = ls1043a_pcie_send_turnoff_msg,
+};
+
+static const struct ls_pcie_drvdata ls1043a_drvdata = {
+   .pf_lut_off = 0x1,
+   .pm_support = true,
+   .ops = _pcie_host_ops,
+   .exit_from_l2 = ls1043a_pcie_exit_from_l2,
+   .flags = LS_PCIE_DRV_SCFG,
+};
+
 static const struct ls_pcie_drvdata layerscape_drvdata = {
.pf_lut_off = 0xc,
.pm_support = true,
@@ -254,7 +338,7 @@ static const struct of_device_id ls_pcie_of_match[] = {
{ .compatible = "fsl,ls1012a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls1021a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls1028a-pcie", .data = _drvdata },
-   { .compatible = "fsl,ls1043a-pcie", .data = _drvdata },
+   { .compatible = "fsl,ls1043a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls1046a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls2080a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls2085a-pcie", .data = _drvdata },
-- 
2.34.1



[PATCH v3 3/4] PCI: layerscape: Rename pf_* as pf_lut_*

2023-10-17 Thread Frank Li
'pf' and 'lut' is just difference name in difference chips, but basic it is
a MMIO base address plus an offset.

Rename it to avoid duplicate pf_* and lut_* in driver.

Signed-off-by: Frank Li 
---

Notes:
change from v1 to v3
- new patch at v3

 drivers/pci/controller/dwc/pci-layerscape.c | 34 ++---
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index 6f47cfe146c44..4b663b20d8612 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -46,7 +46,7 @@
 #define LS_PCIE_DRV_SCFG   BIT(0)
 
 struct ls_pcie_drvdata {
-   const u32 pf_off;
+   const u32 pf_lut_off;
const struct dw_pcie_host_ops *ops;
int (*exit_from_l2)(struct dw_pcie_rp *pp);
int flags;
@@ -56,13 +56,13 @@ struct ls_pcie_drvdata {
 struct ls_pcie {
struct dw_pcie *pci;
const struct ls_pcie_drvdata *drvdata;
-   void __iomem *pf_base;
+   void __iomem *pf_lut_base;
struct regmap *scfg;
int index;
bool big_endian;
 };
 
-#define ls_pcie_pf_readl_addr(addr)ls_pcie_pf_readl(pcie, addr)
+#define ls_pcie_pf_lut_readl_addr(addr)ls_pcie_pf_lut_readl(pcie, addr)
 #define to_ls_pcie(x)  dev_get_drvdata((x)->dev)
 
 static bool ls_pcie_is_bridge(struct ls_pcie *pcie)
@@ -103,20 +103,20 @@ static void ls_pcie_fix_error_response(struct ls_pcie 
*pcie)
iowrite32(PCIE_ABSERR_SETTING, pci->dbi_base + PCIE_ABSERR);
 }
 
-static u32 ls_pcie_pf_readl(struct ls_pcie *pcie, u32 off)
+static u32 ls_pcie_pf_lut_readl(struct ls_pcie *pcie, u32 off)
 {
if (pcie->big_endian)
-   return ioread32be(pcie->pf_base + off);
+   return ioread32be(pcie->pf_lut_base + off);
 
-   return ioread32(pcie->pf_base + off);
+   return ioread32(pcie->pf_lut_base + off);
 }
 
-static void ls_pcie_pf_writel(struct ls_pcie *pcie, u32 off, u32 val)
+static void ls_pcie_pf_lut_writel(struct ls_pcie *pcie, u32 off, u32 val)
 {
if (pcie->big_endian)
-   iowrite32be(val, pcie->pf_base + off);
+   iowrite32be(val, pcie->pf_lut_base + off);
else
-   iowrite32(val, pcie->pf_base + off);
+   iowrite32(val, pcie->pf_lut_base + off);
 }
 
 static void ls_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
@@ -126,11 +126,11 @@ static void ls_pcie_send_turnoff_msg(struct dw_pcie_rp 
*pp)
u32 val;
int ret;
 
-   val = ls_pcie_pf_readl(pcie, LS_PCIE_PF_MCR);
+   val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_PF_MCR);
val |= PF_MCR_PTOMR;
-   ls_pcie_pf_writel(pcie, LS_PCIE_PF_MCR, val);
+   ls_pcie_pf_lut_writel(pcie, LS_PCIE_PF_MCR, val);
 
-   ret = readx_poll_timeout(ls_pcie_pf_readl_addr, LS_PCIE_PF_MCR,
+   ret = readx_poll_timeout(ls_pcie_pf_lut_readl_addr, LS_PCIE_PF_MCR,
 val, !(val & PF_MCR_PTOMR),
 PCIE_PME_TO_L2_TIMEOUT_US/10,
 PCIE_PME_TO_L2_TIMEOUT_US);
@@ -149,15 +149,15 @@ static int ls_pcie_exit_from_l2(struct dw_pcie_rp *pp)
 * Set PF_MCR_EXL2S bit in LS_PCIE_PF_MCR register for the link
 * to exit L2 state.
 */
-   val = ls_pcie_pf_readl(pcie, LS_PCIE_PF_MCR);
+   val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_PF_MCR);
val |= PF_MCR_EXL2S;
-   ls_pcie_pf_writel(pcie, LS_PCIE_PF_MCR, val);
+   ls_pcie_pf_lut_writel(pcie, LS_PCIE_PF_MCR, val);
 
/*
 * L2 exit timeout of 10ms is not defined in the specifications,
 * it was chosen based on empirical observations.
 */
-   ret = readx_poll_timeout(ls_pcie_pf_readl_addr, LS_PCIE_PF_MCR,
+   ret = readx_poll_timeout(ls_pcie_pf_lut_readl_addr, LS_PCIE_PF_MCR,
 val, !(val & PF_MCR_EXL2S),
 1000,
 1);
@@ -245,7 +245,7 @@ static const struct ls_pcie_drvdata ls1021a_drvdata = {
 };
 
 static const struct ls_pcie_drvdata layerscape_drvdata = {
-   .pf_off = 0xc,
+   .pf_lut_off = 0xc,
.pm_support = true,
.exit_from_l2 = ls_pcie_exit_from_l2,
 };
@@ -295,7 +295,7 @@ static int ls_pcie_probe(struct platform_device *pdev)
 
pcie->big_endian = of_property_read_bool(dev->of_node, "big-endian");
 
-   pcie->pf_base = pci->dbi_base + pcie->drvdata->pf_off;
+   pcie->pf_lut_base = pci->dbi_base + pcie->drvdata->pf_lut_off;
 
if (pcie->drvdata->flags & LS_PCIE_DRV_SCFG) {
 
-- 
2.34.1



[PATCH v3 2/4] PCI: layerscape: Add suspend/resume for ls1021a

2023-10-17 Thread Frank Li
ls1021a add suspend/resume support.

Implement callback ls1021a_pcie_send_turnoff_msg(), which write scfg's
SCFG_PEXPMWRCR to issue PME_Turn_off message.

Implement ls1021a_pcie_exit_from_l2() to let controller exit L2 state.

Signed-off-by: Frank Li 
---

Notes:
Change from v2 to v3
- update according to mani's feedback
change from v1 to v2
- change subject 'a' to 'A'

 drivers/pci/controller/dwc/pci-layerscape.c | 86 -
 1 file changed, 85 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index aea89926bcc4f..6f47cfe146c44 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -35,11 +35,21 @@
 #define PF_MCR_PTOMR   BIT(0)
 #define PF_MCR_EXL2S   BIT(1)
 
+/* LS1021A PEXn PM Write Control Register */
+#define SCFG_PEXPMWRCR(idx)(0x5c + (idx) * 0x64)
+#define PMXMTTURNOFF   BIT(31)
+#define SCFG_PEXSFTRSTCR   0x190
+#define PEXSR(idx) BIT(idx)
+
 #define PCIE_IATU_NUM  6
 
+#define LS_PCIE_DRV_SCFG   BIT(0)
+
 struct ls_pcie_drvdata {
const u32 pf_off;
+   const struct dw_pcie_host_ops *ops;
int (*exit_from_l2)(struct dw_pcie_rp *pp);
+   int flags;
bool pm_support;
 };
 
@@ -47,6 +57,8 @@ struct ls_pcie {
struct dw_pcie *pci;
const struct ls_pcie_drvdata *drvdata;
void __iomem *pf_base;
+   struct regmap *scfg;
+   int index;
bool big_endian;
 };
 
@@ -171,13 +183,65 @@ static int ls_pcie_host_init(struct dw_pcie_rp *pp)
return 0;
 }
 
+static void ls1021a_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+   struct ls_pcie *pcie = to_ls_pcie(pci);
+   u32 val;
+
+   /* Send PME_Turn_Off message */
+   regmap_read(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), );
+   val |= PMXMTTURNOFF;
+   regmap_write(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), val);
+
+   /*
+* There is no specific register to check for PME_To_Ack from endpoint.
+* So on the safe side, wait for PCIE_PME_TO_L2_TIMEOUT_US.
+*/
+   mdelay(PCIE_PME_TO_L2_TIMEOUT_US/1000);
+
+   /*
+* Layerscape hardware reference manual recommends clearing the 
PMXMTTURNOFF bit
+* to complete the PME_Turn_Off handshake.
+*/
+   regmap_read(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), );
+   val &= ~PMXMTTURNOFF;
+   regmap_write(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), val);
+}
+
+static int ls1021a_pcie_exit_from_l2(struct dw_pcie_rp *pp)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+   struct ls_pcie *pcie = to_ls_pcie(pci);
+   u32 val;
+
+   /* Only way exit from l2 is that do software reset */
+   regmap_read(pcie->scfg, SCFG_PEXSFTRSTCR, );
+   val |= PEXSR(pcie->index);
+   regmap_write(pcie->scfg, SCFG_PEXSFTRSTCR, val);
+
+   regmap_read(pcie->scfg, SCFG_PEXSFTRSTCR, );
+   val &= ~PEXSR(pcie->index);
+   regmap_write(pcie->scfg, SCFG_PEXSFTRSTCR, val);
+
+   return 0;
+}
+
 static const struct dw_pcie_host_ops ls_pcie_host_ops = {
.host_init = ls_pcie_host_init,
.pme_turn_off = ls_pcie_send_turnoff_msg,
 };
 
+static const struct dw_pcie_host_ops ls1021a_pcie_host_ops = {
+   .host_init = ls_pcie_host_init,
+   .pme_turn_off = ls1021a_pcie_send_turnoff_msg,
+};
+
 static const struct ls_pcie_drvdata ls1021a_drvdata = {
-   .pm_support = false,
+   .pm_support = true,
+   .ops = _pcie_host_ops,
+   .exit_from_l2 = ls1021a_pcie_exit_from_l2,
+   .flags = LS_PCIE_DRV_SCFG,
 };
 
 static const struct ls_pcie_drvdata layerscape_drvdata = {
@@ -205,6 +269,8 @@ static int ls_pcie_probe(struct platform_device *pdev)
struct dw_pcie *pci;
struct ls_pcie *pcie;
struct resource *dbi_base;
+   u32 index[2];
+   int ret;
 
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
if (!pcie)
@@ -220,6 +286,7 @@ static int ls_pcie_probe(struct platform_device *pdev)
pci->pp.ops = _pcie_host_ops;
 
pcie->pci = pci;
+   pci->pp.ops = pcie->drvdata->ops ? pcie->drvdata->ops : 
_pcie_host_ops;
 
dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
pci->dbi_base = devm_pci_remap_cfg_resource(dev, dbi_base);
@@ -230,6 +297,23 @@ static int ls_pcie_probe(struct platform_device *pdev)
 
pcie->pf_base = pci->dbi_base + pcie->drvdata->pf_off;
 
+   if (pcie->drvdata->flags & LS_PCIE_DRV_SCFG) {
+
+   pcie->scfg = syscon_regmap_lookup_by_phandle(dev->of_node, 
"fsl,pcie-scfg");
+   if (IS_ERR(pcie->scfg)) {
+   dev_err(dev, "No syscfg phandle specified\n")

[PATCH v3 1/4] PCI: layerscape: Add function pointer for exit_from_l2()

2023-10-17 Thread Frank Li
Since difference SoCs require different sequence for exiting L2, let's add
a separate "exit_from_l2()" callback. This callback can be used to execute
SoC specific sequence.

Signed-off-by: Frank Li 
---

Notes:
Change from v2 to v3
- fixed according to mani's feedback
  1. update commit message
  2. move dw_pcie_host_ops to next patch
  3. check return value from exit_from_l2()
Change from v1 to v2
- change subject 'a' to 'A'

Change from v1 to v2
- change subject 'a' to 'A'

 drivers/pci/controller/dwc/pci-layerscape.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index 37956e09c65bd..aea89926bcc4f 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -39,6 +39,7 @@
 
 struct ls_pcie_drvdata {
const u32 pf_off;
+   int (*exit_from_l2)(struct dw_pcie_rp *pp);
bool pm_support;
 };
 
@@ -125,7 +126,7 @@ static void ls_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
dev_err(pcie->pci->dev, "PME_Turn_off timeout\n");
 }
 
-static void ls_pcie_exit_from_l2(struct dw_pcie_rp *pp)
+static int ls_pcie_exit_from_l2(struct dw_pcie_rp *pp)
 {
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct ls_pcie *pcie = to_ls_pcie(pci);
@@ -150,6 +151,8 @@ static void ls_pcie_exit_from_l2(struct dw_pcie_rp *pp)
 1);
if (ret)
dev_err(pcie->pci->dev, "L2 exit timeout\n");
+
+   return ret;
 }
 
 static int ls_pcie_host_init(struct dw_pcie_rp *pp)
@@ -180,6 +183,7 @@ static const struct ls_pcie_drvdata ls1021a_drvdata = {
 static const struct ls_pcie_drvdata layerscape_drvdata = {
.pf_off = 0xc,
.pm_support = true,
+   .exit_from_l2 = ls_pcie_exit_from_l2,
 };
 
 static const struct of_device_id ls_pcie_of_match[] = {
@@ -247,11 +251,14 @@ static int ls_pcie_suspend_noirq(struct device *dev)
 static int ls_pcie_resume_noirq(struct device *dev)
 {
struct ls_pcie *pcie = dev_get_drvdata(dev);
+   int ret;
 
if (!pcie->drvdata->pm_support)
return 0;
 
-   ls_pcie_exit_from_l2(>pci->pp);
+   ret = pcie->drvdata->exit_from_l2(>pci->pp);
+   if (ret)
+   return ret;
 
return dw_pcie_resume_noirq(pcie->pci);
 }
-- 
2.34.1



[PATCH v3 0/4] PCI: layerscape: Add suspend/resume support for ls1043 and ls1021

2023-10-17 Thread Frank Li
Add suspend/resume support for ls1043 and ls1021.
Change log see each patch

Frank Li (4):
  PCI: layerscape: Add function pointer for exit_from_l2()
  PCI: layerscape: Add suspend/resume for ls1021a
  PCI: layerscape: Rename pf_* as pf_lut_*
  PCI: layerscape: Add suspend/resume for ls1043a

 drivers/pci/controller/dwc/pci-layerscape.c | 217 ++--
 1 file changed, 196 insertions(+), 21 deletions(-)

-- 
2.34.1



Re: [PATCH 2/3] PCI: layerscape: add suspend/resume for ls1021a

2023-10-16 Thread Frank Li
On Mon, Oct 16, 2023 at 10:28:24PM +0530, Manivannan Sadhasivam wrote:
> On Fri, Sep 15, 2023 at 02:43:05PM -0400, Frank Li wrote:
> > ls1021a add suspend/resume support.
> > 
> 
> Please add what the driver is doing during suspend/resume.
> 
> > Signed-off-by: Frank Li 
> > ---
> >  drivers/pci/controller/dwc/pci-layerscape.c | 88 -
> >  1 file changed, 87 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
> > b/drivers/pci/controller/dwc/pci-layerscape.c
> > index 20c48c06e2248..bc5a8ff1a26ce 100644
> > --- a/drivers/pci/controller/dwc/pci-layerscape.c
> > +++ b/drivers/pci/controller/dwc/pci-layerscape.c
> > @@ -35,6 +35,12 @@
> >  #define PF_MCR_PTOMR   BIT(0)
> >  #define PF_MCR_EXL2S   BIT(1)
> >  
> > +/* LS1021A PEXn PM Write Control Register */
> > +#define SCFG_PEXPMWRCR(idx)(0x5c + (idx) * 0x64)
> > +#define PMXMTTURNOFF   BIT(31)
> > +#define SCFG_PEXSFTRSTCR   0x190
> > +#define PEXSR(idx) BIT(idx)
> > +
> >  #define PCIE_IATU_NUM  6
> >  
> >  struct ls_pcie_drvdata {
> > @@ -48,6 +54,8 @@ struct ls_pcie {
> > struct dw_pcie *pci;
> > const struct ls_pcie_drvdata *drvdata;
> > void __iomem *pf_base;
> > +   struct regmap *scfg;
> > +   int index;
> > bool big_endian;
> >  };
> >  
> > @@ -170,13 +178,91 @@ static int ls_pcie_host_init(struct dw_pcie_rp *pp)
> > return 0;
> >  }
> >  
> > +static void ls1021a_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
> > +{
> > +   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > +   struct ls_pcie *pcie = to_ls_pcie(pci);
> > +   u32 val;
> > +
> > +   if (!pcie->scfg) {
> 
> Can this ever happen?
> 
> > +   dev_dbg(pcie->pci->dev, "SYSCFG is NULL\n");
> > +   return;
> > +   }
> > +
> > +   /* Send Turn_off message */
> 
> "Send PME_Turn_Off message"
> 
> > +   regmap_read(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), );
> > +   val |= PMXMTTURNOFF;
> > +   regmap_write(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), val);
> > +
> > +   /* There are not register to check ACK, so wait 
> > PCIE_PME_TO_L2_TIMEOUT_US */
> 
> "There is no specific register to check for PME_To_Ack from endpoint. So on 
> the
> safe side, wait for PCIE_PME_TO_L2_TIMEOUT_US."
> 
> > +   mdelay(PCIE_PME_TO_L2_TIMEOUT_US/1000);
> > +
> > +   /* Clear Turn_off message */
> 
> "PME_Turn_off". But I'm not sure if this is really required. Are you doing it
> because the layerspace hw implements the PME_Turn_Off bit as "level 
> triggered"?

I am not sure how hardware implement this. But reference manual said:
 
PMXMTTURNOFF:
Generate PM turnoff message for power management of PCI Express controllers.
This bit should be cleared by software.
0 Clear PM turnoff (default)
1 Trigger PM turnoff

Frank

> 
> > +   regmap_read(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), );
> > +   val &= ~PMXMTTURNOFF;
> > +   regmap_write(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), val);
> > +}
> > +
> > +static void ls1021a_pcie_exit_from_l2(struct dw_pcie_rp *pp)
> > +{
> > +   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > +   struct ls_pcie *pcie = to_ls_pcie(pci);
> > +   u32 val;
> > +
> 
> A comment here would be good.
> 
> > +   regmap_read(pcie->scfg, SCFG_PEXSFTRSTCR, );
> > +   val |= PEXSR(pcie->index);
> > +   regmap_write(pcie->scfg, SCFG_PEXSFTRSTCR, val);
> > +
> > +   regmap_read(pcie->scfg, SCFG_PEXSFTRSTCR, );
> > +   val &= ~PEXSR(pcie->index);
> > +   regmap_write(pcie->scfg, SCFG_PEXSFTRSTCR, val);
> > +}
> > +
> > +static int ls1021a_pcie_host_init(struct dw_pcie_rp *pp)
> > +{
> > +   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > +   struct ls_pcie *pcie = to_ls_pcie(pci);
> > +   struct device *dev = pcie->pci->dev;
> > +   u32 index[2];
> > +   int ret;
> > +
> > +   ret = ls_pcie_host_init(pp);
> > +   if (ret)
> > +   return ret;
> > +
> > +   pcie->scfg = syscon_regmap_lookup_by_phandle(dev->of_node, 
> > "fsl,pcie-scfg");
> > +   if (IS_ERR(pcie->scfg)) {
> > +   ret = PTR_ERR(pcie->scfg);
> > +   dev_err(dev, "No syscfg phandle specified\n");
> > +   pcie->scfg = NULL;
> > +   return ret;
> 

Re: [PATCH 2/3] PCI: layerscape: add suspend/resume for ls1021a

2023-10-16 Thread Frank Li
On Mon, Oct 16, 2023 at 11:25:12AM -0500, Bjorn Helgaas wrote:
> On Mon, Oct 16, 2023 at 12:11:04PM -0400, Frank Li wrote:
> > On Mon, Oct 16, 2023 at 10:22:11AM -0500, Bjorn Helgaas wrote:
> 
> > > Obviously Lorenzo *could* edit all your subject lines on your behalf,
> > > but it makes everybody's life easier if people look at the existing
> > > code and follow the style when making changes.
> > 
> > Understand, but simple mark 'a' and 'A' to me. I will update patches and
> > take care for next time instead search whole docuemnt to guess which one
> > violated. I know I make some mistakes at here. But I am working on many
> > difference kernel subsystems, some require upper case, some require low
> > case, someone doesn't care.
> 
> Right, that's why I always suggest following the example of the
> surrounding code and history.  English is the only language I know,
> but I speculate that this typographical detail probably doesn't make
> sense in languages that don't have a similar upper/lowercase
> distinction.

If everyone thinks it is important. I suggest put it in checkpatch.pl
script. The only script check can prevent to human make mistakes.

I asked the same question at:
https://lore.kernel.org/imx/ZSV1sINV%2F2GrAYFr@lizhi-Precision-Tower-5810/T/#t

It lets teach kid mulitplication,  kid did 20 questions. only 1 failure.
The good teacher should tell which one is wrong and grade as 19/20 instead
of just grade 19/20 without any comments.

We are using email communication instead of face to face. The efficient of
communication is important. We have differece background, difference
native languadge, live on difference area in world and do the same jobs to
make linux kernel better.

The simple and straight forward's feedback can save both our time and
efforts.

Frank Li

> 
> Thanks for persevering; we'd be having a lot more trouble if I tried
> to send emails in your native language ;)
> 
> Bjorn


[PATCH v2 3/3] PCI: layerscape: Add suspend/resume for ls1043a

2023-10-16 Thread Frank Li
ls1043a add suspend/resume support.

Signed-off-by: Frank Li 
---

Notes:
Change from v1 to v2
- Change subject 'a' to 'A'

 drivers/pci/controller/dwc/pci-layerscape.c | 91 -
 1 file changed, 90 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index bc5a8ff1a26c..debabb9bb41f 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -41,10 +41,20 @@
 #define SCFG_PEXSFTRSTCR   0x190
 #define PEXSR(idx) BIT(idx)
 
+/* LS1043A PEX PME control register */
+#define SCFG_PEXPMECR  0x144
+#define PEXPME(idx)BIT(31 - (idx) * 4)
+
+/* LS1043A PEX LUT debug register */
+#define LS_PCIE_LDBG   0x7fc
+#define LDBG_SRBIT(30)
+#define LDBG_WEBIT(31)
+
 #define PCIE_IATU_NUM  6
 
 struct ls_pcie_drvdata {
const u32 pf_off;
+   const u32 lut_off;
const struct dw_pcie_host_ops *ops;
void (*exit_from_l2)(struct dw_pcie_rp *pp);
bool pm_support;
@@ -54,6 +64,7 @@ struct ls_pcie {
struct dw_pcie *pci;
const struct ls_pcie_drvdata *drvdata;
void __iomem *pf_base;
+   void __iomem *lut_base;
struct regmap *scfg;
int index;
bool big_endian;
@@ -116,6 +127,23 @@ static void ls_pcie_pf_writel(struct ls_pcie *pcie, u32 
off, u32 val)
iowrite32(val, pcie->pf_base + off);
 }
 
+static u32 ls_pcie_lut_readl(struct ls_pcie *pcie, u32 off)
+{
+   if (pcie->big_endian)
+   return ioread32be(pcie->lut_base + off);
+
+   return ioread32(pcie->lut_base + off);
+}
+
+static void ls_pcie_lut_writel(struct ls_pcie *pcie, u32 off, u32 val)
+{
+   if (pcie->big_endian)
+   iowrite32be(val, pcie->lut_base + off);
+   else
+   iowrite32(val, pcie->lut_base + off);
+}
+
+
 static void ls_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
 {
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
@@ -249,6 +277,54 @@ static int ls1021a_pcie_host_init(struct dw_pcie_rp *pp)
return ret;
 }
 
+static void ls1043a_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+   struct ls_pcie *pcie = to_ls_pcie(pci);
+   u32 val;
+
+   if (!pcie->scfg) {
+   dev_dbg(pcie->pci->dev, "SYSCFG is NULL\n");
+   return;
+   }
+
+   /* Send Turn_off message */
+   regmap_read(pcie->scfg, SCFG_PEXPMECR, );
+   val |= PEXPME(pcie->index);
+   regmap_write(pcie->scfg, SCFG_PEXPMECR, val);
+
+   /* There are not register to check ACK, so wait 
PCIE_PME_TO_L2_TIMEOUT_US */
+   mdelay(PCIE_PME_TO_L2_TIMEOUT_US/1000);
+
+   /* Clear Turn_off message */
+   regmap_read(pcie->scfg, SCFG_PEXPMECR, );
+   val &= ~PEXPME(pcie->index);
+   regmap_write(pcie->scfg, SCFG_PEXPMECR, val);
+}
+
+static void ls1043a_pcie_exit_from_l2(struct dw_pcie_rp *pp)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+   struct ls_pcie *pcie = to_ls_pcie(pci);
+   u32 val;
+
+   val = ls_pcie_lut_readl(pcie, LS_PCIE_LDBG);
+   val |= LDBG_WE;
+   ls_pcie_lut_writel(pcie, LS_PCIE_LDBG, val);
+
+   val = ls_pcie_lut_readl(pcie, LS_PCIE_LDBG);
+   val |= LDBG_SR;
+   ls_pcie_lut_writel(pcie, LS_PCIE_LDBG, val);
+
+   val = ls_pcie_lut_readl(pcie, LS_PCIE_LDBG);
+   val &= ~LDBG_SR;
+   ls_pcie_lut_writel(pcie, LS_PCIE_LDBG, val);
+
+   val = ls_pcie_lut_readl(pcie, LS_PCIE_LDBG);
+   val &= ~LDBG_WE;
+   ls_pcie_lut_writel(pcie, LS_PCIE_LDBG, val);
+}
+
 static const struct dw_pcie_host_ops ls_pcie_host_ops = {
.host_init = ls_pcie_host_init,
.pme_turn_off = ls_pcie_send_turnoff_msg,
@@ -265,6 +341,18 @@ static const struct ls_pcie_drvdata ls1021a_drvdata = {
.exit_from_l2 = ls1021a_pcie_exit_from_l2,
 };
 
+static const struct dw_pcie_host_ops ls1043a_pcie_host_ops = {
+   .host_init = ls1021a_pcie_host_init, /* the same as ls1021 */
+   .pme_turn_off = ls1043a_pcie_send_turnoff_msg,
+};
+
+static const struct ls_pcie_drvdata ls1043a_drvdata = {
+   .lut_off = 0x1,
+   .pm_support = true,
+   .ops = _pcie_host_ops,
+   .exit_from_l2 = ls1043a_pcie_exit_from_l2,
+};
+
 static const struct ls_pcie_drvdata layerscape_drvdata = {
.pf_off = 0xc,
.pm_support = true,
@@ -275,7 +363,7 @@ static const struct of_device_id ls_pcie_of_match[] = {
{ .compatible = "fsl,ls1012a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls1021a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls1028a-pcie", .data = _drvdata },
-   { .compatible = "fsl,ls1043a-pcie", .data = _drvdata },
+   { .compatible = "fsl,ls1043a-pcie", 

[PATCH v2 2/3] PCI: layerscape: Add suspend/resume for ls1021a

2023-10-16 Thread Frank Li
ls1021a add suspend/resume support.

Signed-off-by: Frank Li 
---

Notes:
change from v1 to v2
- change subject 'a' to 'A'

 drivers/pci/controller/dwc/pci-layerscape.c | 88 -
 1 file changed, 87 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index 20c48c06e224..bc5a8ff1a26c 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -35,6 +35,12 @@
 #define PF_MCR_PTOMR   BIT(0)
 #define PF_MCR_EXL2S   BIT(1)
 
+/* LS1021A PEXn PM Write Control Register */
+#define SCFG_PEXPMWRCR(idx)(0x5c + (idx) * 0x64)
+#define PMXMTTURNOFF   BIT(31)
+#define SCFG_PEXSFTRSTCR   0x190
+#define PEXSR(idx) BIT(idx)
+
 #define PCIE_IATU_NUM  6
 
 struct ls_pcie_drvdata {
@@ -48,6 +54,8 @@ struct ls_pcie {
struct dw_pcie *pci;
const struct ls_pcie_drvdata *drvdata;
void __iomem *pf_base;
+   struct regmap *scfg;
+   int index;
bool big_endian;
 };
 
@@ -170,13 +178,91 @@ static int ls_pcie_host_init(struct dw_pcie_rp *pp)
return 0;
 }
 
+static void ls1021a_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+   struct ls_pcie *pcie = to_ls_pcie(pci);
+   u32 val;
+
+   if (!pcie->scfg) {
+   dev_dbg(pcie->pci->dev, "SYSCFG is NULL\n");
+   return;
+   }
+
+   /* Send Turn_off message */
+   regmap_read(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), );
+   val |= PMXMTTURNOFF;
+   regmap_write(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), val);
+
+   /* There are not register to check ACK, so wait 
PCIE_PME_TO_L2_TIMEOUT_US */
+   mdelay(PCIE_PME_TO_L2_TIMEOUT_US/1000);
+
+   /* Clear Turn_off message */
+   regmap_read(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), );
+   val &= ~PMXMTTURNOFF;
+   regmap_write(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), val);
+}
+
+static void ls1021a_pcie_exit_from_l2(struct dw_pcie_rp *pp)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+   struct ls_pcie *pcie = to_ls_pcie(pci);
+   u32 val;
+
+   regmap_read(pcie->scfg, SCFG_PEXSFTRSTCR, );
+   val |= PEXSR(pcie->index);
+   regmap_write(pcie->scfg, SCFG_PEXSFTRSTCR, val);
+
+   regmap_read(pcie->scfg, SCFG_PEXSFTRSTCR, );
+   val &= ~PEXSR(pcie->index);
+   regmap_write(pcie->scfg, SCFG_PEXSFTRSTCR, val);
+}
+
+static int ls1021a_pcie_host_init(struct dw_pcie_rp *pp)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+   struct ls_pcie *pcie = to_ls_pcie(pci);
+   struct device *dev = pcie->pci->dev;
+   u32 index[2];
+   int ret;
+
+   ret = ls_pcie_host_init(pp);
+   if (ret)
+   return ret;
+
+   pcie->scfg = syscon_regmap_lookup_by_phandle(dev->of_node, 
"fsl,pcie-scfg");
+   if (IS_ERR(pcie->scfg)) {
+   ret = PTR_ERR(pcie->scfg);
+   dev_err(dev, "No syscfg phandle specified\n");
+   pcie->scfg = NULL;
+   return ret;
+   }
+
+   ret = of_property_read_u32_array(dev->of_node, "fsl,pcie-scfg", index, 
2);
+   if (ret) {
+   pcie->scfg = NULL;
+   return ret;
+   }
+
+   pcie->index = index[1];
+
+   return ret;
+}
+
 static const struct dw_pcie_host_ops ls_pcie_host_ops = {
.host_init = ls_pcie_host_init,
.pme_turn_off = ls_pcie_send_turnoff_msg,
 };
 
+static const struct dw_pcie_host_ops ls1021a_pcie_host_ops = {
+   .host_init = ls1021a_pcie_host_init,
+   .pme_turn_off = ls1021a_pcie_send_turnoff_msg,
+};
+
 static const struct ls_pcie_drvdata ls1021a_drvdata = {
-   .pm_support = false,
+   .pm_support = true,
+   .ops = _pcie_host_ops,
+   .exit_from_l2 = ls1021a_pcie_exit_from_l2,
 };
 
 static const struct ls_pcie_drvdata layerscape_drvdata = {
-- 
2.34.1



[PATCH v2 1/3] PCI: layerscape: Add function pointer for exit_from_l2()

2023-10-16 Thread Frank Li
Difference layerscape chip have not difference exit_from_l2() method.
Using function pointer for ls1028. It prepare for other layerscape
suspend/resume support.

Signed-off-by: Frank Li 
---

Notes:
Change from v1 to v2
- change subject 'a' to 'A'

 drivers/pci/controller/dwc/pci-layerscape.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index b931d597656f..20c48c06e224 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -39,6 +39,8 @@
 
 struct ls_pcie_drvdata {
const u32 pf_off;
+   const struct dw_pcie_host_ops *ops;
+   void (*exit_from_l2)(struct dw_pcie_rp *pp);
bool pm_support;
 };
 
@@ -180,6 +182,7 @@ static const struct ls_pcie_drvdata ls1021a_drvdata = {
 static const struct ls_pcie_drvdata layerscape_drvdata = {
.pf_off = 0xc,
.pm_support = true,
+   .exit_from_l2 = ls_pcie_exit_from_l2,
 };
 
 static const struct of_device_id ls_pcie_of_match[] = {
@@ -213,7 +216,7 @@ static int ls_pcie_probe(struct platform_device *pdev)
pcie->drvdata = of_device_get_match_data(dev);
 
pci->dev = dev;
-   pci->pp.ops = _pcie_host_ops;
+   pci->pp.ops = pcie->drvdata->ops ? pcie->drvdata->ops : 
_pcie_host_ops;
 
pcie->pci = pci;
 
@@ -251,7 +254,7 @@ static int ls_pcie_resume_noirq(struct device *dev)
if (!pcie->drvdata->pm_support)
return 0;
 
-   ls_pcie_exit_from_l2(>pci->pp);
+   pcie->drvdata->exit_from_l2(>pci->pp);
 
return dw_pcie_resume_noirq(pcie->pci);
 }
-- 
2.34.1



Re: [PATCH 2/3] PCI: layerscape: add suspend/resume for ls1021a

2023-10-16 Thread Frank Li
On Mon, Oct 16, 2023 at 10:22:11AM -0500, Bjorn Helgaas wrote:
> On Mon, Oct 16, 2023 at 10:45:25AM -0400, Frank Li wrote:
> > On Tue, Oct 10, 2023 at 06:02:36PM +0200, Lorenzo Pieralisi wrote:
> > > On Tue, Oct 10, 2023 at 10:20:12AM -0400, Frank Li wrote:
> 
> > > > Ping
> > > 
> > > Read and follow please (and then ping us):
> > > https://lore.kernel.org/linux-pci/20171026223701.ga25...@bhelgaas-glaptop.roam.corp.google.com
> > 
> > Could you please help point which specic one was not follow aboved guide?
> > Then I can update my code. I think that's efficial communication method. I
> > think I have read it serial times. But not sure which one violate the
> > guide?
> > 
> > @Bjorn Helgaas. How do you think so? 
> 
> Since Lorenzo didn't point out anything specific in the patch itself,
> I think he was probably referring to the subject line and this advice:
> 
>   - Follow the existing convention, i.e., run "git log --oneline
> " and make yours match in format, capitalization, and
> sentence structure.  For example, native host bridge driver patch
> titles look like this:
> 
>   PCI: altera: Fix platform_get_irq() error handling
>   PCI: vmd: Remove IRQ affinity so we can allocate more IRQs
>   PCI: mediatek: Add MSI support for MT2712 and MT7622
>   PCI: rockchip: Remove IRQ domain if probe fails
> 
> In this case, your subject line was:
> 
>   PCI: layerscape: add suspend/resume for ls1021a
> 
> The advice was to run this:
> 
>   $ git log --oneline drivers/pci/controller/dwc/pci-layerscape.c
>   83c088148c8e PCI: Use PCI_HEADER_TYPE_* instead of literals
>   9fda4d09905d PCI: layerscape: Add power management support for ls1028a
>   277004d7a4a3 PCI: Remove unnecessary  includes
>   60b3c27fb9b9 PCI: dwc: Rename struct pcie_port to dw_pcie_rp
>   d23f0c11aca2 PCI: layerscape: Change to use the DWC common link-up check 
> function
>   7007b745a508 PCI: layerscape: Convert to builtin_platform_driver()
>   60f5b73fa0f2 PCI: dwc: Remove unnecessary wrappers around 
> dw_pcie_host_init()
>   b9ac0f9dc8ea PCI: dwc: Move dw_pcie_setup_rc() to DWC common code
>   f78f02638af5 PCI: dwc: Rework MSI initialization
> 
> Note that these summaries are all complete sentences that start with a
> capital letter:
> 
>   Use PCI_HEADER_TYPE_* instead of literals
>   Add power management support for ls1028a
>   Remove unnecessary  includes
>   ...
> 
> So yours could be this:
> 
>   PCI: layerscape: Add suspend/resume for ls1021a
>^
> 
> This is trivial, obviously.  But the uppercase/lowercase distinction
> carries information, and it's an unnecessary distraction to notice
> that "oh, this is different from the rest; is the difference
> important or should I ignore it?"

Thanks. Not everyone think it is trivial. Especially for the one, who
English are not native language.

> 
> Obviously Lorenzo *could* edit all your subject lines on your behalf,
> but it makes everybody's life easier if people look at the existing
> code and follow the style when making changes.

Understand, but simple mark 'a' and 'A' to me. I will update patches and
take care for next time instead search whole docuemnt to guess which one
violated. I know I make some mistakes at here. But I am working on many
difference kernel subsystems, some require upper case, some require low
case, someone doesn't care.
 
I respected all reviewer's and maintaner's time, but I hope respected
the contributor's time also.

Just simple words like , 'a' to 'A' or
run git log --oneline to check subject. I will know what exact means. 

Do you think it will better than below words

"Read and follow please (and then ping us):   
https://lore.kernel.org/linux-pci/20171026223701.ga25...@bhelgaas-glaptop.roam.corp.google.com;

Frank

> 
> E.g., write subject lines that are similar in style to previous ones,
> name local variables similarly to other functions, use line lengths
> consistent with the rest of the file, etc.  After applying a change,
> the file should look like a coherent whole; we should not be able to
> tell that this hunk was added later by somebody else.  This all helps
> make the code (and the git history) more readable and maintainable.
> 
> Bjorn


Re: [PATCH 2/3] PCI: layerscape: add suspend/resume for ls1021a

2023-10-16 Thread Frank Li
On Tue, Oct 10, 2023 at 06:02:36PM +0200, Lorenzo Pieralisi wrote:
> On Tue, Oct 10, 2023 at 10:20:12AM -0400, Frank Li wrote:
> > On Wed, Oct 04, 2023 at 10:23:51AM -0400, Frank Li wrote:
> > > On Fri, Sep 15, 2023 at 02:43:05PM -0400, Frank Li wrote:
> > > > ls1021a add suspend/resume support.
> > > > 
> > > > Signed-off-by: Frank Li 
> > > > ---
> > > 
> > > ping
> > > 
> > > Frank
> > 
> > Ping
> 
> Read and follow please (and then ping us):
> https://lore.kernel.org/linux-pci/20171026223701.ga25...@bhelgaas-glaptop.roam.corp.google.com

Could you please help point which specic one was not follow aboved guide?
Then I can update my code. I think that's efficial communication method. I
think I have read it serial times. But not sure which one violate the
guide?

@Bjorn Helgaas. How do you think so? 

best regards
Frank Li

> 
> > Frank
> > 
> > > 
> > > >  drivers/pci/controller/dwc/pci-layerscape.c | 88 -
> > > >  1 file changed, 87 insertions(+), 1 deletion(-)
> > > > 
> > > > diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
> > > > b/drivers/pci/controller/dwc/pci-layerscape.c
> > > > index 20c48c06e2248..bc5a8ff1a26ce 100644
> > > > --- a/drivers/pci/controller/dwc/pci-layerscape.c
> > > > +++ b/drivers/pci/controller/dwc/pci-layerscape.c
> > > > @@ -35,6 +35,12 @@
> > > >  #define PF_MCR_PTOMR   BIT(0)
> > > >  #define PF_MCR_EXL2S   BIT(1)
> > > >  
> > > > +/* LS1021A PEXn PM Write Control Register */
> > > > +#define SCFG_PEXPMWRCR(idx)(0x5c + (idx) * 0x64)
> > > > +#define PMXMTTURNOFF   BIT(31)
> > > > +#define SCFG_PEXSFTRSTCR   0x190
> > > > +#define PEXSR(idx) BIT(idx)
> > > > +
> > > >  #define PCIE_IATU_NUM  6
> > > >  
> > > >  struct ls_pcie_drvdata {
> > > > @@ -48,6 +54,8 @@ struct ls_pcie {
> > > > struct dw_pcie *pci;
> > > > const struct ls_pcie_drvdata *drvdata;
> > > > void __iomem *pf_base;
> > > > +   struct regmap *scfg;
> > > > +   int index;
> > > > bool big_endian;
> > > >  };
> > > >  
> > > > @@ -170,13 +178,91 @@ static int ls_pcie_host_init(struct dw_pcie_rp 
> > > > *pp)
> > > > return 0;
> > > >  }
> > > >  
> > > > +static void ls1021a_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
> > > > +{
> > > > +   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > > > +   struct ls_pcie *pcie = to_ls_pcie(pci);
> > > > +   u32 val;
> > > > +
> > > > +   if (!pcie->scfg) {
> > > > +   dev_dbg(pcie->pci->dev, "SYSCFG is NULL\n");
> > > > +   return;
> > > > +   }
> > > > +
> > > > +   /* Send Turn_off message */
> > > > +   regmap_read(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), );
> > > > +   val |= PMXMTTURNOFF;
> > > > +   regmap_write(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), val);
> > > > +
> > > > +   /* There are not register to check ACK, so wait 
> > > > PCIE_PME_TO_L2_TIMEOUT_US */
> > > > +   mdelay(PCIE_PME_TO_L2_TIMEOUT_US/1000);
> > > > +
> > > > +   /* Clear Turn_off message */
> > > > +   regmap_read(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), );
> > > > +   val &= ~PMXMTTURNOFF;
> > > > +   regmap_write(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), val);
> > > > +}
> > > > +
> > > > +static void ls1021a_pcie_exit_from_l2(struct dw_pcie_rp *pp)
> > > > +{
> > > > +   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > > > +   struct ls_pcie *pcie = to_ls_pcie(pci);
> > > > +   u32 val;
> > > > +
> > > > +   regmap_read(pcie->scfg, SCFG_PEXSFTRSTCR, );
> > > > +   val |= PEXSR(pcie->index);
> > > > +   regmap_write(pcie->scfg, SCFG_PEXSFTRSTCR, val);
> > > > +
> > > > +   regmap_read(pcie->scfg, SCFG_PEXSFTRSTCR, );
> > > > +   val &= ~PEXSR(pcie->index);
> > > > +   regmap_write(pcie->scfg, SCFG_PEXSFTRSTCR, val);
> > > > +}
> &

Re: [PATCH v3 1/1] PCI: layerscape-ep: set 64-bit DMA mask

2023-10-10 Thread Frank Li
On Tue, Oct 10, 2023 at 05:44:23PM +0200, Lorenzo Pieralisi wrote:
> On Tue, 26 Sep 2023 10:04:45 -0400, Frank Li wrote:
> > Set DMA mask and coherent DMA mask to enable 64-bit addressing.
> > 
> > 
> 
> Read this:
> https://lore.kernel.org/linux-pci/20171026223701.ga25...@bhelgaas-glaptop.roam.corp.google.com
> 
> Find the issue with the commit log (that I fixed).

Do you means "set" should be "Set"?

Frank

> 
> This does not apply to v6.6-rc1 so I tweaked it,
> check that everything is OK please.
> 
> Applied to controller/layerscape, thanks!

Thanks, everthing is good!

> 
> [1/1] PCI: layerscape-ep: set 64-bit DMA mask
>   https://git.kernel.org/pci/pci/c/81ef01bc5934
> 
> Thanks,
> Lorenzo


Re: [PATCH 2/3] PCI: layerscape: add suspend/resume for ls1021a

2023-10-10 Thread Frank Li
On Wed, Oct 04, 2023 at 10:23:51AM -0400, Frank Li wrote:
> On Fri, Sep 15, 2023 at 02:43:05PM -0400, Frank Li wrote:
> > ls1021a add suspend/resume support.
> > 
> > Signed-off-by: Frank Li 
> > ---
> 
> ping
> 
> Frank

Ping

Frank

> 
> >  drivers/pci/controller/dwc/pci-layerscape.c | 88 -
> >  1 file changed, 87 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
> > b/drivers/pci/controller/dwc/pci-layerscape.c
> > index 20c48c06e2248..bc5a8ff1a26ce 100644
> > --- a/drivers/pci/controller/dwc/pci-layerscape.c
> > +++ b/drivers/pci/controller/dwc/pci-layerscape.c
> > @@ -35,6 +35,12 @@
> >  #define PF_MCR_PTOMR   BIT(0)
> >  #define PF_MCR_EXL2S   BIT(1)
> >  
> > +/* LS1021A PEXn PM Write Control Register */
> > +#define SCFG_PEXPMWRCR(idx)(0x5c + (idx) * 0x64)
> > +#define PMXMTTURNOFF   BIT(31)
> > +#define SCFG_PEXSFTRSTCR   0x190
> > +#define PEXSR(idx) BIT(idx)
> > +
> >  #define PCIE_IATU_NUM  6
> >  
> >  struct ls_pcie_drvdata {
> > @@ -48,6 +54,8 @@ struct ls_pcie {
> > struct dw_pcie *pci;
> > const struct ls_pcie_drvdata *drvdata;
> > void __iomem *pf_base;
> > +   struct regmap *scfg;
> > +   int index;
> > bool big_endian;
> >  };
> >  
> > @@ -170,13 +178,91 @@ static int ls_pcie_host_init(struct dw_pcie_rp *pp)
> > return 0;
> >  }
> >  
> > +static void ls1021a_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
> > +{
> > +   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > +   struct ls_pcie *pcie = to_ls_pcie(pci);
> > +   u32 val;
> > +
> > +   if (!pcie->scfg) {
> > +   dev_dbg(pcie->pci->dev, "SYSCFG is NULL\n");
> > +   return;
> > +   }
> > +
> > +   /* Send Turn_off message */
> > +   regmap_read(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), );
> > +   val |= PMXMTTURNOFF;
> > +   regmap_write(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), val);
> > +
> > +   /* There are not register to check ACK, so wait 
> > PCIE_PME_TO_L2_TIMEOUT_US */
> > +   mdelay(PCIE_PME_TO_L2_TIMEOUT_US/1000);
> > +
> > +   /* Clear Turn_off message */
> > +   regmap_read(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), );
> > +   val &= ~PMXMTTURNOFF;
> > +   regmap_write(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), val);
> > +}
> > +
> > +static void ls1021a_pcie_exit_from_l2(struct dw_pcie_rp *pp)
> > +{
> > +   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > +   struct ls_pcie *pcie = to_ls_pcie(pci);
> > +   u32 val;
> > +
> > +   regmap_read(pcie->scfg, SCFG_PEXSFTRSTCR, );
> > +   val |= PEXSR(pcie->index);
> > +   regmap_write(pcie->scfg, SCFG_PEXSFTRSTCR, val);
> > +
> > +   regmap_read(pcie->scfg, SCFG_PEXSFTRSTCR, );
> > +   val &= ~PEXSR(pcie->index);
> > +   regmap_write(pcie->scfg, SCFG_PEXSFTRSTCR, val);
> > +}
> > +
> > +static int ls1021a_pcie_host_init(struct dw_pcie_rp *pp)
> > +{
> > +   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > +   struct ls_pcie *pcie = to_ls_pcie(pci);
> > +   struct device *dev = pcie->pci->dev;
> > +   u32 index[2];
> > +   int ret;
> > +
> > +   ret = ls_pcie_host_init(pp);
> > +   if (ret)
> > +   return ret;
> > +
> > +   pcie->scfg = syscon_regmap_lookup_by_phandle(dev->of_node, 
> > "fsl,pcie-scfg");
> > +   if (IS_ERR(pcie->scfg)) {
> > +   ret = PTR_ERR(pcie->scfg);
> > +   dev_err(dev, "No syscfg phandle specified\n");
> > +   pcie->scfg = NULL;
> > +   return ret;
> > +   }
> > +
> > +   ret = of_property_read_u32_array(dev->of_node, "fsl,pcie-scfg", index, 
> > 2);
> > +   if (ret) {
> > +   pcie->scfg = NULL;
> > +   return ret;
> > +   }
> > +
> > +   pcie->index = index[1];
> > +
> > +   return ret;
> > +}
> > +
> >  static const struct dw_pcie_host_ops ls_pcie_host_ops = {
> > .host_init = ls_pcie_host_init,
> > .pme_turn_off = ls_pcie_send_turnoff_msg,
> >  };
> >  
> > +static const struct dw_pcie_host_ops ls1021a_pcie_host_ops = {
> > +   .host_init = ls1021a_pcie_host_init,
> > +   .pme_turn_off = ls1021a_pcie_send_turnoff_msg,
> > +};
> > +
> >  static const struct ls_pcie_drvdata ls1021a_drvdata = {
> > -   .pm_support = false,
> > +   .pm_support = true,
> > +   .ops = _pcie_host_ops,
> > +   .exit_from_l2 = ls1021a_pcie_exit_from_l2,
> >  };
> >  
> >  static const struct ls_pcie_drvdata layerscape_drvdata = {
> > -- 
> > 2.34.1
> > 


Re: [PATCH v3 1/1] PCI: layerscape-ep: set 64-bit DMA mask

2023-10-10 Thread Frank Li
On Wed, Sep 27, 2023 at 02:46:21PM +0200, Manivannan Sadhasivam wrote:
> On Tue, Sep 26, 2023 at 10:04:45AM -0400, Frank Li wrote:
> > From: Guanhua Gao 
> > 
> > Set DMA mask and coherent DMA mask to enable 64-bit addressing.
> > 
> > Signed-off-by: Guanhua Gao 
> > Signed-off-by: Hou Zhiqiang 
> > Signed-off-by: Frank Li 
> 
> Acked-by: Manivannan Sadhasivam 

@Lorenzo 

Could you please consider pick this patch?
Manivannan already reviewed and only impact layerscape.

Frank
 

> 
> - Mani
> 
> > ---
> > 
> > Notes:
> > change from v2 to v3
> > - remove check return value of dma_set_mask_and_coherent. 64bit mask 
> > always
> > return success.
> > - remove redundate comments
> > change from v1 to v2
> > - Remove 32bit DMA mask set.
> > 
> >  drivers/pci/controller/dwc/pci-layerscape-ep.c | 2 ++
> >  1 file changed, 2 insertions(+)
> > 
> > diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
> > b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > index de4c1758a6c3..2c2c9aaa8700 100644
> > --- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > +++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > @@ -249,6 +249,8 @@ static int __init ls_pcie_ep_probe(struct 
> > platform_device *pdev)
> >  
> > pcie->big_endian = of_property_read_bool(dev->of_node, "big-endian");
> >  
> > +   dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
> > +
> > platform_set_drvdata(pdev, pcie);
> >  
> > ret = dw_pcie_ep_init(>ep);
> > -- 
> > 2.34.1
> > 
> 
> -- 
> மணிவண்ணன் சதாசிவம்


Re: [PATCH 2/3] PCI: layerscape: add suspend/resume for ls1021a

2023-10-04 Thread Frank Li
On Fri, Sep 15, 2023 at 02:43:05PM -0400, Frank Li wrote:
> ls1021a add suspend/resume support.
> 
> Signed-off-by: Frank Li 
> ---

ping

Frank

>  drivers/pci/controller/dwc/pci-layerscape.c | 88 -
>  1 file changed, 87 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
> b/drivers/pci/controller/dwc/pci-layerscape.c
> index 20c48c06e2248..bc5a8ff1a26ce 100644
> --- a/drivers/pci/controller/dwc/pci-layerscape.c
> +++ b/drivers/pci/controller/dwc/pci-layerscape.c
> @@ -35,6 +35,12 @@
>  #define PF_MCR_PTOMR BIT(0)
>  #define PF_MCR_EXL2S BIT(1)
>  
> +/* LS1021A PEXn PM Write Control Register */
> +#define SCFG_PEXPMWRCR(idx)  (0x5c + (idx) * 0x64)
> +#define PMXMTTURNOFF BIT(31)
> +#define SCFG_PEXSFTRSTCR 0x190
> +#define PEXSR(idx)   BIT(idx)
> +
>  #define PCIE_IATU_NUM6
>  
>  struct ls_pcie_drvdata {
> @@ -48,6 +54,8 @@ struct ls_pcie {
>   struct dw_pcie *pci;
>   const struct ls_pcie_drvdata *drvdata;
>   void __iomem *pf_base;
> + struct regmap *scfg;
> + int index;
>   bool big_endian;
>  };
>  
> @@ -170,13 +178,91 @@ static int ls_pcie_host_init(struct dw_pcie_rp *pp)
>   return 0;
>  }
>  
> +static void ls1021a_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
> +{
> + struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> + struct ls_pcie *pcie = to_ls_pcie(pci);
> + u32 val;
> +
> + if (!pcie->scfg) {
> + dev_dbg(pcie->pci->dev, "SYSCFG is NULL\n");
> + return;
> + }
> +
> + /* Send Turn_off message */
> + regmap_read(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), );
> + val |= PMXMTTURNOFF;
> + regmap_write(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), val);
> +
> + /* There are not register to check ACK, so wait 
> PCIE_PME_TO_L2_TIMEOUT_US */
> + mdelay(PCIE_PME_TO_L2_TIMEOUT_US/1000);
> +
> + /* Clear Turn_off message */
> + regmap_read(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), );
> + val &= ~PMXMTTURNOFF;
> + regmap_write(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), val);
> +}
> +
> +static void ls1021a_pcie_exit_from_l2(struct dw_pcie_rp *pp)
> +{
> + struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> + struct ls_pcie *pcie = to_ls_pcie(pci);
> + u32 val;
> +
> + regmap_read(pcie->scfg, SCFG_PEXSFTRSTCR, );
> + val |= PEXSR(pcie->index);
> + regmap_write(pcie->scfg, SCFG_PEXSFTRSTCR, val);
> +
> + regmap_read(pcie->scfg, SCFG_PEXSFTRSTCR, );
> + val &= ~PEXSR(pcie->index);
> + regmap_write(pcie->scfg, SCFG_PEXSFTRSTCR, val);
> +}
> +
> +static int ls1021a_pcie_host_init(struct dw_pcie_rp *pp)
> +{
> + struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> + struct ls_pcie *pcie = to_ls_pcie(pci);
> + struct device *dev = pcie->pci->dev;
> + u32 index[2];
> + int ret;
> +
> + ret = ls_pcie_host_init(pp);
> + if (ret)
> + return ret;
> +
> + pcie->scfg = syscon_regmap_lookup_by_phandle(dev->of_node, 
> "fsl,pcie-scfg");
> + if (IS_ERR(pcie->scfg)) {
> + ret = PTR_ERR(pcie->scfg);
> + dev_err(dev, "No syscfg phandle specified\n");
> + pcie->scfg = NULL;
> + return ret;
> + }
> +
> + ret = of_property_read_u32_array(dev->of_node, "fsl,pcie-scfg", index, 
> 2);
> + if (ret) {
> + pcie->scfg = NULL;
> + return ret;
> + }
> +
> + pcie->index = index[1];
> +
> + return ret;
> +}
> +
>  static const struct dw_pcie_host_ops ls_pcie_host_ops = {
>   .host_init = ls_pcie_host_init,
>   .pme_turn_off = ls_pcie_send_turnoff_msg,
>  };
>  
> +static const struct dw_pcie_host_ops ls1021a_pcie_host_ops = {
> + .host_init = ls1021a_pcie_host_init,
> + .pme_turn_off = ls1021a_pcie_send_turnoff_msg,
> +};
> +
>  static const struct ls_pcie_drvdata ls1021a_drvdata = {
> - .pm_support = false,
> + .pm_support = true,
> + .ops = _pcie_host_ops,
> + .exit_from_l2 = ls1021a_pcie_exit_from_l2,
>  };
>  
>  static const struct ls_pcie_drvdata layerscape_drvdata = {
> -- 
> 2.34.1
> 


[PATCH v3 1/1] PCI: layerscape-ep: set 64-bit DMA mask

2023-09-26 Thread Frank Li
From: Guanhua Gao 

Set DMA mask and coherent DMA mask to enable 64-bit addressing.

Signed-off-by: Guanhua Gao 
Signed-off-by: Hou Zhiqiang 
Signed-off-by: Frank Li 
---

Notes:
change from v2 to v3
- remove check return value of dma_set_mask_and_coherent. 64bit mask always
return success.
- remove redundate comments
change from v1 to v2
- Remove 32bit DMA mask set.

 drivers/pci/controller/dwc/pci-layerscape-ep.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index de4c1758a6c3..2c2c9aaa8700 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -249,6 +249,8 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
 
pcie->big_endian = of_property_read_bool(dev->of_node, "big-endian");
 
+   dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
+
platform_set_drvdata(pdev, pcie);
 
ret = dw_pcie_ep_init(>ep);
-- 
2.34.1



Re: [PATCH v2 1/1] PCI: layerscape-ep: set 64-bit DMA mask

2023-09-26 Thread Frank Li
On Tue, Sep 26, 2023 at 12:27:32AM -0700, Christoph Hellwig wrote:
> > +   /* set 64-bit DMA mask and coherent DMA mask */
> > +   ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
> 
> The comment is a bit silly :)
> 
> > +   if (ret)
> > +   return ret;
> 
> Also no need to check the return value when setting a 64-bit mask,
> but I guess it desn't hurt here.
> 

You are right, let me remove check.


[PATCH v2 1/1] PCI: layerscape-ep: set 64-bit DMA mask

2023-09-21 Thread Frank Li
From: Guanhua Gao 

Set DMA mask and coherent DMA mask to enable 64-bit addressing.

Signed-off-by: Guanhua Gao 
Signed-off-by: Hou Zhiqiang 
Signed-off-by: Frank Li 
---

Notes:
change from v1 to v2
- Remove 32bit DMA mask set.

 drivers/pci/controller/dwc/pci-layerscape-ep.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index de4c1758a6c33..026bf08611e13 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -249,6 +249,11 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
 
pcie->big_endian = of_property_read_bool(dev->of_node, "big-endian");
 
+   /* set 64-bit DMA mask and coherent DMA mask */
+   ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
+   if (ret)
+   return ret;
+
platform_set_drvdata(pdev, pcie);
 
ret = dw_pcie_ep_init(>ep);
-- 
2.34.1



Re: [PATCH 1/1] PCI: layerscape-ep: set 64-bit DMA mask

2023-09-21 Thread Frank Li
On Thu, Sep 21, 2023 at 10:04:31PM +0200, Christophe JAILLET wrote:
> Le 21/09/2023 à 20:35, Frank Li a écrit :
> > On Thu, Sep 21, 2023 at 07:59:51PM +0200, Christophe JAILLET wrote:
> > > Le 21/09/2023 à 17:37, Frank Li a écrit :
> > > > From: Guanhua Gao 
> > > > 
> > > > Set DMA mask and coherent DMA mask to enable 64-bit addressing.
> > > > 
> > > > Signed-off-by: Guanhua Gao 
> > > > Signed-off-by: Hou Zhiqiang 
> > > > Signed-off-by: Frank Li 
> > > > ---
> > > >drivers/pci/controller/dwc/pci-layerscape-ep.c | 5 +
> > > >1 file changed, 5 insertions(+)
> > > > 
> > > > diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
> > > > b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > > > index de4c1758a6c33..6fd0dea38a32c 100644
> > > > --- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > > > +++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > > > @@ -249,6 +249,11 @@ static int __init ls_pcie_ep_probe(struct 
> > > > platform_device *pdev)
> > > > pcie->big_endian = of_property_read_bool(dev->of_node, 
> > > > "big-endian");
> > > > +   /* set 64-bit DMA mask and coherent DMA mask */
> > > > +   if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)))
> > > > +   if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)))
> > > 
> > > As stated in [1], dma_set_mask() with a 64-bit mask will never
> > > fail if dev->dma_mask is non-NULL.
> > > 
> > > So, if it fails, the 32 bits case will also fail for the same reason.
> > > There is no need for the 2nd test.
> > > 
> > > 
> > > See [1] for Christoph Hellwig comment about it.
> > 
> > I don't think it is true. the below is dma_set_mask()'s implementation
> 
> I'll try to recollect a more detailled explanation from Christoph.
> 
> I also checked all paths some times ago, and the conclusion was that if
> dma_set_mask(64) failed, dma_set_mask(32) would fail for the exact same
> reasons.
> 
> I'll try to find the corresponding mail and come back to you.

I go through iommu driver and code carefully. You are right.
The dma_supported() actual means iommu require minimized dma capatiblity.

It is quite miss leading. There are many codes in driver like these pattern. 

A example: 
static int sba_dma_supported( struct device *dev, u64 mask)()
{
...
 * check if mask is >= than the current max IO Virt Address 

 * The max IO Virt address will *always* < 30 bits. 

 */ 

return((int)(mask >= (ioc->ibase - 1 +  

(ioc->pdir_size / sizeof(u64) * IOVP_SIZE) )));
...
}

1 means supported. 0 means unsupported. 

So dma_set_mask(64) is enough. Let me send new patch.

Frank


> 
> I don't thing that implementation details have changed since that times, so
> the conclusion should still be valid.
> 
> Adding Christoph in cc, if he wants to give another look at it, or if he
> beats me finding the 1 or 2 years old mails.
> 
> CJ
> 
> > 
> > int dma_set_mask(struct device *dev, u64 mask)
> > {
> > /*
> >  * Truncate the mask to the actually supported dma_addr_t width to
> >  * avoid generating unsupportable addresses.
> >  */
> > mask = (dma_addr_t)mask;
> > 
> > if (!dev->dma_mask || !dma_supported(dev, mask))
> > ^^^
> > return -EIO;
> > 
> > arch_dma_set_mask(dev, mask);
> > *dev->dma_mask = mask;
> > return 0;
> > }
> > 
> > dma_supported() may return failiure.
> > 
> > static int dma_supported(struct device *dev, u64 mask)
> > {
> > const struct dma_map_ops *ops = get_dma_ops(dev);
> > 
> > /*
> >  * ->dma_supported sets the bypass flag, so we must always call
> >  * into the method here unless the device is truly direct mapped.
> >  */
> > if (!ops)
> > return dma_direct_supported(dev, mask);
> > if (!ops->dma_supported)
> > return 1;
> > return ops->dma_supported(dev, mask);
> >  ^^
> > DMA driver or IOMMU driver may return failure.
> > }
> > 
> > Frank
> > 
> > > 
> > > CJ
> > > 
> > > 
> > > [1]: https://lkml.org/lkml/2021/6/7/398
> > > 
> > > > +   return -EIO;
> > > > +
> > > > platform_set_drvdata(pdev, pcie);
> > > > ret = dw_pcie_ep_init(>ep);
> > > 
> > 
> 


Re: [PATCH 1/1] PCI: layerscape-ep: set 64-bit DMA mask

2023-09-21 Thread Frank Li
On Thu, Sep 21, 2023 at 07:59:51PM +0200, Christophe JAILLET wrote:
> Le 21/09/2023 à 17:37, Frank Li a écrit :
> > From: Guanhua Gao 
> > 
> > Set DMA mask and coherent DMA mask to enable 64-bit addressing.
> > 
> > Signed-off-by: Guanhua Gao 
> > Signed-off-by: Hou Zhiqiang 
> > Signed-off-by: Frank Li 
> > ---
> >   drivers/pci/controller/dwc/pci-layerscape-ep.c | 5 +
> >   1 file changed, 5 insertions(+)
> > 
> > diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
> > b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > index de4c1758a6c33..6fd0dea38a32c 100644
> > --- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > +++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > @@ -249,6 +249,11 @@ static int __init ls_pcie_ep_probe(struct 
> > platform_device *pdev)
> > pcie->big_endian = of_property_read_bool(dev->of_node, "big-endian");
> > +   /* set 64-bit DMA mask and coherent DMA mask */
> > +   if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)))
> > +   if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)))
> 
> As stated in [1], dma_set_mask() with a 64-bit mask will never
> fail if dev->dma_mask is non-NULL.
> 
> So, if it fails, the 32 bits case will also fail for the same reason.
> There is no need for the 2nd test.
> 
> 
> See [1] for Christoph Hellwig comment about it.

I don't think it is true. the below is dma_set_mask()'s implementation

int dma_set_mask(struct device *dev, u64 mask)
{
/*
 * Truncate the mask to the actually supported dma_addr_t width to
 * avoid generating unsupportable addresses.
 */
mask = (dma_addr_t)mask;

if (!dev->dma_mask || !dma_supported(dev, mask))
^^^
return -EIO;

arch_dma_set_mask(dev, mask);
*dev->dma_mask = mask;
return 0;
}

dma_supported() may return failiure.

static int dma_supported(struct device *dev, u64 mask)
{
const struct dma_map_ops *ops = get_dma_ops(dev);

/*
 * ->dma_supported sets the bypass flag, so we must always call
 * into the method here unless the device is truly direct mapped.
 */
if (!ops)
return dma_direct_supported(dev, mask);
if (!ops->dma_supported)
return 1;
return ops->dma_supported(dev, mask);
^^
DMA driver or IOMMU driver may return failure.
}

 
Frank

> 
> CJ
> 
> 
> [1]: https://lkml.org/lkml/2021/6/7/398
> 
> > +   return -EIO;
> > +
> > platform_set_drvdata(pdev, pcie);
> > ret = dw_pcie_ep_init(>ep);
> 


[PATCH 1/1] PCI: layerscape-ep: set 64-bit DMA mask

2023-09-21 Thread Frank Li
From: Guanhua Gao 

Set DMA mask and coherent DMA mask to enable 64-bit addressing.

Signed-off-by: Guanhua Gao 
Signed-off-by: Hou Zhiqiang 
Signed-off-by: Frank Li 
---
 drivers/pci/controller/dwc/pci-layerscape-ep.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index de4c1758a6c33..6fd0dea38a32c 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -249,6 +249,11 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
 
pcie->big_endian = of_property_read_bool(dev->of_node, "big-endian");
 
+   /* set 64-bit DMA mask and coherent DMA mask */
+   if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)))
+   if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)))
+   return -EIO;
+
platform_set_drvdata(pdev, pcie);
 
ret = dw_pcie_ep_init(>ep);
-- 
2.34.1



[PATCH 3/3] PCI: layerscape: add suspend/resume for ls1043a

2023-09-15 Thread Frank Li
ls1043a add suspend/resume support.

Signed-off-by: Frank Li 
---
 drivers/pci/controller/dwc/pci-layerscape.c | 91 -
 1 file changed, 90 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index bc5a8ff1a26ce..debabb9bb41f4 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -41,10 +41,20 @@
 #define SCFG_PEXSFTRSTCR   0x190
 #define PEXSR(idx) BIT(idx)
 
+/* LS1043A PEX PME control register */
+#define SCFG_PEXPMECR  0x144
+#define PEXPME(idx)BIT(31 - (idx) * 4)
+
+/* LS1043A PEX LUT debug register */
+#define LS_PCIE_LDBG   0x7fc
+#define LDBG_SRBIT(30)
+#define LDBG_WEBIT(31)
+
 #define PCIE_IATU_NUM  6
 
 struct ls_pcie_drvdata {
const u32 pf_off;
+   const u32 lut_off;
const struct dw_pcie_host_ops *ops;
void (*exit_from_l2)(struct dw_pcie_rp *pp);
bool pm_support;
@@ -54,6 +64,7 @@ struct ls_pcie {
struct dw_pcie *pci;
const struct ls_pcie_drvdata *drvdata;
void __iomem *pf_base;
+   void __iomem *lut_base;
struct regmap *scfg;
int index;
bool big_endian;
@@ -116,6 +127,23 @@ static void ls_pcie_pf_writel(struct ls_pcie *pcie, u32 
off, u32 val)
iowrite32(val, pcie->pf_base + off);
 }
 
+static u32 ls_pcie_lut_readl(struct ls_pcie *pcie, u32 off)
+{
+   if (pcie->big_endian)
+   return ioread32be(pcie->lut_base + off);
+
+   return ioread32(pcie->lut_base + off);
+}
+
+static void ls_pcie_lut_writel(struct ls_pcie *pcie, u32 off, u32 val)
+{
+   if (pcie->big_endian)
+   iowrite32be(val, pcie->lut_base + off);
+   else
+   iowrite32(val, pcie->lut_base + off);
+}
+
+
 static void ls_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
 {
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
@@ -249,6 +277,54 @@ static int ls1021a_pcie_host_init(struct dw_pcie_rp *pp)
return ret;
 }
 
+static void ls1043a_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+   struct ls_pcie *pcie = to_ls_pcie(pci);
+   u32 val;
+
+   if (!pcie->scfg) {
+   dev_dbg(pcie->pci->dev, "SYSCFG is NULL\n");
+   return;
+   }
+
+   /* Send Turn_off message */
+   regmap_read(pcie->scfg, SCFG_PEXPMECR, );
+   val |= PEXPME(pcie->index);
+   regmap_write(pcie->scfg, SCFG_PEXPMECR, val);
+
+   /* There are not register to check ACK, so wait 
PCIE_PME_TO_L2_TIMEOUT_US */
+   mdelay(PCIE_PME_TO_L2_TIMEOUT_US/1000);
+
+   /* Clear Turn_off message */
+   regmap_read(pcie->scfg, SCFG_PEXPMECR, );
+   val &= ~PEXPME(pcie->index);
+   regmap_write(pcie->scfg, SCFG_PEXPMECR, val);
+}
+
+static void ls1043a_pcie_exit_from_l2(struct dw_pcie_rp *pp)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+   struct ls_pcie *pcie = to_ls_pcie(pci);
+   u32 val;
+
+   val = ls_pcie_lut_readl(pcie, LS_PCIE_LDBG);
+   val |= LDBG_WE;
+   ls_pcie_lut_writel(pcie, LS_PCIE_LDBG, val);
+
+   val = ls_pcie_lut_readl(pcie, LS_PCIE_LDBG);
+   val |= LDBG_SR;
+   ls_pcie_lut_writel(pcie, LS_PCIE_LDBG, val);
+
+   val = ls_pcie_lut_readl(pcie, LS_PCIE_LDBG);
+   val &= ~LDBG_SR;
+   ls_pcie_lut_writel(pcie, LS_PCIE_LDBG, val);
+
+   val = ls_pcie_lut_readl(pcie, LS_PCIE_LDBG);
+   val &= ~LDBG_WE;
+   ls_pcie_lut_writel(pcie, LS_PCIE_LDBG, val);
+}
+
 static const struct dw_pcie_host_ops ls_pcie_host_ops = {
.host_init = ls_pcie_host_init,
.pme_turn_off = ls_pcie_send_turnoff_msg,
@@ -265,6 +341,18 @@ static const struct ls_pcie_drvdata ls1021a_drvdata = {
.exit_from_l2 = ls1021a_pcie_exit_from_l2,
 };
 
+static const struct dw_pcie_host_ops ls1043a_pcie_host_ops = {
+   .host_init = ls1021a_pcie_host_init, /* the same as ls1021 */
+   .pme_turn_off = ls1043a_pcie_send_turnoff_msg,
+};
+
+static const struct ls_pcie_drvdata ls1043a_drvdata = {
+   .lut_off = 0x1,
+   .pm_support = true,
+   .ops = _pcie_host_ops,
+   .exit_from_l2 = ls1043a_pcie_exit_from_l2,
+};
+
 static const struct ls_pcie_drvdata layerscape_drvdata = {
.pf_off = 0xc,
.pm_support = true,
@@ -275,7 +363,7 @@ static const struct of_device_id ls_pcie_of_match[] = {
{ .compatible = "fsl,ls1012a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls1021a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls1028a-pcie", .data = _drvdata },
-   { .compatible = "fsl,ls1043a-pcie", .data = _drvdata },
+   { .compatible = "fsl,ls1043a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls1046a-pc

[PATCH 2/3] PCI: layerscape: add suspend/resume for ls1021a

2023-09-15 Thread Frank Li
ls1021a add suspend/resume support.

Signed-off-by: Frank Li 
---
 drivers/pci/controller/dwc/pci-layerscape.c | 88 -
 1 file changed, 87 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index 20c48c06e2248..bc5a8ff1a26ce 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -35,6 +35,12 @@
 #define PF_MCR_PTOMR   BIT(0)
 #define PF_MCR_EXL2S   BIT(1)
 
+/* LS1021A PEXn PM Write Control Register */
+#define SCFG_PEXPMWRCR(idx)(0x5c + (idx) * 0x64)
+#define PMXMTTURNOFF   BIT(31)
+#define SCFG_PEXSFTRSTCR   0x190
+#define PEXSR(idx) BIT(idx)
+
 #define PCIE_IATU_NUM  6
 
 struct ls_pcie_drvdata {
@@ -48,6 +54,8 @@ struct ls_pcie {
struct dw_pcie *pci;
const struct ls_pcie_drvdata *drvdata;
void __iomem *pf_base;
+   struct regmap *scfg;
+   int index;
bool big_endian;
 };
 
@@ -170,13 +178,91 @@ static int ls_pcie_host_init(struct dw_pcie_rp *pp)
return 0;
 }
 
+static void ls1021a_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+   struct ls_pcie *pcie = to_ls_pcie(pci);
+   u32 val;
+
+   if (!pcie->scfg) {
+   dev_dbg(pcie->pci->dev, "SYSCFG is NULL\n");
+   return;
+   }
+
+   /* Send Turn_off message */
+   regmap_read(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), );
+   val |= PMXMTTURNOFF;
+   regmap_write(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), val);
+
+   /* There are not register to check ACK, so wait 
PCIE_PME_TO_L2_TIMEOUT_US */
+   mdelay(PCIE_PME_TO_L2_TIMEOUT_US/1000);
+
+   /* Clear Turn_off message */
+   regmap_read(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), );
+   val &= ~PMXMTTURNOFF;
+   regmap_write(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), val);
+}
+
+static void ls1021a_pcie_exit_from_l2(struct dw_pcie_rp *pp)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+   struct ls_pcie *pcie = to_ls_pcie(pci);
+   u32 val;
+
+   regmap_read(pcie->scfg, SCFG_PEXSFTRSTCR, );
+   val |= PEXSR(pcie->index);
+   regmap_write(pcie->scfg, SCFG_PEXSFTRSTCR, val);
+
+   regmap_read(pcie->scfg, SCFG_PEXSFTRSTCR, );
+   val &= ~PEXSR(pcie->index);
+   regmap_write(pcie->scfg, SCFG_PEXSFTRSTCR, val);
+}
+
+static int ls1021a_pcie_host_init(struct dw_pcie_rp *pp)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+   struct ls_pcie *pcie = to_ls_pcie(pci);
+   struct device *dev = pcie->pci->dev;
+   u32 index[2];
+   int ret;
+
+   ret = ls_pcie_host_init(pp);
+   if (ret)
+   return ret;
+
+   pcie->scfg = syscon_regmap_lookup_by_phandle(dev->of_node, 
"fsl,pcie-scfg");
+   if (IS_ERR(pcie->scfg)) {
+   ret = PTR_ERR(pcie->scfg);
+   dev_err(dev, "No syscfg phandle specified\n");
+   pcie->scfg = NULL;
+   return ret;
+   }
+
+   ret = of_property_read_u32_array(dev->of_node, "fsl,pcie-scfg", index, 
2);
+   if (ret) {
+   pcie->scfg = NULL;
+   return ret;
+   }
+
+   pcie->index = index[1];
+
+   return ret;
+}
+
 static const struct dw_pcie_host_ops ls_pcie_host_ops = {
.host_init = ls_pcie_host_init,
.pme_turn_off = ls_pcie_send_turnoff_msg,
 };
 
+static const struct dw_pcie_host_ops ls1021a_pcie_host_ops = {
+   .host_init = ls1021a_pcie_host_init,
+   .pme_turn_off = ls1021a_pcie_send_turnoff_msg,
+};
+
 static const struct ls_pcie_drvdata ls1021a_drvdata = {
-   .pm_support = false,
+   .pm_support = true,
+   .ops = _pcie_host_ops,
+   .exit_from_l2 = ls1021a_pcie_exit_from_l2,
 };
 
 static const struct ls_pcie_drvdata layerscape_drvdata = {
-- 
2.34.1



[PATCH 1/3] PCI: layerscape: add function pointer for exit_from_l2()

2023-09-15 Thread Frank Li
Difference layerscape chip have not difference exit_from_l2() method.
Using function pointer for ls1028. It prepare for other layerscape
suspend/resume support.

Signed-off-by: Frank Li 
---
 drivers/pci/controller/dwc/pci-layerscape.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index b931d597656f6..20c48c06e2248 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -39,6 +39,8 @@
 
 struct ls_pcie_drvdata {
const u32 pf_off;
+   const struct dw_pcie_host_ops *ops;
+   void (*exit_from_l2)(struct dw_pcie_rp *pp);
bool pm_support;
 };
 
@@ -180,6 +182,7 @@ static const struct ls_pcie_drvdata ls1021a_drvdata = {
 static const struct ls_pcie_drvdata layerscape_drvdata = {
.pf_off = 0xc,
.pm_support = true,
+   .exit_from_l2 = ls_pcie_exit_from_l2,
 };
 
 static const struct of_device_id ls_pcie_of_match[] = {
@@ -213,7 +216,7 @@ static int ls_pcie_probe(struct platform_device *pdev)
pcie->drvdata = of_device_get_match_data(dev);
 
pci->dev = dev;
-   pci->pp.ops = _pcie_host_ops;
+   pci->pp.ops = pcie->drvdata->ops ? pcie->drvdata->ops : 
_pcie_host_ops;
 
pcie->pci = pci;
 
@@ -251,7 +254,7 @@ static int ls_pcie_resume_noirq(struct device *dev)
if (!pcie->drvdata->pm_support)
return 0;
 
-   ls_pcie_exit_from_l2(>pci->pp);
+   pcie->drvdata->exit_from_l2(>pci->pp);
 
return dw_pcie_resume_noirq(pcie->pci);
 }
-- 
2.34.1



Re: [PATCH v4 1/2] PCI: layerscape: Add support for Link down notification

2023-08-23 Thread Frank Li
On Wed, Aug 16, 2023 at 11:53:16AM -0400, Frank Li wrote:
> On Mon, Jul 31, 2023 at 11:06:31AM -0400, Frank Li wrote:
> > On Thu, Jul 20, 2023 at 09:58:33AM -0400, Frank Li wrote:
> > > Add support to pass Link down notification to Endpoint function driver
> > > so that the LINK_DOWN event can be processed by the function.
> > > 
> > > Acked-by: Manivannan Sadhasivam 
> > > Signed-off-by: Frank Li 
> > > ---
> > 
> > @Lorenzo
> > 
> > Could you please consider pick both patches?
> > Manivannan already reviewed and only impact layerscape.
> 
> @lorenzo:
>   ping
> 
> > 
> > Frank

@lorenzo
ping

Frank

> > 
> > > Change from v2 to v4
> > >  - none
> > > Change from v1 to v2
> > > 
> > >  drivers/pci/controller/dwc/pci-layerscape-ep.c | 1 +
> > >  1 file changed, 1 insertion(+)
> > > 
> > > diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
> > > b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > > index de4c1758a6c3..e0969ff2ddf7 100644
> > > --- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > > +++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > > @@ -89,6 +89,7 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, 
> > > void *dev_id)
> > >   dev_dbg(pci->dev, "Link up\n");
> > >   } else if (val & PEX_PF0_PME_MES_DR_LDD) {
> > >   dev_dbg(pci->dev, "Link down\n");
> > > + pci_epc_linkdown(pci->ep.epc);
> > >   } else if (val & PEX_PF0_PME_MES_DR_HRD) {
> > >   dev_dbg(pci->dev, "Hot reset\n");
> > >   }
> > > -- 
> > > 2.34.1
> > > 


Re: [PATCH v4 1/2] PCI: layerscape: Add support for Link down notification

2023-08-16 Thread Frank Li
On Mon, Jul 31, 2023 at 11:06:31AM -0400, Frank Li wrote:
> On Thu, Jul 20, 2023 at 09:58:33AM -0400, Frank Li wrote:
> > Add support to pass Link down notification to Endpoint function driver
> > so that the LINK_DOWN event can be processed by the function.
> > 
> > Acked-by: Manivannan Sadhasivam 
> > Signed-off-by: Frank Li 
> > ---
> 
> @Lorenzo
> 
> Could you please consider pick both patches?
> Manivannan already reviewed and only impact layerscape.

@lorenzo:
ping

> 
> Frank
> 
> > Change from v2 to v4
> >  - none
> > Change from v1 to v2
> > 
> >  drivers/pci/controller/dwc/pci-layerscape-ep.c | 1 +
> >  1 file changed, 1 insertion(+)
> > 
> > diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
> > b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > index de4c1758a6c3..e0969ff2ddf7 100644
> > --- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > +++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > @@ -89,6 +89,7 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, void 
> > *dev_id)
> > dev_dbg(pci->dev, "Link up\n");
> > } else if (val & PEX_PF0_PME_MES_DR_LDD) {
> > dev_dbg(pci->dev, "Link down\n");
> > +   pci_epc_linkdown(pci->ep.epc);
> > } else if (val & PEX_PF0_PME_MES_DR_HRD) {
> > dev_dbg(pci->dev, "Hot reset\n");
> > }
> > -- 
> > 2.34.1
> > 


Re: [PATCH v4 1/2] PCI: layerscape: Add support for Link down notification

2023-07-31 Thread Frank Li
On Thu, Jul 20, 2023 at 09:58:33AM -0400, Frank Li wrote:
> Add support to pass Link down notification to Endpoint function driver
> so that the LINK_DOWN event can be processed by the function.
> 
> Acked-by: Manivannan Sadhasivam 
> Signed-off-by: Frank Li 
> ---

@Lorenzo

Could you please consider pick both patches?
Manivannan already reviewed and only impact layerscape.

Frank

> Change from v2 to v4
>  - none
> Change from v1 to v2
> 
>  drivers/pci/controller/dwc/pci-layerscape-ep.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
> b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> index de4c1758a6c3..e0969ff2ddf7 100644
> --- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
> +++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> @@ -89,6 +89,7 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, void 
> *dev_id)
>   dev_dbg(pci->dev, "Link up\n");
>   } else if (val & PEX_PF0_PME_MES_DR_LDD) {
>   dev_dbg(pci->dev, "Link down\n");
> + pci_epc_linkdown(pci->ep.epc);
>   } else if (val & PEX_PF0_PME_MES_DR_HRD) {
>   dev_dbg(pci->dev, "Hot reset\n");
>   }
> -- 
> 2.34.1
> 


[PATCH v4 2/2] PCI: layerscape: Add the workaround for lost link capabilities during reset.

2023-07-20 Thread Frank Li
From: Xiaowei Bao 

A workaround for the issue where the PCI Express Endpoint (EP) controller
loses the values of the Maximum Link Width and Supported Link Speed from
the Link Capabilities Register, which initially configured by the Reset
Configuration Word (RCW) during a link-down or hot reset event.

Fixes: a805770d8a22 ("PCI: layerscape: Add EP mode support")
Acked-by: Manivannan Sadhasivam 
Signed-off-by: Xiaowei Bao 
Signed-off-by: Hou Zhiqiang 
Signed-off-by: Frank Li 
---
change from v3 to v4
 - fix wrong commit a debug code, change pr_err to pr_dbg
change from v2 to v3
 - fix subject typo capabilities
change from v1 to v2:
 - add comments at restore register
 - add fixes tag
 - dw_pcie_writew_dbi to dw_pcie_writel_dbi

 .../pci/controller/dwc/pci-layerscape-ep.c| 19 +++
 1 file changed, 19 insertions(+)

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index e0969ff2ddf7..b1faf41a2fae 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -45,6 +45,7 @@ struct ls_pcie_ep {
struct pci_epc_features *ls_epc;
const struct ls_pcie_ep_drvdata *drvdata;
int irq;
+   u32 lnkcap;
boolbig_endian;
 };
 
@@ -73,6 +74,7 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, void 
*dev_id)
struct ls_pcie_ep *pcie = dev_id;
struct dw_pcie *pci = pcie->pci;
u32 val, cfg;
+   u8 offset;
 
val = ls_lut_readl(pcie, PEX_PF0_PME_MES_DR);
ls_lut_writel(pcie, PEX_PF0_PME_MES_DR, val);
@@ -81,6 +83,19 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, void 
*dev_id)
return IRQ_NONE;
 
if (val & PEX_PF0_PME_MES_DR_LUD) {
+
+   offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+
+   /*
+* The values of the Maximum Link Width and Supported Link
+* Speed from the Link Capabilities Register will be lost
+* during link down or hot reset. Restore initial value
+* that configured by the Reset Configuration Word (RCW).
+*/
+   dw_pcie_dbi_ro_wr_en(pci);
+   dw_pcie_writel_dbi(pci, offset + PCI_EXP_LNKCAP, pcie->lnkcap);
+   dw_pcie_dbi_ro_wr_dis(pci);
+
cfg = ls_lut_readl(pcie, PEX_PF0_CONFIG);
cfg |= PEX_PF0_CFG_READY;
ls_lut_writel(pcie, PEX_PF0_CONFIG, cfg);
@@ -216,6 +231,7 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
struct ls_pcie_ep *pcie;
struct pci_epc_features *ls_epc;
struct resource *dbi_base;
+   u8 offset;
int ret;
 
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
@@ -252,6 +268,9 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
 
platform_set_drvdata(pdev, pcie);
 
+   offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+   pcie->lnkcap = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP);
+
ret = dw_pcie_ep_init(>ep);
if (ret)
return ret;
-- 
2.34.1



[PATCH v4 1/2] PCI: layerscape: Add support for Link down notification

2023-07-20 Thread Frank Li
Add support to pass Link down notification to Endpoint function driver
so that the LINK_DOWN event can be processed by the function.

Acked-by: Manivannan Sadhasivam 
Signed-off-by: Frank Li 
---
Change from v2 to v4
 - none
Change from v1 to v2

 drivers/pci/controller/dwc/pci-layerscape-ep.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index de4c1758a6c3..e0969ff2ddf7 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -89,6 +89,7 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, void 
*dev_id)
dev_dbg(pci->dev, "Link up\n");
} else if (val & PEX_PF0_PME_MES_DR_LDD) {
dev_dbg(pci->dev, "Link down\n");
+   pci_epc_linkdown(pci->ep.epc);
} else if (val & PEX_PF0_PME_MES_DR_HRD) {
dev_dbg(pci->dev, "Hot reset\n");
}
-- 
2.34.1



Re: [PATCH v3 2/2] PCI: layerscape: Add the workaround for lost link capabilities during reset.

2023-07-19 Thread Frank Li
On Wed, Jul 19, 2023 at 11:57:07AM -0400, Frank Li wrote:
> From: Xiaowei Bao 
> 
> A workaround for the issue where the PCI Express Endpoint (EP) controller
> loses the values of the Maximum Link Width and Supported Link Speed from
> the Link Capabilities Register, which initially configured by the Reset
> Configuration Word (RCW) during a link-down or hot reset event.
> 
> Fixes: a805770d8a22 ("PCI: layerscape: Add EP mode support")
> Acked-by: Manivannan Sadhasivam 
> Signed-off-by: Xiaowei Bao 
> Signed-off-by: Hou Zhiqiang 
> Signed-off-by: Frank Li 
> ---
> change from v2 to v3
>  - fix subject typo capabilities
> change from v1 to v2:
>  - add comments at restore register
>  - add fixes tag
>  - dw_pcie_writew_dbi to dw_pcie_writel_dbi
> 
>  .../pci/controller/dwc/pci-layerscape-ep.c| 21 ++-
>  1 file changed, 20 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
> b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> index e0969ff2ddf7..39dbd911c3f8 100644
> --- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
> +++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> @@ -45,6 +45,7 @@ struct ls_pcie_ep {
>   struct pci_epc_features *ls_epc;
>   const struct ls_pcie_ep_drvdata *drvdata;
>   int irq;
> + u32 lnkcap;
>   boolbig_endian;
>  };
>  
> @@ -73,6 +74,7 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, void 
> *dev_id)
>   struct ls_pcie_ep *pcie = dev_id;
>   struct dw_pcie *pci = pcie->pci;
>   u32 val, cfg;
> + u8 offset;
>  
>   val = ls_lut_readl(pcie, PEX_PF0_PME_MES_DR);
>   ls_lut_writel(pcie, PEX_PF0_PME_MES_DR, val);
> @@ -81,12 +83,25 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, void 
> *dev_id)
>   return IRQ_NONE;
>  
>   if (val & PEX_PF0_PME_MES_DR_LUD) {
> +
> + offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
> +
> + /*
> +  * The values of the Maximum Link Width and Supported Link
> +  * Speed from the Link Capabilities Register will be lost
> +  * during link down or hot reset. Restore initial value
> +  * that configured by the Reset Configuration Word (RCW).
> +  */
> + dw_pcie_dbi_ro_wr_en(pci);
> + dw_pcie_writel_dbi(pci, offset + PCI_EXP_LNKCAP, pcie->lnkcap);
> + dw_pcie_dbi_ro_wr_dis(pci);
> +
>   cfg = ls_lut_readl(pcie, PEX_PF0_CONFIG);
>   cfg |= PEX_PF0_CFG_READY;
>   ls_lut_writel(pcie, PEX_PF0_CONFIG, cfg);
>   dw_pcie_ep_linkup(>ep);
>  
> - dev_dbg(pci->dev, "Link up\n");
> + dev_err(pci->dev, "Link up\n");

Sorry, Just found that. mistake merge a debug code.
It should be dev_dbg here, will send update patch soon

Frank

>   } else if (val & PEX_PF0_PME_MES_DR_LDD) {
>   dev_dbg(pci->dev, "Link down\n");
>   pci_epc_linkdown(pci->ep.epc);
> @@ -216,6 +231,7 @@ static int __init ls_pcie_ep_probe(struct platform_device 
> *pdev)
>   struct ls_pcie_ep *pcie;
>   struct pci_epc_features *ls_epc;
>   struct resource *dbi_base;
> + u8 offset;
>   int ret;
>  
>   pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
> @@ -252,6 +268,9 @@ static int __init ls_pcie_ep_probe(struct platform_device 
> *pdev)
>  
>   platform_set_drvdata(pdev, pcie);
>  
> + offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
> + pcie->lnkcap = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP);
> +
>   ret = dw_pcie_ep_init(>ep);
>   if (ret)
>   return ret;
> -- 
> 2.34.1
> 


Re: [v3 1/2] PCI: layerscape: Add support for Link down notification

2023-07-19 Thread Frank Li
On Wed, Jul 19, 2023 at 10:08:16PM +0200, Markus Elfring wrote:
> > Cover letter just annoise people here.
> 
> How do you think about advices from another information source?
> 
> See also:
> https://kernelnewbies.org/PatchSeries

"You may like to include a cover letter with your patch series."

Generally, I think cover letter will be needed only if it really
help reviewer to get main idea about patches. 

Such as my on going pathes(with cover letter):
  https://lore.kernel.org/imx/ZLglBiSz0meJm5os@lizhi-Precision-Tower-5810/T/#t

Similar case without(cover leter) and accepted.
 https://lore.kernel.org/imx/20230719063425.GE151430@dragon/T/#t

I don't think cover letter real help reviewer to review these two patches.

I more like to get "real problem"(such as comments about "typo").

It is just waste time to discuss if need add cover letter here.

Frank

> 
> Regards,
> Markus


Re: [PATCH v3 1/2] PCI: layerscape: Add support for Link down notification

2023-07-19 Thread Frank Li
On Wed, Jul 19, 2023 at 09:27:23PM +0200, Markus Elfring wrote:
> > Add support to pass …
> 
> Why did you omit a cover letter for the discussed patch series once more?

Your comments is 
"Will a cover letter become helpful also for the presented small patch series?"

According to my understand it is optional. I don't think cover letter will
help this case. Patch 1 and 2 is that independent at all. 

I sent these together just because easy to test once.

Maintainer can pick any one individually. 

Cover letter just annoise people here.

Frank


> 
> Do you care for consequences according to message threading?
> 
> Regards,
> Markus


[PATCH v3 2/2] PCI: layerscape: Add the workaround for lost link capabilities during reset.

2023-07-19 Thread Frank Li
From: Xiaowei Bao 

A workaround for the issue where the PCI Express Endpoint (EP) controller
loses the values of the Maximum Link Width and Supported Link Speed from
the Link Capabilities Register, which initially configured by the Reset
Configuration Word (RCW) during a link-down or hot reset event.

Fixes: a805770d8a22 ("PCI: layerscape: Add EP mode support")
Acked-by: Manivannan Sadhasivam 
Signed-off-by: Xiaowei Bao 
Signed-off-by: Hou Zhiqiang 
Signed-off-by: Frank Li 
---
change from v2 to v3
 - fix subject typo capabilities
change from v1 to v2:
 - add comments at restore register
 - add fixes tag
 - dw_pcie_writew_dbi to dw_pcie_writel_dbi

 .../pci/controller/dwc/pci-layerscape-ep.c| 21 ++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index e0969ff2ddf7..39dbd911c3f8 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -45,6 +45,7 @@ struct ls_pcie_ep {
struct pci_epc_features *ls_epc;
const struct ls_pcie_ep_drvdata *drvdata;
int irq;
+   u32 lnkcap;
boolbig_endian;
 };
 
@@ -73,6 +74,7 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, void 
*dev_id)
struct ls_pcie_ep *pcie = dev_id;
struct dw_pcie *pci = pcie->pci;
u32 val, cfg;
+   u8 offset;
 
val = ls_lut_readl(pcie, PEX_PF0_PME_MES_DR);
ls_lut_writel(pcie, PEX_PF0_PME_MES_DR, val);
@@ -81,12 +83,25 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, void 
*dev_id)
return IRQ_NONE;
 
if (val & PEX_PF0_PME_MES_DR_LUD) {
+
+   offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+
+   /*
+* The values of the Maximum Link Width and Supported Link
+* Speed from the Link Capabilities Register will be lost
+* during link down or hot reset. Restore initial value
+* that configured by the Reset Configuration Word (RCW).
+*/
+   dw_pcie_dbi_ro_wr_en(pci);
+   dw_pcie_writel_dbi(pci, offset + PCI_EXP_LNKCAP, pcie->lnkcap);
+   dw_pcie_dbi_ro_wr_dis(pci);
+
cfg = ls_lut_readl(pcie, PEX_PF0_CONFIG);
cfg |= PEX_PF0_CFG_READY;
ls_lut_writel(pcie, PEX_PF0_CONFIG, cfg);
dw_pcie_ep_linkup(>ep);
 
-   dev_dbg(pci->dev, "Link up\n");
+   dev_err(pci->dev, "Link up\n");
} else if (val & PEX_PF0_PME_MES_DR_LDD) {
dev_dbg(pci->dev, "Link down\n");
pci_epc_linkdown(pci->ep.epc);
@@ -216,6 +231,7 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
struct ls_pcie_ep *pcie;
struct pci_epc_features *ls_epc;
struct resource *dbi_base;
+   u8 offset;
int ret;
 
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
@@ -252,6 +268,9 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
 
platform_set_drvdata(pdev, pcie);
 
+   offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+   pcie->lnkcap = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP);
+
ret = dw_pcie_ep_init(>ep);
if (ret)
return ret;
-- 
2.34.1



[PATCH v3 1/2] PCI: layerscape: Add support for Link down notification

2023-07-19 Thread Frank Li
Add support to pass Link down notification to Endpoint function driver
so that the LINK_DOWN event can be processed by the function.

Acked-by: Manivannan Sadhasivam 
Signed-off-by: Frank Li 
---
Change from v2 to v3
 - none
Change from v1 to v2
 - move pci_epc_linkdown() after dev_dbg()

 drivers/pci/controller/dwc/pci-layerscape-ep.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index de4c1758a6c3..e0969ff2ddf7 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -89,6 +89,7 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, void 
*dev_id)
dev_dbg(pci->dev, "Link up\n");
} else if (val & PEX_PF0_PME_MES_DR_LDD) {
dev_dbg(pci->dev, "Link down\n");
+   pci_epc_linkdown(pci->ep.epc);
} else if (val & PEX_PF0_PME_MES_DR_HRD) {
dev_dbg(pci->dev, "Hot reset\n");
}
-- 
2.34.1



[PATCH v2 2/2] PCI: layerscape: Add the workaround for lost link capablities during reset

2023-07-18 Thread Frank Li
From: Xiaowei Bao 

A workaround for the issue where the PCI Express Endpoint (EP) controller
loses the values of the Maximum Link Width and Supported Link Speed from
the Link Capabilities Register, which initially configured by the Reset
Configuration Word (RCW) during a link-down or hot reset event.

Fixes: a805770d8a22 ("PCI: layerscape: Add EP mode support")
Signed-off-by: Xiaowei Bao 
Signed-off-by: Hou Zhiqiang 
Signed-off-by: Frank Li 
---
change from v1 to v2:
 - add comments at restore register
 - add fixes tag

 .../pci/controller/dwc/pci-layerscape-ep.c| 19 +++
 1 file changed, 19 insertions(+)

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index e0969ff2ddf7..b1faf41a2fae 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -45,6 +45,7 @@ struct ls_pcie_ep {
struct pci_epc_features *ls_epc;
const struct ls_pcie_ep_drvdata *drvdata;
int irq;
+   u32 lnkcap;
boolbig_endian;
 };
 
@@ -73,6 +74,7 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, void 
*dev_id)
struct ls_pcie_ep *pcie = dev_id;
struct dw_pcie *pci = pcie->pci;
u32 val, cfg;
+   u8 offset;
 
val = ls_lut_readl(pcie, PEX_PF0_PME_MES_DR);
ls_lut_writel(pcie, PEX_PF0_PME_MES_DR, val);
@@ -81,6 +83,19 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, void 
*dev_id)
return IRQ_NONE;
 
if (val & PEX_PF0_PME_MES_DR_LUD) {
+
+   offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+
+   /*
+* The values of the Maximum Link Width and Supported Link
+* Speed from the Link Capabilities Register will be lost
+* during link down or hot reset. Restore initial value
+* that configured by the Reset Configuration Word (RCW).
+*/
+   dw_pcie_dbi_ro_wr_en(pci);
+   dw_pcie_writel_dbi(pci, offset + PCI_EXP_LNKCAP, pcie->lnkcap);
+   dw_pcie_dbi_ro_wr_dis(pci);
+
cfg = ls_lut_readl(pcie, PEX_PF0_CONFIG);
cfg |= PEX_PF0_CFG_READY;
ls_lut_writel(pcie, PEX_PF0_CONFIG, cfg);
@@ -216,6 +231,7 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
struct ls_pcie_ep *pcie;
struct pci_epc_features *ls_epc;
struct resource *dbi_base;
+   u8 offset;
int ret;
 
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
@@ -252,6 +268,9 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
 
platform_set_drvdata(pdev, pcie);
 
+   offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+   pcie->lnkcap = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP);
+
ret = dw_pcie_ep_init(>ep);
if (ret)
return ret;
-- 
2.34.1



[PATCH v2 1/2] PCI: layerscape: Add support for Link down notification

2023-07-18 Thread Frank Li
Add support to pass Link down notification to Endpoint function driver
so that the LINK_DOWN event can be processed by the function.

Acked-by: Manivannan Sadhasivam 
Signed-off-by: Frank Li 
---
Change from v1 to v2
 - move pci_epc_linkdown() after dev_dbg()

 drivers/pci/controller/dwc/pci-layerscape-ep.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index de4c1758a6c3..e0969ff2ddf7 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -89,6 +89,7 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, void 
*dev_id)
dev_dbg(pci->dev, "Link up\n");
} else if (val & PEX_PF0_PME_MES_DR_LDD) {
dev_dbg(pci->dev, "Link down\n");
+   pci_epc_linkdown(pci->ep.epc);
} else if (val & PEX_PF0_PME_MES_DR_HRD) {
dev_dbg(pci->dev, "Hot reset\n");
}
-- 
2.34.1



Re: [PATCH 2/2] PCI: layerscape: Add the workaround for lost link capablities during reset

2023-07-17 Thread Frank Li
On Mon, Jul 17, 2023 at 09:29:10PM +0530, Manivannan Sadhasivam wrote:
> On Thu, Jun 15, 2023 at 12:41:12PM -0400, Frank Li wrote:
> > From: Xiaowei Bao 
> > 
> > A workaround for the issue where the PCI Express Endpoint (EP) controller
> > loses the values of the Maximum Link Width and Supported Link Speed from
> > the Link Capabilities Register, which initially configured by the Reset
> > Configuration Word (RCW) during a link-down or hot reset event.
> > 
> 
> If this fixes an issue, then there should be a Fixes tag.

It is not fixed a exist software issue, just workaround a hardwre errata.

> 
> > Signed-off-by: Xiaowei Bao 
> > Signed-off-by: Hou Zhiqiang 
> > Signed-off-by: Frank Li 
> > ---
> >  drivers/pci/controller/dwc/pci-layerscape-ep.c | 13 +
> >  1 file changed, 13 insertions(+)
> > 
> > diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
> > b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > index 4e4fdd1dfea7..2ef02d827eeb 100644
> > --- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > +++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > @@ -45,6 +45,7 @@ struct ls_pcie_ep {
> > struct pci_epc_features *ls_epc;
> > const struct ls_pcie_ep_drvdata *drvdata;
> > int irq;
> > +   u32 lnkcap;
> > boolbig_endian;
> >  };
> >  
> > @@ -73,6 +74,7 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, void 
> > *dev_id)
> > struct ls_pcie_ep *pcie = dev_id;
> > struct dw_pcie *pci = pcie->pci;
> > u32 val, cfg;
> > +   u8 offset;
> >  
> > val = ls_lut_readl(pcie, PEX_PF0_PME_MES_DR);
> > ls_lut_writel(pcie, PEX_PF0_PME_MES_DR, val);
> > @@ -81,6 +83,13 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, 
> > void *dev_id)
> > return IRQ_NONE;
> >  
> > if (val & PEX_PF0_PME_MES_DR_LUD) {
> > +
> 
> Please add a comment on why the LNKCAP is being restored here.
> 
> > +   offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
> > +
> > +   dw_pcie_dbi_ro_wr_en(pci);
> > +   dw_pcie_writew_dbi(pci, offset + PCI_EXP_LNKCAP, pcie->lnkcap);
> 
> lnkcap is a 32-bit variable, so you should use dw_pcie_writel_dbi().
> 
> - Mani
> 
> > +   dw_pcie_dbi_ro_wr_dis(pci);
> > +
> > cfg = ls_lut_readl(pcie, PEX_PF0_CONFIG);
> > cfg |= PEX_PF0_CFG_READY;
> > ls_lut_writel(pcie, PEX_PF0_CONFIG, cfg);
> > @@ -216,6 +225,7 @@ static int __init ls_pcie_ep_probe(struct 
> > platform_device *pdev)
> > struct ls_pcie_ep *pcie;
> > struct pci_epc_features *ls_epc;
> > struct resource *dbi_base;
> > +   u8 offset;
> > int ret;
> >  
> > pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
> > @@ -252,6 +262,9 @@ static int __init ls_pcie_ep_probe(struct 
> > platform_device *pdev)
> >  
> > platform_set_drvdata(pdev, pcie);
> >  
> > +   offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
> > +   pcie->lnkcap = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP);
> > +
> > ret = dw_pcie_ep_init(>ep);
> > if (ret)
> > return ret;
> > -- 
> > 2.34.1
> > 
> 
> -- 
> மணிவண்ணன் சதாசிவம்


Re: [PATCH 2/2] PCI: layerscape: Add the workaround for lost link capablities during reset

2023-07-17 Thread Frank Li
On Mon, Jul 17, 2023 at 08:45:14AM -0600, Rob Herring wrote:
> On Thu, Jun 15, 2023 at 10:41 AM Frank Li  wrote:
> >
> > From: Xiaowei Bao 
> >
> > A workaround for the issue where the PCI Express Endpoint (EP) controller
> > loses the values of the Maximum Link Width and Supported Link Speed from
> > the Link Capabilities Register, which initially configured by the Reset
> > Configuration Word (RCW) during a link-down or hot reset event.
> 
> What makes this Layerscape specific? Seems like something internal to DWC.

layerscape designed behavor is that LINK speed and width controled by RCW.
But design have been 'defect' when switch to dwc controller, may not
correct connect some wire. So provide an errata, ask software recover such
information when link up/down to align design spec.

For example, RCW config max link is 2lan, after link down/up, DWC reset
to max link to 4lan. So host side get a report, max link is 4 lan. 

It will not impact function, just information miss matched.

Frank

> 
> >
> > Signed-off-by: Xiaowei Bao 
> > Signed-off-by: Hou Zhiqiang 
> > Signed-off-by: Frank Li 
> > ---
> >  drivers/pci/controller/dwc/pci-layerscape-ep.c | 13 +
> >  1 file changed, 13 insertions(+)
> >
> > diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
> > b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > index 4e4fdd1dfea7..2ef02d827eeb 100644
> > --- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > +++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > @@ -45,6 +45,7 @@ struct ls_pcie_ep {
> > struct pci_epc_features *ls_epc;
> > const struct ls_pcie_ep_drvdata *drvdata;
> > int irq;
> > +   u32 lnkcap;
> > boolbig_endian;
> >  };
> >
> > @@ -73,6 +74,7 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, void 
> > *dev_id)
> > struct ls_pcie_ep *pcie = dev_id;
> > struct dw_pcie *pci = pcie->pci;
> > u32 val, cfg;
> > +   u8 offset;
> >
> > val = ls_lut_readl(pcie, PEX_PF0_PME_MES_DR);
> > ls_lut_writel(pcie, PEX_PF0_PME_MES_DR, val);
> > @@ -81,6 +83,13 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, 
> > void *dev_id)
> > return IRQ_NONE;
> >
> > if (val & PEX_PF0_PME_MES_DR_LUD) {
> > +
> > +   offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
> > +
> > +   dw_pcie_dbi_ro_wr_en(pci);
> > +   dw_pcie_writew_dbi(pci, offset + PCI_EXP_LNKCAP, 
> > pcie->lnkcap);
> > +   dw_pcie_dbi_ro_wr_dis(pci);
> > +
> > cfg = ls_lut_readl(pcie, PEX_PF0_CONFIG);
> > cfg |= PEX_PF0_CFG_READY;
> > ls_lut_writel(pcie, PEX_PF0_CONFIG, cfg);
> > @@ -216,6 +225,7 @@ static int __init ls_pcie_ep_probe(struct 
> > platform_device *pdev)
> > struct ls_pcie_ep *pcie;
> > struct pci_epc_features *ls_epc;
> > struct resource *dbi_base;
> > +   u8 offset;
> > int ret;
> >
> > pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
> > @@ -252,6 +262,9 @@ static int __init ls_pcie_ep_probe(struct 
> > platform_device *pdev)
> >
> > platform_set_drvdata(pdev, pcie);
> >
> > +   offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
> > +   pcie->lnkcap = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP);
> > +
> > ret = dw_pcie_ep_init(>ep);
> > if (ret)
> > return ret;
> > --
> > 2.34.1
> >


Re: [PATCH 2/2] PCI: layerscape: Add the workaround for lost link capablities during reset

2023-07-17 Thread Frank Li
On Thu, Jun 15, 2023 at 12:41:12PM -0400, Frank Li wrote:
> From: Xiaowei Bao 
> 
> A workaround for the issue where the PCI Express Endpoint (EP) controller
> loses the values of the Maximum Link Width and Supported Link Speed from
> the Link Capabilities Register, which initially configured by the Reset
> Configuration Word (RCW) during a link-down or hot reset event.
> 
> Signed-off-by: Xiaowei Bao 
> Signed-off-by: Hou Zhiqiang 
> Signed-off-by: Frank Li 
> ---

@lorenzo:
It is only for layerscape and workaround a small errata.
Could you please pick this up?

Frank

>  drivers/pci/controller/dwc/pci-layerscape-ep.c | 13 +
>  1 file changed, 13 insertions(+)
> 
> diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
> b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> index 4e4fdd1dfea7..2ef02d827eeb 100644
> --- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
> +++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> @@ -45,6 +45,7 @@ struct ls_pcie_ep {
>   struct pci_epc_features *ls_epc;
>   const struct ls_pcie_ep_drvdata *drvdata;
>   int irq;
> + u32 lnkcap;
>   boolbig_endian;
>  };
>  
> @@ -73,6 +74,7 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, void 
> *dev_id)
>   struct ls_pcie_ep *pcie = dev_id;
>   struct dw_pcie *pci = pcie->pci;
>   u32 val, cfg;
> + u8 offset;
>  
>   val = ls_lut_readl(pcie, PEX_PF0_PME_MES_DR);
>   ls_lut_writel(pcie, PEX_PF0_PME_MES_DR, val);
> @@ -81,6 +83,13 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, void 
> *dev_id)
>   return IRQ_NONE;
>  
>   if (val & PEX_PF0_PME_MES_DR_LUD) {
> +
> + offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
> +
> + dw_pcie_dbi_ro_wr_en(pci);
> + dw_pcie_writew_dbi(pci, offset + PCI_EXP_LNKCAP, pcie->lnkcap);
> + dw_pcie_dbi_ro_wr_dis(pci);
> +
>   cfg = ls_lut_readl(pcie, PEX_PF0_CONFIG);
>   cfg |= PEX_PF0_CFG_READY;
>   ls_lut_writel(pcie, PEX_PF0_CONFIG, cfg);
> @@ -216,6 +225,7 @@ static int __init ls_pcie_ep_probe(struct platform_device 
> *pdev)
>   struct ls_pcie_ep *pcie;
>   struct pci_epc_features *ls_epc;
>   struct resource *dbi_base;
> + u8 offset;
>   int ret;
>  
>   pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
> @@ -252,6 +262,9 @@ static int __init ls_pcie_ep_probe(struct platform_device 
> *pdev)
>  
>   platform_set_drvdata(pdev, pcie);
>  
> + offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
> + pcie->lnkcap = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP);
> +
>   ret = dw_pcie_ep_init(>ep);
>   if (ret)
>   return ret;
> -- 
> 2.34.1
> 


Re: [PATCH 1/2] PCI: layerscape: Add support for Link down notification

2023-07-17 Thread Frank Li
O Thu, Jun 15, 2023 at 12:41:11PM -0400, Frank Li wrote:
> Add support to pass Link down notification to Endpoint function driver
> so that the LINK_DOWN event can be processed by the function.
> 
> Signed-off-by: Frank Li 
> ---

@Lorenzo:
No comment over 1 months. Just change layerscape
and 1 line code change.

Could you please consider pick this up?

Frank Li

>  drivers/pci/controller/dwc/pci-layerscape-ep.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
> b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> index de4c1758a6c3..4e4fdd1dfea7 100644
> --- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
> +++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> @@ -88,6 +88,7 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, void 
> *dev_id)
>  
>   dev_dbg(pci->dev, "Link up\n");
>   } else if (val & PEX_PF0_PME_MES_DR_LDD) {
> + pci_epc_linkdown(pci->ep.epc);
>   dev_dbg(pci->dev, "Link down\n");
>   } else if (val & PEX_PF0_PME_MES_DR_HRD) {
>   dev_dbg(pci->dev, "Hot reset\n");
> -- 
> 2.34.1
> 


[PATCH 2/2] PCI: layerscape: Add the workaround for lost link capablities during reset

2023-06-15 Thread Frank Li
From: Xiaowei Bao 

A workaround for the issue where the PCI Express Endpoint (EP) controller
loses the values of the Maximum Link Width and Supported Link Speed from
the Link Capabilities Register, which initially configured by the Reset
Configuration Word (RCW) during a link-down or hot reset event.

Signed-off-by: Xiaowei Bao 
Signed-off-by: Hou Zhiqiang 
Signed-off-by: Frank Li 
---
 drivers/pci/controller/dwc/pci-layerscape-ep.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index 4e4fdd1dfea7..2ef02d827eeb 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -45,6 +45,7 @@ struct ls_pcie_ep {
struct pci_epc_features *ls_epc;
const struct ls_pcie_ep_drvdata *drvdata;
int irq;
+   u32 lnkcap;
boolbig_endian;
 };
 
@@ -73,6 +74,7 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, void 
*dev_id)
struct ls_pcie_ep *pcie = dev_id;
struct dw_pcie *pci = pcie->pci;
u32 val, cfg;
+   u8 offset;
 
val = ls_lut_readl(pcie, PEX_PF0_PME_MES_DR);
ls_lut_writel(pcie, PEX_PF0_PME_MES_DR, val);
@@ -81,6 +83,13 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, void 
*dev_id)
return IRQ_NONE;
 
if (val & PEX_PF0_PME_MES_DR_LUD) {
+
+   offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+
+   dw_pcie_dbi_ro_wr_en(pci);
+   dw_pcie_writew_dbi(pci, offset + PCI_EXP_LNKCAP, pcie->lnkcap);
+   dw_pcie_dbi_ro_wr_dis(pci);
+
cfg = ls_lut_readl(pcie, PEX_PF0_CONFIG);
cfg |= PEX_PF0_CFG_READY;
ls_lut_writel(pcie, PEX_PF0_CONFIG, cfg);
@@ -216,6 +225,7 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
struct ls_pcie_ep *pcie;
struct pci_epc_features *ls_epc;
struct resource *dbi_base;
+   u8 offset;
int ret;
 
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
@@ -252,6 +262,9 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
 
platform_set_drvdata(pdev, pcie);
 
+   offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+   pcie->lnkcap = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP);
+
ret = dw_pcie_ep_init(>ep);
if (ret)
return ret;
-- 
2.34.1



[PATCH 1/2] PCI: layerscape: Add support for Link down notification

2023-06-15 Thread Frank Li
Add support to pass Link down notification to Endpoint function driver
so that the LINK_DOWN event can be processed by the function.

Signed-off-by: Frank Li 
---
 drivers/pci/controller/dwc/pci-layerscape-ep.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index de4c1758a6c3..4e4fdd1dfea7 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -88,6 +88,7 @@ static irqreturn_t ls_pcie_ep_event_handler(int irq, void 
*dev_id)
 
dev_dbg(pci->dev, "Link up\n");
} else if (val & PEX_PF0_PME_MES_DR_LDD) {
+   pci_epc_linkdown(pci->ep.epc);
dev_dbg(pci->dev, "Link down\n");
} else if (val & PEX_PF0_PME_MES_DR_HRD) {
dev_dbg(pci->dev, "Hot reset\n");
-- 
2.34.1



Re: [PATCH v4 1/1] PCI: layerscape: Add the endpoint linkup notifier support

2023-06-14 Thread Frank Li
On Mon, Jun 12, 2023 at 12:12:53PM -0400, Frank Li wrote:
> On Mon, May 15, 2023 at 11:10:49AM -0400, Frank Li wrote:
> > Layerscape has PME interrupt, which can be used as linkup notifier.
> > Set CFG_READY bit of PEX_PF0_CONFIG to enable accesses from root complex
> > when linkup detected.
> > 
> > Acked-by: Manivannan Sadhasivam 
> > Signed-off-by: Xiaowei Bao 
> > Signed-off-by: Frank Li 
> > ---
> 
> Ping, not comments almost over 1 months.

@lorenzo and @Bjorn

Could you please pick this patch? This just added a linkup notification for
layerscape platform and there are not futher comments over 1 months.

Frank

> 
> > Change from v3 to v4
> >  - swap irq and big_endian
> > Change from v2 to v3
> >  - align 80 column
> >  - clear irq firstly
> >  - dev_info to dev_dbg
> >  - remove double space
> >  - update commit message
> > 
> > Change from v1 to v2
> > - pme -> PME
> > - irq -> IRQ
> > - update dev_info message according to Bjorn's suggestion
> > 
> >  .../pci/controller/dwc/pci-layerscape-ep.c| 102 +-
> >  1 file changed, 101 insertions(+), 1 deletion(-)
> > 
> > 


Re: [PATCH v4 1/1] PCI: layerscape: Add the endpoint linkup notifier support

2023-06-12 Thread Frank Li
On Mon, May 15, 2023 at 11:10:49AM -0400, Frank Li wrote:
> Layerscape has PME interrupt, which can be used as linkup notifier.
> Set CFG_READY bit of PEX_PF0_CONFIG to enable accesses from root complex
> when linkup detected.
> 
> Acked-by: Manivannan Sadhasivam 
> Signed-off-by: Xiaowei Bao 
> Signed-off-by: Frank Li 
> ---

Ping, not comments almost over 1 months.

> Change from v3 to v4
>  - swap irq and big_endian
> Change from v2 to v3
>  - align 80 column
>  - clear irq firstly
>  - dev_info to dev_dbg
>  - remove double space
>  - update commit message
> 
> Change from v1 to v2
> - pme -> PME
> - irq -> IRQ
> - update dev_info message according to Bjorn's suggestion
> 
>  .../pci/controller/dwc/pci-layerscape-ep.c| 102 +-
>  1 file changed, 101 insertions(+), 1 deletion(-)
> 
> 


[PATCH v4 1/1] PCI: layerscape: Add the endpoint linkup notifier support

2023-05-15 Thread Frank Li
Layerscape has PME interrupt, which can be used as linkup notifier.
Set CFG_READY bit of PEX_PF0_CONFIG to enable accesses from root complex
when linkup detected.

Acked-by: Manivannan Sadhasivam 
Signed-off-by: Xiaowei Bao 
Signed-off-by: Frank Li 
---
Change from v3 to v4
 - swap irq and big_endian
Change from v2 to v3
 - align 80 column
 - clear irq firstly
 - dev_info to dev_dbg
 - remove double space
 - update commit message

Change from v1 to v2
- pme -> PME
- irq -> IRQ
- update dev_info message according to Bjorn's suggestion

 .../pci/controller/dwc/pci-layerscape-ep.c| 102 +-
 1 file changed, 101 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index c640db60edc6..5398641b6b7e 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -18,6 +18,20 @@
 
 #include "pcie-designware.h"
 
+#define PEX_PF0_CONFIG 0xC0014
+#define PEX_PF0_CFG_READY  BIT(0)
+
+/* PEX PFa PCIE PME and message interrupt registers*/
+#define PEX_PF0_PME_MES_DR 0xC0020
+#define PEX_PF0_PME_MES_DR_LUD BIT(7)
+#define PEX_PF0_PME_MES_DR_LDD BIT(9)
+#define PEX_PF0_PME_MES_DR_HRD BIT(10)
+
+#define PEX_PF0_PME_MES_IER0xC0028
+#define PEX_PF0_PME_MES_IER_LUDIE  BIT(7)
+#define PEX_PF0_PME_MES_IER_LDDIE  BIT(9)
+#define PEX_PF0_PME_MES_IER_HRDIE  BIT(10)
+
 #define to_ls_pcie_ep(x)   dev_get_drvdata((x)->dev)
 
 struct ls_pcie_ep_drvdata {
@@ -30,8 +44,86 @@ struct ls_pcie_ep {
struct dw_pcie  *pci;
struct pci_epc_features *ls_epc;
const struct ls_pcie_ep_drvdata *drvdata;
+   int irq;
+   boolbig_endian;
 };
 
+static u32 ls_lut_readl(struct ls_pcie_ep *pcie, u32 offset)
+{
+   struct dw_pcie *pci = pcie->pci;
+
+   if (pcie->big_endian)
+   return ioread32be(pci->dbi_base + offset);
+   else
+   return ioread32(pci->dbi_base + offset);
+}
+
+static void ls_lut_writel(struct ls_pcie_ep *pcie, u32 offset, u32 value)
+{
+   struct dw_pcie *pci = pcie->pci;
+
+   if (pcie->big_endian)
+   iowrite32be(value, pci->dbi_base + offset);
+   else
+   iowrite32(value, pci->dbi_base + offset);
+}
+
+static irqreturn_t ls_pcie_ep_event_handler(int irq, void *dev_id)
+{
+   struct ls_pcie_ep *pcie = dev_id;
+   struct dw_pcie *pci = pcie->pci;
+   u32 val, cfg;
+
+   val = ls_lut_readl(pcie, PEX_PF0_PME_MES_DR);
+   ls_lut_writel(pcie, PEX_PF0_PME_MES_DR, val);
+
+   if (!val)
+   return IRQ_NONE;
+
+   if (val & PEX_PF0_PME_MES_DR_LUD) {
+   cfg = ls_lut_readl(pcie, PEX_PF0_CONFIG);
+   cfg |= PEX_PF0_CFG_READY;
+   ls_lut_writel(pcie, PEX_PF0_CONFIG, cfg);
+   dw_pcie_ep_linkup(>ep);
+
+   dev_dbg(pci->dev, "Link up\n");
+   } else if (val & PEX_PF0_PME_MES_DR_LDD) {
+   dev_dbg(pci->dev, "Link down\n");
+   } else if (val & PEX_PF0_PME_MES_DR_HRD) {
+   dev_dbg(pci->dev, "Hot reset\n");
+   }
+
+   return IRQ_HANDLED;
+}
+
+static int ls_pcie_ep_interrupt_init(struct ls_pcie_ep *pcie,
+struct platform_device *pdev)
+{
+   u32 val;
+   int ret;
+
+   pcie->irq = platform_get_irq_byname(pdev, "pme");
+   if (pcie->irq < 0) {
+   dev_err(>dev, "Can't get 'pme' IRQ\n");
+   return pcie->irq;
+   }
+
+   ret = devm_request_irq(>dev, pcie->irq, ls_pcie_ep_event_handler,
+  IRQF_SHARED, pdev->name, pcie);
+   if (ret) {
+   dev_err(>dev, "Can't register PCIe IRQ\n");
+   return ret;
+   }
+
+   /* Enable interrupts */
+   val = ls_lut_readl(pcie, PEX_PF0_PME_MES_IER);
+   val |=  PEX_PF0_PME_MES_IER_LDDIE | PEX_PF0_PME_MES_IER_HRDIE |
+   PEX_PF0_PME_MES_IER_LUDIE;
+   ls_lut_writel(pcie, PEX_PF0_PME_MES_IER, val);
+
+   return 0;
+}
+
 static const struct pci_epc_features*
 ls_pcie_ep_get_features(struct dw_pcie_ep *ep)
 {
@@ -125,6 +217,7 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
struct ls_pcie_ep *pcie;
struct pci_epc_features *ls_epc;
struct resource *dbi_base;
+   int ret;
 
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
if (!pcie)
@@ -144,6 +237,7 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
pci->ops = pcie->drvdata->dw_pcie_ops;
 
ls_epc->bar_fixed_64bit = (1 << BAR_2) | (1 << BAR_4);
+ 

[PATCH v3 1/1] PCI: layerscape: Add the endpoint linkup notifier support

2023-05-08 Thread Frank Li
Layerscape has PME interrupt, which can be used as linkup notifier.
Set CFG_READY bit of PEX_PF0_CONFIG to enable accesses from root complex
when linkup detected.

Signed-off-by: Xiaowei Bao 
Signed-off-by: Frank Li 
---
Change from v2 to v3
 - align 80 column
 - clear irq firstly
 - dev_info to dev_dbg
 - remove double space
 - update commit message

Change from v1 to v2
- pme -> PME
- irq -> IRQ
- update dev_info message according to Bjorn's suggestion
- remove '.' at error message

 .../pci/controller/dwc/pci-layerscape-ep.c| 102 +-
 1 file changed, 101 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index c640db60edc6..1a431a9be91e 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -18,6 +18,20 @@
 
 #include "pcie-designware.h"
 
+#define PEX_PF0_CONFIG 0xC0014
+#define PEX_PF0_CFG_READY  BIT(0)
+
+/* PEX PFa PCIE PME and message interrupt registers*/
+#define PEX_PF0_PME_MES_DR 0xC0020
+#define PEX_PF0_PME_MES_DR_LUD BIT(7)
+#define PEX_PF0_PME_MES_DR_LDD BIT(9)
+#define PEX_PF0_PME_MES_DR_HRD BIT(10)
+
+#define PEX_PF0_PME_MES_IER0xC0028
+#define PEX_PF0_PME_MES_IER_LUDIE  BIT(7)
+#define PEX_PF0_PME_MES_IER_LDDIE  BIT(9)
+#define PEX_PF0_PME_MES_IER_HRDIE  BIT(10)
+
 #define to_ls_pcie_ep(x)   dev_get_drvdata((x)->dev)
 
 struct ls_pcie_ep_drvdata {
@@ -30,8 +44,86 @@ struct ls_pcie_ep {
struct dw_pcie  *pci;
struct pci_epc_features *ls_epc;
const struct ls_pcie_ep_drvdata *drvdata;
+   boolbig_endian;
+   int irq;
 };
 
+static u32 ls_lut_readl(struct ls_pcie_ep *pcie, u32 offset)
+{
+   struct dw_pcie *pci = pcie->pci;
+
+   if (pcie->big_endian)
+   return ioread32be(pci->dbi_base + offset);
+   else
+   return ioread32(pci->dbi_base + offset);
+}
+
+static void ls_lut_writel(struct ls_pcie_ep *pcie, u32 offset, u32 value)
+{
+   struct dw_pcie *pci = pcie->pci;
+
+   if (pcie->big_endian)
+   iowrite32be(value, pci->dbi_base + offset);
+   else
+   iowrite32(value, pci->dbi_base + offset);
+}
+
+static irqreturn_t ls_pcie_ep_event_handler(int irq, void *dev_id)
+{
+   struct ls_pcie_ep *pcie = dev_id;
+   struct dw_pcie *pci = pcie->pci;
+   u32 val, cfg;
+
+   val = ls_lut_readl(pcie, PEX_PF0_PME_MES_DR);
+   ls_lut_writel(pcie, PEX_PF0_PME_MES_DR, val);
+
+   if (!val)
+   return IRQ_NONE;
+
+   if (val & PEX_PF0_PME_MES_DR_LUD) {
+   cfg = ls_lut_readl(pcie, PEX_PF0_CONFIG);
+   cfg |= PEX_PF0_CFG_READY;
+   ls_lut_writel(pcie, PEX_PF0_CONFIG, cfg);
+   dw_pcie_ep_linkup(>ep);
+
+   dev_dbg(pci->dev, "Link up\n");
+   } else if (val & PEX_PF0_PME_MES_DR_LDD) {
+   dev_dbg(pci->dev, "Link down\n");
+   } else if (val & PEX_PF0_PME_MES_DR_HRD) {
+   dev_dbg(pci->dev, "Hot reset\n");
+   }
+
+   return IRQ_HANDLED;
+}
+
+static int ls_pcie_ep_interrupt_init(struct ls_pcie_ep *pcie,
+struct platform_device *pdev)
+{
+   u32 val;
+   int ret;
+
+   pcie->irq = platform_get_irq_byname(pdev, "pme");
+   if (pcie->irq < 0) {
+   dev_err(>dev, "Can't get 'pme' IRQ\n");
+   return pcie->irq;
+   }
+
+   ret = devm_request_irq(>dev, pcie->irq, ls_pcie_ep_event_handler,
+  IRQF_SHARED, pdev->name, pcie);
+   if (ret) {
+   dev_err(>dev, "Can't register PCIe IRQ\n");
+   return ret;
+   }
+
+   /* Enable interrupts */
+   val = ls_lut_readl(pcie, PEX_PF0_PME_MES_IER);
+   val |=  PEX_PF0_PME_MES_IER_LDDIE | PEX_PF0_PME_MES_IER_HRDIE |
+   PEX_PF0_PME_MES_IER_LUDIE;
+   ls_lut_writel(pcie, PEX_PF0_PME_MES_IER, val);
+
+   return 0;
+}
+
 static const struct pci_epc_features*
 ls_pcie_ep_get_features(struct dw_pcie_ep *ep)
 {
@@ -125,6 +217,7 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
struct ls_pcie_ep *pcie;
struct pci_epc_features *ls_epc;
struct resource *dbi_base;
+   int ret;
 
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
if (!pcie)
@@ -144,6 +237,7 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
pci->ops = pcie->drvdata->dw_pcie_ops;
 
ls_epc->bar_fixed_64bit = (1 << BAR_2) | (1 << BAR_4);
+   ls_epc->linkup_notifier = true;
 
pci

RE: [EXT] Re: [PATCH v2 1/1] PCI: layerscape: Add the endpoint linkup notifier support

2023-05-08 Thread Frank Li
> > > Subject: [EXT] Re: [PATCH v2 1/1] PCI: layerscape: Add the endpoint
> linkup
> > > notifier support
> 
> All these quoted headers are redundant clutter since we've already
> seen them when Manivannan sent his comments.  It would be nice if your
> mailer could be configured to omit them.

Our email client quite stupid. 

> 
> > > > +static int ls_pcie_ep_interrupt_init(struct ls_pcie_ep *pcie,
> > > > +  struct platform_device *pdev)
> > > > +{
> > > > + u32 val;
> > > > + int ret;
> > > > +
> > > > + pcie->irq = platform_get_irq_byname(pdev, "pme");
> > > > + if (pcie->irq < 0) {
> > > > + dev_err(>dev, "Can't get 'pme' IRQ\n");
> > >
> > > PME
> >
> > Here should be dts property `pme`, suppose should match
> > platform_get_irq_byname(pdev, "pme");
> 
> You can also edit out all the other context and questions if you're
> not responding to them.
> 
> There were a lot of other comments that were useful but are not
> relevant to this reply.

Okay, I found I mess up patch version number.
 
> 
> Bjorn


[PATCH v2 1/1] PCI: layerscape: Add the endpoint linkup notifier support

2023-05-08 Thread Frank Li
Layerscape has PME interrupt, which can be used as linkup notifier.
Set CFG_READY bit of PEX_PF0_CONFIG to enable accesses from root complex
when linkup detected.

Signed-off-by: Xiaowei Bao 
Signed-off-by: Frank Li 
---
 .../pci/controller/dwc/pci-layerscape-ep.c| 102 +-
 1 file changed, 101 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index c640db60edc6..1a431a9be91e 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -18,6 +18,20 @@
 
 #include "pcie-designware.h"
 
+#define PEX_PF0_CONFIG 0xC0014
+#define PEX_PF0_CFG_READY  BIT(0)
+
+/* PEX PFa PCIE PME and message interrupt registers*/
+#define PEX_PF0_PME_MES_DR 0xC0020
+#define PEX_PF0_PME_MES_DR_LUD BIT(7)
+#define PEX_PF0_PME_MES_DR_LDD BIT(9)
+#define PEX_PF0_PME_MES_DR_HRD BIT(10)
+
+#define PEX_PF0_PME_MES_IER0xC0028
+#define PEX_PF0_PME_MES_IER_LUDIE  BIT(7)
+#define PEX_PF0_PME_MES_IER_LDDIE  BIT(9)
+#define PEX_PF0_PME_MES_IER_HRDIE  BIT(10)
+
 #define to_ls_pcie_ep(x)   dev_get_drvdata((x)->dev)
 
 struct ls_pcie_ep_drvdata {
@@ -30,8 +44,86 @@ struct ls_pcie_ep {
struct dw_pcie  *pci;
struct pci_epc_features *ls_epc;
const struct ls_pcie_ep_drvdata *drvdata;
+   boolbig_endian;
+   int irq;
 };
 
+static u32 ls_lut_readl(struct ls_pcie_ep *pcie, u32 offset)
+{
+   struct dw_pcie *pci = pcie->pci;
+
+   if (pcie->big_endian)
+   return ioread32be(pci->dbi_base + offset);
+   else
+   return ioread32(pci->dbi_base + offset);
+}
+
+static void ls_lut_writel(struct ls_pcie_ep *pcie, u32 offset, u32 value)
+{
+   struct dw_pcie *pci = pcie->pci;
+
+   if (pcie->big_endian)
+   iowrite32be(value, pci->dbi_base + offset);
+   else
+   iowrite32(value, pci->dbi_base + offset);
+}
+
+static irqreturn_t ls_pcie_ep_event_handler(int irq, void *dev_id)
+{
+   struct ls_pcie_ep *pcie = dev_id;
+   struct dw_pcie *pci = pcie->pci;
+   u32 val, cfg;
+
+   val = ls_lut_readl(pcie, PEX_PF0_PME_MES_DR);
+   ls_lut_writel(pcie, PEX_PF0_PME_MES_DR, val);
+
+   if (!val)
+   return IRQ_NONE;
+
+   if (val & PEX_PF0_PME_MES_DR_LUD) {
+   cfg = ls_lut_readl(pcie, PEX_PF0_CONFIG);
+   cfg |= PEX_PF0_CFG_READY;
+   ls_lut_writel(pcie, PEX_PF0_CONFIG, cfg);
+   dw_pcie_ep_linkup(>ep);
+
+   dev_dbg(pci->dev, "Link up\n");
+   } else if (val & PEX_PF0_PME_MES_DR_LDD) {
+   dev_dbg(pci->dev, "Link down\n");
+   } else if (val & PEX_PF0_PME_MES_DR_HRD) {
+   dev_dbg(pci->dev, "Hot reset\n");
+   }
+
+   return IRQ_HANDLED;
+}
+
+static int ls_pcie_ep_interrupt_init(struct ls_pcie_ep *pcie,
+struct platform_device *pdev)
+{
+   u32 val;
+   int ret;
+
+   pcie->irq = platform_get_irq_byname(pdev, "pme");
+   if (pcie->irq < 0) {
+   dev_err(>dev, "Can't get 'pme' IRQ\n");
+   return pcie->irq;
+   }
+
+   ret = devm_request_irq(>dev, pcie->irq, ls_pcie_ep_event_handler,
+  IRQF_SHARED, pdev->name, pcie);
+   if (ret) {
+   dev_err(>dev, "Can't register PCIe IRQ\n");
+   return ret;
+   }
+
+   /* Enable interrupts */
+   val = ls_lut_readl(pcie, PEX_PF0_PME_MES_IER);
+   val |=  PEX_PF0_PME_MES_IER_LDDIE | PEX_PF0_PME_MES_IER_HRDIE |
+   PEX_PF0_PME_MES_IER_LUDIE;
+   ls_lut_writel(pcie, PEX_PF0_PME_MES_IER, val);
+
+   return 0;
+}
+
 static const struct pci_epc_features*
 ls_pcie_ep_get_features(struct dw_pcie_ep *ep)
 {
@@ -125,6 +217,7 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
struct ls_pcie_ep *pcie;
struct pci_epc_features *ls_epc;
struct resource *dbi_base;
+   int ret;
 
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
if (!pcie)
@@ -144,6 +237,7 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
pci->ops = pcie->drvdata->dw_pcie_ops;
 
ls_epc->bar_fixed_64bit = (1 << BAR_2) | (1 << BAR_4);
+   ls_epc->linkup_notifier = true;
 
pcie->pci = pci;
pcie->ls_epc = ls_epc;
@@ -155,9 +249,15 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
 
pci->ep.ops = _pcie_ep_ops;
 
+   pcie->big_endian = of_property_read_bool(dev->of_node, "big-endian");
+
  

RE: [EXT] Re: [PATCH v2 1/1] PCI: layerscape: Add the endpoint linkup notifier support

2023-05-08 Thread Frank Li


> -Original Message-
> From: Manivannan Sadhasivam 
> Sent: Saturday, May 6, 2023 2:59 AM
> To: Frank Li 
> Cc: M.H. Lian ; Mingkai Hu
> ; Roy Zang ; Lorenzo Pieralisi
> ; Rob Herring ; Krzysztof
> Wilczyński ; Bjorn Helgaas ; open
> list:PCI DRIVER FOR FREESCALE LAYERSCAPE ;
> open list:PCI DRIVER FOR FREESCALE LAYERSCAPE  p...@vger.kernel.org>; moderated list:PCI DRIVER FOR FREESCALE
> LAYERSCAPE ; open list  ker...@vger.kernel.org>; i...@lists.linux.dev
> Subject: [EXT] Re: [PATCH v2 1/1] PCI: layerscape: Add the endpoint linkup
> notifier support
> 
> Caution: This is an external email. Please take care when clicking links or
> opening attachments. When in doubt, report the message using the 'Report
> this email' button
> 
> 
> On Mon, May 01, 2023 at 10:48:06AM -0400, Frank Li wrote:
> > Layerscape has PME interrupt, which can be used as linkup notifier.
> > Set CFG_READY bit when linkup detected.
> 
> Where are you setting this bit?
> 
> >
> > Signed-off-by: Xiaowei Bao 
> > Signed-off-by: Frank Li 
> > ---
> > Change from v1 to v2
> > - pme -> PME
> > - irq -> IRQ
> > - update dev_info message according to Bjorn's suggestion
> > - remove '.' at error message
> >
> >  .../pci/controller/dwc/pci-layerscape-ep.c| 104 +-
> >  1 file changed, 103 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c
> b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > index c640db60edc6..e974fbe3b6d8 100644
> > --- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > +++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > @@ -18,6 +18,20 @@
> >
> >  #include "pcie-designware.h"
> >
> > +#define PEX_PF0_CONFIG   0xC0014
> > +#define PEX_PF0_CFG_READYBIT(0)
> > +
> > +/* PEX PFa PCIE PME and message interrupt registers*/
> > +#define PEX_PF0_PME_MES_DR   0xC0020
> > +#define PEX_PF0_PME_MES_DR_LUD   BIT(7)
> > +#define PEX_PF0_PME_MES_DR_LDD   BIT(9)
> > +#define PEX_PF0_PME_MES_DR_HRD   BIT(10)
> > +
> > +#define PEX_PF0_PME_MES_IER  0xC0028
> > +#define PEX_PF0_PME_MES_IER_LUDIEBIT(7)
> > +#define PEX_PF0_PME_MES_IER_LDDIEBIT(9)
> > +#define PEX_PF0_PME_MES_IER_HRDIEBIT(10)
> > +
> >  #define to_ls_pcie_ep(x) dev_get_drvdata((x)->dev)
> >
> >  struct ls_pcie_ep_drvdata {
> > @@ -30,8 +44,88 @@ struct ls_pcie_ep {
> >   struct dw_pcie  *pci;
> >   struct pci_epc_features *ls_epc;
> >   const struct ls_pcie_ep_drvdata *drvdata;
> > + boolbig_endian;
> > + int irq;
> >  };
> >
> > +static u32 ls_lut_readl(struct ls_pcie_ep *pcie, u32 offset)
> > +{
> > + struct dw_pcie *pci = pcie->pci;
> > +
> > + if (pcie->big_endian)
> > + return ioread32be(pci->dbi_base + offset);
> > + else
> > + return ioread32(pci->dbi_base + offset);
> > +}
> > +
> > +static void ls_lut_writel(struct ls_pcie_ep *pcie, u32 offset,
> > +   u32 value)
> 
> Above function argument could be wrapped within 80 columns.
> 
> > +{
> > + struct dw_pcie *pci = pcie->pci;
> > +
> > + if (pcie->big_endian)
> > + iowrite32be(value, pci->dbi_base + offset);
> > + else
> > + iowrite32(value, pci->dbi_base + offset);
> > +}
> > +
> > +static irqreturn_t ls_pcie_ep_event_handler(int irq, void *dev_id)
> > +{
> > + struct ls_pcie_ep *pcie = (struct ls_pcie_ep *)dev_id;
> 
> No need to do explicit typecase for void pointer.
> 
> > + struct dw_pcie *pci = pcie->pci;
> > + u32 val, cfg;
> > +
> > + val = ls_lut_readl(pcie, PEX_PF0_PME_MES_DR);
> > + if (!val)
> > + return IRQ_NONE;
> > +
> > + if (val & PEX_PF0_PME_MES_DR_LUD) {
> > + cfg = ls_lut_readl(pcie, PEX_PF0_CONFIG);
> > + cfg |= PEX_PF0_CFG_READY;
> > + ls_lut_writel(pcie, PEX_PF0_CONFIG, cfg);
> > + dw_pcie_ep_linkup(>ep);
> > +
> > + dev_info(pci->dev, "Link up\n");
> 
> These messages could be demoted to dev_dbg() logs.
> 
> > + } else if (val & PEX_PF0_PME_MES_DR_LDD) {
> > + dev_info(pci->dev, "Link down\n");
> >

[PATCH v2 1/1] PCI: layerscape: Add the endpoint linkup notifier support

2023-05-01 Thread Frank Li
Layerscape has PME interrupt, which can be used as linkup notifier.
Set CFG_READY bit when linkup detected.

Signed-off-by: Xiaowei Bao 
Signed-off-by: Frank Li 
---
Change from v1 to v2
- pme -> PME
- irq -> IRQ
- update dev_info message according to Bjorn's suggestion
- remove '.' at error message

 .../pci/controller/dwc/pci-layerscape-ep.c| 104 +-
 1 file changed, 103 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index c640db60edc6..e974fbe3b6d8 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -18,6 +18,20 @@
 
 #include "pcie-designware.h"
 
+#define PEX_PF0_CONFIG 0xC0014
+#define PEX_PF0_CFG_READY  BIT(0)
+
+/* PEX PFa PCIE PME and message interrupt registers*/
+#define PEX_PF0_PME_MES_DR 0xC0020
+#define PEX_PF0_PME_MES_DR_LUD BIT(7)
+#define PEX_PF0_PME_MES_DR_LDD BIT(9)
+#define PEX_PF0_PME_MES_DR_HRD BIT(10)
+
+#define PEX_PF0_PME_MES_IER0xC0028
+#define PEX_PF0_PME_MES_IER_LUDIE  BIT(7)
+#define PEX_PF0_PME_MES_IER_LDDIE  BIT(9)
+#define PEX_PF0_PME_MES_IER_HRDIE  BIT(10)
+
 #define to_ls_pcie_ep(x)   dev_get_drvdata((x)->dev)
 
 struct ls_pcie_ep_drvdata {
@@ -30,8 +44,88 @@ struct ls_pcie_ep {
struct dw_pcie  *pci;
struct pci_epc_features *ls_epc;
const struct ls_pcie_ep_drvdata *drvdata;
+   boolbig_endian;
+   int irq;
 };
 
+static u32 ls_lut_readl(struct ls_pcie_ep *pcie, u32 offset)
+{
+   struct dw_pcie *pci = pcie->pci;
+
+   if (pcie->big_endian)
+   return ioread32be(pci->dbi_base + offset);
+   else
+   return ioread32(pci->dbi_base + offset);
+}
+
+static void ls_lut_writel(struct ls_pcie_ep *pcie, u32 offset,
+ u32 value)
+{
+   struct dw_pcie *pci = pcie->pci;
+
+   if (pcie->big_endian)
+   iowrite32be(value, pci->dbi_base + offset);
+   else
+   iowrite32(value, pci->dbi_base + offset);
+}
+
+static irqreturn_t ls_pcie_ep_event_handler(int irq, void *dev_id)
+{
+   struct ls_pcie_ep *pcie = (struct ls_pcie_ep *)dev_id;
+   struct dw_pcie *pci = pcie->pci;
+   u32 val, cfg;
+
+   val = ls_lut_readl(pcie, PEX_PF0_PME_MES_DR);
+   if (!val)
+   return IRQ_NONE;
+
+   if (val & PEX_PF0_PME_MES_DR_LUD) {
+   cfg = ls_lut_readl(pcie, PEX_PF0_CONFIG);
+   cfg |= PEX_PF0_CFG_READY;
+   ls_lut_writel(pcie, PEX_PF0_CONFIG, cfg);
+   dw_pcie_ep_linkup(>ep);
+
+   dev_info(pci->dev, "Link up\n");
+   } else if (val & PEX_PF0_PME_MES_DR_LDD) {
+   dev_info(pci->dev, "Link down\n");
+   } else if (val & PEX_PF0_PME_MES_DR_HRD) {
+   dev_info(pci->dev, "Hot reset\n");
+   }
+
+   ls_lut_writel(pcie, PEX_PF0_PME_MES_DR, val);
+
+   return IRQ_HANDLED;
+}
+
+static int ls_pcie_ep_interrupt_init(struct ls_pcie_ep *pcie,
+struct platform_device *pdev)
+{
+   u32 val;
+   int ret;
+
+   pcie->irq = platform_get_irq_byname(pdev, "pme");
+   if (pcie->irq < 0) {
+   dev_err(>dev, "Can't get 'pme' IRQ\n");
+   return pcie->irq;
+   }
+
+   ret = devm_request_irq(>dev, pcie->irq,
+  ls_pcie_ep_event_handler, IRQF_SHARED,
+  pdev->name, pcie);
+   if (ret) {
+   dev_err(>dev, "Can't register PCIe IRQ\n");
+   return ret;
+   }
+
+   /* Enable interrupts */
+   val = ls_lut_readl(pcie, PEX_PF0_PME_MES_IER);
+   val |=  PEX_PF0_PME_MES_IER_LDDIE | PEX_PF0_PME_MES_IER_HRDIE |
+   PEX_PF0_PME_MES_IER_LUDIE;
+   ls_lut_writel(pcie, PEX_PF0_PME_MES_IER, val);
+
+   return 0;
+}
+
 static const struct pci_epc_features*
 ls_pcie_ep_get_features(struct dw_pcie_ep *ep)
 {
@@ -125,6 +219,7 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
struct ls_pcie_ep *pcie;
struct pci_epc_features *ls_epc;
struct resource *dbi_base;
+   int ret;
 
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
if (!pcie)
@@ -144,6 +239,7 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
pci->ops = pcie->drvdata->dw_pcie_ops;
 
ls_epc->bar_fixed_64bit = (1 << BAR_2) | (1 << BAR_4);
+   ls_epc->linkup_notifier = true;
 
pcie->pci = pci;
pcie->ls_epc = ls_epc;
@@ -155,9 +251,15 @@ static int __init ls_pcie_ep_probe(

[PATCH 1/1] PCI: layerscape: Add the endpoint linkup notifier support

2023-04-20 Thread Frank Li
Layerscape has PME interrupt, which can be use as linkup notifer.
Set CFG_READY bit when linkup detected.

Signed-off-by: Xiaowei Bao 
Signed-off-by: Frank Li 
---
 .../pci/controller/dwc/pci-layerscape-ep.c| 104 +-
 1 file changed, 103 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index c640db60edc6..66d4a78a30a4 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -18,6 +18,20 @@
 
 #include "pcie-designware.h"
 
+#define PEX_PF0_CONFIG 0xC0014
+#define PEX_PF0_CFG_READY  BIT(0)
+
+/* PEX PFa PCIE pme and message interrupt registers*/
+#define PEX_PF0_PME_MES_DR 0xC0020
+#define PEX_PF0_PME_MES_DR_LUD BIT(7)
+#define PEX_PF0_PME_MES_DR_LDD BIT(9)
+#define PEX_PF0_PME_MES_DR_HRD BIT(10)
+
+#define PEX_PF0_PME_MES_IER0xC0028
+#define PEX_PF0_PME_MES_IER_LUDIE  BIT(7)
+#define PEX_PF0_PME_MES_IER_LDDIE  BIT(9)
+#define PEX_PF0_PME_MES_IER_HRDIE  BIT(10)
+
 #define to_ls_pcie_ep(x)   dev_get_drvdata((x)->dev)
 
 struct ls_pcie_ep_drvdata {
@@ -30,8 +44,88 @@ struct ls_pcie_ep {
struct dw_pcie  *pci;
struct pci_epc_features *ls_epc;
const struct ls_pcie_ep_drvdata *drvdata;
+   boolbig_endian;
+   int irq;
 };
 
+static u32 ls_lut_readl(struct ls_pcie_ep *pcie, u32 offset)
+{
+   struct dw_pcie *pci = pcie->pci;
+
+   if (pcie->big_endian)
+   return ioread32be(pci->dbi_base + offset);
+   else
+   return ioread32(pci->dbi_base + offset);
+}
+
+static void ls_lut_writel(struct ls_pcie_ep *pcie, u32 offset,
+ u32 value)
+{
+   struct dw_pcie *pci = pcie->pci;
+
+   if (pcie->big_endian)
+   iowrite32be(value, pci->dbi_base + offset);
+   else
+   iowrite32(value, pci->dbi_base + offset);
+}
+
+static irqreturn_t ls_pcie_ep_event_handler(int irq, void *dev_id)
+{
+   struct ls_pcie_ep *pcie = (struct ls_pcie_ep *)dev_id;
+   struct dw_pcie *pci = pcie->pci;
+   u32 val, cfg;
+
+   val = ls_lut_readl(pcie, PEX_PF0_PME_MES_DR);
+   if (!val)
+   return IRQ_NONE;
+
+   if (val & PEX_PF0_PME_MES_DR_LUD) {
+   cfg = ls_lut_readl(pcie, PEX_PF0_CONFIG);
+   cfg |= PEX_PF0_CFG_READY;
+   ls_lut_writel(pcie, PEX_PF0_CONFIG, cfg);
+   dw_pcie_ep_linkup(>ep);
+
+   dev_info(pci->dev, "Detect the link up state !\n");
+   } else if (val & PEX_PF0_PME_MES_DR_LDD) {
+   dev_info(pci->dev, "Detect the link down state !\n");
+   } else if (val & PEX_PF0_PME_MES_DR_HRD) {
+   dev_info(pci->dev, "Detect the hot reset state !\n");
+   }
+
+   ls_lut_writel(pcie, PEX_PF0_PME_MES_DR, val);
+
+   return IRQ_HANDLED;
+}
+
+static int ls_pcie_ep_interrupt_init(struct ls_pcie_ep *pcie,
+struct platform_device *pdev)
+{
+   u32 val;
+   int ret;
+
+   pcie->irq = platform_get_irq_byname(pdev, "pme");
+   if (pcie->irq < 0) {
+   dev_err(>dev, "Can't get 'pme' irq.\n");
+   return pcie->irq;
+   }
+
+   ret = devm_request_irq(>dev, pcie->irq,
+  ls_pcie_ep_event_handler, IRQF_SHARED,
+  pdev->name, pcie);
+   if (ret) {
+   dev_err(>dev, "Can't register PCIe IRQ.\n");
+   return ret;
+   }
+
+   /* Enable interrupts */
+   val = ls_lut_readl(pcie, PEX_PF0_PME_MES_IER);
+   val |=  PEX_PF0_PME_MES_IER_LDDIE | PEX_PF0_PME_MES_IER_HRDIE |
+   PEX_PF0_PME_MES_IER_LUDIE;
+   ls_lut_writel(pcie, PEX_PF0_PME_MES_IER, val);
+
+   return 0;
+}
+
 static const struct pci_epc_features*
 ls_pcie_ep_get_features(struct dw_pcie_ep *ep)
 {
@@ -125,6 +219,7 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
struct ls_pcie_ep *pcie;
struct pci_epc_features *ls_epc;
struct resource *dbi_base;
+   int ret;
 
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
if (!pcie)
@@ -144,6 +239,7 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
pci->ops = pcie->drvdata->dw_pcie_ops;
 
ls_epc->bar_fixed_64bit = (1 << BAR_2) | (1 << BAR_4);
+   ls_epc->linkup_notifier = true;
 
pcie->pci = pci;
pcie->ls_epc = ls_epc;
@@ -155,9 +251,15 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
 
pci->ep.ops = _pcie_ep_ops;
 
+  

RE: [EXT] Re: [PATCH 1/1] PCI: layerscape: Add the workaround for A-010305

2023-03-17 Thread Frank Li
> >   pci->ep.ops = _pcie_ep_ops;
> >
> > + pcie->big_endian = of_property_read_bool(dev->of_node, "big-
> endian");
> 
> Somewhat surprising that 6c389328c985 ("dt-bindings: pci:
> layerscape-pci: Add a optional property big-endian") added this
> property a year ago, but it has been unused until now?
> 

No, it also for pci host part. Zhiqiang send patch 
https://lore.kernel.org/lkml/20210407030948.3845-1-zhiqiang@nxp.com/

Not sure why bind-doc accepted, but driver code patch have not accepted. 

The same case happen at 
https://lore.kernel.org/imx/20230209151050.233973-1-frank...@nxp.com/T/#t

I tried repost the missed part. But no any response over months.  The above one 
is just one line change. 

> > --
> > 2.34.1
> >


RE: [EXT] Re: [External] : [PATCH v3 1/1] PCI: layerscape: Add EP mode support for ls1028a

2023-03-14 Thread Frank Li
> 
> Reviewed-by: Alok Tiwari 
> 
> On 2/9/2023 8:40 PM, Frank Li wrote:
> > From: Xiaowei Bao 
> >
> > Add PCIe EP mode support for ls1028a.
> >
> > Signed-off-by: Xiaowei Bao 
> > Signed-off-by: Hou Zhiqiang 
> > Signed-off-by: Frank Li 
> > Acked-by:  Roy Zang 
> > ---

Ping!
there are no feedback for over 1 month. 
Just 1 line change. 

> >
> > Change from v2 to v3
> > order by .compatible
> >
> > Change from v2 to v2
> > Added
> > Signed-off-by: Frank Li 
> > Acked-by:  Roy Zang 
> >
> >
> > All other patches were already accepte by maintainer in
> >
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Furlde
> fense.com%2Fv3%2F__https%3A%2F%2Flore.kernel.org%2Flkml%2F202
> 2223457.10599-1-
> leoyang.li%40nxp.com%2F__%3B!!ACWV5N9M2RV99hQ!NR9EU4fPDwxdyrb
> 9tdBm9VNIMHSlw6dLgXCAPDSrm7ftWVNrh6JldLGzzrKyiE0xRlP5OdiGBN7PCf
> 9gRaA%24=05%7C01%7CFrank.Li%40nxp.com%7C1d32974e205b4a8591
> 9f08db0ba30b9b%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C6381
> 16567129733840%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiL
> CJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C
> ata=hGKffPqpE%2Ft66x71Y47ocGbIuFH7vpjLadlAXbnyBOw%3D=0
> >
> > But missed this one.
> >
> > Re-post
> >
> >   drivers/pci/controller/dwc/pci-layerscape-ep.c | 1 +
> >   1 file changed, 1 insertion(+)
> >
> > diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c
> b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > index ad99707b3b99..c640db60edc6 100644
> > --- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > +++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
> > @@ -110,6 +110,7 @@ static const struct ls_pcie_ep_drvdata
> lx2_ep_drvdata = {
> >   };
> >
> >   static const struct of_device_id ls_pcie_ep_of_match[] = {
> > + { .compatible = "fsl,ls1028a-pcie-ep", .data = _ep_drvdata },
> >   { .compatible = "fsl,ls1046a-pcie-ep", .data = _ep_drvdata },
> >   { .compatible = "fsl,ls1088a-pcie-ep", .data = _ep_drvdata },
> >   { .compatible = "fsl,ls2088a-pcie-ep", .data = _ep_drvdata },


RE: [PATCH 1/1] PCI: layerscape: Add the workaround for A-010305

2023-03-14 Thread Frank Li


> 
> > -Original Message-
> > From: Frank Li
> > Subject: RE: [PATCH 1/1] PCI: layerscape: Add the workaround for A-010305
> >
> > > Subject: [PATCH 1/1] PCI: layerscape: Add the workaround for A-010305
> > >
> > > From: Xiaowei Bao 
> > >
> > > When a link down or hot reset event occurs, the PCI Express EP
> > > controller's Link Capabilities Register should retain the values of
> > > the Maximum Link Width and Supported Link Speed configured by RCW.
> > >
> > > Signed-off-by: Xiaowei Bao 
> > > Signed-off-by: Hou Zhiqiang 
> > > Signed-off-by: Frank Li 
> > > ---
> >
> > Ping
> 
> Friendly ping.

Ping.  No feedback for over 1 month!

> 
> >
> >
> > >  static struct platform_driver ls_pcie_ep_driver = {
> > > --
> > > 2.34.1



RE: [EXT] Re: [PATCH 1/1] PCI: layerscape: Set 64-bit DMA mask

2023-02-14 Thread Frank Li
> >
> > + /* set 64-bit DMA mask and coherent DMA mask */
> > + if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)))
> > + dev_warn(dev, "Failed to set 64-bit DMA mask.\n");
> 
> Isn't this mandatory? Why not dev_err_probe and return the error?

I don't think it is mandatory. If failure, dma will use swiotlb. 
Just an additional memcpy involved. 

Frank Li

> 
> --Sean
> 
> >   platform_set_drvdata(pdev, pcie);
> >
> >   ret = dw_pcie_ep_init(>ep);



RE: [PATCH 1/1] PCI: layerscape: Add the workaround for A-010305

2023-02-14 Thread Frank Li
> -Original Message-
> From: Frank Li
> Subject: RE: [PATCH 1/1] PCI: layerscape: Add the workaround for A-010305
> 
> > Subject: [PATCH 1/1] PCI: layerscape: Add the workaround for A-010305
> >
> > From: Xiaowei Bao 
> >
> > When a link down or hot reset event occurs, the PCI Express EP
> > controller's Link Capabilities Register should retain the values of
> > the Maximum Link Width and Supported Link Speed configured by RCW.
> >
> > Signed-off-by: Xiaowei Bao 
> > Signed-off-by: Hou Zhiqiang 
> > Signed-off-by: Frank Li 
> > ---
> 
> Ping

Friendly ping. 

> 
>
> >  static struct platform_driver ls_pcie_ep_driver = {
> > --
> > 2.34.1



  1   2   >