[PATCHv5 6/6] PCI: layerscape: Add power management support

2021-04-06 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Add PME_Turn_Off/PME_TO_Ack handshake sequence, and finally
put the PCIe controller into D3 state after the L2/L3 ready
state transition process completion.

Signed-off-by: Hou Zhiqiang 
---
V5:
 - Fix a typo of the parameter given to function dw_pcie_setup_rc()

 drivers/pci/controller/dwc/pci-layerscape.c  | 382 ++-
 drivers/pci/controller/dwc/pcie-designware.h |   1 +
 2 files changed, 381 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index 71911ca4c589..868e18b12e4a 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -3,13 +3,16 @@
  * PCIe host controller driver for Freescale Layerscape SoCs
  *
  * Copyright (C) 2014 Freescale Semiconductor.
+ * Copyright 2020 NXP
  *
  * Author: Minghuan Lian 
  */
 
+#include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -27,17 +30,60 @@
 #define PCIE_ABSERR0x8d0 /* Bridge Slave Error Response Register */
 #define PCIE_ABSERR_SETTING0x9401 /* Forward error of non-posted request */
 
+/* PF Message Command Register */
+#define LS_PCIE_PF_MCR 0x2c
+#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)
+
+/* 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_IS_L2(v)   \
+   (((v) & PORT_LOGIC_LTSSM_STATE_MASK) == PORT_LOGIC_LTSSM_STATE_L2)
+
+struct ls_pcie;
+
+struct ls_pcie_host_pm_ops {
+   int (*pm_init)(struct ls_pcie *pcie);
+   void (*send_turn_off_message)(struct ls_pcie *pcie);
+   void (*exit_from_l2)(struct ls_pcie *pcie);
+};
+
 struct ls_pcie_drvdata {
+   const u32 pf_off;
+   const u32 lut_off;
const struct dw_pcie_host_ops *ops;
+   const struct ls_pcie_host_pm_ops *pm_ops;
 };
 
 struct ls_pcie {
struct dw_pcie *pci;
const struct ls_pcie_drvdata *drvdata;
+   void __iomem *pf_base;
+   void __iomem *lut_base;
+   bool big_endian;
+   bool ep_presence;
+   bool pm_support;
+   struct regmap *scfg;
+   int index;
 };
 
+#define ls_pcie_lut_readl_addr(addr)   ls_pcie_lut_readl(pcie, addr)
+#define ls_pcie_pf_readl_addr(addr)ls_pcie_pf_readl(pcie, addr)
 #define to_ls_pcie(x)  dev_get_drvdata((x)->dev)
 
 static bool ls_pcie_is_bridge(struct ls_pcie *pcie)
@@ -78,6 +124,210 @@ static void ls_pcie_fix_error_response(struct ls_pcie 
*pcie)
iowrite32(PCIE_ABSERR_SETTING, pci->dbi_base + PCIE_ABSERR);
 }
 
+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)
+   return iowrite32be(val, pcie->lut_base + off);
+
+   return iowrite32(val, pcie->lut_base + off);
+
+}
+
+static u32 ls_pcie_pf_readl(struct ls_pcie *pcie, u32 off)
+{
+   if (pcie->big_endian)
+   return ioread32be(pcie->pf_base + off);
+
+   return ioread32(pcie->pf_base + off);
+}
+
+static void ls_pcie_pf_writel(struct ls_pcie *pcie, u32 off, u32 val)
+{
+   if (pcie->big_endian)
+   return iowrite32be(val, pcie->pf_base + off);
+
+   return iowrite32(val, pcie->pf_base + off);
+
+}
+
+static void ls_pcie_send_turnoff_msg(struct ls_pcie *pcie)
+{
+   u32 val;
+   int ret;
+
+   val = ls_pcie_pf_readl(pcie, LS_PCIE_PF_MCR);
+   val |= PF_MCR_PTOMR;
+   ls_pcie_pf_writel(pcie, LS_PCIE_PF_MCR, val);
+
+   ret = readx_poll_timeout(ls_pcie_pf_readl_addr, LS_PCIE_PF_MCR,
+val, !(val & PF_MCR_PTOMR), 100, 1);
+   if (ret)
+   dev_info(pcie->pci->dev, "poll turn off message timeout\n");
+}
+
+static void ls1021a_pcie_send_turnoff_msg(struct ls_pcie *pcie)
+{
+   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);
+
+   mdelay(10);
+
+   /* Clear Turn_off message */
+   regmap_read(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), );
+   val &= ~PMXMTTURNOFF;
+   regmap_write(pcie->scfg, 

[PATCHv5 5/6] arm64: dts: ls1043a: Add SCFG phandle for PCIe nodes

2021-04-06 Thread Zhiqiang Hou
From: Hou Zhiqiang 

The LS1043A PCIe controller has some control registers
in SCFG block, so add the SCFG phandle for each PCIe
controller DT node.

Signed-off-by: Hou Zhiqiang 
---
V5:
 - No change

 arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index 46826752a691..704e9e249729 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -875,6 +875,7 @@
interrupts = <0 118 0x4>, /* controller interrupt */
 <0 117 0x4>; /* PME interrupt */
interrupt-names = "intr", "pme";
+   fsl,pcie-scfg = < 0>;
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
@@ -902,6 +903,7 @@
interrupts = <0 128 0x4>,
 <0 127 0x4>;
interrupt-names = "intr", "pme";
+   fsl,pcie-scfg = < 1>;
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
@@ -929,6 +931,7 @@
interrupts = <0 162 0x4>,
 <0 161 0x4>;
interrupt-names = "intr", "pme";
+   fsl,pcie-scfg = < 2>;
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
-- 
2.17.1



[PATCHv5 4/6] dt-bindings: pci: layerscape-pci: Update the description of SCFG property

2021-04-06 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Update the description of the second entry of 'fsl,pcie-scfg' property,
as the LS1043A PCIe controller also has some control registers in SCFG
block, while it has 3 controllers.

Signed-off-by: Hou Zhiqiang 
Acked-by: Rob Herring 
---
V5:
 - No change

 Documentation/devicetree/bindings/pci/layerscape-pci.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/pci/layerscape-pci.txt 
b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
index d633c1fabdb4..8231f6729385 100644
--- a/Documentation/devicetree/bindings/pci/layerscape-pci.txt
+++ b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
@@ -34,7 +34,7 @@ Required properties:
   "intr": The interrupt that is asserted for controller interrupts
 - fsl,pcie-scfg: Must include two entries.
   The first entry must be a link to the SCFG device node
-  The second entry must be '0' or '1' based on physical PCIe controller index.
+  The second entry is the physical PCIe controller index starting from '0'.
   This is used to get SCFG PEXN registers
 - dma-coherent: Indicates that the hardware IP block can ensure the coherency
   of the data transferred from/to the IP block. This can avoid the software
-- 
2.17.1



[PATCHv5 3/6] arm64: dts: layerscape: Add big-endian property for PCIe nodes

2021-04-06 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Add the big-endian property for LS1012A, LS1043A and LS1046A
PCIe devicetree nodes.

Signed-off-by: Hou Zhiqiang 
---
V5:
 - No change

 arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi | 1 +
 arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 3 +++
 arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 3 +++
 3 files changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
index 9058cfa4980f..ac23e938fd1d 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
@@ -542,6 +542,7 @@
< 0 0 2  0 111 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 3  0 112 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 4  0 113 
IRQ_TYPE_LEVEL_HIGH>;
+   big-endian;
status = "disabled";
};
 
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index 28c51e521cb2..46826752a691 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -890,6 +890,7 @@
< 0 0 2  0 111 0x4>,
< 0 0 3  0 112 0x4>,
< 0 0 4  0 113 0x4>;
+   big-endian;
status = "disabled";
};
 
@@ -916,6 +917,7 @@
< 0 0 2  0 121 0x4>,
< 0 0 3  0 122 0x4>,
< 0 0 4  0 123 0x4>;
+   big-endian;
status = "disabled";
};
 
@@ -942,6 +944,7 @@
< 0 0 2  0 155 0x4>,
< 0 0 3  0 156 0x4>,
< 0 0 4  0 157 0x4>;
+   big-endian;
status = "disabled";
};
 
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
index 39458305e333..f21ee7825d40 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
@@ -794,6 +794,7 @@
< 0 0 2  GIC_SPI 110 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 3  GIC_SPI 110 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 4  GIC_SPI 110 
IRQ_TYPE_LEVEL_HIGH>;
+   big-endian;
status = "disabled";
};
 
@@ -830,6 +831,7 @@
< 0 0 2  GIC_SPI 120 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 3  GIC_SPI 120 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 4  GIC_SPI 120 
IRQ_TYPE_LEVEL_HIGH>;
+   big-endian;
status = "disabled";
};
 
@@ -866,6 +868,7 @@
< 0 0 2  GIC_SPI 154 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 3  GIC_SPI 154 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 4  GIC_SPI 154 
IRQ_TYPE_LEVEL_HIGH>;
+   big-endian;
status = "disabled";
};
 
-- 
2.17.1



[PATCHv5 2/6] dt-bindings: pci: layerscape-pci: Add a optional property big-endian

2021-04-06 Thread Zhiqiang Hou
From: Hou Zhiqiang 

This property is to indicate the endianness when accessing the
PEX_LUT and PF register block, so if these registers are
implemented in big-endian, specify this property.

Signed-off-by: Hou Zhiqiang 
Acked-by: Rob Herring 
---
V5:
 - No change

 Documentation/devicetree/bindings/pci/layerscape-pci.txt | 4 
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/pci/layerscape-pci.txt 
b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
index 6d898dd4a8e2..d633c1fabdb4 100644
--- a/Documentation/devicetree/bindings/pci/layerscape-pci.txt
+++ b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
@@ -40,6 +40,10 @@ Required properties:
   of the data transferred from/to the IP block. This can avoid the software
   cache flush/invalid actions, and improve the performance significantly.
 
+Optional properties:
+- big-endian: If the PEX_LUT and PF register block is in big-endian, specify
+  this property.
+
 Example:
 
pcie@340 {
-- 
2.17.1



[PATCHv5 1/6] PCI: layerscape: Change to use the DWC common link-up check function

2021-04-06 Thread Zhiqiang Hou
From: Hou Zhiqiang 

The current Layerscape PCIe driver directly uses the physical layer
LTSSM code to check the link-up state, which treats the > L0 states
as link-up. This is not correct, since there is not explicit map
between link-up state and LTSSM. So this patch changes to use the
DWC common link-up check function.

Signed-off-by: Hou Zhiqiang 
Reviewed-by: Rob Herring 
---
V5:
 - No change

 drivers/pci/controller/dwc/pci-layerscape.c | 140 ++--
 1 file changed, 10 insertions(+), 130 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index 5b9c625df7b8..71911ca4c589 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -22,12 +22,6 @@
 
 #include "pcie-designware.h"
 
-/* PEX1/2 Misc Ports Status Register */
-#define SCFG_PEXMSCPORTSR(pex_idx) (0x94 + (pex_idx) * 4)
-#define LTSSM_STATE_SHIFT  20
-#define LTSSM_STATE_MASK   0x3f
-#define LTSSM_PCIE_L0  0x11 /* L0 state */
-
 /* PEX Internal Configuration Registers */
 #define PCIE_STRFMR1   0x71c /* Symbol Timer & Filter Mask Register1 */
 #define PCIE_ABSERR0x8d0 /* Bridge Slave Error Response Register */
@@ -36,19 +30,12 @@
 #define PCIE_IATU_NUM  6
 
 struct ls_pcie_drvdata {
-   u32 lut_offset;
-   u32 ltssm_shift;
-   u32 lut_dbg;
const struct dw_pcie_host_ops *ops;
-   const struct dw_pcie_ops *dw_pcie_ops;
 };
 
 struct ls_pcie {
struct dw_pcie *pci;
-   void __iomem *lut;
-   struct regmap *scfg;
const struct ls_pcie_drvdata *drvdata;
-   int index;
 };
 
 #define to_ls_pcie(x)  dev_get_drvdata((x)->dev)
@@ -83,38 +70,6 @@ static void ls_pcie_drop_msg_tlp(struct ls_pcie *pcie)
iowrite32(val, pci->dbi_base + PCIE_STRFMR1);
 }
 
-static int ls1021_pcie_link_up(struct dw_pcie *pci)
-{
-   u32 state;
-   struct ls_pcie *pcie = to_ls_pcie(pci);
-
-   if (!pcie->scfg)
-   return 0;
-
-   regmap_read(pcie->scfg, SCFG_PEXMSCPORTSR(pcie->index), );
-   state = (state >> LTSSM_STATE_SHIFT) & LTSSM_STATE_MASK;
-
-   if (state < LTSSM_PCIE_L0)
-   return 0;
-
-   return 1;
-}
-
-static int ls_pcie_link_up(struct dw_pcie *pci)
-{
-   struct ls_pcie *pcie = to_ls_pcie(pci);
-   u32 state;
-
-   state = (ioread32(pcie->lut + pcie->drvdata->lut_dbg) >>
-pcie->drvdata->ltssm_shift) &
-LTSSM_STATE_MASK;
-
-   if (state < LTSSM_PCIE_L0)
-   return 0;
-
-   return 1;
-}
-
 /* Forward error response of outbound non-posted requests */
 static void ls_pcie_fix_error_response(struct ls_pcie *pcie)
 {
@@ -139,96 +94,24 @@ static int ls_pcie_host_init(struct pcie_port *pp)
return 0;
 }
 
-static int ls1021_pcie_host_init(struct pcie_port *pp)
-{
-   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
-   struct ls_pcie *pcie = to_ls_pcie(pci);
-   struct device *dev = pci->dev;
-   u32 index[2];
-   int 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;
-   }
-
-   if (of_property_read_u32_array(dev->of_node,
-  "fsl,pcie-scfg", index, 2)) {
-   pcie->scfg = NULL;
-   return -EINVAL;
-   }
-   pcie->index = index[1];
-
-   return ls_pcie_host_init(pp);
-}
-
-static const struct dw_pcie_host_ops ls1021_pcie_host_ops = {
-   .host_init = ls1021_pcie_host_init,
-};
-
 static const struct dw_pcie_host_ops ls_pcie_host_ops = {
.host_init = ls_pcie_host_init,
 };
 
-static const struct dw_pcie_ops dw_ls1021_pcie_ops = {
-   .link_up = ls1021_pcie_link_up,
-};
-
-static const struct dw_pcie_ops dw_ls_pcie_ops = {
-   .link_up = ls_pcie_link_up,
-};
-
-static const struct ls_pcie_drvdata ls1021_drvdata = {
-   .ops = _pcie_host_ops,
-   .dw_pcie_ops = _ls1021_pcie_ops,
-};
-
-static const struct ls_pcie_drvdata ls1043_drvdata = {
-   .lut_offset = 0x1,
-   .ltssm_shift = 24,
-   .lut_dbg = 0x7fc,
+static const struct ls_pcie_drvdata layerscape_drvdata = {
.ops = _pcie_host_ops,
-   .dw_pcie_ops = _ls_pcie_ops,
-};
-
-static const struct ls_pcie_drvdata ls1046_drvdata = {
-   .lut_offset = 0x8,
-   .ltssm_shift = 24,
-   .lut_dbg = 0x407fc,
-   .ops = _pcie_host_ops,
-   .dw_pcie_ops = _ls_pcie_ops,
-};
-
-static const struct ls_pcie_drvdata ls2080_drvdata = {
-   .lut_offset = 0x8,
-   .ltssm_shift = 0,
-   .lut_dbg = 0x7fc,
-   .ops = _pcie_host_ops,
-   .dw_pcie_ops = _ls_pcie_ops,
-};
-
-static const struct 

[PATCHv5 0/6] PCI: layerscape: Add power management support

2021-04-06 Thread Zhiqiang Hou
From: Hou Zhiqiang 

This patch series is to add PCIe power management support for NXP
Layerscape platforms.

Hou Zhiqiang (6):
  PCI: layerscape: Change to use the DWC common link-up check function
  dt-bindings: pci: layerscape-pci: Add a optional property big-endian
  arm64: dts: layerscape: Add big-endian property for PCIe nodes
  dt-bindings: pci: layerscape-pci: Update the description of SCFG
property
  arm64: dts: ls1043a: Add SCFG phandle for PCIe nodes
  PCI: layerscape: Add power management support

 .../bindings/pci/layerscape-pci.txt   |   6 +-
 .../arm64/boot/dts/freescale/fsl-ls1012a.dtsi |   1 +
 .../arm64/boot/dts/freescale/fsl-ls1043a.dtsi |   6 +
 .../arm64/boot/dts/freescale/fsl-ls1046a.dtsi |   3 +
 drivers/pci/controller/dwc/pci-layerscape.c   | 450 ++
 drivers/pci/controller/dwc/pcie-designware.h  |   1 +
 6 files changed, 370 insertions(+), 97 deletions(-)

-- 
2.17.1



[PATCH] PCI: dwc: Change the inheritance between the abstracted structures

2021-04-06 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Currently the core struct dw_pcie includes both struct pcie_port
and dw_pcie_ep and the RC and EP platform drivers directly
includes the dw_pcie. So it results in a RC or EP platform driver
has 2 indirect parents pcie_port and dw_pcie_ep, but it doesn't
make sense let RC platform driver includes the dw_pcie_ep and
so does the EP platform driver.

This patch makes the struct pcie_port and dw_pcie_ep includes
the core struct dw_pcie and the RC and EP platform drivers
include struct pcie_port and dw_pcie_ep respectively.

Signed-off-by: Hou Zhiqiang 
Cc: Kishon Vijay Abraham I 
Cc: Lorenzo Pieralisi 
Cc: Rob Herring 
Cc: Bjorn Helgaas 
Cc: Jingoo Han 
Cc: Richard Zhu 
Cc: Lucas Stach 
Cc: Murali Karicheri 
Cc: Minghuan Lian 
Cc: Mingkai Hu 
Cc: Roy Zang 
Cc: Yue Wang 
Cc: Jonathan Chocron 
Cc: Thomas Petazzoni 
Cc: Jesper Nilsson 
Cc: Gustavo Pimentel 
Cc: Xiaowei Song 
Cc: Binghui Wang 
Cc: Stanimir Varbanov 
Cc: Pratyush Anand 
Cc: Kunihiko Hayashi 
Cc: Jason Yan 
Cc: Thierry Reding 
---
 drivers/pci/controller/dwc/pci-dra7xx.c   |  74 +---
 drivers/pci/controller/dwc/pci-exynos.c   |  26 +--
 drivers/pci/controller/dwc/pci-imx6.c |  46 +++--
 drivers/pci/controller/dwc/pci-keystone.c |  79 +---
 .../pci/controller/dwc/pci-layerscape-ep.c|  18 +-
 drivers/pci/controller/dwc/pci-layerscape.c   |  51 +++---
 drivers/pci/controller/dwc/pci-meson.c|  25 +--
 drivers/pci/controller/dwc/pcie-al.c  |  21 ++-
 drivers/pci/controller/dwc/pcie-armada8k.c|  17 +-
 drivers/pci/controller/dwc/pcie-artpec6.c |  74 +---
 .../pci/controller/dwc/pcie-designware-host.c |   2 +-
 .../pci/controller/dwc/pcie-designware-plat.c |  38 ++--
 drivers/pci/controller/dwc/pcie-designware.h  |  72 
 drivers/pci/controller/dwc/pcie-histb.c   |  27 +--
 drivers/pci/controller/dwc/pcie-intel-gw.c|  42 +++--
 drivers/pci/controller/dwc/pcie-kirin.c   |  42 +++--
 drivers/pci/controller/dwc/pcie-qcom.c|  40 ++---
 drivers/pci/controller/dwc/pcie-spear13xx.c   |  16 +-
 drivers/pci/controller/dwc/pcie-tegra194.c| 169 +++---
 drivers/pci/controller/dwc/pcie-uniphier-ep.c |  14 +-
 drivers/pci/controller/dwc/pcie-uniphier.c|  17 +-
 21 files changed, 557 insertions(+), 353 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-dra7xx.c 
b/drivers/pci/controller/dwc/pci-dra7xx.c
index 12726c63366f..0e914df6eaba 100644
--- a/drivers/pci/controller/dwc/pci-dra7xx.c
+++ b/drivers/pci/controller/dwc/pci-dra7xx.c
@@ -85,7 +85,8 @@
 #define PCIE_B0_B1_TSYNCEN BIT(0)
 
 struct dra7xx_pcie {
-   struct dw_pcie  *pci;
+   struct pcie_port*pp;
+   struct dw_pcie_ep   *ep;
void __iomem*base;  /* DT ti_conf */
int phy_count;  /* DT phy-names count */
struct phy  **phy;
@@ -290,11 +291,19 @@ static void dra7xx_pcie_msi_irq_handler(struct irq_desc 
*desc)
 static irqreturn_t dra7xx_pcie_irq_handler(int irq, void *arg)
 {
struct dra7xx_pcie *dra7xx = arg;
-   struct dw_pcie *pci = dra7xx->pci;
-   struct device *dev = pci->dev;
-   struct dw_pcie_ep *ep = >ep;
+   struct dw_pcie_ep *ep;
+   struct dw_pcie *pci;
+   struct device *dev;
u32 reg;
 
+   if (dra7xx->mode == DW_PCIE_RC_TYPE) {
+   pci = to_dw_pcie_from_pp(dra7xx->pp);
+   } else {
+   ep = dra7xx->ep;
+   pci = to_dw_pcie_from_ep(ep);
+   }
+
+   dev = pci->dev;
reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN);
 
if (reg & ERR_SYS)
@@ -447,11 +456,10 @@ static int __init dra7xx_add_pcie_ep(struct dra7xx_pcie 
*dra7xx,
 struct platform_device *pdev)
 {
int ret;
-   struct dw_pcie_ep *ep;
+   struct dw_pcie_ep *ep = dra7xx->ep;
+   struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
struct device *dev = >dev;
-   struct dw_pcie *pci = dra7xx->pci;
 
-   ep = >ep;
ep->ops = _ep_ops;
 
pci->dbi_base = devm_platform_ioremap_resource_byname(pdev, "ep_dbics");
@@ -476,8 +484,8 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie 
*dra7xx,
   struct platform_device *pdev)
 {
int ret;
-   struct dw_pcie *pci = dra7xx->pci;
-   struct pcie_port *pp = >pp;
+   struct pcie_port *pp = dra7xx->pp;
+   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct device *dev = pci->dev;
 
pp->irq = platform_get_irq(pdev, 1);
@@ -693,6 +701,8 @@ static int __init dra7xx_pcie_probe(struct platform_device 
*pdev)
struct device_link **link;
void __iomem *base;
struct dw_pcie *pci;
+   struct pcie_port *pp;
+   struct dw_pcie_ep *ep;
struct dra7xx_pcie *dra7xx;
struct device *dev = >dev;
struct device_node *np = 

[PATCHv4 5/6] arm64: dts: ls1043a: Add SCFG phandle for PCIe nodes

2021-04-06 Thread Zhiqiang Hou
From: Hou Zhiqiang 

The LS1043A PCIe controller has some control registers
in SCFG block, so add the SCFG phandle for each PCIe
controller DT node.

Signed-off-by: Hou Zhiqiang 
---
V4:
 - Rebased against the latest code base

 arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index 46826752a691..704e9e249729 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -875,6 +875,7 @@
interrupts = <0 118 0x4>, /* controller interrupt */
 <0 117 0x4>; /* PME interrupt */
interrupt-names = "intr", "pme";
+   fsl,pcie-scfg = < 0>;
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
@@ -902,6 +903,7 @@
interrupts = <0 128 0x4>,
 <0 127 0x4>;
interrupt-names = "intr", "pme";
+   fsl,pcie-scfg = < 1>;
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
@@ -929,6 +931,7 @@
interrupts = <0 162 0x4>,
 <0 161 0x4>;
interrupt-names = "intr", "pme";
+   fsl,pcie-scfg = < 2>;
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
-- 
2.17.1



[PATCHv4 6/6] PCI: layerscape: Add power management support

2021-04-06 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Add PME_Turn_Off/PME_TO_Ack handshake sequence, and finally
put the PCIe controller into D3 state after the L2/L3 ready
state transition process completion.

Signed-off-by: Hou Zhiqiang 
---
V4:
 - Rebased against the latest code base

 drivers/pci/controller/dwc/pci-layerscape.c  | 382 ++-
 drivers/pci/controller/dwc/pcie-designware.h |   1 +
 2 files changed, 381 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index 71911ca4c589..868e18b12e4a 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -3,13 +3,16 @@
  * PCIe host controller driver for Freescale Layerscape SoCs
  *
  * Copyright (C) 2014 Freescale Semiconductor.
+ * Copyright 2020 NXP
  *
  * Author: Minghuan Lian 
  */
 
+#include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -27,17 +30,60 @@
 #define PCIE_ABSERR0x8d0 /* Bridge Slave Error Response Register */
 #define PCIE_ABSERR_SETTING0x9401 /* Forward error of non-posted request */
 
+/* PF Message Command Register */
+#define LS_PCIE_PF_MCR 0x2c
+#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)
+
+/* 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_IS_L2(v)   \
+   (((v) & PORT_LOGIC_LTSSM_STATE_MASK) == PORT_LOGIC_LTSSM_STATE_L2)
+
+struct ls_pcie;
+
+struct ls_pcie_host_pm_ops {
+   int (*pm_init)(struct ls_pcie *pcie);
+   void (*send_turn_off_message)(struct ls_pcie *pcie);
+   void (*exit_from_l2)(struct ls_pcie *pcie);
+};
+
 struct ls_pcie_drvdata {
+   const u32 pf_off;
+   const u32 lut_off;
const struct dw_pcie_host_ops *ops;
+   const struct ls_pcie_host_pm_ops *pm_ops;
 };
 
 struct ls_pcie {
struct dw_pcie *pci;
const struct ls_pcie_drvdata *drvdata;
+   void __iomem *pf_base;
+   void __iomem *lut_base;
+   bool big_endian;
+   bool ep_presence;
+   bool pm_support;
+   struct regmap *scfg;
+   int index;
 };
 
+#define ls_pcie_lut_readl_addr(addr)   ls_pcie_lut_readl(pcie, addr)
+#define ls_pcie_pf_readl_addr(addr)ls_pcie_pf_readl(pcie, addr)
 #define to_ls_pcie(x)  dev_get_drvdata((x)->dev)
 
 static bool ls_pcie_is_bridge(struct ls_pcie *pcie)
@@ -78,6 +124,210 @@ static void ls_pcie_fix_error_response(struct ls_pcie 
*pcie)
iowrite32(PCIE_ABSERR_SETTING, pci->dbi_base + PCIE_ABSERR);
 }
 
+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)
+   return iowrite32be(val, pcie->lut_base + off);
+
+   return iowrite32(val, pcie->lut_base + off);
+
+}
+
+static u32 ls_pcie_pf_readl(struct ls_pcie *pcie, u32 off)
+{
+   if (pcie->big_endian)
+   return ioread32be(pcie->pf_base + off);
+
+   return ioread32(pcie->pf_base + off);
+}
+
+static void ls_pcie_pf_writel(struct ls_pcie *pcie, u32 off, u32 val)
+{
+   if (pcie->big_endian)
+   return iowrite32be(val, pcie->pf_base + off);
+
+   return iowrite32(val, pcie->pf_base + off);
+
+}
+
+static void ls_pcie_send_turnoff_msg(struct ls_pcie *pcie)
+{
+   u32 val;
+   int ret;
+
+   val = ls_pcie_pf_readl(pcie, LS_PCIE_PF_MCR);
+   val |= PF_MCR_PTOMR;
+   ls_pcie_pf_writel(pcie, LS_PCIE_PF_MCR, val);
+
+   ret = readx_poll_timeout(ls_pcie_pf_readl_addr, LS_PCIE_PF_MCR,
+val, !(val & PF_MCR_PTOMR), 100, 1);
+   if (ret)
+   dev_info(pcie->pci->dev, "poll turn off message timeout\n");
+}
+
+static void ls1021a_pcie_send_turnoff_msg(struct ls_pcie *pcie)
+{
+   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);
+
+   mdelay(10);
+
+   /* Clear Turn_off message */
+   regmap_read(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), );
+   val &= ~PMXMTTURNOFF;
+   regmap_write(pcie->scfg, 

[PATCHv4 4/6] dt-bindings: pci: layerscape-pci: Update the description of SCFG property

2021-04-06 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Update the description of the second entry of 'fsl,pcie-scfg' property,
as the LS1043A PCIe controller also has some control registers in SCFG
block, while it has 3 controllers.

Signed-off-by: Hou Zhiqiang 
Acked-by: Rob Herring 
---
V4:
 - Rebased against the latest code base

 Documentation/devicetree/bindings/pci/layerscape-pci.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/pci/layerscape-pci.txt 
b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
index d633c1fabdb4..8231f6729385 100644
--- a/Documentation/devicetree/bindings/pci/layerscape-pci.txt
+++ b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
@@ -34,7 +34,7 @@ Required properties:
   "intr": The interrupt that is asserted for controller interrupts
 - fsl,pcie-scfg: Must include two entries.
   The first entry must be a link to the SCFG device node
-  The second entry must be '0' or '1' based on physical PCIe controller index.
+  The second entry is the physical PCIe controller index starting from '0'.
   This is used to get SCFG PEXN registers
 - dma-coherent: Indicates that the hardware IP block can ensure the coherency
   of the data transferred from/to the IP block. This can avoid the software
-- 
2.17.1



[PATCHv4 3/6] arm64: dts: layerscape: Add big-endian property for PCIe nodes

2021-04-06 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Add the big-endian property for LS1012A, LS1043A and LS1046A
PCIe devicetree nodes.

Signed-off-by: Hou Zhiqiang 
---
V4:
 - Rebased against the latest code base

 arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi | 1 +
 arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 3 +++
 arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 3 +++
 3 files changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
index 9058cfa4980f..ac23e938fd1d 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
@@ -542,6 +542,7 @@
< 0 0 2  0 111 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 3  0 112 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 4  0 113 
IRQ_TYPE_LEVEL_HIGH>;
+   big-endian;
status = "disabled";
};
 
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index 28c51e521cb2..46826752a691 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -890,6 +890,7 @@
< 0 0 2  0 111 0x4>,
< 0 0 3  0 112 0x4>,
< 0 0 4  0 113 0x4>;
+   big-endian;
status = "disabled";
};
 
@@ -916,6 +917,7 @@
< 0 0 2  0 121 0x4>,
< 0 0 3  0 122 0x4>,
< 0 0 4  0 123 0x4>;
+   big-endian;
status = "disabled";
};
 
@@ -942,6 +944,7 @@
< 0 0 2  0 155 0x4>,
< 0 0 3  0 156 0x4>,
< 0 0 4  0 157 0x4>;
+   big-endian;
status = "disabled";
};
 
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
index 39458305e333..f21ee7825d40 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
@@ -794,6 +794,7 @@
< 0 0 2  GIC_SPI 110 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 3  GIC_SPI 110 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 4  GIC_SPI 110 
IRQ_TYPE_LEVEL_HIGH>;
+   big-endian;
status = "disabled";
};
 
@@ -830,6 +831,7 @@
< 0 0 2  GIC_SPI 120 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 3  GIC_SPI 120 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 4  GIC_SPI 120 
IRQ_TYPE_LEVEL_HIGH>;
+   big-endian;
status = "disabled";
};
 
@@ -866,6 +868,7 @@
< 0 0 2  GIC_SPI 154 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 3  GIC_SPI 154 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 4  GIC_SPI 154 
IRQ_TYPE_LEVEL_HIGH>;
+   big-endian;
status = "disabled";
};
 
-- 
2.17.1



[PATCHv4 2/6] dt-bindings: pci: layerscape-pci: Add a optional property big-endian

2021-04-06 Thread Zhiqiang Hou
From: Hou Zhiqiang 

This property is to indicate the endianness when accessing the
PEX_LUT and PF register block, so if these registers are
implemented in big-endian, specify this property.

Signed-off-by: Hou Zhiqiang 
Acked-by: Rob Herring 
---
V4:
 - Rebased against the latest code base

 Documentation/devicetree/bindings/pci/layerscape-pci.txt | 4 
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/pci/layerscape-pci.txt 
b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
index 6d898dd4a8e2..d633c1fabdb4 100644
--- a/Documentation/devicetree/bindings/pci/layerscape-pci.txt
+++ b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
@@ -40,6 +40,10 @@ Required properties:
   of the data transferred from/to the IP block. This can avoid the software
   cache flush/invalid actions, and improve the performance significantly.
 
+Optional properties:
+- big-endian: If the PEX_LUT and PF register block is in big-endian, specify
+  this property.
+
 Example:
 
pcie@340 {
-- 
2.17.1



[PATCHv4 1/6] PCI: layerscape: Change to use the DWC common link-up check function

2021-04-06 Thread Zhiqiang Hou
From: Hou Zhiqiang 

The current Layerscape PCIe driver directly uses the physical layer
LTSSM code to check the link-up state, which treats the > L0 states
as link-up. This is not correct, since there is not explicit map
between link-up state and LTSSM. So this patch changes to use the
DWC common link-up check function.

Signed-off-by: Hou Zhiqiang 
Reviewed-by: Rob Herring 
---
V4:
 - Rebased against the latest code base

 drivers/pci/controller/dwc/pci-layerscape.c | 140 ++--
 1 file changed, 10 insertions(+), 130 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index 5b9c625df7b8..71911ca4c589 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -22,12 +22,6 @@
 
 #include "pcie-designware.h"
 
-/* PEX1/2 Misc Ports Status Register */
-#define SCFG_PEXMSCPORTSR(pex_idx) (0x94 + (pex_idx) * 4)
-#define LTSSM_STATE_SHIFT  20
-#define LTSSM_STATE_MASK   0x3f
-#define LTSSM_PCIE_L0  0x11 /* L0 state */
-
 /* PEX Internal Configuration Registers */
 #define PCIE_STRFMR1   0x71c /* Symbol Timer & Filter Mask Register1 */
 #define PCIE_ABSERR0x8d0 /* Bridge Slave Error Response Register */
@@ -36,19 +30,12 @@
 #define PCIE_IATU_NUM  6
 
 struct ls_pcie_drvdata {
-   u32 lut_offset;
-   u32 ltssm_shift;
-   u32 lut_dbg;
const struct dw_pcie_host_ops *ops;
-   const struct dw_pcie_ops *dw_pcie_ops;
 };
 
 struct ls_pcie {
struct dw_pcie *pci;
-   void __iomem *lut;
-   struct regmap *scfg;
const struct ls_pcie_drvdata *drvdata;
-   int index;
 };
 
 #define to_ls_pcie(x)  dev_get_drvdata((x)->dev)
@@ -83,38 +70,6 @@ static void ls_pcie_drop_msg_tlp(struct ls_pcie *pcie)
iowrite32(val, pci->dbi_base + PCIE_STRFMR1);
 }
 
-static int ls1021_pcie_link_up(struct dw_pcie *pci)
-{
-   u32 state;
-   struct ls_pcie *pcie = to_ls_pcie(pci);
-
-   if (!pcie->scfg)
-   return 0;
-
-   regmap_read(pcie->scfg, SCFG_PEXMSCPORTSR(pcie->index), );
-   state = (state >> LTSSM_STATE_SHIFT) & LTSSM_STATE_MASK;
-
-   if (state < LTSSM_PCIE_L0)
-   return 0;
-
-   return 1;
-}
-
-static int ls_pcie_link_up(struct dw_pcie *pci)
-{
-   struct ls_pcie *pcie = to_ls_pcie(pci);
-   u32 state;
-
-   state = (ioread32(pcie->lut + pcie->drvdata->lut_dbg) >>
-pcie->drvdata->ltssm_shift) &
-LTSSM_STATE_MASK;
-
-   if (state < LTSSM_PCIE_L0)
-   return 0;
-
-   return 1;
-}
-
 /* Forward error response of outbound non-posted requests */
 static void ls_pcie_fix_error_response(struct ls_pcie *pcie)
 {
@@ -139,96 +94,24 @@ static int ls_pcie_host_init(struct pcie_port *pp)
return 0;
 }
 
-static int ls1021_pcie_host_init(struct pcie_port *pp)
-{
-   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
-   struct ls_pcie *pcie = to_ls_pcie(pci);
-   struct device *dev = pci->dev;
-   u32 index[2];
-   int 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;
-   }
-
-   if (of_property_read_u32_array(dev->of_node,
-  "fsl,pcie-scfg", index, 2)) {
-   pcie->scfg = NULL;
-   return -EINVAL;
-   }
-   pcie->index = index[1];
-
-   return ls_pcie_host_init(pp);
-}
-
-static const struct dw_pcie_host_ops ls1021_pcie_host_ops = {
-   .host_init = ls1021_pcie_host_init,
-};
-
 static const struct dw_pcie_host_ops ls_pcie_host_ops = {
.host_init = ls_pcie_host_init,
 };
 
-static const struct dw_pcie_ops dw_ls1021_pcie_ops = {
-   .link_up = ls1021_pcie_link_up,
-};
-
-static const struct dw_pcie_ops dw_ls_pcie_ops = {
-   .link_up = ls_pcie_link_up,
-};
-
-static const struct ls_pcie_drvdata ls1021_drvdata = {
-   .ops = _pcie_host_ops,
-   .dw_pcie_ops = _ls1021_pcie_ops,
-};
-
-static const struct ls_pcie_drvdata ls1043_drvdata = {
-   .lut_offset = 0x1,
-   .ltssm_shift = 24,
-   .lut_dbg = 0x7fc,
+static const struct ls_pcie_drvdata layerscape_drvdata = {
.ops = _pcie_host_ops,
-   .dw_pcie_ops = _ls_pcie_ops,
-};
-
-static const struct ls_pcie_drvdata ls1046_drvdata = {
-   .lut_offset = 0x8,
-   .ltssm_shift = 24,
-   .lut_dbg = 0x407fc,
-   .ops = _pcie_host_ops,
-   .dw_pcie_ops = _ls_pcie_ops,
-};
-
-static const struct ls_pcie_drvdata ls2080_drvdata = {
-   .lut_offset = 0x8,
-   .ltssm_shift = 0,
-   .lut_dbg = 0x7fc,
-   .ops = _pcie_host_ops,
-   .dw_pcie_ops = _ls_pcie_ops,
-};
-
-static 

[PATCHv4 0/6] PCI: layerscape: Add power management support

2021-04-06 Thread Zhiqiang Hou
From: Hou Zhiqiang 

This patch series is to add PCIe power management support for NXP
Layerscape platforms.

Hou Zhiqiang (6):
  PCI: layerscape: Change to use the DWC common link-up check function
  dt-bindings: pci: layerscape-pci: Add a optional property big-endian
  arm64: dts: layerscape: Add big-endian property for PCIe nodes
  dt-bindings: pci: layerscape-pci: Update the description of SCFG
property
  arm64: dts: ls1043a: Add SCFG phandle for PCIe nodes
  PCI: layerscape: Add power management support

 .../bindings/pci/layerscape-pci.txt   |   6 +-
 .../arm64/boot/dts/freescale/fsl-ls1012a.dtsi |   1 +
 .../arm64/boot/dts/freescale/fsl-ls1043a.dtsi |   6 +
 .../arm64/boot/dts/freescale/fsl-ls1046a.dtsi |   3 +
 drivers/pci/controller/dwc/pci-layerscape.c   | 450 ++
 drivers/pci/controller/dwc/pcie-designware.h  |   1 +
 6 files changed, 370 insertions(+), 97 deletions(-)

-- 
2.17.1



[PATCH] PCI: dwc: Move forward the iATU detection process

2021-01-24 Thread Zhiqiang Hou
From: Hou Zhiqiang 

In the dw_pcie_ep_init(), it depends on the detected iATU region
numbers to allocate the in/outbound window management bit map.
It fails after the commit 281f1f99cf3a ("PCI: dwc: Detect number
of iATU windows").

So this patch move the iATU region detection into a new function,
move forward the detection to the very beginning of functions
dw_pcie_host_init() and dw_pcie_ep_init(). And also remove it
from the dw_pcie_setup(), since it's more like a software
perspective initialization step than hardware setup.

Fixes: 281f1f99cf3a ("PCI: dwc: Detect number of iATU windows")
Signed-off-by: Hou Zhiqiang 
---
 drivers/pci/controller/dwc/pcie-designware-ep.c   |  2 ++
 drivers/pci/controller/dwc/pcie-designware-host.c |  2 ++
 drivers/pci/controller/dwc/pcie-designware.c  | 11 ---
 drivers/pci/controller/dwc/pcie-designware.h  |  1 +
 4 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c 
b/drivers/pci/controller/dwc/pcie-designware-ep.c
index bcd1cd9ba8c8..fcf935bf6f5e 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -707,6 +707,8 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
}
}
 
+   dw_pcie_iatu_detect(pci);
+
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space");
if (!res)
return -EINVAL;
diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c 
b/drivers/pci/controller/dwc/pcie-designware-host.c
index 8a84c005f32b..8eae817c138d 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -316,6 +316,8 @@ int dw_pcie_host_init(struct pcie_port *pp)
return PTR_ERR(pci->dbi_base);
}
 
+   dw_pcie_iatu_detect(pci);
+
bridge = devm_pci_alloc_host_bridge(dev, 0);
if (!bridge)
return -ENOMEM;
diff --git a/drivers/pci/controller/dwc/pcie-designware.c 
b/drivers/pci/controller/dwc/pcie-designware.c
index 5b72a5448d2e..5b9bf02d918b 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -654,11 +654,9 @@ static void dw_pcie_iatu_detect_regions(struct dw_pcie 
*pci)
pci->num_ob_windows = ob;
 }
 
-void dw_pcie_setup(struct dw_pcie *pci)
+void dw_pcie_iatu_detect(struct dw_pcie *pci)
 {
-   u32 val;
struct device *dev = pci->dev;
-   struct device_node *np = dev->of_node;
struct platform_device *pdev = to_platform_device(dev);
 
if (pci->version >= 0x480A || (!pci->version &&
@@ -687,6 +685,13 @@ void dw_pcie_setup(struct dw_pcie *pci)
 
dev_info(pci->dev, "Detected iATU regions: %u outbound, %u inbound",
 pci->num_ob_windows, pci->num_ib_windows);
+}
+
+void dw_pcie_setup(struct dw_pcie *pci)
+{
+   u32 val;
+   struct device *dev = pci->dev;
+   struct device_node *np = dev->of_node;
 
if (pci->link_gen > 0)
dw_pcie_link_set_max_speed(pci, pci->link_gen);
diff --git a/drivers/pci/controller/dwc/pcie-designware.h 
b/drivers/pci/controller/dwc/pcie-designware.h
index 5d979953800d..867369d4c4f7 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -305,6 +305,7 @@ int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, u8 
func_no, int index,
 void dw_pcie_disable_atu(struct dw_pcie *pci, int index,
 enum dw_pcie_region_type type);
 void dw_pcie_setup(struct dw_pcie *pci);
+void dw_pcie_iatu_detect(struct dw_pcie *pci);
 
 static inline void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val)
 {
-- 
2.17.1



[PATCHv3 2/7] PCI: layerscape: Change to use the DWC common link-up check function

2021-01-08 Thread Zhiqiang Hou
From: Hou Zhiqiang 

The current Layerscape PCIe driver directly uses the physical layer
LTSSM code to check the link-up state, which treats the > L0 states
as link-up. This is not correct, since there is not explicit map
between link-up state and LTSSM. So this patch changes to use the
DWC common link-up check function.

Signed-off-by: Hou Zhiqiang 
Reviewed-by: Rob Herring 
---
V3:
 - Rebased against the latest code base

 drivers/pci/controller/dwc/pci-layerscape.c | 140 ++--
 1 file changed, 10 insertions(+), 130 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index 44ad34cdc3bc..906fac676b6f 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -22,12 +22,6 @@
 
 #include "pcie-designware.h"
 
-/* PEX1/2 Misc Ports Status Register */
-#define SCFG_PEXMSCPORTSR(pex_idx) (0x94 + (pex_idx) * 4)
-#define LTSSM_STATE_SHIFT  20
-#define LTSSM_STATE_MASK   0x3f
-#define LTSSM_PCIE_L0  0x11 /* L0 state */
-
 /* PEX Internal Configuration Registers */
 #define PCIE_STRFMR1   0x71c /* Symbol Timer & Filter Mask Register1 */
 #define PCIE_ABSERR0x8d0 /* Bridge Slave Error Response Register */
@@ -36,19 +30,12 @@
 #define PCIE_IATU_NUM  6
 
 struct ls_pcie_drvdata {
-   u32 lut_offset;
-   u32 ltssm_shift;
-   u32 lut_dbg;
const struct dw_pcie_host_ops *ops;
-   const struct dw_pcie_ops *dw_pcie_ops;
 };
 
 struct ls_pcie {
struct dw_pcie *pci;
-   void __iomem *lut;
-   struct regmap *scfg;
const struct ls_pcie_drvdata *drvdata;
-   int index;
 };
 
 #define to_ls_pcie(x)  dev_get_drvdata((x)->dev)
@@ -83,38 +70,6 @@ static void ls_pcie_drop_msg_tlp(struct ls_pcie *pcie)
iowrite32(val, pci->dbi_base + PCIE_STRFMR1);
 }
 
-static int ls1021_pcie_link_up(struct dw_pcie *pci)
-{
-   u32 state;
-   struct ls_pcie *pcie = to_ls_pcie(pci);
-
-   if (!pcie->scfg)
-   return 0;
-
-   regmap_read(pcie->scfg, SCFG_PEXMSCPORTSR(pcie->index), );
-   state = (state >> LTSSM_STATE_SHIFT) & LTSSM_STATE_MASK;
-
-   if (state < LTSSM_PCIE_L0)
-   return 0;
-
-   return 1;
-}
-
-static int ls_pcie_link_up(struct dw_pcie *pci)
-{
-   struct ls_pcie *pcie = to_ls_pcie(pci);
-   u32 state;
-
-   state = (ioread32(pcie->lut + pcie->drvdata->lut_dbg) >>
-pcie->drvdata->ltssm_shift) &
-LTSSM_STATE_MASK;
-
-   if (state < LTSSM_PCIE_L0)
-   return 0;
-
-   return 1;
-}
-
 /* Forward error response of outbound non-posted requests */
 static void ls_pcie_fix_error_response(struct ls_pcie *pcie)
 {
@@ -139,96 +94,24 @@ static int ls_pcie_host_init(struct pcie_port *pp)
return 0;
 }
 
-static int ls1021_pcie_host_init(struct pcie_port *pp)
-{
-   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
-   struct ls_pcie *pcie = to_ls_pcie(pci);
-   struct device *dev = pci->dev;
-   u32 index[2];
-   int 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;
-   }
-
-   if (of_property_read_u32_array(dev->of_node,
-  "fsl,pcie-scfg", index, 2)) {
-   pcie->scfg = NULL;
-   return -EINVAL;
-   }
-   pcie->index = index[1];
-
-   return ls_pcie_host_init(pp);
-}
-
-static const struct dw_pcie_host_ops ls1021_pcie_host_ops = {
-   .host_init = ls1021_pcie_host_init,
-};
-
 static const struct dw_pcie_host_ops ls_pcie_host_ops = {
.host_init = ls_pcie_host_init,
 };
 
-static const struct dw_pcie_ops dw_ls1021_pcie_ops = {
-   .link_up = ls1021_pcie_link_up,
-};
-
-static const struct dw_pcie_ops dw_ls_pcie_ops = {
-   .link_up = ls_pcie_link_up,
-};
-
-static const struct ls_pcie_drvdata ls1021_drvdata = {
-   .ops = _pcie_host_ops,
-   .dw_pcie_ops = _ls1021_pcie_ops,
-};
-
-static const struct ls_pcie_drvdata ls1043_drvdata = {
-   .lut_offset = 0x1,
-   .ltssm_shift = 24,
-   .lut_dbg = 0x7fc,
+static const struct ls_pcie_drvdata layerscape_drvdata = {
.ops = _pcie_host_ops,
-   .dw_pcie_ops = _ls_pcie_ops,
-};
-
-static const struct ls_pcie_drvdata ls1046_drvdata = {
-   .lut_offset = 0x8,
-   .ltssm_shift = 24,
-   .lut_dbg = 0x407fc,
-   .ops = _pcie_host_ops,
-   .dw_pcie_ops = _ls_pcie_ops,
-};
-
-static const struct ls_pcie_drvdata ls2080_drvdata = {
-   .lut_offset = 0x8,
-   .ltssm_shift = 0,
-   .lut_dbg = 0x7fc,
-   .ops = _pcie_host_ops,
-   .dw_pcie_ops = _ls_pcie_ops,
-};
-
-static 

[PATCHv3 4/7] arm64: dts: layerscape: Add big-endian property for PCIe nodes

2021-01-08 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Add the big-endian property for LS1012A, LS1043A and LS1046A
PCIe devicetree nodes.

Signed-off-by: Hou Zhiqiang 
---
V3:
 - Rebased against the latest code base

 arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi | 1 +
 arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 3 +++
 arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 3 +++
 3 files changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
index 626b709d1fb9..3c1ecb9d843f 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
@@ -515,6 +515,7 @@
< 0 0 2  0 111 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 3  0 112 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 4  0 113 
IRQ_TYPE_LEVEL_HIGH>;
+   big-endian;
status = "disabled";
};
 
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index bbae4b353d3f..aca45bf348b4 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -841,6 +841,7 @@
< 0 0 2  0 111 0x4>,
< 0 0 3  0 112 0x4>,
< 0 0 4  0 113 0x4>;
+   big-endian;
status = "disabled";
};
 
@@ -867,6 +868,7 @@
< 0 0 2  0 121 0x4>,
< 0 0 3  0 122 0x4>,
< 0 0 4  0 123 0x4>;
+   big-endian;
status = "disabled";
};
 
@@ -893,6 +895,7 @@
< 0 0 2  0 155 0x4>,
< 0 0 3  0 156 0x4>,
< 0 0 4  0 157 0x4>;
+   big-endian;
status = "disabled";
};
 
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
index 025e1f587662..facf396ce08a 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
@@ -745,6 +745,7 @@
< 0 0 2  GIC_SPI 110 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 3  GIC_SPI 110 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 4  GIC_SPI 110 
IRQ_TYPE_LEVEL_HIGH>;
+   big-endian;
status = "disabled";
};
 
@@ -781,6 +782,7 @@
< 0 0 2  GIC_SPI 120 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 3  GIC_SPI 120 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 4  GIC_SPI 120 
IRQ_TYPE_LEVEL_HIGH>;
+   big-endian;
status = "disabled";
};
 
@@ -817,6 +819,7 @@
< 0 0 2  GIC_SPI 154 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 3  GIC_SPI 154 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 4  GIC_SPI 154 
IRQ_TYPE_LEVEL_HIGH>;
+   big-endian;
status = "disabled";
};
 
-- 
2.17.1



[PATCHv3 7/7] PCI: layerscape: Add power management support

2021-01-08 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Add PME_Turn_Off/PME_TO_Ack handshake sequence, and finally
put the PCIe controller into D3 state after the L2/L3 ready
state transition process completion.

Signed-off-by: Hou Zhiqiang 
---
V3:
 - Rebased against the latest code base

 drivers/pci/controller/dwc/pci-layerscape.c  | 380 ++-
 drivers/pci/controller/dwc/pcie-designware.h |   1 +
 2 files changed, 379 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index 906fac676b6f..a590194c0f95 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -3,13 +3,16 @@
  * PCIe host controller driver for Freescale Layerscape SoCs
  *
  * Copyright (C) 2014 Freescale Semiconductor.
+ * Copyright 2020 NXP
  *
  * Author: Minghuan Lian 
  */
 
+#include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -27,17 +30,60 @@
 #define PCIE_ABSERR0x8d0 /* Bridge Slave Error Response Register */
 #define PCIE_ABSERR_SETTING0x9401 /* Forward error of non-posted request */
 
+/* PF Message Command Register */
+#define LS_PCIE_PF_MCR 0x2c
+#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)
+
+/* 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_IS_L2(v)   \
+   (((v) & PORT_LOGIC_LTSSM_STATE_MASK) == PORT_LOGIC_LTSSM_STATE_L2)
+
+struct ls_pcie;
+
+struct ls_pcie_host_pm_ops {
+   int (*pm_init)(struct ls_pcie *pcie);
+   void (*send_turn_off_message)(struct ls_pcie *pcie);
+   void (*exit_from_l2)(struct ls_pcie *pcie);
+};
+
 struct ls_pcie_drvdata {
+   const u32 pf_off;
+   const u32 lut_off;
const struct dw_pcie_host_ops *ops;
+   const struct ls_pcie_host_pm_ops *pm_ops;
 };
 
 struct ls_pcie {
struct dw_pcie *pci;
const struct ls_pcie_drvdata *drvdata;
+   void __iomem *pf_base;
+   void __iomem *lut_base;
+   bool big_endian;
+   bool ep_presence;
+   bool pm_support;
+   struct regmap *scfg;
+   int index;
 };
 
+#define ls_pcie_lut_readl_addr(addr)   ls_pcie_lut_readl(pcie, addr)
+#define ls_pcie_pf_readl_addr(addr)ls_pcie_pf_readl(pcie, addr)
 #define to_ls_pcie(x)  dev_get_drvdata((x)->dev)
 
 static bool ls_pcie_is_bridge(struct ls_pcie *pcie)
@@ -78,6 +124,210 @@ static void ls_pcie_fix_error_response(struct ls_pcie 
*pcie)
iowrite32(PCIE_ABSERR_SETTING, pci->dbi_base + PCIE_ABSERR);
 }
 
+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)
+   return iowrite32be(val, pcie->lut_base + off);
+
+   return iowrite32(val, pcie->lut_base + off);
+
+}
+
+static u32 ls_pcie_pf_readl(struct ls_pcie *pcie, u32 off)
+{
+   if (pcie->big_endian)
+   return ioread32be(pcie->pf_base + off);
+
+   return ioread32(pcie->pf_base + off);
+}
+
+static void ls_pcie_pf_writel(struct ls_pcie *pcie, u32 off, u32 val)
+{
+   if (pcie->big_endian)
+   return iowrite32be(val, pcie->pf_base + off);
+
+   return iowrite32(val, pcie->pf_base + off);
+
+}
+
+static void ls_pcie_send_turnoff_msg(struct ls_pcie *pcie)
+{
+   u32 val;
+   int ret;
+
+   val = ls_pcie_pf_readl(pcie, LS_PCIE_PF_MCR);
+   val |= PF_MCR_PTOMR;
+   ls_pcie_pf_writel(pcie, LS_PCIE_PF_MCR, val);
+
+   ret = readx_poll_timeout(ls_pcie_pf_readl_addr, LS_PCIE_PF_MCR,
+val, !(val & PF_MCR_PTOMR), 100, 1);
+   if (ret)
+   dev_info(pcie->pci->dev, "poll turn off message timeout\n");
+}
+
+static void ls1021a_pcie_send_turnoff_msg(struct ls_pcie *pcie)
+{
+   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);
+
+   mdelay(10);
+
+   /* Clear Turn_off message */
+   regmap_read(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), );
+   val &= ~PMXMTTURNOFF;
+   regmap_write(pcie->scfg, 

[PATCHv3 3/7] dt-bindings: pci: layerscape-pci: Add a optional property big-endian

2021-01-08 Thread Zhiqiang Hou
From: Hou Zhiqiang 

This property is to indicate the endianness when accessing the
PEX_LUT and PF register block, so if these registers are
implemented in big-endian, specify this property.

Signed-off-by: Hou Zhiqiang 
Acked-by: Rob Herring 
---
V3:
 - Rebased against the latest code base

 Documentation/devicetree/bindings/pci/layerscape-pci.txt | 4 
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/pci/layerscape-pci.txt 
b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
index daa99f7d4c3f..0033c898976e 100644
--- a/Documentation/devicetree/bindings/pci/layerscape-pci.txt
+++ b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
@@ -39,6 +39,10 @@ Required properties:
   of the data transferred from/to the IP block. This can avoid the software
   cache flush/invalid actions, and improve the performance significantly.
 
+Optional properties:
+- big-endian: If the PEX_LUT and PF register block is in big-endian, specify
+  this property.
+
 Example:
 
pcie@340 {
-- 
2.17.1



[PATCHv3 5/7] dt-bindings: pci: layerscape-pci: Update the description of SCFG property

2021-01-08 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Update the description of the second entry of 'fsl,pcie-scfg' property,
as the LS1043A PCIe controller also has some control registers in SCFG
block, while it has 3 controllers.

Signed-off-by: Hou Zhiqiang 
Acked-by: Rob Herring 
---
V3:
 - Rebased against the latest code base

 Documentation/devicetree/bindings/pci/layerscape-pci.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/pci/layerscape-pci.txt 
b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
index 0033c898976e..4228562be505 100644
--- a/Documentation/devicetree/bindings/pci/layerscape-pci.txt
+++ b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
@@ -33,7 +33,7 @@ Required properties:
   "intr": The interrupt that is asserted for controller interrupts
 - fsl,pcie-scfg: Must include two entries.
   The first entry must be a link to the SCFG device node
-  The second entry must be '0' or '1' based on physical PCIe controller index.
+  The second entry is the physical PCIe controller index starting from '0'.
   This is used to get SCFG PEXN registers
 - dma-coherent: Indicates that the hardware IP block can ensure the coherency
   of the data transferred from/to the IP block. This can avoid the software
-- 
2.17.1



[PATCHv3 0/7] PCI: layerscape: Add power management support

2021-01-08 Thread Zhiqiang Hou
From: Hou Zhiqiang 

This patch series is to add PCIe power management support for NXP
Layerscape platfroms.

Hou Zhiqiang (7):
  PCI: dwc: Fix a bug of the case dw_pci->ops is NULL
  PCI: layerscape: Change to use the DWC common link-up check function
  dt-bindings: pci: layerscape-pci: Add a optional property big-endian
  arm64: dts: layerscape: Add big-endian property for PCIe nodes
  dt-bindings: pci: layerscape-pci: Update the description of SCFG
property
  arm64: dts: ls1043a: Add SCFG phandle for PCIe nodes
  PCI: layerscape: Add power management support

 .../bindings/pci/layerscape-pci.txt   |   6 +-
 .../arm64/boot/dts/freescale/fsl-ls1012a.dtsi |   1 +
 .../arm64/boot/dts/freescale/fsl-ls1043a.dtsi |   6 +
 .../arm64/boot/dts/freescale/fsl-ls1046a.dtsi |   3 +
 drivers/pci/controller/dwc/pci-layerscape.c   | 448 ++
 .../pci/controller/dwc/pcie-designware-host.c |   2 +-
 drivers/pci/controller/dwc/pcie-designware.c  |  14 +-
 drivers/pci/controller/dwc/pcie-designware.h  |   1 +
 8 files changed, 376 insertions(+), 105 deletions(-)

-- 
2.17.1



[PATCHv3 6/7] arm64: dts: ls1043a: Add SCFG phandle for PCIe nodes

2021-01-08 Thread Zhiqiang Hou
From: Hou Zhiqiang 

The LS1043A PCIe controller has some control registers
in SCFG block, so add the SCFG phandle for each PCIe
controller DT node.

Signed-off-by: Hou Zhiqiang 
---
V3:
 - Rebased against the latest code base

 arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index aca45bf348b4..862c6ac0df83 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -826,6 +826,7 @@
interrupts = <0 118 0x4>, /* controller interrupt */
 <0 117 0x4>; /* PME interrupt */
interrupt-names = "intr", "pme";
+   fsl,pcie-scfg = < 0>;
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
@@ -853,6 +854,7 @@
interrupts = <0 128 0x4>,
 <0 127 0x4>;
interrupt-names = "intr", "pme";
+   fsl,pcie-scfg = < 1>;
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
@@ -880,6 +882,7 @@
interrupts = <0 162 0x4>,
 <0 161 0x4>;
interrupt-names = "intr", "pme";
+   fsl,pcie-scfg = < 2>;
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
-- 
2.17.1



[PATCHv3 1/7] PCI: dwc: Fix a bug of the case dw_pci->ops is NULL

2021-01-08 Thread Zhiqiang Hou
From: Hou Zhiqiang 

The dw_pci->ops may be a NULL, and fix it by adding one more check.

Signed-off-by: Hou Zhiqiang 
Reviewed-by: Rob Herring 
Acked-by: Gustavo Pimentel 
---
V3:
 - Rebased against the latest code base

 drivers/pci/controller/dwc/pcie-designware-host.c |  2 +-
 drivers/pci/controller/dwc/pcie-designware.c  | 14 +++---
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c 
b/drivers/pci/controller/dwc/pcie-designware-host.c
index 516b151e0ef3..0413284fdd93 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -429,7 +429,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
dw_pcie_setup_rc(pp);
dw_pcie_msi_init(pp);
 
-   if (!dw_pcie_link_up(pci) && pci->ops->start_link) {
+   if (!dw_pcie_link_up(pci) && pci->ops && pci->ops->start_link) {
ret = pci->ops->start_link(pci);
if (ret)
goto err_free_msi;
diff --git a/drivers/pci/controller/dwc/pcie-designware.c 
b/drivers/pci/controller/dwc/pcie-designware.c
index 645fa1892375..cf895c12f71f 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -141,7 +141,7 @@ u32 dw_pcie_read_dbi(struct dw_pcie *pci, u32 reg, size_t 
size)
int ret;
u32 val;
 
-   if (pci->ops->read_dbi)
+   if (pci->ops && pci->ops->read_dbi)
return pci->ops->read_dbi(pci, pci->dbi_base, reg, size);
 
ret = dw_pcie_read(pci->dbi_base + reg, size, );
@@ -156,7 +156,7 @@ void dw_pcie_write_dbi(struct dw_pcie *pci, u32 reg, size_t 
size, u32 val)
 {
int ret;
 
-   if (pci->ops->write_dbi) {
+   if (pci->ops && pci->ops->write_dbi) {
pci->ops->write_dbi(pci, pci->dbi_base, reg, size, val);
return;
}
@@ -171,7 +171,7 @@ void dw_pcie_write_dbi2(struct dw_pcie *pci, u32 reg, 
size_t size, u32 val)
 {
int ret;
 
-   if (pci->ops->write_dbi2) {
+   if (pci->ops && pci->ops->write_dbi2) {
pci->ops->write_dbi2(pci, pci->dbi_base2, reg, size, val);
return;
}
@@ -186,7 +186,7 @@ static u32 dw_pcie_readl_atu(struct dw_pcie *pci, u32 reg)
int ret;
u32 val;
 
-   if (pci->ops->read_dbi)
+   if (pci->ops && pci->ops->read_dbi)
return pci->ops->read_dbi(pci, pci->atu_base, reg, 4);
 
ret = dw_pcie_read(pci->atu_base + reg, 4, );
@@ -200,7 +200,7 @@ static void dw_pcie_writel_atu(struct dw_pcie *pci, u32 
reg, u32 val)
 {
int ret;
 
-   if (pci->ops->write_dbi) {
+   if (pci->ops && pci->ops->write_dbi) {
pci->ops->write_dbi(pci, pci->atu_base, reg, 4, val);
return;
}
@@ -273,7 +273,7 @@ static void __dw_pcie_prog_outbound_atu(struct dw_pcie 
*pci, u8 func_no,
 {
u32 retries, val;
 
-   if (pci->ops->cpu_addr_fixup)
+   if (pci->ops && pci->ops->cpu_addr_fixup)
cpu_addr = pci->ops->cpu_addr_fixup(pci, cpu_addr);
 
if (pci->iatu_unroll_enabled) {
@@ -481,7 +481,7 @@ int dw_pcie_link_up(struct dw_pcie *pci)
 {
u32 val;
 
-   if (pci->ops->link_up)
+   if (pci->ops && pci->ops->link_up)
return pci->ops->link_up(pci);
 
val = readl(pci->dbi_base + PCIE_PORT_DEBUG1);
-- 
2.17.1



[PATCH 3/4] PCI: dwc: Rename callback function func_conf_select and its instance

2021-01-07 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Rename the callback func_conf_select() and its instance and wrapper
to *get_func_cfg_addr(), such that the code becomes more readable.

Signed-off-by: Hou Zhiqiang 
---
 drivers/pci/controller/dwc/pci-layerscape-ep.c  | 6 +++---
 drivers/pci/controller/dwc/pcie-designware-ep.c | 9 +
 drivers/pci/controller/dwc/pcie-designware.h| 2 +-
 3 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index 4d12efdacd2f..0f5e4104c06c 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -87,8 +87,8 @@ static int ls_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 
func_no,
}
 }
 
-static unsigned int ls_pcie_ep_func_conf_select(struct dw_pcie_ep *ep,
-   u8 func_no)
+static unsigned int ls_pcie_ep_get_func_cfg_addr(struct dw_pcie_ep *ep,
+u8 func_no)
 {
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
struct ls_pcie_ep *pcie = to_ls_pcie_ep(pci);
@@ -101,7 +101,7 @@ static const struct dw_pcie_ep_ops ls_pcie_ep_ops = {
.ep_init = ls_pcie_ep_init,
.raise_irq = ls_pcie_ep_raise_irq,
.get_features = ls_pcie_ep_get_features,
-   .func_conf_select = ls_pcie_ep_func_conf_select,
+   .get_func_cfg_addr = ls_pcie_ep_get_func_cfg_addr,
 };
 
 static const struct ls_pcie_ep_drvdata ls1_ep_drvdata = {
diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c 
b/drivers/pci/controller/dwc/pcie-designware-ep.c
index bc6ad1f96a48..d8eb9a984547 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -40,10 +40,11 @@ dw_pcie_ep_get_func_from_ep(struct dw_pcie_ep *ep, u8 
func_no)
return NULL;
 }
 
-static unsigned int dw_pcie_ep_func_select(struct dw_pcie_ep *ep, u8 func_no)
+static unsigned int dw_pcie_ep_get_func_cfg_addr(struct dw_pcie_ep *ep,
+u8 func_no)
 {
-   if (ep->ops->func_conf_select)
-   return ep->ops->func_conf_select(ep, func_no);
+   if (ep->ops->get_func_cfg_addr)
+   return ep->ops->get_func_cfg_addr(ep, func_no);
 
return 0;
 }
@@ -730,7 +731,7 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
 
for (i = 0; i < epc->max_functions; i++) {
funcs[i].func_no = i;
-   funcs[i].cfg_off = dw_pcie_ep_func_select(ep, i);
+   funcs[i].cfg_off = dw_pcie_ep_get_func_cfg_addr(ep, i);
funcs[i].msi_cap = dw_pcie_ep_find_capability(ep, i,
  PCI_CAP_ID_MSI);
funcs[i].msix_cap = dw_pcie_ep_find_capability(ep, i,
diff --git a/drivers/pci/controller/dwc/pcie-designware.h 
b/drivers/pci/controller/dwc/pcie-designware.h
index 8ee67d4b8109..b8cbe266e01c 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -217,7 +217,7 @@ struct dw_pcie_ep_ops {
 * return a 0, and implement code in callback function of platform
 * driver.
 */
-   unsigned int (*func_conf_select)(struct dw_pcie_ep *ep, u8 func_no);
+   unsigned int (*get_func_cfg_addr)(struct dw_pcie_ep *ep, u8 func_no);
 };
 
 struct dw_pcie_ep_func {
-- 
2.17.1



[PATCH 4/4] PCI: dwc: Change the parameter of function dw_pcie_ep_reset_bar()

2021-01-07 Thread Zhiqiang Hou
From: Hou Zhiqiang 

This helper is endpoint mode specific, so change to use a pointer of
'struct dw_pcie_ep' as the parameter.

Signed-off-by: Hou Zhiqiang 
---
 drivers/pci/controller/dwc/pci-dra7xx.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  | 16 +++-
 .../pci/controller/dwc/pcie-designware-plat.c|  3 +--
 drivers/pci/controller/dwc/pcie-designware.h |  5 +++--
 drivers/pci/controller/dwc/pcie-uniphier-ep.c|  3 +--
 7 files changed, 15 insertions(+), 18 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-dra7xx.c 
b/drivers/pci/controller/dwc/pci-dra7xx.c
index b105af63854a..12726c63366f 100644
--- a/drivers/pci/controller/dwc/pci-dra7xx.c
+++ b/drivers/pci/controller/dwc/pci-dra7xx.c
@@ -383,7 +383,7 @@ static void dra7xx_pcie_ep_init(struct dw_pcie_ep *ep)
enum pci_barno bar;
 
for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
-   dw_pcie_ep_reset_bar(pci, bar);
+   dw_pcie_ep_reset_bar(ep, bar);
 
dra7xx_pcie_enable_wrapper_interrupts(dra7xx);
 }
diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index 0f5e4104c06c..dcee95e16139 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -62,7 +62,7 @@ static void ls_pcie_ep_init(struct dw_pcie_ep *ep)
return;
 
for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
-   dw_pcie_ep_reset_bar(pci, bar);
+   dw_pcie_ep_reset_bar(ep, bar);
 
pcie->ls_epc->msi_capable = ep_func->msi_cap ? true : false;
pcie->ls_epc->msix_capable = ep_func->msix_cap ? true : false;
diff --git a/drivers/pci/controller/dwc/pcie-artpec6.c 
b/drivers/pci/controller/dwc/pcie-artpec6.c
index 597c282f586c..f833daf6d422 100644
--- a/drivers/pci/controller/dwc/pcie-artpec6.c
+++ b/drivers/pci/controller/dwc/pcie-artpec6.c
@@ -348,7 +348,7 @@ static void artpec6_pcie_ep_init(struct dw_pcie_ep *ep)
artpec6_pcie_wait_for_phy(artpec6_pcie);
 
for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
-   dw_pcie_ep_reset_bar(pci, bar);
+   dw_pcie_ep_reset_bar(ep, bar);
 }
 
 static int artpec6_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c 
b/drivers/pci/controller/dwc/pcie-designware-ep.c
index d8eb9a984547..2dc960e74fd0 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -49,11 +49,11 @@ static unsigned int dw_pcie_ep_get_func_cfg_addr(struct 
dw_pcie_ep *ep,
return 0;
 }
 
-static void __dw_pcie_ep_reset_bar(struct dw_pcie *pci, u8 func_no,
+static void __dw_pcie_ep_reset_bar(struct dw_pcie_ep *ep, u8 func_no,
   enum pci_barno bar, int flags)
 {
u32 reg;
-   struct dw_pcie_ep *ep = >ep;
+   struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
struct dw_pcie_ep_func *func = dw_pcie_ep_get_func_from_ep(ep, func_no);
 
if (!func)
@@ -70,14 +70,12 @@ static void __dw_pcie_ep_reset_bar(struct dw_pcie *pci, u8 
func_no,
dw_pcie_dbi_ro_wr_dis(pci);
 }
 
-void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar)
+void dw_pcie_ep_reset_bar(struct dw_pcie_ep *ep, enum pci_barno bar)
 {
-   u8 func_no, funcs;
-
-   funcs = pci->ep.epc->max_functions;
+   u8 func_no;
 
-   for (func_no = 0; func_no < funcs; func_no++)
-   __dw_pcie_ep_reset_bar(pci, func_no, bar, 0);
+   for (func_no = 0; func_no < ep->epc->max_functions; func_no++)
+   __dw_pcie_ep_reset_bar(ep, func_no, bar, 0);
 }
 
 static u8 __dw_pcie_ep_find_next_cap(struct dw_pcie_ep *ep, u8 func_no,
@@ -208,7 +206,7 @@ static void dw_pcie_ep_clear_bar(struct pci_epc *epc, u8 
func_no,
enum pci_barno bar = epf_bar->barno;
u32 atu_index = ep->bar_to_atu[bar];
 
-   __dw_pcie_ep_reset_bar(pci, func_no, bar, epf_bar->flags);
+   __dw_pcie_ep_reset_bar(ep, func_no, bar, epf_bar->flags);
 
dw_pcie_disable_atu(pci, atu_index, DW_PCIE_REGION_INBOUND);
clear_bit(atu_index, ep->ib_window_map);
diff --git a/drivers/pci/controller/dwc/pcie-designware-plat.c 
b/drivers/pci/controller/dwc/pcie-designware-plat.c
index 9b397c807261..49d51584a547 100644
--- a/drivers/pci/controller/dwc/pcie-designware-plat.c
+++ b/drivers/pci/controller/dwc/pcie-designware-plat.c
@@ -47,11 +47,10 @@ static const struct dw_pcie_ops dw_pcie_ops = {
 
 static void dw_plat_pcie_ep_init(struct dw_pcie_ep *ep)
 {
-   struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
enum pci_barno bar;
 
for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
-   dw_pcie_ep_reset_bar(pci, bar);
+   dw_pcie_ep_reset_bar(ep, bar);
 }
 
 static int 

[PATCH 2/4] PCI: dwc: Add CFG offset info into function's represented structure

2021-01-07 Thread Zhiqiang Hou
From: Hou Zhiqiang 

To avoid multiple calculating of the CFG offset for each function, store
the CFG offset info to the function's represented structure, and only do
one time calculation during the initialization.

Signed-off-by: Hou Zhiqiang 
---
 .../pci/controller/dwc/pcie-designware-ep.c   | 138 --
 drivers/pci/controller/dwc/pcie-designware.h  |   1 +
 2 files changed, 59 insertions(+), 80 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c 
b/drivers/pci/controller/dwc/pcie-designware-ep.c
index e583700b5ba3..bc6ad1f96a48 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -42,24 +42,23 @@ dw_pcie_ep_get_func_from_ep(struct dw_pcie_ep *ep, u8 
func_no)
 
 static unsigned int dw_pcie_ep_func_select(struct dw_pcie_ep *ep, u8 func_no)
 {
-   unsigned int func_offset = 0;
-
if (ep->ops->func_conf_select)
-   func_offset = ep->ops->func_conf_select(ep, func_no);
+   return ep->ops->func_conf_select(ep, func_no);
 
-   return func_offset;
+   return 0;
 }
 
 static void __dw_pcie_ep_reset_bar(struct dw_pcie *pci, u8 func_no,
   enum pci_barno bar, int flags)
 {
u32 reg;
-   unsigned int func_offset = 0;
struct dw_pcie_ep *ep = >ep;
+   struct dw_pcie_ep_func *func = dw_pcie_ep_get_func_from_ep(ep, func_no);
 
-   func_offset = dw_pcie_ep_func_select(ep, func_no);
+   if (!func)
+   return;
 
-   reg = func_offset + PCI_BASE_ADDRESS_0 + (4 * bar);
+   reg = func->cfg_off + PCI_BASE_ADDRESS_0 + (4 * bar);
dw_pcie_dbi_ro_wr_en(pci);
dw_pcie_writel_dbi2(pci, reg, 0x0);
dw_pcie_writel_dbi(pci, reg, 0x0);
@@ -83,17 +82,15 @@ void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum 
pci_barno bar)
 static u8 __dw_pcie_ep_find_next_cap(struct dw_pcie_ep *ep, u8 func_no,
u8 cap_ptr, u8 cap)
 {
+   struct dw_pcie_ep_func *func = dw_pcie_ep_get_func_from_ep(ep, func_no);
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
-   unsigned int func_offset = 0;
u8 cap_id, next_cap_ptr;
u16 reg;
 
-   if (!cap_ptr)
+   if (!cap_ptr || !func)
return 0;
 
-   func_offset = dw_pcie_ep_func_select(ep, func_no);
-
-   reg = dw_pcie_readw_dbi(pci, func_offset + cap_ptr);
+   reg = dw_pcie_readw_dbi(pci, func->cfg_off + cap_ptr);
cap_id = (reg & 0x00ff);
 
if (cap_id > PCI_CAP_ID_MAX)
@@ -108,14 +105,15 @@ static u8 __dw_pcie_ep_find_next_cap(struct dw_pcie_ep 
*ep, u8 func_no,
 
 static u8 dw_pcie_ep_find_capability(struct dw_pcie_ep *ep, u8 func_no, u8 cap)
 {
+   struct dw_pcie_ep_func *func = dw_pcie_ep_get_func_from_ep(ep, func_no);
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
-   unsigned int func_offset = 0;
u8 next_cap_ptr;
u16 reg;
 
-   func_offset = dw_pcie_ep_func_select(ep, func_no);
+   if (!func)
+   return 0;
 
-   reg = dw_pcie_readw_dbi(pci, func_offset + PCI_CAPABILITY_LIST);
+   reg = dw_pcie_readw_dbi(pci, func->cfg_off + PCI_CAPABILITY_LIST);
next_cap_ptr = (reg & 0x00ff);
 
return __dw_pcie_ep_find_next_cap(ep, func_no, next_cap_ptr, cap);
@@ -126,23 +124,26 @@ static int dw_pcie_ep_write_header(struct pci_epc *epc, 
u8 func_no,
 {
struct dw_pcie_ep *ep = epc_get_drvdata(epc);
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
-   unsigned int func_offset = 0;
+   struct dw_pcie_ep_func *func = dw_pcie_ep_get_func_from_ep(ep, func_no);
+   u32 cfg_off;
 
-   func_offset = dw_pcie_ep_func_select(ep, func_no);
+   if (!func)
+   return -EINVAL;
 
+   cfg_off = func->cfg_off;
dw_pcie_dbi_ro_wr_en(pci);
-   dw_pcie_writew_dbi(pci, func_offset + PCI_VENDOR_ID, hdr->vendorid);
-   dw_pcie_writew_dbi(pci, func_offset + PCI_DEVICE_ID, hdr->deviceid);
-   dw_pcie_writeb_dbi(pci, func_offset + PCI_REVISION_ID, hdr->revid);
-   dw_pcie_writeb_dbi(pci, func_offset + PCI_CLASS_PROG, hdr->progif_code);
-   dw_pcie_writew_dbi(pci, func_offset + PCI_CLASS_DEVICE,
+   dw_pcie_writew_dbi(pci, cfg_off + PCI_VENDOR_ID, hdr->vendorid);
+   dw_pcie_writew_dbi(pci, cfg_off + PCI_DEVICE_ID, hdr->deviceid);
+   dw_pcie_writeb_dbi(pci, cfg_off + PCI_REVISION_ID, hdr->revid);
+   dw_pcie_writeb_dbi(pci, cfg_off + PCI_CLASS_PROG, hdr->progif_code);
+   dw_pcie_writew_dbi(pci, cfg_off + PCI_CLASS_DEVICE,
   hdr->subclass_code | hdr->baseclass_code << 8);
-   dw_pcie_writeb_dbi(pci, func_offset + PCI_CACHE_LINE_SIZE,
+   dw_pcie_writeb_dbi(pci, cfg_off + PCI_CACHE_LINE_SIZE,
   hdr->cache_line_size);
-   dw_pcie_writew_dbi(pci, func_offset + PCI_SUBSYSTEM_VENDOR_ID,
+   dw_pcie_writew_dbi(pci, cfg_off + PCI_SUBSYSTEM_VENDOR_ID,
   

[PATCH 1/4] PCI: dwc: Change to use an array to store the structure of functions

2021-01-07 Thread Zhiqiang Hou
From: Hou Zhiqiang 

As there isn't dynamically adding and deleting a function's structure,
the list_head is not necessary for this case. Array is easier and
more efficient to search.

Signed-off-by: Hou Zhiqiang 
---
 .../pci/controller/dwc/pcie-designware-ep.c   | 33 ---
 drivers/pci/controller/dwc/pcie-designware.h  |  3 +-
 2 files changed, 15 insertions(+), 21 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c 
b/drivers/pci/controller/dwc/pcie-designware-ep.c
index bcd1cd9ba8c8..e583700b5ba3 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -34,12 +34,8 @@ EXPORT_SYMBOL_GPL(dw_pcie_ep_init_notify);
 struct dw_pcie_ep_func *
 dw_pcie_ep_get_func_from_ep(struct dw_pcie_ep *ep, u8 func_no)
 {
-   struct dw_pcie_ep_func *ep_func;
-
-   list_for_each_entry(ep_func, >func_list, list) {
-   if (ep_func->func_no == func_no)
-   return ep_func;
-   }
+   if (func_no < ep->epc->max_functions)
+   return ep->funcs + func_no;
 
return NULL;
 }
@@ -675,9 +671,9 @@ EXPORT_SYMBOL_GPL(dw_pcie_ep_init_complete);
 
 int dw_pcie_ep_init(struct dw_pcie_ep *ep)
 {
+   u8 i;
int ret;
void *addr;
-   u8 func_no;
struct resource *res;
struct pci_epc *epc;
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
@@ -685,9 +681,7 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
struct platform_device *pdev = to_platform_device(dev);
struct device_node *np = dev->of_node;
const struct pci_epc_features *epc_features;
-   struct dw_pcie_ep_func *ep_func;
-
-   INIT_LIST_HEAD(>func_list);
+   struct dw_pcie_ep_func *funcs;
 
if (!pci->dbi_base) {
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
@@ -750,18 +744,19 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
if (ret < 0)
epc->max_functions = 1;
 
-   for (func_no = 0; func_no < epc->max_functions; func_no++) {
-   ep_func = devm_kzalloc(dev, sizeof(*ep_func), GFP_KERNEL);
-   if (!ep_func)
-   return -ENOMEM;
+   funcs = devm_kcalloc(dev, epc->max_functions, sizeof(*funcs),
+GFP_KERNEL);
+   if (!funcs)
+   return -ENOMEM;
+
+   ep->funcs = funcs;
 
-   ep_func->func_no = func_no;
-   ep_func->msi_cap = dw_pcie_ep_find_capability(ep, func_no,
+   for (i = 0; i < epc->max_functions; i++) {
+   funcs[i].func_no = i;
+   funcs[i].msi_cap = dw_pcie_ep_find_capability(ep, i,
  PCI_CAP_ID_MSI);
-   ep_func->msix_cap = dw_pcie_ep_find_capability(ep, func_no,
+   funcs[i].msix_cap = dw_pcie_ep_find_capability(ep, i,
   PCI_CAP_ID_MSIX);
-
-   list_add_tail(_func->list, >func_list);
}
 
if (ep->ops->ep_init)
diff --git a/drivers/pci/controller/dwc/pcie-designware.h 
b/drivers/pci/controller/dwc/pcie-designware.h
index 98710bf5ab0e..16d239c4d09b 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -221,7 +221,6 @@ struct dw_pcie_ep_ops {
 };
 
 struct dw_pcie_ep_func {
-   struct list_headlist;
u8  func_no;
u8  msi_cap;/* MSI capability offset */
u8  msix_cap;   /* MSI-X capability offset */
@@ -229,7 +228,7 @@ struct dw_pcie_ep_func {
 
 struct dw_pcie_ep {
struct pci_epc  *epc;
-   struct list_headfunc_list;
+   struct dw_pcie_ep_func  *funcs;
const struct dw_pcie_ep_ops *ops;
phys_addr_t phys_base;
size_t  addr_size;
-- 
2.17.1



[PATCH 0/4] PCI: dwc: Refine the EP code no functionality change

2021-01-07 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Tune the EP mode code slightly to make it more readable.

Hou Zhiqiang (4):
  PCI: dwc: Change to use an array to store the structure of functions
  PCI: dwc: Add CFG offset info into function's represented structure
  PCI: dwc: Rename callback function func_conf_select and its instance
  PCI: dwc: Change the parameter of function dw_pcie_ep_reset_bar()

 drivers/pci/controller/dwc/pci-dra7xx.c   |   2 +-
 .../pci/controller/dwc/pci-layerscape-ep.c|   8 +-
 drivers/pci/controller/dwc/pcie-artpec6.c |   2 +-
 .../pci/controller/dwc/pcie-designware-ep.c   | 192 --
 .../pci/controller/dwc/pcie-designware-plat.c |   3 +-
 drivers/pci/controller/dwc/pcie-designware.h  |  11 +-
 drivers/pci/controller/dwc/pcie-uniphier-ep.c |   3 +-
 7 files changed, 96 insertions(+), 125 deletions(-)

-- 
2.17.1



[PATCHv10] arm64: dts: layerscape: Add PCIe EP node for ls1088a

2020-11-01 Thread Zhiqiang Hou
From: Xiaowei Bao 

Add PCIe EP node for ls1088a to support EP mode.

Signed-off-by: Xiaowei Bao 
Signed-off-by: Hou Zhiqiang 
Reviewed-by: Andrew Murray 
---
V10:
 - Add a space between compatibles.

 .../arm64/boot/dts/freescale/fsl-ls1088a.dtsi | 31 +++
 1 file changed, 31 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
index ff5805206a28..8d8e610acba6 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
@@ -517,6 +517,17 @@
status = "disabled";
};
 
+   pcie_ep1: pcie-ep@340 {
+   compatible = "fsl,ls1088a-pcie-ep", "fsl,ls-pcie-ep";
+   reg = <0x00 0x0340 0x0 0x0010
+  0x20 0x 0x8 0x>;
+   reg-names = "regs", "addr_space";
+   num-ib-windows = <24>;
+   num-ob-windows = <256>;
+   max-functions = /bits/ 8 <2>;
+   status = "disabled";
+   };
+
pcie2: pcie@350 {
compatible = "fsl,ls1088a-pcie";
reg = <0x00 0x0350 0x0 0x0010   /* controller 
registers */
@@ -543,6 +554,16 @@
status = "disabled";
};
 
+   pcie_ep2: pcie-ep@350 {
+   compatible = "fsl,ls1088a-pcie-ep", "fsl,ls-pcie-ep";
+   reg = <0x00 0x0350 0x0 0x0010
+  0x28 0x 0x8 0x>;
+   reg-names = "regs", "addr_space";
+   num-ib-windows = <6>;
+   num-ob-windows = <6>;
+   status = "disabled";
+   };
+
pcie3: pcie@360 {
compatible = "fsl,ls1088a-pcie";
reg = <0x00 0x0360 0x0 0x0010   /* controller 
registers */
@@ -569,6 +590,16 @@
status = "disabled";
};
 
+   pcie_ep3: pcie-ep@360 {
+   compatible = "fsl,ls1088a-pcie-ep", "fsl,ls-pcie-ep";
+   reg = <0x00 0x0360 0x0 0x0010
+  0x30 0x 0x8 0x>;
+   reg-names = "regs", "addr_space";
+   num-ib-windows = <6>;
+   num-ob-windows = <6>;
+   status = "disabled";
+   };
+
smmu: iommu@500 {
compatible = "arm,mmu-500";
reg = <0 0x500 0 0x80>;
-- 
2.17.1



[PATCHv2 7/7] PCI: layerscape: Add power management support

2020-10-27 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Add PME_Turn_Off/PME_TO_Ack handshake sequence, and finally
put the PCIe controller into D3 state after the L2/L3 ready
state transition process completion.

Signed-off-by: Hou Zhiqiang 
---
V2:
 - Change to use the common defines to access the RC configuration
   registers.

 drivers/pci/controller/dwc/pci-layerscape.c  | 380 ++-
 drivers/pci/controller/dwc/pcie-designware.h |   1 +
 2 files changed, 379 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index be404c16bcbe..9886eaead593 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -3,13 +3,16 @@
  * PCIe host controller driver for Freescale Layerscape SoCs
  *
  * Copyright (C) 2014 Freescale Semiconductor.
+ * Copyright 2020 NXP
  *
  * Author: Minghuan Lian 
  */
 
+#include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -27,17 +30,60 @@
 #define PCIE_ABSERR0x8d0 /* Bridge Slave Error Response Register */
 #define PCIE_ABSERR_SETTING0x9401 /* Forward error of non-posted request */
 
+/* PF Message Command Register */
+#define LS_PCIE_PF_MCR 0x2c
+#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)
+
+/* 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_IS_L2(v)   \
+   (((v) & PORT_LOGIC_LTSSM_STATE_MASK) == PORT_LOGIC_LTSSM_STATE_L2)
+
+struct ls_pcie;
+
+struct ls_pcie_host_pm_ops {
+   int (*pm_init)(struct ls_pcie *pcie);
+   void (*send_turn_off_message)(struct ls_pcie *pcie);
+   void (*exit_from_l2)(struct ls_pcie *pcie);
+};
+
 struct ls_pcie_drvdata {
+   const u32 pf_off;
+   const u32 lut_off;
const struct dw_pcie_host_ops *ops;
+   const struct ls_pcie_host_pm_ops *pm_ops;
 };
 
 struct ls_pcie {
struct dw_pcie *pci;
const struct ls_pcie_drvdata *drvdata;
+   void __iomem *pf_base;
+   void __iomem *lut_base;
+   bool big_endian;
+   bool ep_presence;
+   bool pm_support;
+   struct regmap *scfg;
+   int index;
 };
 
+#define ls_pcie_lut_readl_addr(addr)   ls_pcie_lut_readl(pcie, addr)
+#define ls_pcie_pf_readl_addr(addr)ls_pcie_pf_readl(pcie, addr)
 #define to_ls_pcie(x)  dev_get_drvdata((x)->dev)
 
 static bool ls_pcie_is_bridge(struct ls_pcie *pcie)
@@ -86,6 +132,210 @@ static void ls_pcie_fix_error_response(struct ls_pcie 
*pcie)
iowrite32(PCIE_ABSERR_SETTING, pci->dbi_base + PCIE_ABSERR);
 }
 
+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)
+   return iowrite32be(val, pcie->lut_base + off);
+
+   return iowrite32(val, pcie->lut_base + off);
+
+}
+
+static u32 ls_pcie_pf_readl(struct ls_pcie *pcie, u32 off)
+{
+   if (pcie->big_endian)
+   return ioread32be(pcie->pf_base + off);
+
+   return ioread32(pcie->pf_base + off);
+}
+
+static void ls_pcie_pf_writel(struct ls_pcie *pcie, u32 off, u32 val)
+{
+   if (pcie->big_endian)
+   return iowrite32be(val, pcie->pf_base + off);
+
+   return iowrite32(val, pcie->pf_base + off);
+
+}
+
+static void ls_pcie_send_turnoff_msg(struct ls_pcie *pcie)
+{
+   u32 val;
+   int ret;
+
+   val = ls_pcie_pf_readl(pcie, LS_PCIE_PF_MCR);
+   val |= PF_MCR_PTOMR;
+   ls_pcie_pf_writel(pcie, LS_PCIE_PF_MCR, val);
+
+   ret = readx_poll_timeout(ls_pcie_pf_readl_addr, LS_PCIE_PF_MCR,
+val, !(val & PF_MCR_PTOMR), 100, 1);
+   if (ret)
+   dev_info(pcie->pci->dev, "poll turn off message timeout\n");
+}
+
+static void ls1021a_pcie_send_turnoff_msg(struct ls_pcie *pcie)
+{
+   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);
+
+   mdelay(10);
+
+   /* Clear Turn_off message */
+   regmap_read(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), );
+   val &= ~PMXMTTURNOFF;
+   

[PATCHv2 6/7] arm64: dts: ls1043a: Add SCFG phandle for PCIe nodes

2020-10-27 Thread Zhiqiang Hou
From: Hou Zhiqiang 

The LS1043A PCIe controller has some control registers
in SCFG block, so add the SCFG phandle for each PCIe
controller DT node.

Signed-off-by: Hou Zhiqiang 
---
V2:
 - Correct the order of the subject prefixes.

 arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index d33a64ae8b0f..23bf3796d98f 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -822,6 +822,7 @@
interrupts = <0 118 0x4>, /* controller interrupt */
 <0 117 0x4>; /* PME interrupt */
interrupt-names = "intr", "pme";
+   fsl,pcie-scfg = < 0>;
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
@@ -849,6 +850,7 @@
interrupts = <0 128 0x4>,
 <0 127 0x4>;
interrupt-names = "intr", "pme";
+   fsl,pcie-scfg = < 1>;
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
@@ -876,6 +878,7 @@
interrupts = <0 162 0x4>,
 <0 161 0x4>;
interrupt-names = "intr", "pme";
+   fsl,pcie-scfg = < 2>;
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
-- 
2.17.1



[PATCHv2 5/7] dt-bindings: pci: layerscape-pci: Update the description of SCFG property

2020-10-27 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Update the description of the second entry of 'fsl,pcie-scfg' property,
as the LS1043A PCIe controller also has some control registers in SCFG
block, while it has 3 controllers.

Signed-off-by: Hou Zhiqiang 
Acked-by: Rob Herring 
---
V2:
 - No change.

 Documentation/devicetree/bindings/pci/layerscape-pci.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/pci/layerscape-pci.txt 
b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
index 0033c898976e..4228562be505 100644
--- a/Documentation/devicetree/bindings/pci/layerscape-pci.txt
+++ b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
@@ -33,7 +33,7 @@ Required properties:
   "intr": The interrupt that is asserted for controller interrupts
 - fsl,pcie-scfg: Must include two entries.
   The first entry must be a link to the SCFG device node
-  The second entry must be '0' or '1' based on physical PCIe controller index.
+  The second entry is the physical PCIe controller index starting from '0'.
   This is used to get SCFG PEXN registers
 - dma-coherent: Indicates that the hardware IP block can ensure the coherency
   of the data transferred from/to the IP block. This can avoid the software
-- 
2.17.1



[PATCHv2 4/7] arm64: dts: layerscape: Add big-endian property for PCIe nodes

2020-10-27 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Add the big-endian property for LS1012A, LS1043A and LS1046A
PCIe devicetree nodes.

Signed-off-by: Hou Zhiqiang 
---
V2:
 - No change.

 arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi | 1 +
 arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 3 +++
 arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 3 +++
 3 files changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
index 6a2c09199047..0f63aea30477 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
@@ -512,6 +512,7 @@
< 0 0 2  0 111 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 3  0 112 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 4  0 113 
IRQ_TYPE_LEVEL_HIGH>;
+   big-endian;
status = "disabled";
};
 
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index 0464b8aa4bc4..d33a64ae8b0f 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -837,6 +837,7 @@
< 0 0 2  0 111 0x4>,
< 0 0 3  0 112 0x4>,
< 0 0 4  0 113 0x4>;
+   big-endian;
status = "disabled";
};
 
@@ -863,6 +864,7 @@
< 0 0 2  0 121 0x4>,
< 0 0 3  0 122 0x4>,
< 0 0 4  0 123 0x4>;
+   big-endian;
status = "disabled";
};
 
@@ -889,6 +891,7 @@
< 0 0 2  0 155 0x4>,
< 0 0 3  0 156 0x4>,
< 0 0 4  0 157 0x4>;
+   big-endian;
status = "disabled";
};
 
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
index 1fa39bacff4b..b01fb93f7d19 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
@@ -741,6 +741,7 @@
< 0 0 2  GIC_SPI 110 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 3  GIC_SPI 110 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 4  GIC_SPI 110 
IRQ_TYPE_LEVEL_HIGH>;
+   big-endian;
status = "disabled";
};
 
@@ -777,6 +778,7 @@
< 0 0 2  GIC_SPI 120 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 3  GIC_SPI 120 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 4  GIC_SPI 120 
IRQ_TYPE_LEVEL_HIGH>;
+   big-endian;
status = "disabled";
};
 
@@ -813,6 +815,7 @@
< 0 0 2  GIC_SPI 154 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 3  GIC_SPI 154 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 4  GIC_SPI 154 
IRQ_TYPE_LEVEL_HIGH>;
+   big-endian;
status = "disabled";
};
 
-- 
2.17.1



[PATCHv2 2/7] PCI: layerscape: Change to use the DWC common link-up check function

2020-10-27 Thread Zhiqiang Hou
From: Hou Zhiqiang 

The current Layerscape PCIe driver directly uses the physical layer
LTSSM code to check the link-up state, which treats the > L0 states
as link-up. This is not correct, since there is not explicit map
between link-up state and LTSSM. So this patch changes to use the
DWC common link-up check function.

Signed-off-by: Hou Zhiqiang 
Reviewed-by: Rob Herring 
---
V2:
 - No change.

 drivers/pci/controller/dwc/pci-layerscape.c | 141 ++--
 1 file changed, 10 insertions(+), 131 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index f24f79a70d9a..be404c16bcbe 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -22,12 +22,6 @@
 
 #include "pcie-designware.h"
 
-/* PEX1/2 Misc Ports Status Register */
-#define SCFG_PEXMSCPORTSR(pex_idx) (0x94 + (pex_idx) * 4)
-#define LTSSM_STATE_SHIFT  20
-#define LTSSM_STATE_MASK   0x3f
-#define LTSSM_PCIE_L0  0x11 /* L0 state */
-
 /* PEX Internal Configuration Registers */
 #define PCIE_STRFMR1   0x71c /* Symbol Timer & Filter Mask Register1 */
 #define PCIE_ABSERR0x8d0 /* Bridge Slave Error Response Register */
@@ -36,19 +30,12 @@
 #define PCIE_IATU_NUM  6
 
 struct ls_pcie_drvdata {
-   u32 lut_offset;
-   u32 ltssm_shift;
-   u32 lut_dbg;
const struct dw_pcie_host_ops *ops;
-   const struct dw_pcie_ops *dw_pcie_ops;
 };
 
 struct ls_pcie {
struct dw_pcie *pci;
-   void __iomem *lut;
-   struct regmap *scfg;
const struct ls_pcie_drvdata *drvdata;
-   int index;
 };
 
 #define to_ls_pcie(x)  dev_get_drvdata((x)->dev)
@@ -91,38 +78,6 @@ static void ls_pcie_disable_outbound_atus(struct ls_pcie 
*pcie)
dw_pcie_disable_atu(pcie->pci, i, DW_PCIE_REGION_OUTBOUND);
 }
 
-static int ls1021_pcie_link_up(struct dw_pcie *pci)
-{
-   u32 state;
-   struct ls_pcie *pcie = to_ls_pcie(pci);
-
-   if (!pcie->scfg)
-   return 0;
-
-   regmap_read(pcie->scfg, SCFG_PEXMSCPORTSR(pcie->index), );
-   state = (state >> LTSSM_STATE_SHIFT) & LTSSM_STATE_MASK;
-
-   if (state < LTSSM_PCIE_L0)
-   return 0;
-
-   return 1;
-}
-
-static int ls_pcie_link_up(struct dw_pcie *pci)
-{
-   struct ls_pcie *pcie = to_ls_pcie(pci);
-   u32 state;
-
-   state = (ioread32(pcie->lut + pcie->drvdata->lut_dbg) >>
-pcie->drvdata->ltssm_shift) &
-LTSSM_STATE_MASK;
-
-   if (state < LTSSM_PCIE_L0)
-   return 0;
-
-   return 1;
-}
-
 /* Forward error response of outbound non-posted requests */
 static void ls_pcie_fix_error_response(struct ls_pcie *pcie)
 {
@@ -155,33 +110,6 @@ static int ls_pcie_host_init(struct pcie_port *pp)
return 0;
 }
 
-static int ls1021_pcie_host_init(struct pcie_port *pp)
-{
-   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
-   struct ls_pcie *pcie = to_ls_pcie(pci);
-   struct device *dev = pci->dev;
-   u32 index[2];
-   int 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;
-   }
-
-   if (of_property_read_u32_array(dev->of_node,
-  "fsl,pcie-scfg", index, 2)) {
-   pcie->scfg = NULL;
-   return -EINVAL;
-   }
-   pcie->index = index[1];
-
-   return ls_pcie_host_init(pp);
-}
-
 static int ls_pcie_msi_host_init(struct pcie_port *pp)
 {
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
@@ -205,71 +133,25 @@ static int ls_pcie_msi_host_init(struct pcie_port *pp)
return 0;
 }
 
-static const struct dw_pcie_host_ops ls1021_pcie_host_ops = {
-   .host_init = ls1021_pcie_host_init,
-   .msi_host_init = ls_pcie_msi_host_init,
-};
-
 static const struct dw_pcie_host_ops ls_pcie_host_ops = {
.host_init = ls_pcie_host_init,
.msi_host_init = ls_pcie_msi_host_init,
 };
 
-static const struct dw_pcie_ops dw_ls1021_pcie_ops = {
-   .link_up = ls1021_pcie_link_up,
-};
-
-static const struct dw_pcie_ops dw_ls_pcie_ops = {
-   .link_up = ls_pcie_link_up,
-};
-
-static const struct ls_pcie_drvdata ls1021_drvdata = {
-   .ops = _pcie_host_ops,
-   .dw_pcie_ops = _ls1021_pcie_ops,
-};
-
-static const struct ls_pcie_drvdata ls1043_drvdata = {
-   .lut_offset = 0x1,
-   .ltssm_shift = 24,
-   .lut_dbg = 0x7fc,
-   .ops = _pcie_host_ops,
-   .dw_pcie_ops = _ls_pcie_ops,
-};
-
-static const struct ls_pcie_drvdata ls1046_drvdata = {
-   .lut_offset = 0x8,
-   .ltssm_shift = 24,
-   .lut_dbg = 0x407fc,
-   .ops = _pcie_host_ops,
-   

[PATCHv2 3/7] dt-bindings: pci: layerscape-pci: Add a optional property big-endian

2020-10-27 Thread Zhiqiang Hou
From: Hou Zhiqiang 

This property is to indicate the endianness when accessing the
PEX_LUT and PF register block, so if these registers are
implemented in big-endian, specify this property.

Signed-off-by: Hou Zhiqiang 
Acked-by: Rob Herring 
---
V2:
 - No change.

 Documentation/devicetree/bindings/pci/layerscape-pci.txt | 4 
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/pci/layerscape-pci.txt 
b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
index daa99f7d4c3f..0033c898976e 100644
--- a/Documentation/devicetree/bindings/pci/layerscape-pci.txt
+++ b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
@@ -39,6 +39,10 @@ Required properties:
   of the data transferred from/to the IP block. This can avoid the software
   cache flush/invalid actions, and improve the performance significantly.
 
+Optional properties:
+- big-endian: If the PEX_LUT and PF register block is in big-endian, specify
+  this property.
+
 Example:
 
pcie@340 {
-- 
2.17.1



[PATCHv2 1/7] PCI: dwc: Fix a bug of the case dw_pci->ops is NULL

2020-10-27 Thread Zhiqiang Hou
From: Hou Zhiqiang 

The dw_pci->ops may be a NULL, and fix it by adding one more check.

Signed-off-by: Hou Zhiqiang 
Reviewed-by: Rob Herring 
Acked-by: Gustavo Pimentel 
---
V2:
 - Rebased the patch against the latest code.

 drivers/pci/controller/dwc/pcie-designware.c | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware.c 
b/drivers/pci/controller/dwc/pcie-designware.c
index c2dea8fc97c8..7a5024450c4d 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -141,7 +141,7 @@ u32 dw_pcie_read_dbi(struct dw_pcie *pci, u32 reg, size_t 
size)
int ret;
u32 val;
 
-   if (pci->ops->read_dbi)
+   if (pci->ops && pci->ops->read_dbi)
return pci->ops->read_dbi(pci, pci->dbi_base, reg, size);
 
ret = dw_pcie_read(pci->dbi_base + reg, size, );
@@ -156,7 +156,7 @@ void dw_pcie_write_dbi(struct dw_pcie *pci, u32 reg, size_t 
size, u32 val)
 {
int ret;
 
-   if (pci->ops->write_dbi) {
+   if (pci->ops && pci->ops->write_dbi) {
pci->ops->write_dbi(pci, pci->dbi_base, reg, size, val);
return;
}
@@ -171,7 +171,7 @@ void dw_pcie_write_dbi2(struct dw_pcie *pci, u32 reg, 
size_t size, u32 val)
 {
int ret;
 
-   if (pci->ops->write_dbi2) {
+   if (pci->ops && pci->ops->write_dbi2) {
pci->ops->write_dbi2(pci, pci->dbi_base2, reg, size, val);
return;
}
@@ -186,7 +186,7 @@ static u32 dw_pcie_readl_atu(struct dw_pcie *pci, u32 reg)
int ret;
u32 val;
 
-   if (pci->ops->read_dbi)
+   if (pci->ops && pci->ops->read_dbi)
return pci->ops->read_dbi(pci, pci->atu_base, reg, 4);
 
ret = dw_pcie_read(pci->atu_base + reg, 4, );
@@ -200,7 +200,7 @@ static void dw_pcie_writel_atu(struct dw_pcie *pci, u32 
reg, u32 val)
 {
int ret;
 
-   if (pci->ops->write_dbi) {
+   if (pci->ops && pci->ops->write_dbi) {
pci->ops->write_dbi(pci, pci->atu_base, reg, 4, val);
return;
}
@@ -271,7 +271,7 @@ static void __dw_pcie_prog_outbound_atu(struct dw_pcie 
*pci, u8 func_no,
 {
u32 retries, val;
 
-   if (pci->ops->cpu_addr_fixup)
+   if (pci->ops && pci->ops->cpu_addr_fixup)
cpu_addr = pci->ops->cpu_addr_fixup(pci, cpu_addr);
 
if (pci->iatu_unroll_enabled) {
@@ -479,7 +479,7 @@ int dw_pcie_link_up(struct dw_pcie *pci)
 {
u32 val;
 
-   if (pci->ops->link_up)
+   if (pci->ops && pci->ops->link_up)
return pci->ops->link_up(pci);
 
val = readl(pci->dbi_base + PCIE_PORT_DEBUG1);
-- 
2.17.1



[PATCHv2 0/7] PCI: layerscape: Add power management support

2020-10-27 Thread Zhiqiang Hou
From: Hou Zhiqiang 

This patch series is to add PCIe power management support for NXP
Layerscape platfroms.

Hou Zhiqiang (7):
  PCI: dwc: Fix a bug of the case dw_pci->ops is NULL
  PCI: layerscape: Change to use the DWC common link-up check function
  dt-bindings: pci: layerscape-pci: Add a optional property big-endian
  arm64: dts: layerscape: Add big-endian property for PCIe nodes
  dt-bindings: pci: layerscape-pci: Update the description of SCFG
property
  dts: arm64: ls1043a: Add SCFG phandle for PCIe nodes
  PCI: layerscape: Add power management support

 .../bindings/pci/layerscape-pci.txt   |   6 +-
 .../arm64/boot/dts/freescale/fsl-ls1012a.dtsi |   1 +
 .../arm64/boot/dts/freescale/fsl-ls1043a.dtsi |   6 +
 .../arm64/boot/dts/freescale/fsl-ls1046a.dtsi |   3 +
 drivers/pci/controller/dwc/pci-layerscape.c   | 469 ++
 drivers/pci/controller/dwc/pcie-designware.c  |  14 +-
 drivers/pci/controller/dwc/pcie-designware.h  |   1 +
 7 files changed, 385 insertions(+), 115 deletions(-)

-- 
2.17.1



[PATCH 2/2] PCI: layerscape: Add EP mode support for LX2160A rev2

2020-10-25 Thread Zhiqiang Hou
From: Hou Zhiqiang 

The LX2160A rev2 uses the same PCIe IP as LS2088A, but LX2160A rev2
PCIe controller is integrated with different stride between PFs'
register address.

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

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index 84206f265e54..b125fa1519c8 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -117,10 +117,17 @@ static const struct ls_pcie_ep_drvdata ls2_ep_drvdata = {
.dw_pcie_ops = _ls_pcie_ep_ops,
 };
 
+static const struct ls_pcie_ep_drvdata lx2_ep_drvdata = {
+   .func_offset = 0x8000,
+   .ops = _pcie_ep_ops,
+   .dw_pcie_ops = _ls_pcie_ep_ops,
+};
+
 static const struct of_device_id ls_pcie_ep_of_match[] = {
{ .compatible = "fsl,ls1046a-pcie-ep", .data = _ep_drvdata },
{ .compatible = "fsl,ls1088a-pcie-ep", .data = _ep_drvdata },
{ .compatible = "fsl,ls2088a-pcie-ep", .data = _ep_drvdata },
+   { .compatible = "fsl,lx2160ar2-pcie-ep", .data = _ep_drvdata },
{ },
 };
 
-- 
2.17.1



[PATCH 1/2] dt-bindings: pci: layerscape-pci: Add compatible strings for LX2160A rev2

2020-10-25 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Add PCIe Endpoint mode compatible string "fsl,lx2160ar2-pcie-ep"

Signed-off-by: Hou Zhiqiang 
---
 Documentation/devicetree/bindings/pci/layerscape-pci.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/pci/layerscape-pci.txt 
b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
index daa99f7d4c3f..6d898dd4a8e2 100644
--- a/Documentation/devicetree/bindings/pci/layerscape-pci.txt
+++ b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
@@ -26,6 +26,7 @@ Required properties:
"fsl,ls1046a-pcie-ep", "fsl,ls-pcie-ep"
"fsl,ls1088a-pcie-ep", "fsl,ls-pcie-ep"
"fsl,ls2088a-pcie-ep", "fsl,ls-pcie-ep"
+   "fsl,lx2160ar2-pcie-ep", "fsl,ls-pcie-ep"
 - reg: base addresses and lengths of the PCIe controller register blocks.
 - interrupts: A list of interrupt outputs of the controller. Must contain an
   entry for each entry in the interrupt-names property.
-- 
2.17.1



[PATCHv9] arm64: dts: layerscape: Add PCIe EP node for ls1088a

2020-10-25 Thread Zhiqiang Hou
From: Xiaowei Bao 

Add PCIe EP node for ls1088a to support EP mode.

Signed-off-by: Xiaowei Bao 
Signed-off-by: Hou Zhiqiang 
Reviewed-by: Andrew Murray 
---
V9:
 - Rebase the patch since V8 patch was not accepted due to conflict.
 - Correct the number of outbound windows.
 - Add lables for EP nodes.

 .../arm64/boot/dts/freescale/fsl-ls1088a.dtsi | 31 +++
 1 file changed, 31 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
index ff5805206a28..8d8e610acba6 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
@@ -517,6 +517,17 @@
status = "disabled";
};
 
+   pcie_ep1: pcie-ep@340 {
+   compatible = "fsl,ls1088a-pcie-ep","fsl,ls-pcie-ep";
+   reg = <0x00 0x0340 0x0 0x0010
+  0x20 0x 0x8 0x>;
+   reg-names = "regs", "addr_space";
+   num-ib-windows = <24>;
+   num-ob-windows = <256>;
+   max-functions = /bits/ 8 <2>;
+   status = "disabled";
+   };
+
pcie2: pcie@350 {
compatible = "fsl,ls1088a-pcie";
reg = <0x00 0x0350 0x0 0x0010   /* controller 
registers */
@@ -543,6 +554,16 @@
status = "disabled";
};
 
+   pcie_ep2: pcie-ep@350 {
+   compatible = "fsl,ls1088a-pcie-ep","fsl,ls-pcie-ep";
+   reg = <0x00 0x0350 0x0 0x0010
+  0x28 0x 0x8 0x>;
+   reg-names = "regs", "addr_space";
+   num-ib-windows = <6>;
+   num-ob-windows = <6>;
+   status = "disabled";
+   };
+
pcie3: pcie@360 {
compatible = "fsl,ls1088a-pcie";
reg = <0x00 0x0360 0x0 0x0010   /* controller 
registers */
@@ -569,6 +590,16 @@
status = "disabled";
};
 
+   pcie_ep3: pcie-ep@360 {
+   compatible = "fsl,ls1088a-pcie-ep","fsl,ls-pcie-ep";
+   reg = <0x00 0x0360 0x0 0x0010
+  0x30 0x 0x8 0x>;
+   reg-names = "regs", "addr_space";
+   num-ib-windows = <6>;
+   num-ob-windows = <6>;
+   status = "disabled";
+   };
+
smmu: iommu@500 {
compatible = "arm,mmu-500";
reg = <0 0x500 0 0x80>;
-- 
2.17.1



[PATCH] PCI: layerscape: Change back to the default error response behavior

2020-09-29 Thread Zhiqiang Hou
From: Hou Zhiqiang 

In the current error response behavior, it will send a SLVERR response
to device's internal AXI slave system interface when the PCIe controller
experiences an erroneous completion (UR, CA and CT) from an external
completer for its outbound non-posted request, which will result in
SError and crash the kernel directly.
This patch change back it to the default behavior to increase the
robustness of the kernel. In the default behavior, it always sends an
OKAY response to the internal AXI slave interface when the controller
gets these erroneous completions. And the AER driver will report and
try to recover these errors.

Signed-off-by: Hou Zhiqiang 
---
 drivers/pci/controller/dwc/pci-layerscape.c | 11 ---
 1 file changed, 11 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index f24f79a70d9a..e92ab8a77046 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -30,8 +30,6 @@
 
 /* PEX Internal Configuration Registers */
 #define PCIE_STRFMR1   0x71c /* Symbol Timer & Filter Mask Register1 */
-#define PCIE_ABSERR0x8d0 /* Bridge Slave Error Response Register */
-#define PCIE_ABSERR_SETTING0x9401 /* Forward error of non-posted request */
 
 #define PCIE_IATU_NUM  6
 
@@ -123,14 +121,6 @@ static int ls_pcie_link_up(struct dw_pcie *pci)
return 1;
 }
 
-/* Forward error response of outbound non-posted requests */
-static void ls_pcie_fix_error_response(struct ls_pcie *pcie)
-{
-   struct dw_pcie *pci = pcie->pci;
-
-   iowrite32(PCIE_ABSERR_SETTING, pci->dbi_base + PCIE_ABSERR);
-}
-
 static int ls_pcie_host_init(struct pcie_port *pp)
 {
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
@@ -142,7 +132,6 @@ static int ls_pcie_host_init(struct pcie_port *pp)
 * dw_pcie_setup_rc() will reconfigure the outbound windows.
 */
ls_pcie_disable_outbound_atus(pcie);
-   ls_pcie_fix_error_response(pcie);
 
dw_pcie_dbi_ro_wr_en(pci);
ls_pcie_clear_multifunction(pcie);
-- 
2.17.1



[PATCHv8 03/12] PCI: designware-ep: Move the function of getting MSI capability forward

2020-09-18 Thread Zhiqiang Hou
From: Xiaowei Bao 

Move the function of getting MSI capability to the front of init
function, because the init function of the EP platform driver will use
the return value by the function of getting MSI capability.

Signed-off-by: Xiaowei Bao 
Signed-off-by: Hou Zhiqiang 
Reviewed-by: Andrew Murray 
---
V8:
 - No change.

 drivers/pci/controller/dwc/pcie-designware-ep.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c 
b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 5ae87e8ffb85..25767a334259 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -582,10 +582,6 @@ int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep)
return -EIO;
}
 
-   ep->msi_cap = dw_pcie_find_capability(pci, PCI_CAP_ID_MSI);
-
-   ep->msix_cap = dw_pcie_find_capability(pci, PCI_CAP_ID_MSIX);
-
offset = dw_pcie_ep_find_ext_capability(pci, PCI_EXT_CAP_ID_REBAR);
 
dw_pcie_dbi_ro_wr_en(pci);
@@ -677,6 +673,10 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
if (ret < 0)
epc->max_functions = 1;
 
+   ep->msi_cap = dw_pcie_find_capability(pci, PCI_CAP_ID_MSI);
+
+   ep->msix_cap = dw_pcie_find_capability(pci, PCI_CAP_ID_MSIX);
+
if (ep->ops->ep_init)
ep->ops->ep_init(ep);
 
-- 
2.17.1



[PATCHv8 01/12] PCI: designware-ep: Add multiple PFs support for DWC

2020-09-18 Thread Zhiqiang Hou
From: Xiaowei Bao 

Add multiple PFs support for DWC, due to different PF have different
config space, we use func_conf_select callback function to access
the different PF's config space, the different chip company need to
implement this callback function when use the DWC IP core and intend
to support multiple PFs feature.

Signed-off-by: Xiaowei Bao 
Signed-off-by: Hou Zhiqiang 
Reviewed-by: Rob Herring 
Acked-by: Gustavo Pimentel 
---
V8:
 - No change.

 .../pci/controller/dwc/pcie-designware-ep.c   | 125 --
 drivers/pci/controller/dwc/pcie-designware.c  |  59 ++---
 drivers/pci/controller/dwc/pcie-designware.h  |  18 ++-
 3 files changed, 143 insertions(+), 59 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c 
b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 05415a82e9f4..500d4ca04947 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -30,12 +30,26 @@ void dw_pcie_ep_init_notify(struct dw_pcie_ep *ep)
 }
 EXPORT_SYMBOL_GPL(dw_pcie_ep_init_notify);
 
-static void __dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar,
-  int flags)
+static unsigned int dw_pcie_ep_func_select(struct dw_pcie_ep *ep, u8 func_no)
+{
+   unsigned int func_offset = 0;
+
+   if (ep->ops->func_conf_select)
+   func_offset = ep->ops->func_conf_select(ep, func_no);
+
+   return func_offset;
+}
+
+static void __dw_pcie_ep_reset_bar(struct dw_pcie *pci, u8 func_no,
+  enum pci_barno bar, int flags)
 {
u32 reg;
+   unsigned int func_offset = 0;
+   struct dw_pcie_ep *ep = >ep;
+
+   func_offset = dw_pcie_ep_func_select(ep, func_no);
 
-   reg = PCI_BASE_ADDRESS_0 + (4 * bar);
+   reg = func_offset + PCI_BASE_ADDRESS_0 + (4 * bar);
dw_pcie_dbi_ro_wr_en(pci);
dw_pcie_writel_dbi2(pci, reg, 0x0);
dw_pcie_writel_dbi(pci, reg, 0x0);
@@ -48,7 +62,12 @@ static void __dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum 
pci_barno bar,
 
 void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar)
 {
-   __dw_pcie_ep_reset_bar(pci, bar, 0);
+   u8 func_no, funcs;
+
+   funcs = pci->ep.epc->max_functions;
+
+   for (func_no = 0; func_no < funcs; func_no++)
+   __dw_pcie_ep_reset_bar(pci, func_no, bar, 0);
 }
 
 static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no,
@@ -56,28 +75,31 @@ static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 
func_no,
 {
struct dw_pcie_ep *ep = epc_get_drvdata(epc);
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+   unsigned int func_offset = 0;
+
+   func_offset = dw_pcie_ep_func_select(ep, func_no);
 
dw_pcie_dbi_ro_wr_en(pci);
-   dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, hdr->vendorid);
-   dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, hdr->deviceid);
-   dw_pcie_writeb_dbi(pci, PCI_REVISION_ID, hdr->revid);
-   dw_pcie_writeb_dbi(pci, PCI_CLASS_PROG, hdr->progif_code);
-   dw_pcie_writew_dbi(pci, PCI_CLASS_DEVICE,
+   dw_pcie_writew_dbi(pci, func_offset + PCI_VENDOR_ID, hdr->vendorid);
+   dw_pcie_writew_dbi(pci, func_offset + PCI_DEVICE_ID, hdr->deviceid);
+   dw_pcie_writeb_dbi(pci, func_offset + PCI_REVISION_ID, hdr->revid);
+   dw_pcie_writeb_dbi(pci, func_offset + PCI_CLASS_PROG, hdr->progif_code);
+   dw_pcie_writew_dbi(pci, func_offset + PCI_CLASS_DEVICE,
   hdr->subclass_code | hdr->baseclass_code << 8);
-   dw_pcie_writeb_dbi(pci, PCI_CACHE_LINE_SIZE,
+   dw_pcie_writeb_dbi(pci, func_offset + PCI_CACHE_LINE_SIZE,
   hdr->cache_line_size);
-   dw_pcie_writew_dbi(pci, PCI_SUBSYSTEM_VENDOR_ID,
+   dw_pcie_writew_dbi(pci, func_offset + PCI_SUBSYSTEM_VENDOR_ID,
   hdr->subsys_vendor_id);
-   dw_pcie_writew_dbi(pci, PCI_SUBSYSTEM_ID, hdr->subsys_id);
-   dw_pcie_writeb_dbi(pci, PCI_INTERRUPT_PIN,
+   dw_pcie_writew_dbi(pci, func_offset + PCI_SUBSYSTEM_ID, hdr->subsys_id);
+   dw_pcie_writeb_dbi(pci, func_offset + PCI_INTERRUPT_PIN,
   hdr->interrupt_pin);
dw_pcie_dbi_ro_wr_dis(pci);
 
return 0;
 }
 
-static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, enum pci_barno bar,
- dma_addr_t cpu_addr,
+static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, u8 func_no,
+ enum pci_barno bar, dma_addr_t cpu_addr,
  enum dw_pcie_as_type as_type)
 {
int ret;
@@ -90,7 +112,7 @@ static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, 
enum pci_barno bar,
return -EINVAL;
}
 
-   ret = dw_pcie_prog_inbound_atu(pci, free_win, bar, cpu_addr,
+   ret = dw_pcie_prog_inbound_atu(pci, func_no, free_win, bar, cpu_addr,
   as_type);
if 

[PATCHv8 02/12] PCI: designware-ep: Add the doorbell mode of MSI-X in EP mode

2020-09-18 Thread Zhiqiang Hou
From: Xiaowei Bao 

Add the doorbell mode of MSI-X in DWC EP driver.

Signed-off-by: Xiaowei Bao 
Signed-off-by: Hou Zhiqiang 
Reviewed-by: Andrew Murray 
---
V8:
 - Add msix cap check.

 .../pci/controller/dwc/pcie-designware-ep.c   | 19 +++
 drivers/pci/controller/dwc/pcie-designware.h  | 12 
 2 files changed, 31 insertions(+)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c 
b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 500d4ca04947..5ae87e8ffb85 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -473,6 +473,25 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 
func_no,
return 0;
 }
 
+int dw_pcie_ep_raise_msix_irq_doorbell(struct dw_pcie_ep *ep, u8 func_no,
+  u16 interrupt_num)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+   struct dw_pcie_ep_func *ep_func;
+   u32 msg_data;
+
+   ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
+   if (!ep_func || !ep_func->msix_cap)
+   return -EINVAL;
+
+   msg_data = (func_no << PCIE_MSIX_DOORBELL_PF_SHIFT) |
+  (interrupt_num - 1);
+
+   dw_pcie_writel_dbi(pci, PCIE_MSIX_DOORBELL, msg_data);
+
+   return 0;
+}
+
 int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
  u16 interrupt_num)
 {
diff --git a/drivers/pci/controller/dwc/pcie-designware.h 
b/drivers/pci/controller/dwc/pcie-designware.h
index 32102ebc5c37..4b75b798de98 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -105,6 +105,9 @@
 #define PCIE_MISC_CONTROL_1_OFF0x8BC
 #define PCIE_DBI_RO_WR_EN  BIT(0)
 
+#define PCIE_MSIX_DOORBELL 0x948
+#define PCIE_MSIX_DOORBELL_PF_SHIFT24
+
 #define PCIE_PL_CHK_REG_CONTROL_STATUS 0xB20
 #define PCIE_PL_CHK_REG_CHK_REG_START  BIT(0)
 #define PCIE_PL_CHK_REG_CHK_REG_CONTINUOUS BIT(1)
@@ -414,6 +417,8 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 
func_no,
 u8 interrupt_num);
 int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
 u16 interrupt_num);
+int dw_pcie_ep_raise_msix_irq_doorbell(struct dw_pcie_ep *ep, u8 func_no,
+  u16 interrupt_num);
 void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar);
 #else
 static inline void dw_pcie_ep_linkup(struct dw_pcie_ep *ep)
@@ -455,6 +460,13 @@ static inline int dw_pcie_ep_raise_msix_irq(struct 
dw_pcie_ep *ep, u8 func_no,
return 0;
 }
 
+static inline int dw_pcie_ep_raise_msix_irq_doorbell(struct dw_pcie_ep *ep,
+u8 func_no,
+u16 interrupt_num)
+{
+   return 0;
+}
+
 static inline void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno 
bar)
 {
 }
-- 
2.17.1



[PATCHv8 00/12]PCI: dwc: Add the multiple PF support for DWC and Layerscape

2020-09-18 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Add the PCIe EP multiple PF support for DWC and Layerscape, and use
a list to manage the PFs of each PCIe controller; add the doorbell
MSIX function for DWC; and refactor the Layerscape EP driver due to
some difference in Layercape platforms PCIe integration.

Rebased this series against pci/dwc branch of git tree:
https://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/pci.git

Hou Zhiqiang (1):
  misc: pci_endpoint_test: Add driver data for Layerscape PCIe
controllers

Xiaowei Bao (11):
  PCI: designware-ep: Add multiple PFs support for DWC
  PCI: designware-ep: Add the doorbell mode of MSI-X in EP mode
  PCI: designware-ep: Move the function of getting MSI capability
forward
  PCI: designware-ep: Modify MSI and MSIX CAP way of finding
  dt-bindings: pci: layerscape-pci: Add compatible strings for ls1088a
and ls2088a
  PCI: layerscape: Fix some format issue of the code
  PCI: layerscape: Modify the way of getting capability with different
PEX
  PCI: layerscape: Modify the MSIX to the doorbell mode
  PCI: layerscape: Add EP mode support for ls1088a and ls2088a
  arm64: dts: layerscape: Add PCIe EP node for ls1088a
  misc: pci_endpoint_test: Add LS1088a in pci_device_id table

 .../bindings/pci/layerscape-pci.txt   |   2 +
 .../arm64/boot/dts/freescale/fsl-ls1088a.dtsi |  31 +++
 drivers/misc/pci_endpoint_test.c  |   8 +-
 .../pci/controller/dwc/pci-layerscape-ep.c| 100 +--
 .../pci/controller/dwc/pcie-designware-ep.c   | 245 ++
 drivers/pci/controller/dwc/pcie-designware.c  |  59 +++--
 drivers/pci/controller/dwc/pcie-designware.h  |  48 +++-
 7 files changed, 397 insertions(+), 96 deletions(-)

-- 
2.17.1



[PATCHv8 05/12] dt-bindings: pci: layerscape-pci: Add compatible strings for ls1088a and ls2088a

2020-09-18 Thread Zhiqiang Hou
From: Xiaowei Bao 

Add compatible strings for ls1088a and ls2088a.

Signed-off-by: Xiaowei Bao 
Signed-off-by: Hou Zhiqiang 
Acked-by: Rob Herring 
---
V8:
 - No change.

 Documentation/devicetree/bindings/pci/layerscape-pci.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/pci/layerscape-pci.txt 
b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
index 99a386ea691c..daa99f7d4c3f 100644
--- a/Documentation/devicetree/bindings/pci/layerscape-pci.txt
+++ b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
@@ -24,6 +24,8 @@ Required properties:
 "fsl,ls1028a-pcie"
   EP mode:
"fsl,ls1046a-pcie-ep", "fsl,ls-pcie-ep"
+   "fsl,ls1088a-pcie-ep", "fsl,ls-pcie-ep"
+   "fsl,ls2088a-pcie-ep", "fsl,ls-pcie-ep"
 - reg: base addresses and lengths of the PCIe controller register blocks.
 - interrupts: A list of interrupt outputs of the controller. Must contain an
   entry for each entry in the interrupt-names property.
-- 
2.17.1



[PATCHv8 07/12] PCI: layerscape: Modify the way of getting capability with different PEX

2020-09-18 Thread Zhiqiang Hou
From: Xiaowei Bao 

The different PCIe controller in one board may be have different
capability of MSI or MSIX, so change the way of getting the MSI
capability, make it more flexible.

Signed-off-by: Xiaowei Bao 
Signed-off-by: Hou Zhiqiang 
Reviewed-by: Rob Herring 
---
V8:
 - No change.

 .../pci/controller/dwc/pci-layerscape-ep.c| 31 ++-
 1 file changed, 23 insertions(+), 8 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index 0691d9ad1356..9601f9c09cb1 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -22,6 +22,7 @@
 
 struct ls_pcie_ep {
struct dw_pcie  *pci;
+   struct pci_epc_features *ls_epc;
 };
 
 #define to_ls_pcie_ep(x)   dev_get_drvdata((x)->dev)
@@ -40,26 +41,31 @@ static const struct of_device_id ls_pcie_ep_of_match[] = {
{ },
 };
 
-static const struct pci_epc_features ls_pcie_epc_features = {
-   .linkup_notifier = false,
-   .msi_capable = true,
-   .msix_capable = false,
-   .bar_fixed_64bit = (1 << BAR_2) | (1 << BAR_4),
-};
-
 static const struct pci_epc_features*
 ls_pcie_ep_get_features(struct dw_pcie_ep *ep)
 {
-   return _pcie_epc_features;
+   struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+   struct ls_pcie_ep *pcie = to_ls_pcie_ep(pci);
+
+   return pcie->ls_epc;
 }
 
 static void ls_pcie_ep_init(struct dw_pcie_ep *ep)
 {
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+   struct ls_pcie_ep *pcie = to_ls_pcie_ep(pci);
+   struct dw_pcie_ep_func *ep_func;
enum pci_barno bar;
 
+   ep_func = dw_pcie_ep_get_func_from_ep(ep, 0);
+   if (!ep_func)
+   return;
+
for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
dw_pcie_ep_reset_bar(pci, bar);
+
+   pcie->ls_epc->msi_capable = ep_func->msi_cap ? true : false;
+   pcie->ls_epc->msix_capable = ep_func->msix_cap ? true : false;
 }
 
 static int ls_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
@@ -119,6 +125,7 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
struct device *dev = >dev;
struct dw_pcie *pci;
struct ls_pcie_ep *pcie;
+   struct pci_epc_features *ls_epc;
struct resource *dbi_base;
int ret;
 
@@ -130,6 +137,10 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
if (!pci)
return -ENOMEM;
 
+   ls_epc = devm_kzalloc(dev, sizeof(*ls_epc), GFP_KERNEL);
+   if (!ls_epc)
+   return -ENOMEM;
+
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))
@@ -140,6 +151,10 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
pci->ops = _pcie_ep_ops;
pcie->pci = pci;
 
+   ls_epc->bar_fixed_64bit = (1 << BAR_2) | (1 << BAR_4),
+
+   pcie->ls_epc = ls_epc;
+
platform_set_drvdata(pdev, pcie);
 
ret = ls_add_pcie_ep(pcie, pdev);
-- 
2.17.1



[PATCHv8 12/12] misc: pci_endpoint_test: Add driver data for Layerscape PCIe controllers

2020-09-18 Thread Zhiqiang Hou
From: Hou Zhiqiang 

The commit 0a121f9bc3f5 ("misc: pci_endpoint_test: Use streaming DMA
APIs for buffer allocation") changed to use streaming DMA APIs, however,
dma_map_single() might not return a 4KB aligned address, so add the
default_data as driver data for Layerscape PCIe controllers to make it
4KB aligned.

Signed-off-by: Hou Zhiqiang 
Acked-by: Rob Herring 
---
V8:
 - No change.

 drivers/misc/pci_endpoint_test.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c
index 4a17f08de60f..70a790cd14c5 100644
--- a/drivers/misc/pci_endpoint_test.c
+++ b/drivers/misc/pci_endpoint_test.c
@@ -946,8 +946,12 @@ static const struct pci_device_id pci_endpoint_test_tbl[] 
= {
{ PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA72x),
  .driver_data = (kernel_ulong_t)_data,
},
-   { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, 0x81c0) },
-   { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, PCI_DEVICE_ID_LS1088A) },
+   { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, 0x81c0),
+ .driver_data = (kernel_ulong_t)_data,
+   },
+   { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, PCI_DEVICE_ID_LS1088A),
+ .driver_data = (kernel_ulong_t)_data,
+   },
{ PCI_DEVICE_DATA(SYNOPSYS, EDDA, NULL) },
{ PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_AM654),
  .driver_data = (kernel_ulong_t)_data
-- 
2.17.1



[PATCHv8 06/12] PCI: layerscape: Fix some format issue of the code

2020-09-18 Thread Zhiqiang Hou
From: Xiaowei Bao 

Fix some format issue of the code in EP driver.

Signed-off-by: Xiaowei Bao 
Signed-off-by: Hou Zhiqiang 
Reviewed-by: Andrew Murray 
---
V8:
 - No change.

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

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index 0d151cead1b7..0691d9ad1356 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -63,7 +63,7 @@ static void ls_pcie_ep_init(struct dw_pcie_ep *ep)
 }
 
 static int ls_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
- enum pci_epc_irq_type type, u16 interrupt_num)
+   enum pci_epc_irq_type type, u16 interrupt_num)
 {
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
 
@@ -87,7 +87,7 @@ static const struct dw_pcie_ep_ops pcie_ep_ops = {
 };
 
 static int __init ls_add_pcie_ep(struct ls_pcie_ep *pcie,
-   struct platform_device *pdev)
+struct platform_device *pdev)
 {
struct dw_pcie *pci = pcie->pci;
struct device *dev = pci->dev;
-- 
2.17.1



[PATCHv8 10/12] arm64: dts: layerscape: Add PCIe EP node for ls1088a

2020-09-18 Thread Zhiqiang Hou
From: Xiaowei Bao 

Add PCIe EP node for ls1088a to support EP mode.

Signed-off-by: Xiaowei Bao 
Signed-off-by: Hou Zhiqiang 
Reviewed-by: Andrew Murray 
---
V8:
 - s/pcie_ep/pcie-ep.

 .../arm64/boot/dts/freescale/fsl-ls1088a.dtsi | 31 +++
 1 file changed, 31 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
index 169f4742ae3b..f21dd143ab6d 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
@@ -499,6 +499,17 @@
status = "disabled";
};
 
+   pcie-ep@340 {
+   compatible = "fsl,ls1088a-pcie-ep","fsl,ls-pcie-ep";
+   reg = <0x00 0x0340 0x0 0x0010
+  0x20 0x 0x8 0x>;
+   reg-names = "regs", "addr_space";
+   num-ib-windows = <24>;
+   num-ob-windows = <128>;
+   max-functions = /bits/ 8 <2>;
+   status = "disabled";
+   };
+
pcie@350 {
compatible = "fsl,ls1088a-pcie";
reg = <0x00 0x0350 0x0 0x0010   /* controller 
registers */
@@ -525,6 +536,16 @@
status = "disabled";
};
 
+   pcie-ep@350 {
+   compatible = "fsl,ls1088a-pcie-ep","fsl,ls-pcie-ep";
+   reg = <0x00 0x0350 0x0 0x0010
+  0x28 0x 0x8 0x>;
+   reg-names = "regs", "addr_space";
+   num-ib-windows = <6>;
+   num-ob-windows = <8>;
+   status = "disabled";
+   };
+
pcie@360 {
compatible = "fsl,ls1088a-pcie";
reg = <0x00 0x0360 0x0 0x0010   /* controller 
registers */
@@ -551,6 +572,16 @@
status = "disabled";
};
 
+   pcie-ep@360 {
+   compatible = "fsl,ls1088a-pcie-ep","fsl,ls-pcie-ep";
+   reg = <0x00 0x0360 0x0 0x0010
+  0x30 0x 0x8 0x>;
+   reg-names = "regs", "addr_space";
+   num-ib-windows = <6>;
+   num-ob-windows = <8>;
+   status = "disabled";
+   };
+
smmu: iommu@500 {
compatible = "arm,mmu-500";
reg = <0 0x500 0 0x80>;
-- 
2.17.1



[PATCHv8 08/12] PCI: layerscape: Modify the MSIX to the doorbell mode

2020-09-18 Thread Zhiqiang Hou
From: Xiaowei Bao 

dw_pcie_ep_raise_msix_irq was never called in the exisitng driver
before, because the ls1046a platform don't support the MSIX feature
and msix_capable was always set to false.
Now that add the ls1088a platform with MSIX support, use the doorbell
method to support the MSIX feature.

Signed-off-by: Xiaowei Bao 
Signed-off-by: Hou Zhiqiang 
Reviewed-by: Andrew Murray 
---
V8:
 - No change.

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

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index 9601f9c09cb1..bfab1c694f00 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -79,7 +79,8 @@ static int ls_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 
func_no,
case PCI_EPC_IRQ_MSI:
return dw_pcie_ep_raise_msi_irq(ep, func_no, interrupt_num);
case PCI_EPC_IRQ_MSIX:
-   return dw_pcie_ep_raise_msix_irq(ep, func_no, interrupt_num);
+   return dw_pcie_ep_raise_msix_irq_doorbell(ep, func_no,
+ interrupt_num);
default:
dev_err(pci->dev, "UNKNOWN IRQ type\n");
return -EINVAL;
-- 
2.17.1



[PATCHv8 04/12] PCI: designware-ep: Modify MSI and MSIX CAP way of finding

2020-09-18 Thread Zhiqiang Hou
From: Xiaowei Bao 

Each PF of EP device should have its own MSI or MSIX capabitily
struct, so create a dw_pcie_ep_func struct and move the msi_cap
and msix_cap to this struct from dw_pcie_ep, and manage the PFs
via a list.

Signed-off-by: Xiaowei Bao 
Signed-off-by: Hou Zhiqiang 

---
V8:
 - Put the ep_func and ep_func->msi_cap pointer checking in one line.

 .../pci/controller/dwc/pcie-designware-ep.c   | 121 +++---
 drivers/pci/controller/dwc/pcie-designware.h  |  18 ++-
 2 files changed, 118 insertions(+), 21 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c 
b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 25767a334259..ad7da4ea43a5 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -30,6 +30,19 @@ void dw_pcie_ep_init_notify(struct dw_pcie_ep *ep)
 }
 EXPORT_SYMBOL_GPL(dw_pcie_ep_init_notify);
 
+struct dw_pcie_ep_func *
+dw_pcie_ep_get_func_from_ep(struct dw_pcie_ep *ep, u8 func_no)
+{
+   struct dw_pcie_ep_func *ep_func;
+
+   list_for_each_entry(ep_func, >func_list, list) {
+   if (ep_func->func_no == func_no)
+   return ep_func;
+   }
+
+   return NULL;
+}
+
 static unsigned int dw_pcie_ep_func_select(struct dw_pcie_ep *ep, u8 func_no)
 {
unsigned int func_offset = 0;
@@ -70,6 +83,47 @@ void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum 
pci_barno bar)
__dw_pcie_ep_reset_bar(pci, func_no, bar, 0);
 }
 
+static u8 __dw_pcie_ep_find_next_cap(struct dw_pcie_ep *ep, u8 func_no,
+   u8 cap_ptr, u8 cap)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+   unsigned int func_offset = 0;
+   u8 cap_id, next_cap_ptr;
+   u16 reg;
+
+   if (!cap_ptr)
+   return 0;
+
+   func_offset = dw_pcie_ep_func_select(ep, func_no);
+
+   reg = dw_pcie_readw_dbi(pci, func_offset + cap_ptr);
+   cap_id = (reg & 0x00ff);
+
+   if (cap_id > PCI_CAP_ID_MAX)
+   return 0;
+
+   if (cap_id == cap)
+   return cap_ptr;
+
+   next_cap_ptr = (reg & 0xff00) >> 8;
+   return __dw_pcie_ep_find_next_cap(ep, func_no, next_cap_ptr, cap);
+}
+
+static u8 dw_pcie_ep_find_capability(struct dw_pcie_ep *ep, u8 func_no, u8 cap)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+   unsigned int func_offset = 0;
+   u8 next_cap_ptr;
+   u16 reg;
+
+   func_offset = dw_pcie_ep_func_select(ep, func_no);
+
+   reg = dw_pcie_readw_dbi(pci, func_offset + PCI_CAPABILITY_LIST);
+   next_cap_ptr = (reg & 0x00ff);
+
+   return __dw_pcie_ep_find_next_cap(ep, func_no, next_cap_ptr, cap);
+}
+
 static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no,
   struct pci_epf_header *hdr)
 {
@@ -259,13 +313,15 @@ static int dw_pcie_ep_get_msi(struct pci_epc *epc, u8 
func_no)
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
u32 val, reg;
unsigned int func_offset = 0;
+   struct dw_pcie_ep_func *ep_func;
 
-   if (!ep->msi_cap)
+   ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
+   if (!ep_func || !ep_func->msi_cap)
return -EINVAL;
 
func_offset = dw_pcie_ep_func_select(ep, func_no);
 
-   reg = ep->msi_cap + func_offset + PCI_MSI_FLAGS;
+   reg = ep_func->msi_cap + func_offset + PCI_MSI_FLAGS;
val = dw_pcie_readw_dbi(pci, reg);
if (!(val & PCI_MSI_FLAGS_ENABLE))
return -EINVAL;
@@ -281,13 +337,15 @@ static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 
func_no, u8 interrupts)
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
u32 val, reg;
unsigned int func_offset = 0;
+   struct dw_pcie_ep_func *ep_func;
 
-   if (!ep->msi_cap)
+   ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
+   if (!ep_func || !ep_func->msi_cap)
return -EINVAL;
 
func_offset = dw_pcie_ep_func_select(ep, func_no);
 
-   reg = ep->msi_cap + func_offset + PCI_MSI_FLAGS;
+   reg = ep_func->msi_cap + func_offset + PCI_MSI_FLAGS;
val = dw_pcie_readw_dbi(pci, reg);
val &= ~PCI_MSI_FLAGS_QMASK;
val |= (interrupts << 1) & PCI_MSI_FLAGS_QMASK;
@@ -304,13 +362,15 @@ static int dw_pcie_ep_get_msix(struct pci_epc *epc, u8 
func_no)
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
u32 val, reg;
unsigned int func_offset = 0;
+   struct dw_pcie_ep_func *ep_func;
 
-   if (!ep->msix_cap)
+   ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
+   if (!ep_func || !ep_func->msix_cap)
return -EINVAL;
 
func_offset = dw_pcie_ep_func_select(ep, func_no);
 
-   reg = ep->msix_cap + func_offset + PCI_MSIX_FLAGS;
+   reg = ep_func->msix_cap + func_offset + PCI_MSIX_FLAGS;
val = dw_pcie_readw_dbi(pci, reg);
if (!(val & PCI_MSIX_FLAGS_ENABLE))
return -EINVAL;
@@ 

[PATCHv8 11/12] misc: pci_endpoint_test: Add LS1088a in pci_device_id table

2020-09-18 Thread Zhiqiang Hou
From: Xiaowei Bao 

Add LS1088a in pci_device_id table so that pci-epf-test can be used
for testing PCIe EP in LS1088a.

Signed-off-by: Xiaowei Bao 
Signed-off-by: Hou Zhiqiang 
Reviewed-by: Andrew Murray 
---
V8:
 - No change.

 drivers/misc/pci_endpoint_test.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c
index e060796f9caa..4a17f08de60f 100644
--- a/drivers/misc/pci_endpoint_test.c
+++ b/drivers/misc/pci_endpoint_test.c
@@ -70,6 +70,7 @@
 
 #define PCI_DEVICE_ID_TI_J721E 0xb00d
 #define PCI_DEVICE_ID_TI_AM654 0xb00c
+#define PCI_DEVICE_ID_LS1088A  0x80c0
 
 #define is_am654_pci_dev(pdev) \
((pdev)->device == PCI_DEVICE_ID_TI_AM654)
@@ -946,6 +947,7 @@ static const struct pci_device_id pci_endpoint_test_tbl[] = 
{
  .driver_data = (kernel_ulong_t)_data,
},
{ PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, 0x81c0) },
+   { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, PCI_DEVICE_ID_LS1088A) },
{ PCI_DEVICE_DATA(SYNOPSYS, EDDA, NULL) },
{ PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_AM654),
  .driver_data = (kernel_ulong_t)_data
-- 
2.17.1



[PATCHv8 09/12] PCI: layerscape: Add EP mode support for ls1088a and ls2088a

2020-09-18 Thread Zhiqiang Hou
From: Xiaowei Bao 

Add PCIe EP mode support for ls1088a and ls2088a, there are some
difference between LS1 and LS2 platform, so refactor the code of
the EP driver.

Signed-off-by: Xiaowei Bao 
Signed-off-by: Hou Zhiqiang 
Reviewed-by: Rob Herring 
---
V8:
 - No change.

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

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index bfab1c694f00..84206f265e54 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -20,27 +20,29 @@
 
 #define PCIE_DBI2_OFFSET   0x1000  /* DBI2 base address*/
 
-struct ls_pcie_ep {
-   struct dw_pcie  *pci;
-   struct pci_epc_features *ls_epc;
+#define to_ls_pcie_ep(x)   dev_get_drvdata((x)->dev)
+
+struct ls_pcie_ep_drvdata {
+   u32 func_offset;
+   const struct dw_pcie_ep_ops *ops;
+   const struct dw_pcie_ops*dw_pcie_ops;
 };
 
-#define to_ls_pcie_ep(x)   dev_get_drvdata((x)->dev)
+struct ls_pcie_ep {
+   struct dw_pcie  *pci;
+   struct pci_epc_features *ls_epc;
+   const struct ls_pcie_ep_drvdata *drvdata;
+};
 
 static int ls_pcie_establish_link(struct dw_pcie *pci)
 {
return 0;
 }
 
-static const struct dw_pcie_ops ls_pcie_ep_ops = {
+static const struct dw_pcie_ops dw_ls_pcie_ep_ops = {
.start_link = ls_pcie_establish_link,
 };
 
-static const struct of_device_id ls_pcie_ep_of_match[] = {
-   { .compatible = "fsl,ls-pcie-ep",},
-   { },
-};
-
 static const struct pci_epc_features*
 ls_pcie_ep_get_features(struct dw_pcie_ep *ep)
 {
@@ -87,10 +89,39 @@ static int ls_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 
func_no,
}
 }
 
-static const struct dw_pcie_ep_ops pcie_ep_ops = {
+static unsigned int ls_pcie_ep_func_conf_select(struct dw_pcie_ep *ep,
+   u8 func_no)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+   struct ls_pcie_ep *pcie = to_ls_pcie_ep(pci);
+
+   WARN_ON(func_no && !pcie->drvdata->func_offset);
+   return pcie->drvdata->func_offset * func_no;
+}
+
+static const struct dw_pcie_ep_ops ls_pcie_ep_ops = {
.ep_init = ls_pcie_ep_init,
.raise_irq = ls_pcie_ep_raise_irq,
.get_features = ls_pcie_ep_get_features,
+   .func_conf_select = ls_pcie_ep_func_conf_select,
+};
+
+static const struct ls_pcie_ep_drvdata ls1_ep_drvdata = {
+   .ops = _pcie_ep_ops,
+   .dw_pcie_ops = _ls_pcie_ep_ops,
+};
+
+static const struct ls_pcie_ep_drvdata ls2_ep_drvdata = {
+   .func_offset = 0x2,
+   .ops = _pcie_ep_ops,
+   .dw_pcie_ops = _ls_pcie_ep_ops,
+};
+
+static const struct of_device_id ls_pcie_ep_of_match[] = {
+   { .compatible = "fsl,ls1046a-pcie-ep", .data = _ep_drvdata },
+   { .compatible = "fsl,ls1088a-pcie-ep", .data = _ep_drvdata },
+   { .compatible = "fsl,ls2088a-pcie-ep", .data = _ep_drvdata },
+   { },
 };
 
 static int __init ls_add_pcie_ep(struct ls_pcie_ep *pcie,
@@ -103,7 +134,7 @@ static int __init ls_add_pcie_ep(struct ls_pcie_ep *pcie,
int ret;
 
ep = >ep;
-   ep->ops = _ep_ops;
+   ep->ops = pcie->drvdata->ops;
 
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space");
if (!res)
@@ -142,20 +173,23 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
if (!ls_epc)
return -ENOMEM;
 
-   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);
+   pcie->drvdata = of_device_get_match_data(dev);
 
-   pci->dbi_base2 = pci->dbi_base + PCIE_DBI2_OFFSET;
pci->dev = dev;
-   pci->ops = _pcie_ep_ops;
-   pcie->pci = pci;
+   pci->ops = pcie->drvdata->dw_pcie_ops;
 
ls_epc->bar_fixed_64bit = (1 << BAR_2) | (1 << BAR_4),
 
+   pcie->pci = pci;
pcie->ls_epc = ls_epc;
 
+   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);
+
+   pci->dbi_base2 = pci->dbi_base + PCIE_DBI2_OFFSET;
+
platform_set_drvdata(pdev, pcie);
 
ret = ls_add_pcie_ep(pcie, pdev);
-- 
2.17.1



[PATCH] PCI: dwc: Added link up check in map_bus of dw_child_pcie_ops

2020-09-15 Thread Zhiqiang Hou
From: Hou Zhiqiang 

On NXP Layerscape platforms, it results in SError in the
enumeration of the PCIe controller, which is not connecting
with an Endpoint device. And it doesn't make sense to
enumerate the Endpoints when the PCIe link is down. So this
patch added the link up check to avoid to fire configuration
transactions on link down bus.

[0.807773] SError Interrupt on CPU2, code 0xbf02 -- SError
[0.807775] CPU: 2 PID: 1 Comm: swapper/0 Not tainted 
5.9.0-rc5-next-20200914-1-gf965d3ec86fa #67
[0.807776] Hardware name: LS1046A RDB Board (DT)
[0.80] pstate: 2085 (nzCv daIf -PAN -UAO BTYPE=--)
[0.807778] pc : pci_generic_config_read+0x3c/0xe0
[0.807778] lr : pci_generic_config_read+0x24/0xe0
[0.807779] sp : 80001003b7b0
[0.807780] x29: 80001003b7b0 x28: 80001003ba74
[0.807782] x27: 000971d96800 x26: 00096e77e0a8
[0.807784] x25: 80001003b874 x24: 80001003b924
[0.807786] x23: 0004 x22: 
[0.807788] x21:  x20: 80001003b874
[0.807790] x19: 0004 x18: 
[0.807791] x17: 00c0 x16: fe0025981840
[0.807793] x15: b94c75b69948 x14: 62203a383634203a
[0.807795] x13: 666e6f635f726568 x12: 202c31203d207265
[0.807797] x11: 626d756e3e2d7375 x10: 656877202c307830
[0.807799] x9 : 203d206e66766564 x8 : 0908
[0.807801] x7 : 0908 x6 : 80001090
[0.807802] x5 : 00096e77e080 x4 : 
[0.807804] x3 : 0003 x2 : 84fa3440ff7e7000
[0.807806] x1 :  x0 : 800010034000
[0.807808] Kernel panic - not syncing: Asynchronous SError Interrupt
[0.807809] CPU: 2 PID: 1 Comm: swapper/0 Not tainted 
5.9.0-rc5-next-20200914-1-gf965d3ec86fa #67
[0.807810] Hardware name: LS1046A RDB Board (DT)
[0.807811] Call trace:
[0.807812]  dump_backtrace+0x0/0x1c0
[0.807813]  show_stack+0x18/0x28
[0.807814]  dump_stack+0xd8/0x134
[0.807814]  panic+0x180/0x398
[0.807815]  add_taint+0x0/0xb0
[0.807816]  arm64_serror_panic+0x78/0x88
[0.807817]  do_serror+0x68/0x180
[0.807818]  el1_error+0x84/0x100
[0.807818]  pci_generic_config_read+0x3c/0xe0
[0.807819]  dw_pcie_rd_other_conf+0x78/0x110
[0.807820]  pci_bus_read_config_dword+0x88/0xe8
[0.807821]  pci_bus_generic_read_dev_vendor_id+0x30/0x1b0
[0.807822]  pci_bus_read_dev_vendor_id+0x4c/0x78
[0.807823]  pci_scan_single_device+0x80/0x100
[0.807824]  pci_scan_slot+0x38/0x130
[0.807825]  pci_scan_child_bus_extend+0x54/0x2a0
[0.807826]  pci_scan_child_bus+0x14/0x20
[0.807827]  pci_scan_bridge_extend+0x230/0x570
[0.807828]  pci_scan_child_bus_extend+0x134/0x2a0
[0.807829]  pci_scan_root_bus_bridge+0x64/0xf0
[0.807829]  pci_host_probe+0x18/0xc8
[0.807830]  dw_pcie_host_init+0x220/0x378
[0.807831]  ls_pcie_probe+0x104/0x140
[0.807832]  platform_drv_probe+0x54/0xa8
[0.807833]  really_probe+0x118/0x3e0
[0.807834]  driver_probe_device+0x5c/0xc0
[0.807835]  device_driver_attach+0x74/0x80
[0.807835]  __driver_attach+0x8c/0xd8
[0.807836]  bus_for_each_dev+0x7c/0xd8
[0.807837]  driver_attach+0x24/0x30
[0.807838]  bus_add_driver+0x154/0x200
[0.807839]  driver_register+0x64/0x120
[0.807839]  __platform_driver_probe+0x7c/0x148
[0.807840]  ls_pcie_driver_init+0x24/0x30
[0.807841]  do_one_initcall+0x60/0x1d8
[0.807842]  kernel_init_freeable+0x1f4/0x24c
[0.807843]  kernel_init+0x14/0x118
[0.807843]  ret_from_fork+0x10/0x34
[0.807854] SMP: stopping secondary CPUs
[0.807855] Kernel Offset: 0x394c6408 from 0x80001000
[0.807856] PHYS_OFFSET: 0x8bfd4000
[0.807856] CPU features: 0x0240022,21806000
[0.807857] Memory Limit: none

Fixes: c2b0c098fbd1 ("PCI: dwc: Use generic config accessors")
Signed-off-by: Hou Zhiqiang 
---
 drivers/pci/controller/dwc/pcie-designware-host.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c 
b/drivers/pci/controller/dwc/pcie-designware-host.c
index c01c9d2fb3f9..e82b518430c5 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -442,6 +442,9 @@ static void __iomem *dw_pcie_other_conf_map_bus(struct 
pci_bus *bus,
struct pcie_port *pp = bus->sysdata;
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
 
+   if (!dw_pcie_link_up(pci))
+   return NULL;
+
busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) |
 PCIE_ATU_FUNC(PCI_FUNC(devfn));
 
-- 
2.17.1



[PATCH 5/7] dt-bindings: pci: layerscape-pci: Update the description of SCFG property

2020-09-06 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Update the description of the second entry of 'fsl,pcie-scfg' property,
as the LS1043A PCIe controller also has some control registers in SCFG
block, while it has 3 controllers.

Signed-off-by: Hou Zhiqiang 
---
 Documentation/devicetree/bindings/pci/layerscape-pci.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/pci/layerscape-pci.txt 
b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
index 2236d3f3089b..e992ec712bf6 100644
--- a/Documentation/devicetree/bindings/pci/layerscape-pci.txt
+++ b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
@@ -31,7 +31,7 @@ Required properties:
   "intr": The interrupt that is asserted for controller interrupts
 - fsl,pcie-scfg: Must include two entries.
   The first entry must be a link to the SCFG device node
-  The second entry must be '0' or '1' based on physical PCIe controller index.
+  The second entry is the physical PCIe controller index starting from '0'.
   This is used to get SCFG PEXN registers
 - dma-coherent: Indicates that the hardware IP block can ensure the coherency
   of the data transferred from/to the IP block. This can avoid the software
-- 
2.17.1



[PATCH 6/7] dts: arm64: ls1043a: Add SCFG phandle for PCIe nodes

2020-09-06 Thread Zhiqiang Hou
From: Hou Zhiqiang 

The LS1043A PCIe controller has some control registers
in SCFG block, so add the SCFG phandle for each PCIe
controller DT node.

Signed-off-by: Hou Zhiqiang 
---
 arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index 70e07612da12..30ccf1fdb851 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -822,6 +822,7 @@
interrupts = <0 118 0x4>, /* controller interrupt */
 <0 117 0x4>; /* PME interrupt */
interrupt-names = "intr", "pme";
+   fsl,pcie-scfg = < 0>;
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
@@ -849,6 +850,7 @@
interrupts = <0 128 0x4>,
 <0 127 0x4>;
interrupt-names = "intr", "pme";
+   fsl,pcie-scfg = < 1>;
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
@@ -876,6 +878,7 @@
interrupts = <0 162 0x4>,
 <0 161 0x4>;
interrupt-names = "intr", "pme";
+   fsl,pcie-scfg = < 2>;
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
-- 
2.17.1



[PATCH 7/7] PCI: layerscape: Add power management support

2020-09-06 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Add PME_Turn_Off/PME_TO_Ack handshake sequence, and finally
put the PCIe controller into D3 state after the L2/L3 ready
state transition process completion.

Signed-off-by: Hou Zhiqiang 
---
 drivers/pci/controller/dwc/pci-layerscape.c  | 384 ++-
 drivers/pci/controller/dwc/pcie-designware.h |   1 +
 2 files changed, 383 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index be404c16bcbe..ca9ea07f77c1 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -3,13 +3,16 @@
  * PCIe host controller driver for Freescale Layerscape SoCs
  *
  * Copyright (C) 2014 Freescale Semiconductor.
+ * Copyright 2020 NXP
  *
  * Author: Minghuan Lian 
  */
 
+#include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -27,17 +30,66 @@
 #define PCIE_ABSERR0x8d0 /* Bridge Slave Error Response Register */
 #define PCIE_ABSERR_SETTING0x9401 /* Forward error of non-posted request */
 
+#define PCIE_PM_SCR0x44
+#define PCIE_PM_SCR_PMEPS_D0   0x0
+#define PCIE_PM_SCR_PMEPS_D3   0x3
+
+#define PCIE_LNKCTL0x80  /* PCIe link ctrl Register */
+
+/* PF Message Command Register */
+#define LS_PCIE_PF_MCR 0x2c
+#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)
+
+/* 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_IS_L2(v)   \
+   (((v) & PORT_LOGIC_LTSSM_STATE_MASK) == PORT_LOGIC_LTSSM_STATE_L2)
+
+struct ls_pcie;
+
+struct ls_pcie_host_pm_ops {
+   int (*pm_init)(struct ls_pcie *pcie);
+   void (*send_turn_off_message)(struct ls_pcie *pcie);
+   void (*exit_from_l2)(struct ls_pcie *pcie);
+};
+
 struct ls_pcie_drvdata {
+   const u32 pf_off;
+   const u32 lut_off;
const struct dw_pcie_host_ops *ops;
+   const struct ls_pcie_host_pm_ops *pm_ops;
 };
 
 struct ls_pcie {
struct dw_pcie *pci;
const struct ls_pcie_drvdata *drvdata;
+   void __iomem *pf_base;
+   void __iomem *lut_base;
+   bool big_endian;
+   bool ep_presence;
+   bool pm_support;
+   struct regmap *scfg;
+   int index;
 };
 
+#define ls_pcie_lut_readl_addr(addr)   ls_pcie_lut_readl(pcie, addr)
+#define ls_pcie_pf_readl_addr(addr)ls_pcie_pf_readl(pcie, addr)
 #define to_ls_pcie(x)  dev_get_drvdata((x)->dev)
 
 static bool ls_pcie_is_bridge(struct ls_pcie *pcie)
@@ -86,6 +138,208 @@ static void ls_pcie_fix_error_response(struct ls_pcie 
*pcie)
iowrite32(PCIE_ABSERR_SETTING, pci->dbi_base + PCIE_ABSERR);
 }
 
+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)
+   return iowrite32be(val, pcie->lut_base + off);
+
+   return iowrite32(val, pcie->lut_base + off);
+
+}
+
+static u32 ls_pcie_pf_readl(struct ls_pcie *pcie, u32 off)
+{
+   if (pcie->big_endian)
+   return ioread32be(pcie->pf_base + off);
+
+   return ioread32(pcie->pf_base + off);
+}
+
+static void ls_pcie_pf_writel(struct ls_pcie *pcie, u32 off, u32 val)
+{
+   if (pcie->big_endian)
+   return iowrite32be(val, pcie->pf_base + off);
+
+   return iowrite32(val, pcie->pf_base + off);
+
+}
+
+static void ls_pcie_send_turnoff_msg(struct ls_pcie *pcie)
+{
+   u32 val;
+   int ret;
+
+   val = ls_pcie_pf_readl(pcie, LS_PCIE_PF_MCR);
+   val |= PF_MCR_PTOMR;
+   ls_pcie_pf_writel(pcie, LS_PCIE_PF_MCR, val);
+
+   ret = readx_poll_timeout(ls_pcie_pf_readl_addr, LS_PCIE_PF_MCR,
+val, !(val & PF_MCR_PTOMR), 100, 1);
+   if (ret)
+   dev_info(pcie->pci->dev, "poll turn off message timeout\n");
+}
+
+static void ls1021a_pcie_send_turnoff_msg(struct ls_pcie *pcie)
+{
+   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);
+
+   mdelay(10);
+
+   /* Clear Turn_off message */
+   

[PATCH 1/7] PCI: dwc: Fix a bug of the case dw_pci->ops is NULL

2020-09-06 Thread Zhiqiang Hou
From: Hou Zhiqiang 

The dw_pci->ops may be a NULL, and fix it by adding one more check.

Signed-off-by: Hou Zhiqiang 
---
 drivers/pci/controller/dwc/pcie-designware.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware.c 
b/drivers/pci/controller/dwc/pcie-designware.c
index b723e0cc41fb..bdf8938da9cd 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -140,7 +140,7 @@ u32 dw_pcie_read_dbi(struct dw_pcie *pci, u32 reg, size_t 
size)
int ret;
u32 val;
 
-   if (pci->ops->read_dbi)
+   if (pci->ops && pci->ops->read_dbi)
return pci->ops->read_dbi(pci, pci->dbi_base, reg, size);
 
ret = dw_pcie_read(pci->dbi_base + reg, size, );
@@ -155,7 +155,7 @@ void dw_pcie_write_dbi(struct dw_pcie *pci, u32 reg, size_t 
size, u32 val)
 {
int ret;
 
-   if (pci->ops->write_dbi) {
+   if (pci->ops && pci->ops->write_dbi) {
pci->ops->write_dbi(pci, pci->dbi_base, reg, size, val);
return;
}
@@ -200,7 +200,7 @@ u32 dw_pcie_read_atu(struct dw_pcie *pci, u32 reg, size_t 
size)
int ret;
u32 val;
 
-   if (pci->ops->read_dbi)
+   if (pci->ops && pci->ops->read_dbi)
return pci->ops->read_dbi(pci, pci->atu_base, reg, size);
 
ret = dw_pcie_read(pci->atu_base + reg, size, );
@@ -214,7 +214,7 @@ void dw_pcie_write_atu(struct dw_pcie *pci, u32 reg, size_t 
size, u32 val)
 {
int ret;
 
-   if (pci->ops->write_dbi) {
+   if (pci->ops && pci->ops->write_dbi) {
pci->ops->write_dbi(pci, pci->atu_base, reg, size, val);
return;
}
@@ -283,7 +283,7 @@ void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int 
index, int type,
 {
u32 retries, val;
 
-   if (pci->ops->cpu_addr_fixup)
+   if (pci->ops && pci->ops->cpu_addr_fixup)
cpu_addr = pci->ops->cpu_addr_fixup(pci, cpu_addr);
 
if (pci->iatu_unroll_enabled) {
@@ -470,7 +470,7 @@ int dw_pcie_link_up(struct dw_pcie *pci)
 {
u32 val;
 
-   if (pci->ops->link_up)
+   if (pci->ops && pci->ops->link_up)
return pci->ops->link_up(pci);
 
val = readl(pci->dbi_base + PCIE_PORT_DEBUG1);
-- 
2.17.1



[PATCH 4/7] arm64: dts: layerscape: Add big-endian property for PCIe nodes

2020-09-06 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Add the big-endian property for LS1012A, LS1043A and LS1046A
PCIe devicetree nodes.

Signed-off-by: Hou Zhiqiang 
---
 arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi | 1 +
 arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 3 +++
 arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 3 +++
 3 files changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
index ff19ec415b60..77a0d401c177 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
@@ -511,6 +511,7 @@
< 0 0 2  0 111 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 3  0 112 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 4  0 113 
IRQ_TYPE_LEVEL_HIGH>;
+   big-endian;
status = "disabled";
};
 
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index 5c2e370f6316..70e07612da12 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -837,6 +837,7 @@
< 0 0 2  0 111 0x4>,
< 0 0 3  0 112 0x4>,
< 0 0 4  0 113 0x4>;
+   big-endian;
status = "disabled";
};
 
@@ -863,6 +864,7 @@
< 0 0 2  0 121 0x4>,
< 0 0 3  0 122 0x4>,
< 0 0 4  0 123 0x4>;
+   big-endian;
status = "disabled";
};
 
@@ -889,6 +891,7 @@
< 0 0 2  0 155 0x4>,
< 0 0 3  0 156 0x4>,
< 0 0 4  0 157 0x4>;
+   big-endian;
status = "disabled";
};
 
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
index 0246d975a206..efcbfe8e5e1d 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
@@ -741,6 +741,7 @@
< 0 0 2  GIC_SPI 110 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 3  GIC_SPI 110 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 4  GIC_SPI 110 
IRQ_TYPE_LEVEL_HIGH>;
+   big-endian;
status = "disabled";
};
 
@@ -777,6 +778,7 @@
< 0 0 2  GIC_SPI 120 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 3  GIC_SPI 120 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 4  GIC_SPI 120 
IRQ_TYPE_LEVEL_HIGH>;
+   big-endian;
status = "disabled";
};
 
@@ -813,6 +815,7 @@
< 0 0 2  GIC_SPI 154 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 3  GIC_SPI 154 
IRQ_TYPE_LEVEL_HIGH>,
< 0 0 4  GIC_SPI 154 
IRQ_TYPE_LEVEL_HIGH>;
+   big-endian;
status = "disabled";
};
 
-- 
2.17.1



[PATCH 3/7] dt-bindings: pci: layerscape-pci: Add a optional property big-endian

2020-09-06 Thread Zhiqiang Hou
From: Hou Zhiqiang 

This property is to indicate the endianness when accessing the
PEX_LUT and PF register block, so if these registers are
implemented in big-endian, specify this property.

Signed-off-by: Hou Zhiqiang 
---
 Documentation/devicetree/bindings/pci/layerscape-pci.txt | 4 
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/pci/layerscape-pci.txt 
b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
index 99a386ea691c..2236d3f3089b 100644
--- a/Documentation/devicetree/bindings/pci/layerscape-pci.txt
+++ b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
@@ -37,6 +37,10 @@ Required properties:
   of the data transferred from/to the IP block. This can avoid the software
   cache flush/invalid actions, and improve the performance significantly.
 
+Optional properties:
+- big-endian: If the PEX_LUT and PF register block is in big-endian, specify
+  this property.
+
 Example:
 
pcie@340 {
-- 
2.17.1



[PATCH 2/7] PCI: layerscape: Change to use the DWC common link-up check function

2020-09-06 Thread Zhiqiang Hou
From: Hou Zhiqiang 

The current Layerscape PCIe driver directly uses the physical layer
LTSSM code to check the link-up state, which treats the > L0 states
as link-up. This is not correct, since there is not explicit map
between link-up state and LTSSM. So this patch changes to use the
DWC common link-up check function.

Signed-off-by: Hou Zhiqiang 
---
 drivers/pci/controller/dwc/pci-layerscape.c | 141 ++--
 1 file changed, 10 insertions(+), 131 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape.c 
b/drivers/pci/controller/dwc/pci-layerscape.c
index f24f79a70d9a..be404c16bcbe 100644
--- a/drivers/pci/controller/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
@@ -22,12 +22,6 @@
 
 #include "pcie-designware.h"
 
-/* PEX1/2 Misc Ports Status Register */
-#define SCFG_PEXMSCPORTSR(pex_idx) (0x94 + (pex_idx) * 4)
-#define LTSSM_STATE_SHIFT  20
-#define LTSSM_STATE_MASK   0x3f
-#define LTSSM_PCIE_L0  0x11 /* L0 state */
-
 /* PEX Internal Configuration Registers */
 #define PCIE_STRFMR1   0x71c /* Symbol Timer & Filter Mask Register1 */
 #define PCIE_ABSERR0x8d0 /* Bridge Slave Error Response Register */
@@ -36,19 +30,12 @@
 #define PCIE_IATU_NUM  6
 
 struct ls_pcie_drvdata {
-   u32 lut_offset;
-   u32 ltssm_shift;
-   u32 lut_dbg;
const struct dw_pcie_host_ops *ops;
-   const struct dw_pcie_ops *dw_pcie_ops;
 };
 
 struct ls_pcie {
struct dw_pcie *pci;
-   void __iomem *lut;
-   struct regmap *scfg;
const struct ls_pcie_drvdata *drvdata;
-   int index;
 };
 
 #define to_ls_pcie(x)  dev_get_drvdata((x)->dev)
@@ -91,38 +78,6 @@ static void ls_pcie_disable_outbound_atus(struct ls_pcie 
*pcie)
dw_pcie_disable_atu(pcie->pci, i, DW_PCIE_REGION_OUTBOUND);
 }
 
-static int ls1021_pcie_link_up(struct dw_pcie *pci)
-{
-   u32 state;
-   struct ls_pcie *pcie = to_ls_pcie(pci);
-
-   if (!pcie->scfg)
-   return 0;
-
-   regmap_read(pcie->scfg, SCFG_PEXMSCPORTSR(pcie->index), );
-   state = (state >> LTSSM_STATE_SHIFT) & LTSSM_STATE_MASK;
-
-   if (state < LTSSM_PCIE_L0)
-   return 0;
-
-   return 1;
-}
-
-static int ls_pcie_link_up(struct dw_pcie *pci)
-{
-   struct ls_pcie *pcie = to_ls_pcie(pci);
-   u32 state;
-
-   state = (ioread32(pcie->lut + pcie->drvdata->lut_dbg) >>
-pcie->drvdata->ltssm_shift) &
-LTSSM_STATE_MASK;
-
-   if (state < LTSSM_PCIE_L0)
-   return 0;
-
-   return 1;
-}
-
 /* Forward error response of outbound non-posted requests */
 static void ls_pcie_fix_error_response(struct ls_pcie *pcie)
 {
@@ -155,33 +110,6 @@ static int ls_pcie_host_init(struct pcie_port *pp)
return 0;
 }
 
-static int ls1021_pcie_host_init(struct pcie_port *pp)
-{
-   struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
-   struct ls_pcie *pcie = to_ls_pcie(pci);
-   struct device *dev = pci->dev;
-   u32 index[2];
-   int 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;
-   }
-
-   if (of_property_read_u32_array(dev->of_node,
-  "fsl,pcie-scfg", index, 2)) {
-   pcie->scfg = NULL;
-   return -EINVAL;
-   }
-   pcie->index = index[1];
-
-   return ls_pcie_host_init(pp);
-}
-
 static int ls_pcie_msi_host_init(struct pcie_port *pp)
 {
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
@@ -205,71 +133,25 @@ static int ls_pcie_msi_host_init(struct pcie_port *pp)
return 0;
 }
 
-static const struct dw_pcie_host_ops ls1021_pcie_host_ops = {
-   .host_init = ls1021_pcie_host_init,
-   .msi_host_init = ls_pcie_msi_host_init,
-};
-
 static const struct dw_pcie_host_ops ls_pcie_host_ops = {
.host_init = ls_pcie_host_init,
.msi_host_init = ls_pcie_msi_host_init,
 };
 
-static const struct dw_pcie_ops dw_ls1021_pcie_ops = {
-   .link_up = ls1021_pcie_link_up,
-};
-
-static const struct dw_pcie_ops dw_ls_pcie_ops = {
-   .link_up = ls_pcie_link_up,
-};
-
-static const struct ls_pcie_drvdata ls1021_drvdata = {
-   .ops = _pcie_host_ops,
-   .dw_pcie_ops = _ls1021_pcie_ops,
-};
-
-static const struct ls_pcie_drvdata ls1043_drvdata = {
-   .lut_offset = 0x1,
-   .ltssm_shift = 24,
-   .lut_dbg = 0x7fc,
-   .ops = _pcie_host_ops,
-   .dw_pcie_ops = _ls_pcie_ops,
-};
-
-static const struct ls_pcie_drvdata ls1046_drvdata = {
-   .lut_offset = 0x8,
-   .ltssm_shift = 24,
-   .lut_dbg = 0x407fc,
-   .ops = _pcie_host_ops,
-   .dw_pcie_ops = _ls_pcie_ops,
-};
-
-static 

[PATCH 0/7] PCI: layerscape: Add power management support

2020-09-06 Thread Zhiqiang Hou
From: Hou Zhiqiang 

This patch series is to add PCIe power management support for NXP
Layerscape platfroms.

Hou Zhiqiang (7):
  PCI: dwc: Fix a bug of the case dw_pci->ops is NULL
  PCI: layerscape: Change to use the DWC common link-up check function
  dt-bindings: pci: layerscape-pci: Add a optional property big-endian
  arm64: dts: layerscape: Add big-endian property for PCIe nodes
  dt-bindings: pci: layerscape-pci: Update the description of SCFG
property
  dts: arm64: ls1043a: Add SCFG phandle for PCIe nodes
  PCI: layerscape: Add power management support

 .../bindings/pci/layerscape-pci.txt   |   6 +-
 .../arm64/boot/dts/freescale/fsl-ls1012a.dtsi |   1 +
 .../arm64/boot/dts/freescale/fsl-ls1043a.dtsi |   6 +
 .../arm64/boot/dts/freescale/fsl-ls1046a.dtsi |   3 +
 drivers/pci/controller/dwc/pci-layerscape.c   | 473 ++
 drivers/pci/controller/dwc/pcie-designware.c  |  12 +-
 drivers/pci/controller/dwc/pcie-designware.h  |   1 +
 7 files changed, 388 insertions(+), 114 deletions(-)

-- 
2.17.1



[PATCHv2] PCI: designware-ep: Fix the Header Type check

2020-08-18 Thread Zhiqiang Hou
From: Hou Zhiqiang 

The current check will result in the multiple function device
fails to initialize. So fix the check by masking out the
multiple function bit.

Fixes: 0b24134f7888 ("PCI: dwc: Add validation that PCIe core is set to correct 
mode")
Signed-off-by: Hou Zhiqiang 
---
V2:
 - Add marco PCI_HEADER_TYPE_MASK and print the masked value.

 drivers/pci/controller/dwc/pcie-designware-ep.c | 3 ++-
 include/uapi/linux/pci_regs.h   | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c 
b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 4680a51c49c0..0634bd3a0b96 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -653,7 +653,8 @@ int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep)
u32 reg;
int i;
 
-   hdr_type = dw_pcie_readb_dbi(pci, PCI_HEADER_TYPE);
+   hdr_type = dw_pcie_readb_dbi(pci, PCI_HEADER_TYPE) &
+  PCI_HEADER_TYPE_MASK;
if (hdr_type != PCI_HEADER_TYPE_NORMAL) {
dev_err(pci->dev,
"PCIe controller is not set to EP mode 
(hdr_type:0x%x)!\n",
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
index f9701410d3b5..57a222014cd2 100644
--- a/include/uapi/linux/pci_regs.h
+++ b/include/uapi/linux/pci_regs.h
@@ -76,6 +76,7 @@
 #define PCI_CACHE_LINE_SIZE0x0c/* 8 bits */
 #define PCI_LATENCY_TIMER  0x0d/* 8 bits */
 #define PCI_HEADER_TYPE0x0e/* 8 bits */
+#define  PCI_HEADER_TYPE_MASK  0x7f
 #define  PCI_HEADER_TYPE_NORMAL0
 #define  PCI_HEADER_TYPE_BRIDGE1
 #define  PCI_HEADER_TYPE_CARDBUS   2
-- 
2.17.1



[PATCH] PCI: designware-ep: Fix the Header Type check

2020-08-14 Thread Zhiqiang Hou
From: Hou Zhiqiang 

The current check will result in the multiple function device
fails to initialize. So fix the check by masking out the
multiple function bit.

Fixes: 0b24134f7888 ("PCI: dwc: Add validation that PCIe core is set to correct 
mode")
Signed-off-by: Hou Zhiqiang 
---
 drivers/pci/controller/dwc/pcie-designware-ep.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c 
b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 4680a51c49c0..4b7abfb1e669 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -654,7 +654,7 @@ int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep)
int i;
 
hdr_type = dw_pcie_readb_dbi(pci, PCI_HEADER_TYPE);
-   if (hdr_type != PCI_HEADER_TYPE_NORMAL) {
+   if (hdr_type & 0x7f != PCI_HEADER_TYPE_NORMAL) {
dev_err(pci->dev,
"PCIe controller is not set to EP mode 
(hdr_type:0x%x)!\n",
hdr_type);
-- 
2.17.1



[PATCHv7 08/12] PCI: layerscape: Modify the MSIX to the doorbell mode

2020-08-11 Thread Zhiqiang Hou
From: Xiaowei Bao 

dw_pcie_ep_raise_msix_irq was never called in the exisitng driver
before, because the ls1046a platform don't support the MSIX feature
and msix_capable was always set to false.
Now that add the ls1088a platform with MSIX support, use the doorbell
method to support the MSIX feature.

Signed-off-by: Xiaowei Bao 
Reviewed-by: Andrew Murray 
Signed-off-by: Hou Zhiqiang 
---
V7:
 - Rebase the patch without functionality change.

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

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index 9601f9c09cb1..bfab1c694f00 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -79,7 +79,8 @@ static int ls_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 
func_no,
case PCI_EPC_IRQ_MSI:
return dw_pcie_ep_raise_msi_irq(ep, func_no, interrupt_num);
case PCI_EPC_IRQ_MSIX:
-   return dw_pcie_ep_raise_msix_irq(ep, func_no, interrupt_num);
+   return dw_pcie_ep_raise_msix_irq_doorbell(ep, func_no,
+ interrupt_num);
default:
dev_err(pci->dev, "UNKNOWN IRQ type\n");
return -EINVAL;
-- 
2.17.1



[PATCHv7 10/12] arm64: dts: layerscape: Add PCIe EP node for ls1088a

2020-08-11 Thread Zhiqiang Hou
From: Xiaowei Bao 

Add PCIe EP node for ls1088a to support EP mode.

Signed-off-by: Xiaowei Bao 
Reviewed-by: Andrew Murray 
Signed-off-by: Hou Zhiqiang 
---
V7:
 - Rebase the patch without functionality change.

 .../arm64/boot/dts/freescale/fsl-ls1088a.dtsi | 31 +++
 1 file changed, 31 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
index 169f4742ae3b..915592141f1b 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
@@ -499,6 +499,17 @@
status = "disabled";
};
 
+   pcie_ep@340 {
+   compatible = "fsl,ls1088a-pcie-ep","fsl,ls-pcie-ep";
+   reg = <0x00 0x0340 0x0 0x0010
+  0x20 0x 0x8 0x>;
+   reg-names = "regs", "addr_space";
+   num-ib-windows = <24>;
+   num-ob-windows = <128>;
+   max-functions = /bits/ 8 <2>;
+   status = "disabled";
+   };
+
pcie@350 {
compatible = "fsl,ls1088a-pcie";
reg = <0x00 0x0350 0x0 0x0010   /* controller 
registers */
@@ -525,6 +536,16 @@
status = "disabled";
};
 
+   pcie_ep@350 {
+   compatible = "fsl,ls1088a-pcie-ep","fsl,ls-pcie-ep";
+   reg = <0x00 0x0350 0x0 0x0010
+  0x28 0x 0x8 0x>;
+   reg-names = "regs", "addr_space";
+   num-ib-windows = <6>;
+   num-ob-windows = <8>;
+   status = "disabled";
+   };
+
pcie@360 {
compatible = "fsl,ls1088a-pcie";
reg = <0x00 0x0360 0x0 0x0010   /* controller 
registers */
@@ -551,6 +572,16 @@
status = "disabled";
};
 
+   pcie_ep@360 {
+   compatible = "fsl,ls1088a-pcie-ep","fsl,ls-pcie-ep";
+   reg = <0x00 0x0360 0x0 0x0010
+  0x30 0x 0x8 0x>;
+   reg-names = "regs", "addr_space";
+   num-ib-windows = <6>;
+   num-ob-windows = <8>;
+   status = "disabled";
+   };
+
smmu: iommu@500 {
compatible = "arm,mmu-500";
reg = <0 0x500 0 0x80>;
-- 
2.17.1



[PATCHv7 07/12] PCI: layerscape: Modify the way of getting capability with different PEX

2020-08-11 Thread Zhiqiang Hou
From: Xiaowei Bao 

The different PCIe controller in one board may be have different
capability of MSI or MSIX, so change the way of getting the MSI
capability, make it more flexible.

Signed-off-by: Xiaowei Bao 
Reviewed-by: Rob Herring 
Signed-off-by: Hou Zhiqiang 
---
V7:
 - Rebase the patch without functionality change.

 .../pci/controller/dwc/pci-layerscape-ep.c| 31 ++-
 1 file changed, 23 insertions(+), 8 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index 0691d9ad1356..9601f9c09cb1 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -22,6 +22,7 @@
 
 struct ls_pcie_ep {
struct dw_pcie  *pci;
+   struct pci_epc_features *ls_epc;
 };
 
 #define to_ls_pcie_ep(x)   dev_get_drvdata((x)->dev)
@@ -40,26 +41,31 @@ static const struct of_device_id ls_pcie_ep_of_match[] = {
{ },
 };
 
-static const struct pci_epc_features ls_pcie_epc_features = {
-   .linkup_notifier = false,
-   .msi_capable = true,
-   .msix_capable = false,
-   .bar_fixed_64bit = (1 << BAR_2) | (1 << BAR_4),
-};
-
 static const struct pci_epc_features*
 ls_pcie_ep_get_features(struct dw_pcie_ep *ep)
 {
-   return _pcie_epc_features;
+   struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+   struct ls_pcie_ep *pcie = to_ls_pcie_ep(pci);
+
+   return pcie->ls_epc;
 }
 
 static void ls_pcie_ep_init(struct dw_pcie_ep *ep)
 {
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+   struct ls_pcie_ep *pcie = to_ls_pcie_ep(pci);
+   struct dw_pcie_ep_func *ep_func;
enum pci_barno bar;
 
+   ep_func = dw_pcie_ep_get_func_from_ep(ep, 0);
+   if (!ep_func)
+   return;
+
for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
dw_pcie_ep_reset_bar(pci, bar);
+
+   pcie->ls_epc->msi_capable = ep_func->msi_cap ? true : false;
+   pcie->ls_epc->msix_capable = ep_func->msix_cap ? true : false;
 }
 
 static int ls_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
@@ -119,6 +125,7 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
struct device *dev = >dev;
struct dw_pcie *pci;
struct ls_pcie_ep *pcie;
+   struct pci_epc_features *ls_epc;
struct resource *dbi_base;
int ret;
 
@@ -130,6 +137,10 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
if (!pci)
return -ENOMEM;
 
+   ls_epc = devm_kzalloc(dev, sizeof(*ls_epc), GFP_KERNEL);
+   if (!ls_epc)
+   return -ENOMEM;
+
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))
@@ -140,6 +151,10 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
pci->ops = _pcie_ep_ops;
pcie->pci = pci;
 
+   ls_epc->bar_fixed_64bit = (1 << BAR_2) | (1 << BAR_4),
+
+   pcie->ls_epc = ls_epc;
+
platform_set_drvdata(pdev, pcie);
 
ret = ls_add_pcie_ep(pcie, pdev);
-- 
2.17.1



[PATCHv7 04/12] PCI: designware-ep: Modify MSI and MSIX CAP way of finding

2020-08-11 Thread Zhiqiang Hou
From: Xiaowei Bao 

Each PF of EP device should have its own MSI or MSIX capabitily
struct, so create a dw_pcie_ep_func struct and move the msi_cap
and msix_cap to this struct from dw_pcie_ep, and manage the PFs
via a list.

Signed-off-by: Xiaowei Bao 
Signed-off-by: Hou Zhiqiang 
---
V7:
 - Rebase the patch without functionality change.

 .../pci/controller/dwc/pcie-designware-ep.c   | 139 +++---
 drivers/pci/controller/dwc/pcie-designware.h  |  18 ++-
 2 files changed, 136 insertions(+), 21 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c 
b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 56bd1cd71f16..4680a51c49c0 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -28,6 +28,19 @@ void dw_pcie_ep_init_notify(struct dw_pcie_ep *ep)
 }
 EXPORT_SYMBOL_GPL(dw_pcie_ep_init_notify);
 
+struct dw_pcie_ep_func *
+dw_pcie_ep_get_func_from_ep(struct dw_pcie_ep *ep, u8 func_no)
+{
+   struct dw_pcie_ep_func *ep_func;
+
+   list_for_each_entry(ep_func, >func_list, list) {
+   if (ep_func->func_no == func_no)
+   return ep_func;
+   }
+
+   return NULL;
+}
+
 static unsigned int dw_pcie_ep_func_select(struct dw_pcie_ep *ep, u8 func_no)
 {
unsigned int func_offset = 0;
@@ -68,6 +81,47 @@ void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum 
pci_barno bar)
__dw_pcie_ep_reset_bar(pci, func_no, bar, 0);
 }
 
+static u8 __dw_pcie_ep_find_next_cap(struct dw_pcie_ep *ep, u8 func_no,
+   u8 cap_ptr, u8 cap)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+   unsigned int func_offset = 0;
+   u8 cap_id, next_cap_ptr;
+   u16 reg;
+
+   if (!cap_ptr)
+   return 0;
+
+   func_offset = dw_pcie_ep_func_select(ep, func_no);
+
+   reg = dw_pcie_readw_dbi(pci, func_offset + cap_ptr);
+   cap_id = (reg & 0x00ff);
+
+   if (cap_id > PCI_CAP_ID_MAX)
+   return 0;
+
+   if (cap_id == cap)
+   return cap_ptr;
+
+   next_cap_ptr = (reg & 0xff00) >> 8;
+   return __dw_pcie_ep_find_next_cap(ep, func_no, next_cap_ptr, cap);
+}
+
+static u8 dw_pcie_ep_find_capability(struct dw_pcie_ep *ep, u8 func_no, u8 cap)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+   unsigned int func_offset = 0;
+   u8 next_cap_ptr;
+   u16 reg;
+
+   func_offset = dw_pcie_ep_func_select(ep, func_no);
+
+   reg = dw_pcie_readw_dbi(pci, func_offset + PCI_CAPABILITY_LIST);
+   next_cap_ptr = (reg & 0x00ff);
+
+   return __dw_pcie_ep_find_next_cap(ep, func_no, next_cap_ptr, cap);
+}
+
 static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no,
   struct pci_epf_header *hdr)
 {
@@ -257,13 +311,18 @@ static int dw_pcie_ep_get_msi(struct pci_epc *epc, u8 
func_no)
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
u32 val, reg;
unsigned int func_offset = 0;
+   struct dw_pcie_ep_func *ep_func;
 
-   if (!ep->msi_cap)
+   ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
+   if (!ep_func)
+   return -EINVAL;
+
+   if (!ep_func->msi_cap)
return -EINVAL;
 
func_offset = dw_pcie_ep_func_select(ep, func_no);
 
-   reg = ep->msi_cap + func_offset + PCI_MSI_FLAGS;
+   reg = ep_func->msi_cap + func_offset + PCI_MSI_FLAGS;
val = dw_pcie_readw_dbi(pci, reg);
if (!(val & PCI_MSI_FLAGS_ENABLE))
return -EINVAL;
@@ -279,13 +338,18 @@ static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 
func_no, u8 interrupts)
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
u32 val, reg;
unsigned int func_offset = 0;
+   struct dw_pcie_ep_func *ep_func;
+
+   ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
+   if (!ep_func)
+   return -EINVAL;
 
-   if (!ep->msi_cap)
+   if (!ep_func->msi_cap)
return -EINVAL;
 
func_offset = dw_pcie_ep_func_select(ep, func_no);
 
-   reg = ep->msi_cap + func_offset + PCI_MSI_FLAGS;
+   reg = ep_func->msi_cap + func_offset + PCI_MSI_FLAGS;
val = dw_pcie_readw_dbi(pci, reg);
val &= ~PCI_MSI_FLAGS_QMASK;
val |= (interrupts << 1) & PCI_MSI_FLAGS_QMASK;
@@ -302,13 +366,18 @@ static int dw_pcie_ep_get_msix(struct pci_epc *epc, u8 
func_no)
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
u32 val, reg;
unsigned int func_offset = 0;
+   struct dw_pcie_ep_func *ep_func;
+
+   ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);
+   if (!ep_func)
+   return -EINVAL;
 
-   if (!ep->msix_cap)
+   if (!ep_func->msix_cap)
return -EINVAL;
 
func_offset = dw_pcie_ep_func_select(ep, func_no);
 
-   reg = ep->msix_cap + func_offset + PCI_MSIX_FLAGS;
+   reg = ep_func->msix_cap + func_offset + PCI_MSIX_FLAGS;
val 

[PATCHv7 09/12] PCI: layerscape: Add EP mode support for ls1088a and ls2088a

2020-08-11 Thread Zhiqiang Hou
From: Xiaowei Bao 

Add PCIe EP mode support for ls1088a and ls2088a, there are some
difference between LS1 and LS2 platform, so refactor the code of
the EP driver.

Signed-off-by: Xiaowei Bao 
Reviewed-by: Rob Herring 
Signed-off-by: Hou Zhiqiang 
---
V7:
 - Rebase the patch without functionality change.

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

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index bfab1c694f00..84206f265e54 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -20,27 +20,29 @@
 
 #define PCIE_DBI2_OFFSET   0x1000  /* DBI2 base address*/
 
-struct ls_pcie_ep {
-   struct dw_pcie  *pci;
-   struct pci_epc_features *ls_epc;
+#define to_ls_pcie_ep(x)   dev_get_drvdata((x)->dev)
+
+struct ls_pcie_ep_drvdata {
+   u32 func_offset;
+   const struct dw_pcie_ep_ops *ops;
+   const struct dw_pcie_ops*dw_pcie_ops;
 };
 
-#define to_ls_pcie_ep(x)   dev_get_drvdata((x)->dev)
+struct ls_pcie_ep {
+   struct dw_pcie  *pci;
+   struct pci_epc_features *ls_epc;
+   const struct ls_pcie_ep_drvdata *drvdata;
+};
 
 static int ls_pcie_establish_link(struct dw_pcie *pci)
 {
return 0;
 }
 
-static const struct dw_pcie_ops ls_pcie_ep_ops = {
+static const struct dw_pcie_ops dw_ls_pcie_ep_ops = {
.start_link = ls_pcie_establish_link,
 };
 
-static const struct of_device_id ls_pcie_ep_of_match[] = {
-   { .compatible = "fsl,ls-pcie-ep",},
-   { },
-};
-
 static const struct pci_epc_features*
 ls_pcie_ep_get_features(struct dw_pcie_ep *ep)
 {
@@ -87,10 +89,39 @@ static int ls_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 
func_no,
}
 }
 
-static const struct dw_pcie_ep_ops pcie_ep_ops = {
+static unsigned int ls_pcie_ep_func_conf_select(struct dw_pcie_ep *ep,
+   u8 func_no)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+   struct ls_pcie_ep *pcie = to_ls_pcie_ep(pci);
+
+   WARN_ON(func_no && !pcie->drvdata->func_offset);
+   return pcie->drvdata->func_offset * func_no;
+}
+
+static const struct dw_pcie_ep_ops ls_pcie_ep_ops = {
.ep_init = ls_pcie_ep_init,
.raise_irq = ls_pcie_ep_raise_irq,
.get_features = ls_pcie_ep_get_features,
+   .func_conf_select = ls_pcie_ep_func_conf_select,
+};
+
+static const struct ls_pcie_ep_drvdata ls1_ep_drvdata = {
+   .ops = _pcie_ep_ops,
+   .dw_pcie_ops = _ls_pcie_ep_ops,
+};
+
+static const struct ls_pcie_ep_drvdata ls2_ep_drvdata = {
+   .func_offset = 0x2,
+   .ops = _pcie_ep_ops,
+   .dw_pcie_ops = _ls_pcie_ep_ops,
+};
+
+static const struct of_device_id ls_pcie_ep_of_match[] = {
+   { .compatible = "fsl,ls1046a-pcie-ep", .data = _ep_drvdata },
+   { .compatible = "fsl,ls1088a-pcie-ep", .data = _ep_drvdata },
+   { .compatible = "fsl,ls2088a-pcie-ep", .data = _ep_drvdata },
+   { },
 };
 
 static int __init ls_add_pcie_ep(struct ls_pcie_ep *pcie,
@@ -103,7 +134,7 @@ static int __init ls_add_pcie_ep(struct ls_pcie_ep *pcie,
int ret;
 
ep = >ep;
-   ep->ops = _ep_ops;
+   ep->ops = pcie->drvdata->ops;
 
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space");
if (!res)
@@ -142,20 +173,23 @@ static int __init ls_pcie_ep_probe(struct platform_device 
*pdev)
if (!ls_epc)
return -ENOMEM;
 
-   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);
+   pcie->drvdata = of_device_get_match_data(dev);
 
-   pci->dbi_base2 = pci->dbi_base + PCIE_DBI2_OFFSET;
pci->dev = dev;
-   pci->ops = _pcie_ep_ops;
-   pcie->pci = pci;
+   pci->ops = pcie->drvdata->dw_pcie_ops;
 
ls_epc->bar_fixed_64bit = (1 << BAR_2) | (1 << BAR_4),
 
+   pcie->pci = pci;
pcie->ls_epc = ls_epc;
 
+   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);
+
+   pci->dbi_base2 = pci->dbi_base + PCIE_DBI2_OFFSET;
+
platform_set_drvdata(pdev, pcie);
 
ret = ls_add_pcie_ep(pcie, pdev);
-- 
2.17.1



[PATCHv7 05/12] dt-bindings: pci: layerscape-pci: Add compatible strings for ls1088a and ls2088a

2020-08-11 Thread Zhiqiang Hou
From: Xiaowei Bao 

Add compatible strings for ls1088a and ls2088a.

Signed-off-by: Xiaowei Bao 
Acked-by: Rob Herring 
Signed-off-by: Hou Zhiqiang 
---
V7:
 - Rebase the patch without functionality change.

 Documentation/devicetree/bindings/pci/layerscape-pci.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/pci/layerscape-pci.txt 
b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
index 99a386ea691c..daa99f7d4c3f 100644
--- a/Documentation/devicetree/bindings/pci/layerscape-pci.txt
+++ b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
@@ -24,6 +24,8 @@ Required properties:
 "fsl,ls1028a-pcie"
   EP mode:
"fsl,ls1046a-pcie-ep", "fsl,ls-pcie-ep"
+   "fsl,ls1088a-pcie-ep", "fsl,ls-pcie-ep"
+   "fsl,ls2088a-pcie-ep", "fsl,ls-pcie-ep"
 - reg: base addresses and lengths of the PCIe controller register blocks.
 - interrupts: A list of interrupt outputs of the controller. Must contain an
   entry for each entry in the interrupt-names property.
-- 
2.17.1



[PATCHv7 11/12] misc: pci_endpoint_test: Add LS1088a in pci_device_id table

2020-08-11 Thread Zhiqiang Hou
From: Xiaowei Bao 

Add LS1088a in pci_device_id table so that pci-epf-test can be used
for testing PCIe EP in LS1088a.

Signed-off-by: Xiaowei Bao 
Reviewed-by: Andrew Murray 
Signed-off-by: Hou Zhiqiang 
---
V7:
 - Rebase the patch without functionality change.

 drivers/misc/pci_endpoint_test.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c
index e060796f9caa..4a17f08de60f 100644
--- a/drivers/misc/pci_endpoint_test.c
+++ b/drivers/misc/pci_endpoint_test.c
@@ -70,6 +70,7 @@
 
 #define PCI_DEVICE_ID_TI_J721E 0xb00d
 #define PCI_DEVICE_ID_TI_AM654 0xb00c
+#define PCI_DEVICE_ID_LS1088A  0x80c0
 
 #define is_am654_pci_dev(pdev) \
((pdev)->device == PCI_DEVICE_ID_TI_AM654)
@@ -946,6 +947,7 @@ static const struct pci_device_id pci_endpoint_test_tbl[] = 
{
  .driver_data = (kernel_ulong_t)_data,
},
{ PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, 0x81c0) },
+   { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, PCI_DEVICE_ID_LS1088A) },
{ PCI_DEVICE_DATA(SYNOPSYS, EDDA, NULL) },
{ PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_AM654),
  .driver_data = (kernel_ulong_t)_data
-- 
2.17.1



[PATCHv7 03/12] PCI: designware-ep: Move the function of getting MSI capability forward

2020-08-11 Thread Zhiqiang Hou
From: Xiaowei Bao 

Move the function of getting MSI capability to the front of init
function, because the init function of the EP platform driver will use
the return value by the function of getting MSI capability.

Signed-off-by: Xiaowei Bao 
Reviewed-by: Andrew Murray 
Signed-off-by: Hou Zhiqiang 
---
V7:
 - Rebase the patch without functionality change.

 drivers/pci/controller/dwc/pcie-designware-ep.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c 
b/drivers/pci/controller/dwc/pcie-designware-ep.c
index e76b504ed465..56bd1cd71f16 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -574,10 +574,6 @@ int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep)
return -EIO;
}
 
-   ep->msi_cap = dw_pcie_find_capability(pci, PCI_CAP_ID_MSI);
-
-   ep->msix_cap = dw_pcie_find_capability(pci, PCI_CAP_ID_MSIX);
-
offset = dw_pcie_ep_find_ext_capability(pci, PCI_EXT_CAP_ID_REBAR);
if (offset) {
reg = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL);
@@ -664,6 +660,10 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
if (ret < 0)
epc->max_functions = 1;
 
+   ep->msi_cap = dw_pcie_find_capability(pci, PCI_CAP_ID_MSI);
+
+   ep->msix_cap = dw_pcie_find_capability(pci, PCI_CAP_ID_MSIX);
+
if (ep->ops->ep_init)
ep->ops->ep_init(ep);
 
-- 
2.17.1



[PATCHv7 12/12] misc: pci_endpoint_test: Add driver data for Layerscape PCIe controllers

2020-08-11 Thread Zhiqiang Hou
From: Hou Zhiqiang 

The commit 0a121f9bc3f5 ("misc: pci_endpoint_test: Use streaming DMA
APIs for buffer allocation") changed to use streaming DMA APIs, however,
dma_map_single() might not return a 4KB aligned address, so add the
default_data as driver data for Layerscape PCIe controllers to make it
4KB aligned.

Signed-off-by: Hou Zhiqiang 
---
V7:
 - New patch.

 drivers/misc/pci_endpoint_test.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c
index 4a17f08de60f..70a790cd14c5 100644
--- a/drivers/misc/pci_endpoint_test.c
+++ b/drivers/misc/pci_endpoint_test.c
@@ -946,8 +946,12 @@ static const struct pci_device_id pci_endpoint_test_tbl[] 
= {
{ PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA72x),
  .driver_data = (kernel_ulong_t)_data,
},
-   { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, 0x81c0) },
-   { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, PCI_DEVICE_ID_LS1088A) },
+   { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, 0x81c0),
+ .driver_data = (kernel_ulong_t)_data,
+   },
+   { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, PCI_DEVICE_ID_LS1088A),
+ .driver_data = (kernel_ulong_t)_data,
+   },
{ PCI_DEVICE_DATA(SYNOPSYS, EDDA, NULL) },
{ PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_AM654),
  .driver_data = (kernel_ulong_t)_data
-- 
2.17.1



[PATCHv7 06/12] PCI: layerscape: Fix some format issue of the code

2020-08-11 Thread Zhiqiang Hou
From: Xiaowei Bao 

Fix some format issue of the code in EP driver.

Signed-off-by: Xiaowei Bao 
Reviewed-by: Andrew Murray 
Signed-off-by: Hou Zhiqiang 
---
V7:
 - Rebase the patch without functionality change.

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

diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c 
b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index 0d151cead1b7..0691d9ad1356 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -63,7 +63,7 @@ static void ls_pcie_ep_init(struct dw_pcie_ep *ep)
 }
 
 static int ls_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
- enum pci_epc_irq_type type, u16 interrupt_num)
+   enum pci_epc_irq_type type, u16 interrupt_num)
 {
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
 
@@ -87,7 +87,7 @@ static const struct dw_pcie_ep_ops pcie_ep_ops = {
 };
 
 static int __init ls_add_pcie_ep(struct ls_pcie_ep *pcie,
-   struct platform_device *pdev)
+struct platform_device *pdev)
 {
struct dw_pcie *pci = pcie->pci;
struct device *dev = pci->dev;
-- 
2.17.1



[PATCHv7 01/12] PCI: designware-ep: Add multiple PFs support for DWC

2020-08-11 Thread Zhiqiang Hou
From: Xiaowei Bao 

Add multiple PFs support for DWC, due to different PF have different
config space, we use func_conf_select callback function to access
the different PF's config space, the different chip company need to
implement this callback function when use the DWC IP core and intend
to support multiple PFs feature.

Signed-off-by: Xiaowei Bao 
Acked-by: Gustavo Pimentel 
Reviewed-by: Rob Herring 
Signed-off-by: Hou Zhiqiang 
---
V7:
 - Rebase the patch without functionality change.

 .../pci/controller/dwc/pcie-designware-ep.c   | 125 --
 drivers/pci/controller/dwc/pcie-designware.c  |  59 ++---
 drivers/pci/controller/dwc/pcie-designware.h  |  18 ++-
 3 files changed, 143 insertions(+), 59 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c 
b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 305bfec2424d..e5bd3a5ef380 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -28,12 +28,26 @@ void dw_pcie_ep_init_notify(struct dw_pcie_ep *ep)
 }
 EXPORT_SYMBOL_GPL(dw_pcie_ep_init_notify);
 
-static void __dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar,
-  int flags)
+static unsigned int dw_pcie_ep_func_select(struct dw_pcie_ep *ep, u8 func_no)
+{
+   unsigned int func_offset = 0;
+
+   if (ep->ops->func_conf_select)
+   func_offset = ep->ops->func_conf_select(ep, func_no);
+
+   return func_offset;
+}
+
+static void __dw_pcie_ep_reset_bar(struct dw_pcie *pci, u8 func_no,
+  enum pci_barno bar, int flags)
 {
u32 reg;
+   unsigned int func_offset = 0;
+   struct dw_pcie_ep *ep = >ep;
+
+   func_offset = dw_pcie_ep_func_select(ep, func_no);
 
-   reg = PCI_BASE_ADDRESS_0 + (4 * bar);
+   reg = func_offset + PCI_BASE_ADDRESS_0 + (4 * bar);
dw_pcie_dbi_ro_wr_en(pci);
dw_pcie_writel_dbi2(pci, reg, 0x0);
dw_pcie_writel_dbi(pci, reg, 0x0);
@@ -46,7 +60,12 @@ static void __dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum 
pci_barno bar,
 
 void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar)
 {
-   __dw_pcie_ep_reset_bar(pci, bar, 0);
+   u8 func_no, funcs;
+
+   funcs = pci->ep.epc->max_functions;
+
+   for (func_no = 0; func_no < funcs; func_no++)
+   __dw_pcie_ep_reset_bar(pci, func_no, bar, 0);
 }
 
 static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no,
@@ -54,28 +73,31 @@ static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 
func_no,
 {
struct dw_pcie_ep *ep = epc_get_drvdata(epc);
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+   unsigned int func_offset = 0;
+
+   func_offset = dw_pcie_ep_func_select(ep, func_no);
 
dw_pcie_dbi_ro_wr_en(pci);
-   dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, hdr->vendorid);
-   dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, hdr->deviceid);
-   dw_pcie_writeb_dbi(pci, PCI_REVISION_ID, hdr->revid);
-   dw_pcie_writeb_dbi(pci, PCI_CLASS_PROG, hdr->progif_code);
-   dw_pcie_writew_dbi(pci, PCI_CLASS_DEVICE,
+   dw_pcie_writew_dbi(pci, func_offset + PCI_VENDOR_ID, hdr->vendorid);
+   dw_pcie_writew_dbi(pci, func_offset + PCI_DEVICE_ID, hdr->deviceid);
+   dw_pcie_writeb_dbi(pci, func_offset + PCI_REVISION_ID, hdr->revid);
+   dw_pcie_writeb_dbi(pci, func_offset + PCI_CLASS_PROG, hdr->progif_code);
+   dw_pcie_writew_dbi(pci, func_offset + PCI_CLASS_DEVICE,
   hdr->subclass_code | hdr->baseclass_code << 8);
-   dw_pcie_writeb_dbi(pci, PCI_CACHE_LINE_SIZE,
+   dw_pcie_writeb_dbi(pci, func_offset + PCI_CACHE_LINE_SIZE,
   hdr->cache_line_size);
-   dw_pcie_writew_dbi(pci, PCI_SUBSYSTEM_VENDOR_ID,
+   dw_pcie_writew_dbi(pci, func_offset + PCI_SUBSYSTEM_VENDOR_ID,
   hdr->subsys_vendor_id);
-   dw_pcie_writew_dbi(pci, PCI_SUBSYSTEM_ID, hdr->subsys_id);
-   dw_pcie_writeb_dbi(pci, PCI_INTERRUPT_PIN,
+   dw_pcie_writew_dbi(pci, func_offset + PCI_SUBSYSTEM_ID, hdr->subsys_id);
+   dw_pcie_writeb_dbi(pci, func_offset + PCI_INTERRUPT_PIN,
   hdr->interrupt_pin);
dw_pcie_dbi_ro_wr_dis(pci);
 
return 0;
 }
 
-static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, enum pci_barno bar,
- dma_addr_t cpu_addr,
+static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, u8 func_no,
+ enum pci_barno bar, dma_addr_t cpu_addr,
  enum dw_pcie_as_type as_type)
 {
int ret;
@@ -88,7 +110,7 @@ static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, 
enum pci_barno bar,
return -EINVAL;
}
 
-   ret = dw_pcie_prog_inbound_atu(pci, free_win, bar, cpu_addr,
+   ret = dw_pcie_prog_inbound_atu(pci, func_no, free_win, bar, cpu_addr,
 

[PATCHv7 02/12] PCI: designware-ep: Add the doorbell mode of MSI-X in EP mode

2020-08-11 Thread Zhiqiang Hou
From: Xiaowei Bao 

Add the doorbell mode of MSI-X in DWC EP driver.

Signed-off-by: Xiaowei Bao 
Reviewed-by: Andrew Murray 
Signed-off-by: Hou Zhiqiang 
---
V7:
 - Rebase the patch without functionality change.

 drivers/pci/controller/dwc/pcie-designware-ep.c | 14 ++
 drivers/pci/controller/dwc/pcie-designware.h| 12 
 2 files changed, 26 insertions(+)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c 
b/drivers/pci/controller/dwc/pcie-designware-ep.c
index e5bd3a5ef380..e76b504ed465 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -471,6 +471,20 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 
func_no,
return 0;
 }
 
+int dw_pcie_ep_raise_msix_irq_doorbell(struct dw_pcie_ep *ep, u8 func_no,
+  u16 interrupt_num)
+{
+   struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+   u32 msg_data;
+
+   msg_data = (func_no << PCIE_MSIX_DOORBELL_PF_SHIFT) |
+  (interrupt_num - 1);
+
+   dw_pcie_writel_dbi(pci, PCIE_MSIX_DOORBELL, msg_data);
+
+   return 0;
+}
+
 int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
  u16 interrupt_num)
 {
diff --git a/drivers/pci/controller/dwc/pcie-designware.h 
b/drivers/pci/controller/dwc/pcie-designware.h
index 89f8271ec5ee..745b4938225a 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -97,6 +97,9 @@
 #define PCIE_MISC_CONTROL_1_OFF0x8BC
 #define PCIE_DBI_RO_WR_EN  BIT(0)
 
+#define PCIE_MSIX_DOORBELL 0x948
+#define PCIE_MSIX_DOORBELL_PF_SHIFT24
+
 #define PCIE_PL_CHK_REG_CONTROL_STATUS 0xB20
 #define PCIE_PL_CHK_REG_CHK_REG_START  BIT(0)
 #define PCIE_PL_CHK_REG_CHK_REG_CONTINUOUS BIT(1)
@@ -434,6 +437,8 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 
func_no,
 u8 interrupt_num);
 int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
 u16 interrupt_num);
+int dw_pcie_ep_raise_msix_irq_doorbell(struct dw_pcie_ep *ep, u8 func_no,
+  u16 interrupt_num);
 void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar);
 #else
 static inline void dw_pcie_ep_linkup(struct dw_pcie_ep *ep)
@@ -475,6 +480,13 @@ static inline int dw_pcie_ep_raise_msix_irq(struct 
dw_pcie_ep *ep, u8 func_no,
return 0;
 }
 
+static inline int dw_pcie_ep_raise_msix_irq_doorbell(struct dw_pcie_ep *ep,
+u8 func_no,
+u16 interrupt_num)
+{
+   return 0;
+}
+
 static inline void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno 
bar)
 {
 }
-- 
2.17.1



[PATCHv7 00/12]PCI: dwc: Add the multiple PF support for DWC and Layerscape

2020-08-11 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Add the PCIe EP multiple PF support for DWC and Layerscape, and use
a list to manage the PFs of each PCIe controller; add the doorbell
MSIX function for DWC; and refactor the Layerscape EP driver due to
some difference in Layercape platforms PCIe integration.

Hou Zhiqiang (1):
  misc: pci_endpoint_test: Add driver data for Layerscape PCIe
controllers

Xiaowei Bao (11):
  PCI: designware-ep: Add multiple PFs support for DWC
  PCI: designware-ep: Add the doorbell mode of MSI-X in EP mode
  PCI: designware-ep: Move the function of getting MSI capability
forward
  PCI: designware-ep: Modify MSI and MSIX CAP way of finding
  dt-bindings: pci: layerscape-pci: Add compatible strings for ls1088a
and ls2088a
  PCI: layerscape: Fix some format issue of the code
  PCI: layerscape: Modify the way of getting capability with different
PEX
  PCI: layerscape: Modify the MSIX to the doorbell mode
  PCI: layerscape: Add EP mode support for ls1088a and ls2088a
  arm64: dts: layerscape: Add PCIe EP node for ls1088a
  misc: pci_endpoint_test: Add LS1088a in pci_device_id table

 .../bindings/pci/layerscape-pci.txt   |   2 +
 .../arm64/boot/dts/freescale/fsl-ls1088a.dtsi |  31 +++
 drivers/misc/pci_endpoint_test.c  |   8 +-
 .../pci/controller/dwc/pci-layerscape-ep.c| 100 +--
 .../pci/controller/dwc/pcie-designware-ep.c   | 258 ++
 drivers/pci/controller/dwc/pcie-designware.c  |  59 ++--
 drivers/pci/controller/dwc/pcie-designware.h  |  48 +++-
 7 files changed, 410 insertions(+), 96 deletions(-)

-- 
2.17.1



[PATCH] PCI: ERR: Don't override the status returned by error_detect()

2020-05-27 Thread Zhiqiang Hou
From: Hou Zhiqiang 

The commit 6d2c89441571 ("PCI/ERR: Update error status after reset_link()")
overrode the 'status' returned by the error_detect() call back function,
which is depended on by the next step. This overriding makes the Endpoint
driver's required info (kept in the var status) lost, so it results in the
fatal errors' recovery failed and then kernel panic.

In the e1000e case, the error logs:
pcieport 0002:00:00.0: AER: Uncorrected (Fatal) error received: 0002:01:00.0
e1000e 0002:01:00.0: AER: PCIe Bus Error: severity=Uncorrected (Fatal), 
type=Inaccessible, (Unregistered Agent ID)
pcieport 0002:00:00.0: AER: Root Port link has been reset
SError Interrupt on CPU0, code 0xbf02 -- SError
CPU: 0 PID: 111 Comm: irq/76-aerdrv Not tainted 5.7.0-rc7-next-20200526 #8
Hardware name: LS1046A RDB Board (DT)
pstate: 8005 (Nzcv daif -PAN -UAO BTYPE=--)
pc : __pci_enable_msix_range+0x4c8/0x5b8
lr : __pci_enable_msix_range+0x480/0x5b8
sp : 80001116bb30
x29: 80001116bb30 x28: 0003
x27: 0003 x26: 
x25: 00097243e0a8 x24: 0001
x23: 00097243e2d8 x22: 
x21: 0003 x20: 00095bd46080
x19: 00097243e000 x18: 
x17:  x16: 
x15: b958fa0e9948 x14: 00095bd46303
x13: 00095bd46302 x12: 0038
x11: 0040 x10: b958fa101e68
x9 : b958fa101e60 x8 : 0908
x7 : 0908 x6 : 80001160
x5 : 00095bd46800 x4 : 00096e7f6080
x3 :  x2 : 
x1 :  x0 : 
Kernel panic - not syncing: Asynchronous SError Interrupt
CPU: 0 PID: 111 Comm: irq/76-aerdrv Not tainted 5.7.0-rc7-next-20200526 #8

I think it's the expected result that "if the initial value of error
status is PCI_ERS_RESULT_DISCONNECT or PCI_ERS_RESULT_NO_AER_DRIVER
then even after successful recovery (using reset_link()) pcie_do_recovery()
will report the recovery result as failure" which is described in
commit 6d2c89441571 ("PCI/ERR: Update error status after reset_link()").

Refer to the Documentation/PCI/pci-error-recovery.rst.
As the error_detect() is mandatory callback if the pci_err_handlers is
implemented, if it return the PCI_ERS_RESULT_DISCONNECT, it means the
driver doesn't want to recover at all;
For the case PCI_ERS_RESULT_NO_AER_DRIVER, if the pci_err_handlers is not
implemented, the failure is more expected.

Fixes: commit 6d2c89441571 ("PCI/ERR: Update error status after reset_link()")
Signed-off-by: Hou Zhiqiang 
---
 drivers/pci/pcie/err.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c
index 14bb8f54723e..84f72342259c 100644
--- a/drivers/pci/pcie/err.c
+++ b/drivers/pci/pcie/err.c
@@ -165,8 +165,7 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
pci_dbg(dev, "broadcast error_detected message\n");
if (state == pci_channel_io_frozen) {
pci_walk_bus(bus, report_frozen_detected, );
-   status = reset_link(dev);
-   if (status != PCI_ERS_RESULT_RECOVERED) {
+   if (reset_link(dev) != PCI_ERS_RESULT_RECOVERED) {
pci_warn(dev, "link reset failed\n");
goto failed;
}
-- 
2.17.1



[PATCH 4/4] dts/arm64/layerscape: Clean PCIe controller compatible strings

2018-10-07 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Removed the wrong compatible string "snps,dw-pcie", in case
match incorrect driver.

Signed-off-by: Hou Zhiqiang 
---
 arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi |  2 +-
 arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi |  6 +++---
 arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi |  6 +++---
 arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi |  6 +++---
 arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi |  8 
 arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi | 12 
 6 files changed, 18 insertions(+), 22 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
index 68ac78c4564d..d3fe0771d3a0 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
@@ -475,7 +475,7 @@
};
 
pcie@340 {
-   compatible = "fsl,ls1012a-pcie", "snps,dw-pcie";
+   compatible = "fsl,ls1012a-pcie";
reg = <0x00 0x0340 0x0 0x0010   /* controller 
registers */
   0x40 0x 0x0 0x2000>; /* 
configuration space */
reg-names = "regs", "config";
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index 6cc4c87614b6..1b61782df73e 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -661,7 +661,7 @@
};
 
pcie@340 {
-   compatible = "fsl,ls1043a-pcie", "snps,dw-pcie";
+   compatible = "fsl,ls1043a-pcie";
reg = <0x00 0x0340 0x0 0x0010   /* controller 
registers */
   0x40 0x 0x0 0x2000>; /* 
configuration space */
reg-names = "regs", "config";
@@ -686,7 +686,7 @@
};
 
pcie@350 {
-   compatible = "fsl,ls1043a-pcie", "snps,dw-pcie";
+   compatible = "fsl,ls1043a-pcie";
reg = <0x00 0x0350 0x0 0x0010   /* controller 
registers */
   0x48 0x 0x0 0x2000>; /* 
configuration space */
reg-names = "regs", "config";
@@ -711,7 +711,7 @@
};
 
pcie@360 {
-   compatible = "fsl,ls1043a-pcie", "snps,dw-pcie";
+   compatible = "fsl,ls1043a-pcie";
reg = <0x00 0x0360 0x0 0x0010   /* controller 
registers */
   0x50 0x 0x0 0x2000>; /* 
configuration space */
reg-names = "regs", "config";
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
index 3a2a14a8e187..71585aefe1ef 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
@@ -630,7 +630,7 @@
};
 
pcie@340 {
-   compatible = "fsl,ls1046a-pcie", "snps,dw-pcie";
+   compatible = "fsl,ls1046a-pcie";
reg = <0x00 0x0340 0x0 0x0010   /* controller 
registers */
   0x40 0x 0x0 0x2000>; /* 
configuration space */
reg-names = "regs", "config";
@@ -655,7 +655,7 @@
};
 
pcie@350 {
-   compatible = "fsl,ls1046a-pcie", "snps,dw-pcie";
+   compatible = "fsl,ls1046a-pcie";
reg = <0x00 0x0350 0x0 0x0010   /* controller 
registers */
   0x48 0x 0x0 0x2000>; /* 
configuration space */
reg-names = "regs", "config";
@@ -680,7 +680,7 @@
};
 
pcie@360 {
-   compatible = "fsl,ls1046a-pcie", "snps,dw-pcie";
+   compatible = "fsl,ls1046a-pcie";
reg = <0x00 0x0360 0x0 0x0010   /* controller 
registers */
   0x50 0x 0x0 0x2000>; /* 
configuration space */
reg-names = "regs", "config";
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
index a07f612ab56b..10b253c88a16 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
@@ -512,7 +512,7 @@
};
 
pcie@340 {
-   compatible = "fsl,ls1088a-pcie", "snps,dw-pcie";
+   compatible = "fsl,ls1088a-pcie";
reg = <0x00 0x0340 0x0 0x0010   /* controller 
registers */
   0x20 0x 0x0 

[PATCH 4/4] dts/arm64/layerscape: Clean PCIe controller compatible strings

2018-10-07 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Removed the wrong compatible string "snps,dw-pcie", in case
match incorrect driver.

Signed-off-by: Hou Zhiqiang 
---
 arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi |  2 +-
 arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi |  6 +++---
 arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi |  6 +++---
 arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi |  6 +++---
 arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi |  8 
 arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi | 12 
 6 files changed, 18 insertions(+), 22 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
index 68ac78c4564d..d3fe0771d3a0 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
@@ -475,7 +475,7 @@
};
 
pcie@340 {
-   compatible = "fsl,ls1012a-pcie", "snps,dw-pcie";
+   compatible = "fsl,ls1012a-pcie";
reg = <0x00 0x0340 0x0 0x0010   /* controller 
registers */
   0x40 0x 0x0 0x2000>; /* 
configuration space */
reg-names = "regs", "config";
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index 6cc4c87614b6..1b61782df73e 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -661,7 +661,7 @@
};
 
pcie@340 {
-   compatible = "fsl,ls1043a-pcie", "snps,dw-pcie";
+   compatible = "fsl,ls1043a-pcie";
reg = <0x00 0x0340 0x0 0x0010   /* controller 
registers */
   0x40 0x 0x0 0x2000>; /* 
configuration space */
reg-names = "regs", "config";
@@ -686,7 +686,7 @@
};
 
pcie@350 {
-   compatible = "fsl,ls1043a-pcie", "snps,dw-pcie";
+   compatible = "fsl,ls1043a-pcie";
reg = <0x00 0x0350 0x0 0x0010   /* controller 
registers */
   0x48 0x 0x0 0x2000>; /* 
configuration space */
reg-names = "regs", "config";
@@ -711,7 +711,7 @@
};
 
pcie@360 {
-   compatible = "fsl,ls1043a-pcie", "snps,dw-pcie";
+   compatible = "fsl,ls1043a-pcie";
reg = <0x00 0x0360 0x0 0x0010   /* controller 
registers */
   0x50 0x 0x0 0x2000>; /* 
configuration space */
reg-names = "regs", "config";
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
index 3a2a14a8e187..71585aefe1ef 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
@@ -630,7 +630,7 @@
};
 
pcie@340 {
-   compatible = "fsl,ls1046a-pcie", "snps,dw-pcie";
+   compatible = "fsl,ls1046a-pcie";
reg = <0x00 0x0340 0x0 0x0010   /* controller 
registers */
   0x40 0x 0x0 0x2000>; /* 
configuration space */
reg-names = "regs", "config";
@@ -655,7 +655,7 @@
};
 
pcie@350 {
-   compatible = "fsl,ls1046a-pcie", "snps,dw-pcie";
+   compatible = "fsl,ls1046a-pcie";
reg = <0x00 0x0350 0x0 0x0010   /* controller 
registers */
   0x48 0x 0x0 0x2000>; /* 
configuration space */
reg-names = "regs", "config";
@@ -680,7 +680,7 @@
};
 
pcie@360 {
-   compatible = "fsl,ls1046a-pcie", "snps,dw-pcie";
+   compatible = "fsl,ls1046a-pcie";
reg = <0x00 0x0360 0x0 0x0010   /* controller 
registers */
   0x50 0x 0x0 0x2000>; /* 
configuration space */
reg-names = "regs", "config";
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
index a07f612ab56b..10b253c88a16 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
@@ -512,7 +512,7 @@
};
 
pcie@340 {
-   compatible = "fsl,ls1088a-pcie", "snps,dw-pcie";
+   compatible = "fsl,ls1088a-pcie";
reg = <0x00 0x0340 0x0 0x0010   /* controller 
registers */
   0x20 0x 0x0 

[PATCH 2/4] doc/layerscape-pci: removed unsuitable compatible string

2018-10-07 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Removed the compatible string "snps,dw-pcie", it is for the reference
platform driver for PCI RC IP Protoyping Kits based on the ARC SDP,
so it is not suitable for all platform with designware PCIe controller,
and platform vendors have themselves' drivers.

The compatible string "snsp,dw-pcie" was added by mistake and it's not
matched that time, but it is matched because pcie drivers has been
collected recently.

Signed-off-by: Hou Zhiqiang 
---
 Documentation/devicetree/bindings/pci/layerscape-pci.txt | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/pci/layerscape-pci.txt 
b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
index 5eb1c202932f..9b2b8d66d1f4 100644
--- a/Documentation/devicetree/bindings/pci/layerscape-pci.txt
+++ b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
@@ -13,8 +13,8 @@ information.
 
 Required properties:
 - compatible: should contain the platform identifier such as:
-"fsl,ls1021a-pcie", "snps,dw-pcie"
-"fsl,ls2080a-pcie", "fsl,ls2085a-pcie", "snps,dw-pcie"
+"fsl,ls1021a-pcie"
+"fsl,ls2080a-pcie", "fsl,ls2085a-pcie"
 "fsl,ls2088a-pcie"
 "fsl,ls1088a-pcie"
 "fsl,ls1046a-pcie"
@@ -36,7 +36,7 @@ Required properties:
 Example:
 
pcie@340 {
-   compatible = "fsl,ls1021a-pcie", "snps,dw-pcie";
+   compatible = "fsl,ls1021a-pcie";
reg = <0x00 0x0340 0x0 0x0001   /* controller registers 
*/
   0x40 0x 0x0 0x2000>; /* configuration space 
*/
reg-names = "regs", "config";
-- 
2.17.1



[PATCH 3/4] dts/arm/ls1021a: Clean PCIe controller compatible strings

2018-10-07 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Removed the wrong compatible string "snps,dw-pcie", in case
match incorrect driver.

Signed-off-by: Hou Zhiqiang 
---
 arch/arm/boot/dts/ls1021a.dtsi | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
index f70025c2ab0f..13e91d577a26 100644
--- a/arch/arm/boot/dts/ls1021a.dtsi
+++ b/arch/arm/boot/dts/ls1021a.dtsi
@@ -716,7 +716,7 @@
};
 
pcie@340 {
-   compatible = "fsl,ls1021a-pcie", "snps,dw-pcie";
+   compatible = "fsl,ls1021a-pcie";
reg = <0x00 0x0340 0x0 0x0001   /* controller 
registers */
   0x40 0x 0x0 0x2000>; /* 
configuration space */
reg-names = "regs", "config";
@@ -739,7 +739,7 @@
};
 
pcie@350 {
-   compatible = "fsl,ls1021a-pcie", "snps,dw-pcie";
+   compatible = "fsl,ls1021a-pcie";
reg = <0x00 0x0350 0x0 0x0001   /* controller 
registers */
   0x48 0x 0x0 0x2000>; /* 
configuration space */
reg-names = "regs", "config";
-- 
2.17.1



[PATCH 2/4] doc/layerscape-pci: removed unsuitable compatible string

2018-10-07 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Removed the compatible string "snps,dw-pcie", it is for the reference
platform driver for PCI RC IP Protoyping Kits based on the ARC SDP,
so it is not suitable for all platform with designware PCIe controller,
and platform vendors have themselves' drivers.

The compatible string "snsp,dw-pcie" was added by mistake and it's not
matched that time, but it is matched because pcie drivers has been
collected recently.

Signed-off-by: Hou Zhiqiang 
---
 Documentation/devicetree/bindings/pci/layerscape-pci.txt | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/pci/layerscape-pci.txt 
b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
index 5eb1c202932f..9b2b8d66d1f4 100644
--- a/Documentation/devicetree/bindings/pci/layerscape-pci.txt
+++ b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
@@ -13,8 +13,8 @@ information.
 
 Required properties:
 - compatible: should contain the platform identifier such as:
-"fsl,ls1021a-pcie", "snps,dw-pcie"
-"fsl,ls2080a-pcie", "fsl,ls2085a-pcie", "snps,dw-pcie"
+"fsl,ls1021a-pcie"
+"fsl,ls2080a-pcie", "fsl,ls2085a-pcie"
 "fsl,ls2088a-pcie"
 "fsl,ls1088a-pcie"
 "fsl,ls1046a-pcie"
@@ -36,7 +36,7 @@ Required properties:
 Example:
 
pcie@340 {
-   compatible = "fsl,ls1021a-pcie", "snps,dw-pcie";
+   compatible = "fsl,ls1021a-pcie";
reg = <0x00 0x0340 0x0 0x0001   /* controller registers 
*/
   0x40 0x 0x0 0x2000>; /* configuration space 
*/
reg-names = "regs", "config";
-- 
2.17.1



[PATCH 3/4] dts/arm/ls1021a: Clean PCIe controller compatible strings

2018-10-07 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Removed the wrong compatible string "snps,dw-pcie", in case
match incorrect driver.

Signed-off-by: Hou Zhiqiang 
---
 arch/arm/boot/dts/ls1021a.dtsi | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
index f70025c2ab0f..13e91d577a26 100644
--- a/arch/arm/boot/dts/ls1021a.dtsi
+++ b/arch/arm/boot/dts/ls1021a.dtsi
@@ -716,7 +716,7 @@
};
 
pcie@340 {
-   compatible = "fsl,ls1021a-pcie", "snps,dw-pcie";
+   compatible = "fsl,ls1021a-pcie";
reg = <0x00 0x0340 0x0 0x0001   /* controller 
registers */
   0x40 0x 0x0 0x2000>; /* 
configuration space */
reg-names = "regs", "config";
@@ -739,7 +739,7 @@
};
 
pcie@350 {
-   compatible = "fsl,ls1021a-pcie", "snps,dw-pcie";
+   compatible = "fsl,ls1021a-pcie";
reg = <0x00 0x0350 0x0 0x0001   /* controller 
registers */
   0x48 0x 0x0 0x2000>; /* 
configuration space */
reg-names = "regs", "config";
-- 
2.17.1



[PATCH 1/4] doc/layerscape-pci: update the PCIe compatible strings

2018-10-07 Thread Zhiqiang Hou
From: Hou Zhiqiang 

The pcie compatible string for LS1043A was lost, so add it.

Signed-off-by: Hou Zhiqiang 
---
 Documentation/devicetree/bindings/pci/layerscape-pci.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/pci/layerscape-pci.txt 
b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
index 66df1e81e0b8..5eb1c202932f 100644
--- a/Documentation/devicetree/bindings/pci/layerscape-pci.txt
+++ b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
@@ -18,6 +18,7 @@ Required properties:
 "fsl,ls2088a-pcie"
 "fsl,ls1088a-pcie"
 "fsl,ls1046a-pcie"
+"fsl,ls1043a-pcie"
 "fsl,ls1012a-pcie"
 - reg: base addresses and lengths of the PCIe controller register blocks.
 - interrupts: A list of interrupt outputs of the controller. Must contain an
-- 
2.17.1



[PATCH 0/4] dts/layerscape-pci: removed unsuitable compatible string

2018-10-07 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Removed the compatible string "snps,dw-pcie" from FSL layerscape-pci compatible
string list.

Hou Zhiqiang (4):
  doc/layerscape-pci: update the PCIe compatible strings
  doc/layerscape-pci: removed unsuitable compatible string
  dts/arm/ls1021a: Clean PCIe controller compatible strings
  dts/arm64/layerscape: Clean PCIe controller compatible strings

 .../devicetree/bindings/pci/layerscape-pci.txt   |  7 ---
 arch/arm/boot/dts/ls1021a.dtsi   |  4 ++--
 arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi   |  2 +-
 arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi   |  6 +++---
 arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi   |  6 +++---
 arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi   |  6 +++---
 arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi   |  8 
 arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi   | 12 
 8 files changed, 24 insertions(+), 27 deletions(-)

-- 
2.17.1



[PATCH 1/4] doc/layerscape-pci: update the PCIe compatible strings

2018-10-07 Thread Zhiqiang Hou
From: Hou Zhiqiang 

The pcie compatible string for LS1043A was lost, so add it.

Signed-off-by: Hou Zhiqiang 
---
 Documentation/devicetree/bindings/pci/layerscape-pci.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/pci/layerscape-pci.txt 
b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
index 66df1e81e0b8..5eb1c202932f 100644
--- a/Documentation/devicetree/bindings/pci/layerscape-pci.txt
+++ b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
@@ -18,6 +18,7 @@ Required properties:
 "fsl,ls2088a-pcie"
 "fsl,ls1088a-pcie"
 "fsl,ls1046a-pcie"
+"fsl,ls1043a-pcie"
 "fsl,ls1012a-pcie"
 - reg: base addresses and lengths of the PCIe controller register blocks.
 - interrupts: A list of interrupt outputs of the controller. Must contain an
-- 
2.17.1



[PATCH 0/4] dts/layerscape-pci: removed unsuitable compatible string

2018-10-07 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Removed the compatible string "snps,dw-pcie" from FSL layerscape-pci compatible
string list.

Hou Zhiqiang (4):
  doc/layerscape-pci: update the PCIe compatible strings
  doc/layerscape-pci: removed unsuitable compatible string
  dts/arm/ls1021a: Clean PCIe controller compatible strings
  dts/arm64/layerscape: Clean PCIe controller compatible strings

 .../devicetree/bindings/pci/layerscape-pci.txt   |  7 ---
 arch/arm/boot/dts/ls1021a.dtsi   |  4 ++--
 arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi   |  2 +-
 arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi   |  6 +++---
 arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi   |  6 +++---
 arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi   |  6 +++---
 arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi   |  8 
 arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi   | 12 
 8 files changed, 24 insertions(+), 27 deletions(-)

-- 
2.17.1



[PATCHv3 0/2] mtd: m25p80: restore the addressing mode when exiting

2017-12-05 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Restore the status to be compatible with legacy devices.
Take Freescale eSPI boot for example, it copies (in 3 Byte
addressing mode) the RCW and bootloader images from SPI flash
without firing a reset signal previously, so the reboot command
will fail without reseting the addressing mode of SPI flash.

Hou Zhiqiang (2):
  mtd: spi-nor: add an API to restore the status of SPI flash chip
  mtd: m25p80: restore the status of SPI flash when exiting

 Documentation/mtd/spi-nor.txt |  3 +++
 drivers/mtd/devices/m25p80.c  |  9 +
 drivers/mtd/spi-nor/spi-nor.c | 10 ++
 include/linux/mtd/spi-nor.h   |  6 ++
 4 files changed, 28 insertions(+)

-- 
2.14.1



[PATCHv3 1/2] mtd: spi-nor: add an API to restore the status of SPI flash chip

2017-12-05 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Add this API to restore the status of SPI flash chip to the default
such as addressing mode, whenever detach the driver from device or
reboot the system.

Signed-off-by: Hou Zhiqiang 
---
V3:
 - no change.

 Documentation/mtd/spi-nor.txt |  3 +++
 drivers/mtd/spi-nor/spi-nor.c | 10 ++
 include/linux/mtd/spi-nor.h   |  6 ++
 3 files changed, 19 insertions(+)

diff --git a/Documentation/mtd/spi-nor.txt b/Documentation/mtd/spi-nor.txt
index 548d6306ebca..da1fbff5a24c 100644
--- a/Documentation/mtd/spi-nor.txt
+++ b/Documentation/mtd/spi-nor.txt
@@ -60,3 +60,6 @@ The main API is spi_nor_scan(). Before you call the hook, a 
driver should
 initialize the necessary fields for spi_nor{}. Please see
 drivers/mtd/spi-nor/spi-nor.c for detail. Please also refer to fsl-quadspi.c
 when you want to write a new driver for a SPI NOR controller.
+Another API is spi_nor_restore(), this is used to restore the status of SPI
+flash chip such as addressing mode. Call it whenever detach the driver from
+device or reboot the system.
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index bc266f70a15b..4a925378d434 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -2713,6 +2713,16 @@ static void spi_nor_resume(struct mtd_info *mtd)
dev_err(dev, "resume() failed\n");
 }
 
+void spi_nor_restore(struct spi_nor *nor)
+{
+   /* restore the addressing mode */
+   if ((nor->addr_width == 4) &&
+   (JEDEC_MFR(nor->info) != SNOR_MFR_SPANSION) &&
+   !(nor->info->flags & SPI_NOR_4B_OPCODES))
+   set_4byte(nor, nor->info, 0);
+}
+EXPORT_SYMBOL_GPL(spi_nor_restore);
+
 int spi_nor_scan(struct spi_nor *nor, const char *name,
 const struct spi_nor_hwcaps *hwcaps)
 {
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index d0c66a0975cf..0a182c3d0884 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -399,4 +399,10 @@ struct spi_nor_hwcaps {
 int spi_nor_scan(struct spi_nor *nor, const char *name,
 const struct spi_nor_hwcaps *hwcaps);
 
+/*
+ * spi_nor_restore_addr_mode() - restore the status of SPI NOR
+ * @nor:   the spi_nor structure
+ */
+void spi_nor_restore(struct spi_nor *nor);
+
 #endif
-- 
2.14.1



[PATCHv3 0/2] mtd: m25p80: restore the addressing mode when exiting

2017-12-05 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Restore the status to be compatible with legacy devices.
Take Freescale eSPI boot for example, it copies (in 3 Byte
addressing mode) the RCW and bootloader images from SPI flash
without firing a reset signal previously, so the reboot command
will fail without reseting the addressing mode of SPI flash.

Hou Zhiqiang (2):
  mtd: spi-nor: add an API to restore the status of SPI flash chip
  mtd: m25p80: restore the status of SPI flash when exiting

 Documentation/mtd/spi-nor.txt |  3 +++
 drivers/mtd/devices/m25p80.c  |  9 +
 drivers/mtd/spi-nor/spi-nor.c | 10 ++
 include/linux/mtd/spi-nor.h   |  6 ++
 4 files changed, 28 insertions(+)

-- 
2.14.1



[PATCHv3 1/2] mtd: spi-nor: add an API to restore the status of SPI flash chip

2017-12-05 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Add this API to restore the status of SPI flash chip to the default
such as addressing mode, whenever detach the driver from device or
reboot the system.

Signed-off-by: Hou Zhiqiang 
---
V3:
 - no change.

 Documentation/mtd/spi-nor.txt |  3 +++
 drivers/mtd/spi-nor/spi-nor.c | 10 ++
 include/linux/mtd/spi-nor.h   |  6 ++
 3 files changed, 19 insertions(+)

diff --git a/Documentation/mtd/spi-nor.txt b/Documentation/mtd/spi-nor.txt
index 548d6306ebca..da1fbff5a24c 100644
--- a/Documentation/mtd/spi-nor.txt
+++ b/Documentation/mtd/spi-nor.txt
@@ -60,3 +60,6 @@ The main API is spi_nor_scan(). Before you call the hook, a 
driver should
 initialize the necessary fields for spi_nor{}. Please see
 drivers/mtd/spi-nor/spi-nor.c for detail. Please also refer to fsl-quadspi.c
 when you want to write a new driver for a SPI NOR controller.
+Another API is spi_nor_restore(), this is used to restore the status of SPI
+flash chip such as addressing mode. Call it whenever detach the driver from
+device or reboot the system.
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index bc266f70a15b..4a925378d434 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -2713,6 +2713,16 @@ static void spi_nor_resume(struct mtd_info *mtd)
dev_err(dev, "resume() failed\n");
 }
 
+void spi_nor_restore(struct spi_nor *nor)
+{
+   /* restore the addressing mode */
+   if ((nor->addr_width == 4) &&
+   (JEDEC_MFR(nor->info) != SNOR_MFR_SPANSION) &&
+   !(nor->info->flags & SPI_NOR_4B_OPCODES))
+   set_4byte(nor, nor->info, 0);
+}
+EXPORT_SYMBOL_GPL(spi_nor_restore);
+
 int spi_nor_scan(struct spi_nor *nor, const char *name,
 const struct spi_nor_hwcaps *hwcaps)
 {
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index d0c66a0975cf..0a182c3d0884 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -399,4 +399,10 @@ struct spi_nor_hwcaps {
 int spi_nor_scan(struct spi_nor *nor, const char *name,
 const struct spi_nor_hwcaps *hwcaps);
 
+/*
+ * spi_nor_restore_addr_mode() - restore the status of SPI NOR
+ * @nor:   the spi_nor structure
+ */
+void spi_nor_restore(struct spi_nor *nor);
+
 #endif
-- 
2.14.1



[PATCHv3 2/2] mtd: m25p80: restore the status of SPI flash when exiting

2017-12-05 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Restore the status to be compatible with legacy devices.
Take Freescale eSPI boot for example, it copies (in 3 Byte
addressing mode) the RCW and bootloader images from SPI flash
without firing a reset signal previously, so the reboot command
will fail without reseting the addressing mode of SPI flash.
This patch implement .shutdown function to restore the status
in reboot process, and add the same operation to the .remove
function.

Signed-off-by: Hou Zhiqiang 
---
V3:
 - Modified the commit to make this patch specific.

 drivers/mtd/devices/m25p80.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index dbe6a1de2bb8..a4e18f6aaa33 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -307,10 +307,18 @@ static int m25p_remove(struct spi_device *spi)
 {
struct m25p *flash = spi_get_drvdata(spi);
 
+   spi_nor_restore(>spi_nor);
+
/* Clean up MTD stuff. */
return mtd_device_unregister(>spi_nor.mtd);
 }
 
+static void m25p_shutdown(struct spi_device *spi)
+{
+   struct m25p *flash = spi_get_drvdata(spi);
+
+   spi_nor_restore(>spi_nor);
+}
 /*
  * Do NOT add to this array without reading the following:
  *
@@ -386,6 +394,7 @@ static struct spi_driver m25p80_driver = {
.id_table   = m25p_ids,
.probe  = m25p_probe,
.remove = m25p_remove,
+   .shutdown   = m25p_shutdown,
 
/* REVISIT: many of these chips have deep power-down modes, which
 * should clearly be entered on suspend() to minimize power use.
-- 
2.14.1



[PATCHv3 2/2] mtd: m25p80: restore the status of SPI flash when exiting

2017-12-05 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Restore the status to be compatible with legacy devices.
Take Freescale eSPI boot for example, it copies (in 3 Byte
addressing mode) the RCW and bootloader images from SPI flash
without firing a reset signal previously, so the reboot command
will fail without reseting the addressing mode of SPI flash.
This patch implement .shutdown function to restore the status
in reboot process, and add the same operation to the .remove
function.

Signed-off-by: Hou Zhiqiang 
---
V3:
 - Modified the commit to make this patch specific.

 drivers/mtd/devices/m25p80.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index dbe6a1de2bb8..a4e18f6aaa33 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -307,10 +307,18 @@ static int m25p_remove(struct spi_device *spi)
 {
struct m25p *flash = spi_get_drvdata(spi);
 
+   spi_nor_restore(>spi_nor);
+
/* Clean up MTD stuff. */
return mtd_device_unregister(>spi_nor.mtd);
 }
 
+static void m25p_shutdown(struct spi_device *spi)
+{
+   struct m25p *flash = spi_get_drvdata(spi);
+
+   spi_nor_restore(>spi_nor);
+}
 /*
  * Do NOT add to this array without reading the following:
  *
@@ -386,6 +394,7 @@ static struct spi_driver m25p80_driver = {
.id_table   = m25p_ids,
.probe  = m25p_probe,
.remove = m25p_remove,
+   .shutdown   = m25p_shutdown,
 
/* REVISIT: many of these chips have deep power-down modes, which
 * should clearly be entered on suspend() to minimize power use.
-- 
2.14.1



[PATCHv2 2/2] mtd: m25p80: restore the status of SPI flash when stop using it

2017-12-04 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Implement .shutdown function to restore the status in reboot
process, and add the same operation to the .remove function.

Signed-off-by: Hou Zhiqiang 
---
V2:
 - Changed code format slightly.

 drivers/mtd/devices/m25p80.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index dbe6a1de2bb8..a4e18f6aaa33 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -307,10 +307,18 @@ static int m25p_remove(struct spi_device *spi)
 {
struct m25p *flash = spi_get_drvdata(spi);
 
+   spi_nor_restore(>spi_nor);
+
/* Clean up MTD stuff. */
return mtd_device_unregister(>spi_nor.mtd);
 }
 
+static void m25p_shutdown(struct spi_device *spi)
+{
+   struct m25p *flash = spi_get_drvdata(spi);
+
+   spi_nor_restore(>spi_nor);
+}
 /*
  * Do NOT add to this array without reading the following:
  *
@@ -386,6 +394,7 @@ static struct spi_driver m25p80_driver = {
.id_table   = m25p_ids,
.probe  = m25p_probe,
.remove = m25p_remove,
+   .shutdown   = m25p_shutdown,
 
/* REVISIT: many of these chips have deep power-down modes, which
 * should clearly be entered on suspend() to minimize power use.
-- 
2.14.1



[PATCHv2 2/2] mtd: m25p80: restore the status of SPI flash when stop using it

2017-12-04 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Implement .shutdown function to restore the status in reboot
process, and add the same operation to the .remove function.

Signed-off-by: Hou Zhiqiang 
---
V2:
 - Changed code format slightly.

 drivers/mtd/devices/m25p80.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index dbe6a1de2bb8..a4e18f6aaa33 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -307,10 +307,18 @@ static int m25p_remove(struct spi_device *spi)
 {
struct m25p *flash = spi_get_drvdata(spi);
 
+   spi_nor_restore(>spi_nor);
+
/* Clean up MTD stuff. */
return mtd_device_unregister(>spi_nor.mtd);
 }
 
+static void m25p_shutdown(struct spi_device *spi)
+{
+   struct m25p *flash = spi_get_drvdata(spi);
+
+   spi_nor_restore(>spi_nor);
+}
 /*
  * Do NOT add to this array without reading the following:
  *
@@ -386,6 +394,7 @@ static struct spi_driver m25p80_driver = {
.id_table   = m25p_ids,
.probe  = m25p_probe,
.remove = m25p_remove,
+   .shutdown   = m25p_shutdown,
 
/* REVISIT: many of these chips have deep power-down modes, which
 * should clearly be entered on suspend() to minimize power use.
-- 
2.14.1



[PATCHv2 1/2] mtd: spi-nor: add an API to restore the status of SPI flash chip

2017-12-04 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Add this API to restore the status of SPI flash chip to the default
such as addressing mode, whenever detach the driver from device or
reboot the system.

Signed-off-by: Hou Zhiqiang 
---
V2:
 - Changed the API name and added the comments and kernel document for it.
 - Export this symbol for modules.

 Documentation/mtd/spi-nor.txt |  3 +++
 drivers/mtd/spi-nor/spi-nor.c | 10 ++
 include/linux/mtd/spi-nor.h   |  6 ++
 3 files changed, 19 insertions(+)

diff --git a/Documentation/mtd/spi-nor.txt b/Documentation/mtd/spi-nor.txt
index 548d6306ebca..da1fbff5a24c 100644
--- a/Documentation/mtd/spi-nor.txt
+++ b/Documentation/mtd/spi-nor.txt
@@ -60,3 +60,6 @@ The main API is spi_nor_scan(). Before you call the hook, a 
driver should
 initialize the necessary fields for spi_nor{}. Please see
 drivers/mtd/spi-nor/spi-nor.c for detail. Please also refer to fsl-quadspi.c
 when you want to write a new driver for a SPI NOR controller.
+Another API is spi_nor_restore(), this is used to restore the status of SPI
+flash chip such as addressing mode. Call it whenever detach the driver from
+device or reboot the system.
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index bc266f70a15b..4a925378d434 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -2713,6 +2713,16 @@ static void spi_nor_resume(struct mtd_info *mtd)
dev_err(dev, "resume() failed\n");
 }
 
+void spi_nor_restore(struct spi_nor *nor)
+{
+   /* restore the addressing mode */
+   if ((nor->addr_width == 4) &&
+   (JEDEC_MFR(nor->info) != SNOR_MFR_SPANSION) &&
+   !(nor->info->flags & SPI_NOR_4B_OPCODES))
+   set_4byte(nor, nor->info, 0);
+}
+EXPORT_SYMBOL_GPL(spi_nor_restore);
+
 int spi_nor_scan(struct spi_nor *nor, const char *name,
 const struct spi_nor_hwcaps *hwcaps)
 {
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index d0c66a0975cf..0a182c3d0884 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -399,4 +399,10 @@ struct spi_nor_hwcaps {
 int spi_nor_scan(struct spi_nor *nor, const char *name,
 const struct spi_nor_hwcaps *hwcaps);
 
+/*
+ * spi_nor_restore_addr_mode() - restore the status of SPI NOR
+ * @nor:   the spi_nor structure
+ */
+void spi_nor_restore(struct spi_nor *nor);
+
 #endif
-- 
2.14.1



[PATCHv2 1/2] mtd: spi-nor: add an API to restore the status of SPI flash chip

2017-12-04 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Add this API to restore the status of SPI flash chip to the default
such as addressing mode, whenever detach the driver from device or
reboot the system.

Signed-off-by: Hou Zhiqiang 
---
V2:
 - Changed the API name and added the comments and kernel document for it.
 - Export this symbol for modules.

 Documentation/mtd/spi-nor.txt |  3 +++
 drivers/mtd/spi-nor/spi-nor.c | 10 ++
 include/linux/mtd/spi-nor.h   |  6 ++
 3 files changed, 19 insertions(+)

diff --git a/Documentation/mtd/spi-nor.txt b/Documentation/mtd/spi-nor.txt
index 548d6306ebca..da1fbff5a24c 100644
--- a/Documentation/mtd/spi-nor.txt
+++ b/Documentation/mtd/spi-nor.txt
@@ -60,3 +60,6 @@ The main API is spi_nor_scan(). Before you call the hook, a 
driver should
 initialize the necessary fields for spi_nor{}. Please see
 drivers/mtd/spi-nor/spi-nor.c for detail. Please also refer to fsl-quadspi.c
 when you want to write a new driver for a SPI NOR controller.
+Another API is spi_nor_restore(), this is used to restore the status of SPI
+flash chip such as addressing mode. Call it whenever detach the driver from
+device or reboot the system.
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index bc266f70a15b..4a925378d434 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -2713,6 +2713,16 @@ static void spi_nor_resume(struct mtd_info *mtd)
dev_err(dev, "resume() failed\n");
 }
 
+void spi_nor_restore(struct spi_nor *nor)
+{
+   /* restore the addressing mode */
+   if ((nor->addr_width == 4) &&
+   (JEDEC_MFR(nor->info) != SNOR_MFR_SPANSION) &&
+   !(nor->info->flags & SPI_NOR_4B_OPCODES))
+   set_4byte(nor, nor->info, 0);
+}
+EXPORT_SYMBOL_GPL(spi_nor_restore);
+
 int spi_nor_scan(struct spi_nor *nor, const char *name,
 const struct spi_nor_hwcaps *hwcaps)
 {
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index d0c66a0975cf..0a182c3d0884 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -399,4 +399,10 @@ struct spi_nor_hwcaps {
 int spi_nor_scan(struct spi_nor *nor, const char *name,
 const struct spi_nor_hwcaps *hwcaps);
 
+/*
+ * spi_nor_restore_addr_mode() - restore the status of SPI NOR
+ * @nor:   the spi_nor structure
+ */
+void spi_nor_restore(struct spi_nor *nor);
+
 #endif
-- 
2.14.1



  1   2   >