[PATCHv4 3/9] arm64: dts: ls1043a: fix typo of MSI compatible string

2017-07-05 Thread Zhiqiang Hou
From: Minghuan Lian 

"1" should be replaced by "l". This is a typo.
The patch is to fix it.

Signed-off-by: Minghuan Lian 
Signed-off-by: Hou Zhiqiang 
---
v4-v1:
 - None

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

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index 31fd77f..7ff98f4 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -653,21 +653,21 @@
};
 
msi1: msi-controller1@1571000 {
-   compatible = "fsl,1s1043a-msi";
+   compatible = "fsl,ls1043a-msi";
reg = <0x0 0x1571000 0x0 0x8>;
msi-controller;
interrupts = <0 116 0x4>;
};
 
msi2: msi-controller2@1572000 {
-   compatible = "fsl,1s1043a-msi";
+   compatible = "fsl,ls1043a-msi";
reg = <0x0 0x1572000 0x0 0x8>;
msi-controller;
interrupts = <0 126 0x4>;
};
 
msi3: msi-controller3@1573000 {
-   compatible = "fsl,1s1043a-msi";
+   compatible = "fsl,ls1043a-msi";
reg = <0x0 0x1573000 0x0 0x8>;
msi-controller;
interrupts = <0 160 0x4>;
-- 
2.1.0.27.g96db324



[PATCHv4 7/9] irqchip/ls-scfg-msi: add LS1046a MSI support

2017-07-05 Thread Zhiqiang Hou
From: Minghuan Lian 

LS1046a includes 4 MSIRs, each MSIR is assigned a dedicate GIC
SPI interrupt and provides 32 MSI interrupts. Compared to previous
MSI, LS1046a's IBS(interrupt bit select) shift is changed to 2 and
total MSI interrupt number is changed to 128.

The patch adds structure 'ls_scfg_msir' to describe MSIR setting and
'ibs_shift' to store the different value between the SoCs.

Signed-off-by: Minghuan Lian 
Signed-off-by: Hou Zhiqiang 
---
v4:
 - None
v3-v2:
 - keep the old misspelled compatible strings
v2-v1:
 - MSI dts node change has been merged into the patch 6/9

 drivers/irqchip/irq-ls-scfg-msi.c | 165 ++
 1 file changed, 130 insertions(+), 35 deletions(-)

diff --git a/drivers/irqchip/irq-ls-scfg-msi.c 
b/drivers/irqchip/irq-ls-scfg-msi.c
index cef67cc..0b1f34d 100644
--- a/drivers/irqchip/irq-ls-scfg-msi.c
+++ b/drivers/irqchip/irq-ls-scfg-msi.c
@@ -17,13 +17,24 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 
-#define MSI_MAX_IRQS   32
-#define MSI_IBS_SHIFT  3
-#define MSIR   4
+#define MSI_IRQS_PER_MSIR  32
+#define MSI_MSIR_OFFSET4
+
+struct ls_scfg_msi_cfg {
+   u32 ibs_shift; /* Shift of interrupt bit select */
+};
+
+struct ls_scfg_msir {
+   struct ls_scfg_msi *msi_data;
+   unsigned int index;
+   unsigned int gic_irq;
+   void __iomem *reg;
+};
 
 struct ls_scfg_msi {
spinlock_t  lock;
@@ -32,8 +43,11 @@ struct ls_scfg_msi {
struct irq_domain   *msi_domain;
void __iomem*regs;
phys_addr_t msiir_addr;
-   int irq;
-   DECLARE_BITMAP(used, MSI_MAX_IRQS);
+   struct ls_scfg_msi_cfg  *cfg;
+   u32 msir_num;
+   struct ls_scfg_msir *msir;
+   u32 irqs_num;
+   unsigned long   *used;
 };
 
 static struct irq_chip ls_scfg_msi_irq_chip = {
@@ -55,7 +69,7 @@ static void ls_scfg_msi_compose_msg(struct irq_data *data, 
struct msi_msg *msg)
 
msg->address_hi = upper_32_bits(msi_data->msiir_addr);
msg->address_lo = lower_32_bits(msi_data->msiir_addr);
-   msg->data = data->hwirq << MSI_IBS_SHIFT;
+   msg->data = data->hwirq;
 }
 
 static int ls_scfg_msi_set_affinity(struct irq_data *irq_data,
@@ -81,8 +95,8 @@ static int ls_scfg_msi_domain_irq_alloc(struct irq_domain 
*domain,
WARN_ON(nr_irqs != 1);
 
spin_lock(_data->lock);
-   pos = find_first_zero_bit(msi_data->used, MSI_MAX_IRQS);
-   if (pos < MSI_MAX_IRQS)
+   pos = find_first_zero_bit(msi_data->used, msi_data->irqs_num);
+   if (pos < msi_data->irqs_num)
__set_bit(pos, msi_data->used);
else
err = -ENOSPC;
@@ -106,7 +120,7 @@ static void ls_scfg_msi_domain_irq_free(struct irq_domain 
*domain,
int pos;
 
pos = d->hwirq;
-   if (pos < 0 || pos >= MSI_MAX_IRQS) {
+   if (pos < 0 || pos >= msi_data->irqs_num) {
pr_err("failed to teardown msi. Invalid hwirq %d\n", pos);
return;
}
@@ -123,15 +137,17 @@ static const struct irq_domain_ops ls_scfg_msi_domain_ops 
= {
 
 static void ls_scfg_msi_irq_handler(struct irq_desc *desc)
 {
-   struct ls_scfg_msi *msi_data = irq_desc_get_handler_data(desc);
+   struct ls_scfg_msir *msir = irq_desc_get_handler_data(desc);
+   struct ls_scfg_msi *msi_data = msir->msi_data;
unsigned long val;
-   int pos, virq;
+   int pos, virq, hwirq;
 
chained_irq_enter(irq_desc_get_chip(desc), desc);
 
-   val = ioread32be(msi_data->regs + MSIR);
-   for_each_set_bit(pos, , MSI_MAX_IRQS) {
-   virq = irq_find_mapping(msi_data->parent, (31 - pos));
+   val = ioread32be(msir->reg);
+   for_each_set_bit(pos, , MSI_IRQS_PER_MSIR) {
+   hwirq = ((31 - pos) << msi_data->cfg->ibs_shift) | msir->index;
+   virq = irq_find_mapping(msi_data->parent, hwirq);
if (virq)
generic_handle_irq(virq);
}
@@ -143,7 +159,7 @@ static int ls_scfg_msi_domains_init(struct ls_scfg_msi 
*msi_data)
 {
/* Initialize MSI domain parent */
msi_data->parent = irq_domain_add_linear(NULL,
-MSI_MAX_IRQS,
+msi_data->irqs_num,
 _scfg_msi_domain_ops,
 msi_data);
if (!msi_data->parent) {
@@ -164,16 +180,87 @@ static int ls_scfg_msi_domains_init(struct ls_scfg_msi 
*msi_data)
return 0;
 }
 
+static int ls_scfg_msi_setup_hwirq(struct ls_scfg_msi *msi_data, int index)
+{
+   struct ls_scfg_msir *msir;
+   int virq, i, hwirq;
+
+   virq = platform_get_irq(msi_data->pdev, index);
+   

[PATCHv4 5/9] arm64: dts: ls1043a: share all MSIs

2017-07-05 Thread Zhiqiang Hou
From: Minghuan Lian 

In order to maximize the use of MSI, a PCIe controller will share
all MSI controllers. The patch changes "msi-parent" to refer to all
MSI controller dts nodes.

Signed-off-by: Minghuan Lian 
Signed-off-by: Hou Zhiqiang 
---
v4-v1:
 - None

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

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index 7ff98f4..d16b9cc 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -689,7 +689,7 @@
bus-range = <0x0 0xff>;
ranges = <0x8100 0x0 0x 0x40 0x0001 0x0 
0x0001   /* downstream I/O */
  0x8200 0x0 0x4000 0x40 0x4000 0x0 
0x4000>; /* non-prefetchable memory */
-   msi-parent = <>;
+   msi-parent = <>, <>, <>;
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = < 0 0 1  0 110 0x4>,
@@ -714,7 +714,7 @@
bus-range = <0x0 0xff>;
ranges = <0x8100 0x0 0x 0x48 0x0001 0x0 
0x0001   /* downstream I/O */
  0x8200 0x0 0x4000 0x48 0x4000 0x0 
0x4000>; /* non-prefetchable memory */
-   msi-parent = <>;
+   msi-parent = <>, <>, <>;
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = < 0 0 1  0 120  0x4>,
@@ -739,7 +739,7 @@
bus-range = <0x0 0xff>;
ranges = <0x8100 0x0 0x 0x50 0x0001 0x0 
0x0001   /* downstream I/O */
  0x8200 0x0 0x4000 0x50 0x4000 0x0 
0x4000>; /* non-prefetchable memory */
-   msi-parent = <>;
+   msi-parent = <>, <>, <>;
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = < 0 0 1  0 154 0x4>,
-- 
2.1.0.27.g96db324



[PATCHv4 2/9] arm: dts: ls1021a: fix typo of MSI compatible string

2017-07-05 Thread Zhiqiang Hou
From: Minghuan Lian 

"1" should be replaced by "l". This is a typo.
The patch is to fix it.

Signed-off-by: Minghuan Lian 
Signed-off-by: Hou Zhiqiang 
---
v4-v1:
 - None

 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 7bb9df2..51b0f69 100644
--- a/arch/arm/boot/dts/ls1021a.dtsi
+++ b/arch/arm/boot/dts/ls1021a.dtsi
@@ -129,14 +129,14 @@
};
 
msi1: msi-controller@1570e00 {
-   compatible = "fsl,1s1021a-msi";
+   compatible = "fsl,ls1021a-msi";
reg = <0x0 0x1570e00 0x0 0x8>;
msi-controller;
interrupts =  ;
};
 
msi2: msi-controller@1570e08 {
-   compatible = "fsl,1s1021a-msi";
+   compatible = "fsl,ls1021a-msi";
reg = <0x0 0x1570e08 0x0 0x8>;
msi-controller;
interrupts = ;
-- 
2.1.0.27.g96db324



[PATCHv4 9/9] irqchip/ls-scfg-msi: add MSI affinity support

2017-07-05 Thread Zhiqiang Hou
From: Minghuan Lian 

For LS1046a and LS1043a v1.1, the MSI controller has 4 MSIRs and 4 GIC
SPI interrupts which can be associated with different Core.
So we can support affinity to improve the performance.
The MSI message data is a byte for Layerscape MSI.
  76   5  4  3  2   1   0
| - |   IBS   |  SRS |
SRS bit0-1 is to select a MSIR which is associated with a CPU.
IBS bit2-6 of ls1046, bit2-4 of ls1043a v1.1 is to select bit of the
MSIR. With affinity, only bits of MSIR0(srs=0 cpu0) are available.
All other bits of the MSIR1-3(cpu1-3) are reserved. The MSI hwirq
always equals bit index of the MSIR0. When changing affinity, MSI
message data will be appended corresponding SRS then MSI will be
moved to the corresponding core.
But in affinity mode, there is only 8 MSI interrupts for a controller
of LS1043a v1.1. It cannot meet the requirement of the some PCIe
devices such as 4 ports Ethernet card. In contrast, without affinity,
all MSIRs can be used for core 0, the MSI interrupts can up to 32.
So the parameter is added to control affinity mode.
"lsmsi=no-affinity" will disable affinity and increase MSI
interrupt number.

Signed-off-by: Minghuan Lian 
Signed-off-by: Hou Zhiqiang 
---
v4:
 - None
v3-v2:
 - 1. update the description
 - 2. remove unnecessary msir_index checking
v2-v1:
 - None


 drivers/irqchip/irq-ls-scfg-msi.c | 68 ---
 1 file changed, 63 insertions(+), 5 deletions(-)

diff --git a/drivers/irqchip/irq-ls-scfg-msi.c 
b/drivers/irqchip/irq-ls-scfg-msi.c
index 8d57a59..119f4ef 100644
--- a/drivers/irqchip/irq-ls-scfg-msi.c
+++ b/drivers/irqchip/irq-ls-scfg-msi.c
@@ -40,6 +40,7 @@ struct ls_scfg_msir {
unsigned int gic_irq;
unsigned int bit_start;
unsigned int bit_end;
+   unsigned int srs; /* Shared interrupt register select */
void __iomem *reg;
 };
 
@@ -70,6 +71,19 @@ static struct msi_domain_info ls_scfg_msi_domain_info = {
.chip   = _scfg_msi_irq_chip,
 };
 
+static int msi_affinity_flag = 1;
+
+static int __init early_parse_ls_scfg_msi(char *p)
+{
+   if (p && strncmp(p, "no-affinity", 11) == 0)
+   msi_affinity_flag = 0;
+   else
+   msi_affinity_flag = 1;
+
+   return 0;
+}
+early_param("lsmsi", early_parse_ls_scfg_msi);
+
 static void ls_scfg_msi_compose_msg(struct irq_data *data, struct msi_msg *msg)
 {
struct ls_scfg_msi *msi_data = irq_data_get_irq_chip_data(data);
@@ -77,12 +91,36 @@ static void ls_scfg_msi_compose_msg(struct irq_data *data, 
struct msi_msg *msg)
msg->address_hi = upper_32_bits(msi_data->msiir_addr);
msg->address_lo = lower_32_bits(msi_data->msiir_addr);
msg->data = data->hwirq;
+
+   if (msi_affinity_flag)
+   msg->data |= cpumask_first(data->common->affinity);
 }
 
 static int ls_scfg_msi_set_affinity(struct irq_data *irq_data,
const struct cpumask *mask, bool force)
 {
-   return -EINVAL;
+   struct ls_scfg_msi *msi_data = irq_data_get_irq_chip_data(irq_data);
+   u32 cpu;
+
+   if (!msi_affinity_flag)
+   return -EINVAL;
+
+   if (!force)
+   cpu = cpumask_any_and(mask, cpu_online_mask);
+   else
+   cpu = cpumask_first(mask);
+
+   if (cpu >= msi_data->msir_num)
+   return -EINVAL;
+
+   if (msi_data->msir[cpu].gic_irq <= 0) {
+   pr_warn("cannot bind the irq to cpu%d\n", cpu);
+   return -EINVAL;
+   }
+
+   cpumask_copy(irq_data->common->affinity, mask);
+
+   return IRQ_SET_MASK_OK;
 }
 
 static struct irq_chip ls_scfg_msi_parent_chip = {
@@ -158,7 +196,7 @@ static void ls_scfg_msi_irq_handler(struct irq_desc *desc)
 
for_each_set_bit_from(pos, , size) {
hwirq = ((msir->bit_end - pos) << msi_data->cfg->ibs_shift) |
-   msir->index;
+   msir->srs;
virq = irq_find_mapping(msi_data->parent, hwirq);
if (virq)
generic_handle_irq(virq);
@@ -221,10 +259,19 @@ static int ls_scfg_msi_setup_hwirq(struct ls_scfg_msi 
*msi_data, int index)
 ls_scfg_msi_irq_handler,
 msir);
 
+   if (msi_affinity_flag) {
+   /* Associate MSIR interrupt to the cpu */
+   irq_set_affinity(msir->gic_irq, get_cpu_mask(index));
+   msir->srs = 0; /* This value is determined by the CPU */
+   } else
+   msir->srs = index;
+
/* Release the hwirqs corresponding to this MSIR */
-   for (i = 0; i < msi_data->cfg->msir_irqs; i++) {
-   hwirq = i << msi_data->cfg->ibs_shift | msir->index;
-   bitmap_clear(msi_data->used, hwirq, 1);
+   if (!msi_affinity_flag || msir->index == 0) {
+   for (i = 0; i < 

[PATCHv4 6/9] arm64: dts: ls1046a: add MSI dts node

2017-07-05 Thread Zhiqiang Hou
From: Minghuan Lian 

LS1046a includes 3 MSI controllers.
Each controller supports 128 interrupts.

Signed-off-by: Minghuan Lian 
Acked-by: Rob Herring 
Signed-off-by: Hou Zhiqiang 
---
v4:
 - rebased code
v3-v2:
 - None
v2-v1:
 - change whitespace number

 .../interrupt-controller/fsl,ls-scfg-msi.txt   |  1 +
 arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 31 ++
 2 files changed, 32 insertions(+)

diff --git 
a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt 
b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
index 2755cd1..dde4552 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
@@ -6,6 +6,7 @@ Required properties:
  Layerscape PCIe MSI controller block such as:
   "fsl,ls1021a-msi"
   "fsl,ls1043a-msi"
+  "fsl,ls1046a-msi"
 - msi-controller: indicates that this is a PCIe MSI controller node
 - reg: physical base address of the controller and length of memory mapped.
 - interrupts: an interrupt to the parent interrupt controller.
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
index dc1640b..c8ff0ba 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
@@ -630,6 +630,37 @@
interrupts = ;
clocks = < 4 1>;
};
+
+   msi1: msi-controller@158 {
+   compatible = "fsl,ls1046a-msi";
+   msi-controller;
+   reg = <0x0 0x158 0x0 0x1>;
+   interrupts = ,
+,
+,
+;
+   };
+
+   msi2: msi-controller@159 {
+   compatible = "fsl,ls1046a-msi";
+   msi-controller;
+   reg = <0x0 0x159 0x0 0x1>;
+   interrupts = ,
+,
+,
+;
+   };
+
+   msi3: msi-controller@15a {
+   compatible = "fsl,ls1046a-msi";
+   msi-controller;
+   reg = <0x0 0x15a 0x0 0x1>;
+   interrupts = ,
+,
+,
+;
+   };
+
};
 
reserved-memory {
-- 
2.1.0.27.g96db324



[PATCHv4 4/9] arm: dts: ls1021a: share all MSIs

2017-07-05 Thread Zhiqiang Hou
From: Minghuan Lian 

In order to maximize the use of MSI, a PCIe controller will share
all MSI controllers. The patch changes msi-parent to refer to all
MSI controller dts nodes.

Signed-off-by: Minghuan Lian 
Signed-off-by: Hou Zhiqiang 
---
v4-v1:
 - None

 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 51b0f69..9319e1f 100644
--- a/arch/arm/boot/dts/ls1021a.dtsi
+++ b/arch/arm/boot/dts/ls1021a.dtsi
@@ -699,7 +699,7 @@
bus-range = <0x0 0xff>;
ranges = <0x8100 0x0 0x 0x40 0x0001 0x0 
0x0001   /* downstream I/O */
  0x8200 0x0 0x4000 0x40 0x4000 0x0 
0x4000>; /* non-prefetchable memory */
-   msi-parent = <>;
+   msi-parent = <>, <>;
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = < 0 0 1  GIC_SPI 91  
IRQ_TYPE_LEVEL_HIGH>,
@@ -722,7 +722,7 @@
bus-range = <0x0 0xff>;
ranges = <0x8100 0x0 0x 0x48 0x0001 0x0 
0x0001   /* downstream I/O */
  0x8200 0x0 0x4000 0x48 0x4000 0x0 
0x4000>; /* non-prefetchable memory */
-   msi-parent = <>;
+   msi-parent = <>, <>;
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = < 0 0 1  GIC_SPI 92  
IRQ_TYPE_LEVEL_HIGH>,
-- 
2.1.0.27.g96db324



[PATCHv4 8/9] irqchip/ls-scfg-msi: add LS1043a v1.1 MSI support

2017-07-05 Thread Zhiqiang Hou
From: Minghuan Lian 

A MSI controller of LS1043a v1.0 only includes one MSIR and
is assigned one GIC interrupt. In order to support affinity,
LS1043a v1.1 MSI is assigned 4 MSIRs and 4 GIC interrupts.
But the MSIR has the different offset and only supports 8 MSIs.
The bits between variable bit_start and bit_end in structure
ls_scfg_msir are used to show 8 MSI interrupts. msir_irqs and
msir_base are added to describe the difference of MSI between
LS1043a v1.1 and other SoCs.

Signed-off-by: Minghuan Lian 
Acked-by: Rob Herring 
Signed-off-by: Hou Zhiqiang 
---
v4-v1:
 - None

 .../interrupt-controller/fsl,ls-scfg-msi.txt   |  1 +
 drivers/irqchip/irq-ls-scfg-msi.c  | 45 +++---
 2 files changed, 40 insertions(+), 6 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt 
b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
index dde4552..49ccabb 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
@@ -7,6 +7,7 @@ Required properties:
   "fsl,ls1021a-msi"
   "fsl,ls1043a-msi"
   "fsl,ls1046a-msi"
+  "fsl,ls1043a-v1.1-msi"
 - msi-controller: indicates that this is a PCIe MSI controller node
 - reg: physical base address of the controller and length of memory mapped.
 - interrupts: an interrupt to the parent interrupt controller.
diff --git a/drivers/irqchip/irq-ls-scfg-msi.c 
b/drivers/irqchip/irq-ls-scfg-msi.c
index 0b1f34d..8d57a59 100644
--- a/drivers/irqchip/irq-ls-scfg-msi.c
+++ b/drivers/irqchip/irq-ls-scfg-msi.c
@@ -25,14 +25,21 @@
 #define MSI_IRQS_PER_MSIR  32
 #define MSI_MSIR_OFFSET4
 
+#define MSI_LS1043V1_1_IRQS_PER_MSIR   8
+#define MSI_LS1043V1_1_MSIR_OFFSET 0x10
+
 struct ls_scfg_msi_cfg {
u32 ibs_shift; /* Shift of interrupt bit select */
+   u32 msir_irqs; /* The irq number per MSIR */
+   u32 msir_base; /* The base address of MSIR */
 };
 
 struct ls_scfg_msir {
struct ls_scfg_msi *msi_data;
unsigned int index;
unsigned int gic_irq;
+   unsigned int bit_start;
+   unsigned int bit_end;
void __iomem *reg;
 };
 
@@ -140,13 +147,18 @@ static void ls_scfg_msi_irq_handler(struct irq_desc *desc)
struct ls_scfg_msir *msir = irq_desc_get_handler_data(desc);
struct ls_scfg_msi *msi_data = msir->msi_data;
unsigned long val;
-   int pos, virq, hwirq;
+   int pos, size, virq, hwirq;
 
chained_irq_enter(irq_desc_get_chip(desc), desc);
 
val = ioread32be(msir->reg);
-   for_each_set_bit(pos, , MSI_IRQS_PER_MSIR) {
-   hwirq = ((31 - pos) << msi_data->cfg->ibs_shift) | msir->index;
+
+   pos = msir->bit_start;
+   size = msir->bit_end + 1;
+
+   for_each_set_bit_from(pos, , size) {
+   hwirq = ((msir->bit_end - pos) << msi_data->cfg->ibs_shift) |
+   msir->index;
virq = irq_find_mapping(msi_data->parent, hwirq);
if (virq)
generic_handle_irq(virq);
@@ -193,14 +205,24 @@ static int ls_scfg_msi_setup_hwirq(struct ls_scfg_msi 
*msi_data, int index)
msir->index = index;
msir->msi_data = msi_data;
msir->gic_irq = virq;
-   msir->reg = msi_data->regs + MSI_MSIR_OFFSET + 4 * index;
+   msir->reg = msi_data->regs + msi_data->cfg->msir_base + 4 * index;
+
+   if (msi_data->cfg->msir_irqs == MSI_LS1043V1_1_IRQS_PER_MSIR) {
+   msir->bit_start = 32 - ((msir->index + 1) *
+ MSI_LS1043V1_1_IRQS_PER_MSIR);
+   msir->bit_end = msir->bit_start +
+   MSI_LS1043V1_1_IRQS_PER_MSIR - 1;
+   } else {
+   msir->bit_start = 0;
+   msir->bit_end = msi_data->cfg->msir_irqs - 1;
+   }
 
irq_set_chained_handler_and_data(msir->gic_irq,
 ls_scfg_msi_irq_handler,
 msir);
 
/* Release the hwirqs corresponding to this MSIR */
-   for (i = 0; i < MSI_IRQS_PER_MSIR; i++) {
+   for (i = 0; i < msi_data->cfg->msir_irqs; i++) {
hwirq = i << msi_data->cfg->ibs_shift | msir->index;
bitmap_clear(msi_data->used, hwirq, 1);
}
@@ -216,7 +238,7 @@ static int ls_scfg_msi_teardown_hwirq(struct ls_scfg_msir 
*msir)
if (msir->gic_irq > 0)
irq_set_chained_handler_and_data(msir->gic_irq, NULL, NULL);
 
-   for (i = 0; i < MSI_IRQS_PER_MSIR; i++) {
+   for (i = 0; i < msi_data->cfg->msir_irqs; i++) {
hwirq = i << msi_data->cfg->ibs_shift | msir->index;
bitmap_set(msi_data->used, hwirq, 1);
}
@@ -226,10 

[PATCHv4 1/9] irqchip/ls-scfg-msi: fix typo of MSI compatible strings

2017-07-05 Thread Zhiqiang Hou
From: Minghuan Lian 

The patch is to fix typo of the Layerscape SCFG MSI dts compatible
strings. "1" is replaced by "l".

Signed-off-by: Minghuan Lian 
Acked-by: Rob Herring 
Signed-off-by: Hou Zhiqiang 
---
v4-v1:
 - None

 .../devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt| 6 +++---
 drivers/irqchip/irq-ls-scfg-msi.c   | 6 --
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt 
b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
index 9e38949..2755cd1 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
@@ -4,8 +4,8 @@ Required properties:
 
 - compatible: should be "fsl,-msi" to identify
  Layerscape PCIe MSI controller block such as:
-  "fsl,1s1021a-msi"
-  "fsl,1s1043a-msi"
+  "fsl,ls1021a-msi"
+  "fsl,ls1043a-msi"
 - msi-controller: indicates that this is a PCIe MSI controller node
 - reg: physical base address of the controller and length of memory mapped.
 - interrupts: an interrupt to the parent interrupt controller.
@@ -23,7 +23,7 @@ MSI controller node
 Examples:
 
msi1: msi-controller@1571000 {
-   compatible = "fsl,1s1043a-msi";
+   compatible = "fsl,ls1043a-msi";
reg = <0x0 0x1571000 0x0 0x8>,
msi-controller;
interrupts = <0 116 0x4>;
diff --git a/drivers/irqchip/irq-ls-scfg-msi.c 
b/drivers/irqchip/irq-ls-scfg-msi.c
index 02cca74c..cef67cc 100644
--- a/drivers/irqchip/irq-ls-scfg-msi.c
+++ b/drivers/irqchip/irq-ls-scfg-msi.c
@@ -219,8 +219,10 @@ static int ls_scfg_msi_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id ls_scfg_msi_id[] = {
-   { .compatible = "fsl,1s1021a-msi", },
-   { .compatible = "fsl,1s1043a-msi", },
+   { .compatible = "fsl,1s1021a-msi", }, /* a typo */
+   { .compatible = "fsl,1s1043a-msi", }, /* a typo */
+   { .compatible = "fsl,ls1021a-msi", },
+   { .compatible = "fsl,ls1043a-msi", },
{},
 };
 
-- 
2.1.0.27.g96db324



[PATCH 1/5] irqchip/ls-scfg-msi: add LS1012a MSI support

2017-09-19 Thread Zhiqiang Hou
From: Hou Zhiqiang 

The ls1012a implement only 1 msi controller, and it is the same as
ls1043a.

Signed-off-by: Hou Zhiqiang 
---
 .../devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt | 1 +
 drivers/irqchip/irq-ls-scfg-msi.c| 1 +
 2 files changed, 2 insertions(+)

diff --git 
a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt 
b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
index 49ccabbfa6f3..a4ff93d6b7f3 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
@@ -8,6 +8,7 @@ Required properties:
   "fsl,ls1043a-msi"
   "fsl,ls1046a-msi"
   "fsl,ls1043a-v1.1-msi"
+  "fsl,ls1012a-msi"
 - msi-controller: indicates that this is a PCIe MSI controller node
 - reg: physical base address of the controller and length of memory mapped.
 - interrupts: an interrupt to the parent interrupt controller.
diff --git a/drivers/irqchip/irq-ls-scfg-msi.c 
b/drivers/irqchip/irq-ls-scfg-msi.c
index 119f4ef0d421..57e3d900f19e 100644
--- a/drivers/irqchip/irq-ls-scfg-msi.c
+++ b/drivers/irqchip/irq-ls-scfg-msi.c
@@ -316,6 +316,7 @@ static const struct of_device_id ls_scfg_msi_id[] = {
{ .compatible = "fsl,1s1021a-msi", .data = _msi_cfg},
{ .compatible = "fsl,1s1043a-msi", .data = _msi_cfg},
 
+   { .compatible = "fsl,ls1012a-msi", .data = _msi_cfg },
{ .compatible = "fsl,ls1021a-msi", .data = _msi_cfg },
{ .compatible = "fsl,ls1043a-msi", .data = _msi_cfg },
{ .compatible = "fsl,ls1043a-v1.1-msi", .data = _v1_1_msi_cfg },
-- 
2.14.1



[PATCH 5/5] arm64: dts: ls1046a: add PCIe controller DT nodes

2017-09-19 Thread Zhiqiang Hou
From: Hou Zhiqiang 

LS1046a implements 3 PCIe 3.0 controllers.

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

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
index c8ff0baddf1d..eac8c32f64b0 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
@@ -661,6 +661,81 @@
 ;
};
 
+   pcie@340 {
+   compatible = "fsl,ls1046a-pcie", "snps,dw-pcie";
+   reg = <0x00 0x0340 0x0 0x0010   /* controller 
registers */
+  0x40 0x 0x0 0x2000>; /* 
configuration space */
+   reg-names = "regs", "config";
+   interrupts = , /* 
controller interrupt */
+; /* PME 
interrupt */
+   interrupt-names = "aer", "pme";
+   #address-cells = <3>;
+   #size-cells = <2>;
+   device_type = "pci";
+   dma-coherent;
+   num-lanes = <4>;
+   bus-range = <0x0 0xff>;
+   ranges = <0x8100 0x0 0x 0x40 0x0001 0x0 
0x0001   /* downstream I/O */
+ 0x8200 0x0 0x4000 0x40 0x4000 0x0 
0x4000>; /* non-prefetchable memory */
+   msi-parent = <>, <>, <>;
+   #interrupt-cells = <1>;
+   interrupt-map-mask = <0 0 0 7>;
+   interrupt-map = < 0 0 1  GIC_SPI 110 
IRQ_TYPE_LEVEL_HIGH>,
+   < 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>;
+   };
+
+   pcie@350 {
+   compatible = "fsl,ls1046a-pcie", "snps,dw-pcie";
+   reg = <0x00 0x0350 0x0 0x0010   /* controller 
registers */
+  0x48 0x 0x0 0x2000>; /* 
configuration space */
+   reg-names = "regs", "config";
+   interrupts = , /* 
controller interrupt */
+; /* PME 
interrupt */
+   interrupt-names = "aer", "pme";
+   #address-cells = <3>;
+   #size-cells = <2>;
+   device_type = "pci";
+   dma-coherent;
+   num-lanes = <2>;
+   bus-range = <0x0 0xff>;
+   ranges = <0x8100 0x0 0x 0x48 0x0001 0x0 
0x0001   /* downstream I/O */
+ 0x8200 0x0 0x4000 0x48 0x4000 0x0 
0x4000>; /* non-prefetchable memory */
+   msi-parent = <>, <>, <>;
+   #interrupt-cells = <1>;
+   interrupt-map-mask = <0 0 0 7>;
+   interrupt-map = < 0 0 1  GIC_SPI 120 
IRQ_TYPE_LEVEL_HIGH>,
+   < 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>;
+   };
+
+   pcie@360 {
+   compatible = "fsl,ls1046a-pcie", "snps,dw-pcie";
+   reg = <0x00 0x0360 0x0 0x0010   /* controller 
registers */
+  0x50 0x 0x0 0x2000>; /* 
configuration space */
+   reg-names = "regs", "config";
+   interrupts = , /* 
controller interrupt */
+; /* PME 
interrupt */
+   interrupt-names = "aer", "pme";
+   #address-cells = <3>;
+   #size-cells = <2>;
+   device_type = "pci";
+   dma-coherent;
+   num-lanes = <2>;
+   bus-range = <0x0 0xff>;
+   ranges = <0x8100 0x0 0x 0x50 0x0001 0x0 
0x0001   /* downstream I/O */
+ 0x8200 0x0 0x4000 0x50 0x4000 0x0 
0x4000>; /* non-prefetchable memory */
+   msi-parent = <>, <>, <>;
+   #interrupt-cells = <1>;
+   interrupt-map-mask = <0 0 0 7>;
+   interrupt-map = < 0 0 1  GIC_SPI 154 
IRQ_TYPE_LEVEL_HIGH>,
+   

[PATCH 2/5] arm64: dts: ls1012a: Add MSI controller DT node

2017-09-19 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Add MSI controller node for ls1012a platform.

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

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
index df83915d6ea6..a7698ac7264b 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
@@ -471,5 +471,12 @@
dr_mode = "host";
phy_type = "ulpi";
};
+
+   msi: msi-controller1@1572000 {
+   compatible = "fsl,ls1012a-msi";
+   reg = <0x0 0x1572000 0x0 0x8>;
+   msi-controller;
+   interrupts = <0 126 IRQ_TYPE_LEVEL_HIGH>;
+   };
};
 };
-- 
2.14.1



[PATCH 0/5] arm64: add ls1012a and ls1046a pcie support

2017-09-19 Thread Zhiqiang Hou
From: Hou Zhiqiang 

This patch set adds ls1012a MSI and PCIe support, including driver
and device tree nodes. The ls1046a's MSI support patch and PCIe
driver patch has been applied, so only adds the PCIe device tree
nodes.

Hou Zhiqiang (5):
  irqchip/ls-scfg-msi: add LS1012a MSI support
  arm64: dts: ls1012a: Add MSI controller DT node
  PCI: layerscape: Add support for ls1012a
  arm64: dts: ls1012a: Add PCIe controller DT node
  arm64: dts: ls1046a: add PCIe controller DT nodes

 .../interrupt-controller/fsl,ls-scfg-msi.txt   |  1 +
 .../devicetree/bindings/pci/layerscape-pci.txt |  1 +
 arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi | 31 +
 arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 75 ++
 drivers/irqchip/irq-ls-scfg-msi.c  |  1 +
 drivers/pci/dwc/pci-layerscape.c   |  1 +
 6 files changed, 110 insertions(+)

-- 
2.14.1



[PATCH 3/5] PCI: layerscape: Add support for ls1012a

2017-09-19 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Signed-off-by: Hou Zhiqiang 
---
 Documentation/devicetree/bindings/pci/layerscape-pci.txt | 1 +
 drivers/pci/dwc/pci-layerscape.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/pci/layerscape-pci.txt 
b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
index c0484da0f20d..66df1e81e0b8 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,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
   entry for each entry in the interrupt-names property.
diff --git a/drivers/pci/dwc/pci-layerscape.c b/drivers/pci/dwc/pci-layerscape.c
index 87fa486bee2c..3b01e309a55e 100644
--- a/drivers/pci/dwc/pci-layerscape.c
+++ b/drivers/pci/dwc/pci-layerscape.c
@@ -253,6 +253,7 @@ static struct ls_pcie_drvdata ls2088_drvdata = {
 };
 
 static const struct of_device_id ls_pcie_of_match[] = {
+   { .compatible = "fsl,ls1012a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls1021a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls1043a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls1046a-pcie", .data = _drvdata },
-- 
2.14.1



[PATCH 4/5] arm64: dts: ls1012a: Add PCIe controller DT node

2017-09-19 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Add PCIe controller node for ls1012a platform.

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

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
index a7698ac7264b..140570d45ff3 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
@@ -478,5 +478,29 @@
msi-controller;
interrupts = <0 126 IRQ_TYPE_LEVEL_HIGH>;
};
+
+   pcie@340 {
+   compatible = "fsl,ls1012a-pcie", "snps,dw-pcie";
+   reg = <0x00 0x0340 0x0 0x0010   /* controller 
registers */
+  0x40 0x 0x0 0x2000>; /* 
configuration space */
+   reg-names = "regs", "config";
+   interrupts = <0 118 0x4>, /* controller interrupt */
+<0 117 0x4>; /* PME interrupt */
+   interrupt-names = "aer", "pme";
+   #address-cells = <3>;
+   #size-cells = <2>;
+   device_type = "pci";
+   num-lanes = <4>;
+   bus-range = <0x0 0xff>;
+   ranges = <0x8100 0x0 0x 0x40 0x0001 0x0 
0x0001   /* downstream I/O */
+ 0x8200 0x0 0x4000 0x40 0x4000 0x0 
0x4000>; /* non-prefetchable memory */
+   msi-parent = <>;
+   #interrupt-cells = <1>;
+   interrupt-map-mask = <0 0 0 7>;
+   interrupt-map = < 0 0 1  0 110 
IRQ_TYPE_LEVEL_HIGH>,
+   < 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>;
+   };
};
 };
-- 
2.14.1



[PATCH 2/2] pci/layerscape: change the default error response behavior

2017-09-22 Thread Zhiqiang Hou
From: Minghuan Lian 

By default, when the PCIe controller experiences an erroneous
completion from an external completer for its outbound non-posted
request, it always sends an OKAY response to the device's internal
AXI slave system interface. However, such default system error
response behavior cannot be used for other types of outbound
non-posted requests. For example, the outbound memory read
transaction requires an actual ERROR response, like UR completion
or completion timeout. The patch is to fix it by forwarding
the error response of the non-posted request.

Signed-off-by: Minghuan Lian 
Signed-off-by: Hou Zhiqiang 
---
 drivers/pci/dwc/pci-layerscape.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/drivers/pci/dwc/pci-layerscape.c b/drivers/pci/dwc/pci-layerscape.c
index 3b01e309a55e..a647090c140e 100644
--- a/drivers/pci/dwc/pci-layerscape.c
+++ b/drivers/pci/dwc/pci-layerscape.c
@@ -33,6 +33,8 @@
 
 /* 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
 
@@ -54,6 +56,19 @@ struct ls_pcie {
 
 #define to_ls_pcie(x)  dev_get_drvdata((x)->dev)
 
+static int err_response_flag = 1;
+
+static int __init ls_pcie_param(char *p)
+{
+   if (p && strncmp(p, "no-err-response", 15) == 0)
+   err_response_flag = 0;
+   else
+   err_response_flag = 1;
+
+   return 0;
+}
+early_param("ls_pcie", ls_pcie_param);
+
 static bool ls_pcie_is_bridge(struct ls_pcie *pcie)
 {
struct dw_pcie *pci = pcie->pci;
@@ -124,6 +139,14 @@ 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);
@@ -135,6 +158,8 @@ 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);
+   if (err_response_flag)
+   ls_pcie_fix_error_response(pcie);
 
dw_pcie_dbi_ro_wr_en(pci);
ls_pcie_clear_multifunction(pcie);
-- 
2.14.1



[PATCH 0/2] PCI: layerscape: add fixes for layerscape-pcie errata

2017-09-22 Thread Zhiqiang Hou
From: Hou Zhiqiang 

The [1/2] is to fix layerscape PCIe MSI/MSI-X capability errata.
The [2/2] is to change the default AXI system error response behavior
for PCI Express outbound non-posted requests.

Hou Zhiqiang (1):
  PCI: Disable MSI for Freescale PCIe RC mode

Minghuan Lian (1):
  pci/layerscape: change the default error response behavior

 drivers/pci/dwc/pci-layerscape.c | 25 +
 drivers/pci/quirks.c |  8 
 2 files changed, 33 insertions(+)

-- 
2.14.1



[PATCH 1/2] PCI: Disable MSI for Freescale PCIe RC mode

2017-09-22 Thread Zhiqiang Hou
From: Hou Zhiqiang 

The Freescale PCIe controller advertises the MSI/MSI-X capability
in both RC and Endpoint mode, but in RC mode it doesn't support
MSI/MSI-X by it self, it can only transfer MSI/MSI-X from downstream
devices. So add this quirk to prevent use of MSI/MSI-X in RC mode.

Signed-off-by: Hou Zhiqiang 
---
 drivers/pci/quirks.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index a4d33619a7bb..c1063a420f0c 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -4799,3 +4799,11 @@ static void quirk_no_ats(struct pci_dev *pdev)
 /* AMD Stoney platform GPU */
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x98e4, quirk_no_ats);
 #endif /* CONFIG_PCI_ATS */
+
+/* Freescale PCIe doesn't support MSI in RC mode */
+static void quirk_fsl_no_msi(struct pci_dev *pdev)
+{
+   if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT)
+   pdev->no_msi = 1;
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, quirk_fsl_no_msi);
-- 
2.14.1



[PATCHv2 2/2] pci/layerscape: change the default error response behavior

2017-10-12 Thread Zhiqiang Hou
From: Minghuan Lian 

By default, when the PCIe controller experiences an erroneous
completion from an external completer for its outbound non-posted
request, it always sends an OKAY response to the device's internal
AXI slave system interface. However, such default system error
response behavior cannot be used for other types of outbound
non-posted requests. For example, the outbound memory read
transaction requires an actual ERROR response, like UR completion
or completion timeout. The patch is to fix it by forwarding
the error response of the non-posted request.

Signed-off-by: Minghuan Lian 
Signed-off-by: Hou Zhiqiang 
---
V2:
 - Removed the parameter ls_pcie which is for debugging.

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

diff --git a/drivers/pci/dwc/pci-layerscape.c b/drivers/pci/dwc/pci-layerscape.c
index 87fa486bee2c..3a4277a5ab2c 100644
--- a/drivers/pci/dwc/pci-layerscape.c
+++ b/drivers/pci/dwc/pci-layerscape.c
@@ -33,6 +33,8 @@
 
 /* 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
 
@@ -124,6 +126,14 @@ 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);
@@ -135,6 +145,7 @@ 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.14.1



[PATCHv2 1/2] PCI: Disable MSI for Freescale PCIe RC mode

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

The Freescale PCIe controller advertises the MSI/MSI-X capability
in both RC and Endpoint mode, but in RC mode it doesn't support
MSI/MSI-X by itself, it can only transfer MSI/MSI-X from downstream
devices. So add this quirk to prevent use of MSI/MSI-X in RC mode.

Signed-off-by: Hou Zhiqiang 
Acked-by: Minghuan Lian 
---
V2:
 - Fixed a typo in the commit message.

 drivers/pci/quirks.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index a4d33619a7bb..c1063a420f0c 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -4799,3 +4799,11 @@ static void quirk_no_ats(struct pci_dev *pdev)
 /* AMD Stoney platform GPU */
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x98e4, quirk_no_ats);
 #endif /* CONFIG_PCI_ATS */
+
+/* Freescale PCIe doesn't support MSI in RC mode */
+static void quirk_fsl_no_msi(struct pci_dev *pdev)
+{
+   if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT)
+   pdev->no_msi = 1;
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, quirk_fsl_no_msi);
-- 
2.14.1



[PATCHv2 0/2] PCI: layerscape: add fixes for layerscape-pcie errata

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

The [1/2] is to fix layerscape PCIe MSI/MSI-X capability errata.
The [2/2] is to change the default AXI system error response behavior
for PCI Express outbound non-posted requests.

Hou Zhiqiang (1):
  PCI: Disable MSI for Freescale PCIe RC mode

Minghuan Lian (1):
  pci/layerscape: change the default error response behavior

 drivers/pci/dwc/pci-layerscape.c | 11 +++
 drivers/pci/quirks.c |  8 
 2 files changed, 19 insertions(+)

-- 
2.14.1



[PATCHv2 0/3] arm64: dts: ls1012a: add the DTS node for DSPI support

2017-08-30 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Corrected the subject for 3/5 patch v1.

Yuan Yao (3):
  arm64: dts: ls1012a: add the DTS node for DSPI support
  Documentation: fsl: dspi: Add fsl,ls1012a-dspi compatible string
  Documentation: dt: mtd: add sst25wf040b and en25s64 to the SPI NOR
support list

 .../devicetree/bindings/mtd/jedec,spi-nor.txt  |  2 ++
 .../devicetree/bindings/spi/spi-fsl-dspi.txt   |  1 +
 arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts  | 33 ++
 arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi | 13 +
 4 files changed, 49 insertions(+)

-- 
2.14.1



[PATCHv2 2/3] Documentation: fsl: dspi: Add fsl,ls1012a-dspi compatible string

2017-08-30 Thread Zhiqiang Hou
From: Yuan Yao 

new compatible string: "fsl,ls1012a-dspi".

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

 Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt 
b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
index ff5893d275a2..800c483b0076 100644
--- a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
+++ b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
@@ -5,6 +5,7 @@ Required properties:
"fsl,ls2085a-dspi"
or
"fsl,ls2080a-dspi" followed by "fsl,ls2085a-dspi"
+   "fsl,ls1012a-dspi" followed by "fsl,ls1021a-v1.0-dspi"
 - reg : Offset and length of the register set for the device
 - interrupts : Should contain SPI controller interrupt
 - clocks: from common clock binding: handle to dspi clock.
-- 
2.14.1



[PATCHv2 1/3] arm64: dts: ls1012a: add the DTS node for DSPI support

2017-08-30 Thread Zhiqiang Hou
From: Yuan Yao 

Signed-off-by: Yuan Yao 
Signed-off-by: Hou Zhiqiang 
---
V2:
 - No change

 arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts | 33 +++
 arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi| 13 +
 2 files changed, 46 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts 
b/arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts
index 8c013b54db14..cdc4aee75227 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts
@@ -93,6 +93,39 @@
};
 };
 
+ {
+   bus-num = <0>;
+   status = "okay";
+
+   flash@0 {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   compatible = "n25q128a11", "jedec,spi-nor";
+   reg = <0>;
+   spi-max-frequency = <1000>;
+   };
+
+   flash@1 {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   compatible = "sst25wf040b", "jedec,spi-nor";
+   spi-cpol;
+   spi-cpha;
+   reg = <1>;
+   spi-max-frequency = <1000>;
+   };
+
+   flash@2 {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   compatible = "en25s64", "jedec,spi-nor";
+   spi-cpol;
+   spi-cpha;
+   reg = <2>;
+   spi-max-frequency = <1000>;
+   };
+};
+
  {
status = "okay";
 };
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
index df83915d6ea6..09ce00022728 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
@@ -355,6 +355,19 @@
status = "disabled";
};
 
+   dspi: dspi@210 {
+   compatible = "fsl,ls1012a-dspi", 
"fsl,ls1021a-v1.0-dspi";
+   #address-cells = <1>;
+   #size-cells = <0>;
+   reg = <0x0 0x210 0x0 0x1>;
+   interrupts = <0 64 IRQ_TYPE_LEVEL_HIGH>;
+   clock-names = "dspi";
+   clocks = < 4 0>;
+   spi-num-chipselects = <5>;
+   big-endian;
+   status = "disabled";
+   };
+
duart0: serial@21c0500 {
compatible = "fsl,ns16550", "ns16550a";
reg = <0x00 0x21c0500 0x0 0x100>;
-- 
2.14.1



[PATCHv2 3/3] Documentation: dt: mtd: add sst25wf040b and en25s64 to the SPI NOR support list

2017-08-30 Thread Zhiqiang Hou
From: Yuan Yao 

The chip sst25wf040b and en25s64 are compatible with SPI NOR flash.

Signed-off-by: Yuan Yao 
Signed-off-by: Hou Zhiqiang 
Acked-by: Rob Herring 
---
V2:
 - Corrected the subject.

 Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt 
b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt
index 9ce35af8507c..4cab5d85cf6f 100644
--- a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt
+++ b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt
@@ -13,6 +13,7 @@ Required properties:
  at25df321a
  at25df641
  at26df081a
+ en25s64
  mr25h256
  mr25h10
  mr25h40
@@ -31,6 +32,7 @@ Required properties:
  s25fl008k
  s25fl064k
  sst25vf040b
+ sst25wf040b
  m25p40
  m25p80
  m25p16
-- 
2.14.1



[PATCH 1/2] mtd: spi-nor: add a API to restore the addressing mode

2017-11-24 Thread Zhiqiang Hou
From: Hou Zhiqiang 

It's better to restore the addressing mode of the SPI flash
whenever remove the driver or reboot the system.

Signed-off-by: Hou Zhiqiang 
---
 drivers/mtd/spi-nor/spi-nor.c | 8 
 include/linux/mtd/spi-nor.h   | 1 +
 2 files changed, 9 insertions(+)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index bc266f70a15b..801cbe99b059 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -2713,6 +2713,14 @@ static void spi_nor_resume(struct mtd_info *mtd)
dev_err(dev, "resume() failed\n");
 }
 
+void spi_nor_restore_addr_mode(struct spi_nor *nor)
+{
+   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);
+}
+
 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..fe9357da2049 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -398,5 +398,6 @@ struct spi_nor_hwcaps {
  */
 int spi_nor_scan(struct spi_nor *nor, const char *name,
 const struct spi_nor_hwcaps *hwcaps);
+void spi_nor_restore_addr_mode(struct spi_nor *nor);
 
 #endif
-- 
2.14.1



[PATCH 0/2] mtd: m25p80: restore the addressing mode when stop using the flash

2017-11-24 Thread Zhiqiang Hou
From: Hou Zhiqiang 

To be compatible with legacy device, reset the addressing mode
to the default mode. Such as Freescale eSPI boot, it copies the
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 a API to restore the addressing mode
  mtd: m25p80: restore the addressing mode when stop using the flash

 drivers/mtd/devices/m25p80.c  | 8 
 drivers/mtd/spi-nor/spi-nor.c | 8 
 include/linux/mtd/spi-nor.h   | 1 +
 3 files changed, 17 insertions(+)

-- 
2.14.1



[PATCH 2/2] mtd: m25p80: restore the addressing mode when stop using the flash

2017-11-24 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Add .shutdown function to restore the addressing mode in reboot
process, and add the same operation to the .remove function.

Signed-off-by: Hou Zhiqiang 
---
 drivers/mtd/devices/m25p80.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index dbe6a1de2bb8..867bd2d5a267 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -307,10 +307,17 @@ static int m25p_remove(struct spi_device *spi)
 {
struct m25p *flash = spi_get_drvdata(spi);
 
+   spi_nor_restore_addr_mode(>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_addr_mode(>spi_nor);
+}
 /*
  * Do NOT add to this array without reading the following:
  *
@@ -386,6 +393,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 0/2] mtd: m25p80: restore the addressing mode when stop using the flash

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

To be compatible with legacy device, reset the addressing mode
to the default mode. Such as Freescale eSPI boot, it copies the
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 stop using it

 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



[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 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



[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 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



[PATCH 0/2] arm64: dts: Add ls1088a DSPI device tree nodes

2017-10-31 Thread Zhiqiang Hou
From: Hou Zhiqiang 

LS1088A reuse LS2085A DSPI driver, this patchset just adds device tree
nodes and adds compatible entry to documentation.

Hou Zhiqiang (2):
  arm64: dts: ls1088a: add DT nodes for DSPI support
  Documentation: fsl: dspi: Add a compatible string for ls1088a DSPI

 .../devicetree/bindings/spi/spi-fsl-dspi.txt   |  1 +
 arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts  | 28 ++
 arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi | 13 ++
 3 files changed, 42 insertions(+)

-- 
2.14.1



[PATCH 2/2] Documentation: fsl: dspi: Add a compatible string for ls1088a DSPI

2017-10-31 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Add a new compatible string "fsl,ls1088a-dspi".

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

diff --git a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt 
b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
index dcc7eaada511..5fc467211cc6 100644
--- a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
+++ b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
@@ -6,6 +6,7 @@ Required properties:
or
"fsl,ls2080a-dspi" followed by "fsl,ls2085a-dspi"
"fsl,ls1012a-dspi" followed by "fsl,ls1021a-v1.0-dspi"
+   "fsl,ls1088a-dspi" followed by "fsl,ls2085a-dspi"
 - reg : Offset and length of the register set for the device
 - interrupts : Should contain SPI controller interrupt
 - clocks: from common clock binding: handle to dspi clock.
-- 
2.14.1



[PATCH 1/2] arm64: dts: ls1088a: add DT nodes for DSPI support

2017-10-31 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Signed-off-by: Hou Zhiqiang 
---
 arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts | 28 +++
 arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi| 13 +++
 2 files changed, 41 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts 
b/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts
index 30128051d0c0..cf5b85b93ae6 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts
@@ -134,6 +134,34 @@
};
 };
 
+ {
+   status = "okay";
+
+   dflash0: n25q128a {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   compatible = "n25q128a11", "jedec,spi-nor";
+   reg = <0>;
+   spi-max-frequency = <300>;
+   };
+
+   dflash1: sst25wf040b {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   compatible = "sst,sst25wf040b", "jedec,spi-nor";
+   reg = <1>;
+   spi-max-frequency = <300>;
+   };
+
+   dflash2: en25s64 {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   compatible = "eon,en25s64", "jedec,spi-nor";
+   reg = <2>;
+   spi-max-frequency = <300>;
+   };
+};
+
  {
status = "okay";
 };
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
index bd80e9a2e67c..f5ed3878abb7 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
@@ -276,6 +276,19 @@
};
};
 
+   dspi: dspi@210 {
+   compatible = "fsl,ls1088a-dspi", "fsl,ls2085a-dspi";
+   #address-cells = <1>;
+   #size-cells = <0>;
+   reg = <0x0 0x210 0x0 0x1>;
+   interrupts = <0 26 0x4>; /* Level high type */
+   clocks = < 4 3>;
+   clock-names = "dspi";
+   spi-num-chipselects = <5>;
+   bus-num = <0>;
+   status = "disabled";
+   };
+
duart0: serial@21c0500 {
compatible = "fsl,ns16550", "ns16550a";
reg = <0x0 0x21c0500 0x0 0x100>;
-- 
2.14.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 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 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 

[PATCHv2 0/3] arm64: dts: ls1012a: add the DTS node for DSPI support

2017-08-30 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Corrected the subject for 3/5 patch v1.

Yuan Yao (3):
  arm64: dts: ls1012a: add the DTS node for DSPI support
  Documentation: fsl: dspi: Add fsl,ls1012a-dspi compatible string
  Documentation: dt: mtd: add sst25wf040b and en25s64 to the SPI NOR
support list

 .../devicetree/bindings/mtd/jedec,spi-nor.txt  |  2 ++
 .../devicetree/bindings/spi/spi-fsl-dspi.txt   |  1 +
 arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts  | 33 ++
 arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi | 13 +
 4 files changed, 49 insertions(+)

-- 
2.14.1



[PATCHv2 2/3] Documentation: fsl: dspi: Add fsl,ls1012a-dspi compatible string

2017-08-30 Thread Zhiqiang Hou
From: Yuan Yao 

new compatible string: "fsl,ls1012a-dspi".

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

 Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt 
b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
index ff5893d275a2..800c483b0076 100644
--- a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
+++ b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
@@ -5,6 +5,7 @@ Required properties:
"fsl,ls2085a-dspi"
or
"fsl,ls2080a-dspi" followed by "fsl,ls2085a-dspi"
+   "fsl,ls1012a-dspi" followed by "fsl,ls1021a-v1.0-dspi"
 - reg : Offset and length of the register set for the device
 - interrupts : Should contain SPI controller interrupt
 - clocks: from common clock binding: handle to dspi clock.
-- 
2.14.1



[PATCHv2 1/3] arm64: dts: ls1012a: add the DTS node for DSPI support

2017-08-30 Thread Zhiqiang Hou
From: Yuan Yao 

Signed-off-by: Yuan Yao 
Signed-off-by: Hou Zhiqiang 
---
V2:
 - No change

 arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts | 33 +++
 arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi| 13 +
 2 files changed, 46 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts 
b/arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts
index 8c013b54db14..cdc4aee75227 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts
@@ -93,6 +93,39 @@
};
 };
 
+ {
+   bus-num = <0>;
+   status = "okay";
+
+   flash@0 {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   compatible = "n25q128a11", "jedec,spi-nor";
+   reg = <0>;
+   spi-max-frequency = <1000>;
+   };
+
+   flash@1 {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   compatible = "sst25wf040b", "jedec,spi-nor";
+   spi-cpol;
+   spi-cpha;
+   reg = <1>;
+   spi-max-frequency = <1000>;
+   };
+
+   flash@2 {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   compatible = "en25s64", "jedec,spi-nor";
+   spi-cpol;
+   spi-cpha;
+   reg = <2>;
+   spi-max-frequency = <1000>;
+   };
+};
+
  {
status = "okay";
 };
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
index df83915d6ea6..09ce00022728 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
@@ -355,6 +355,19 @@
status = "disabled";
};
 
+   dspi: dspi@210 {
+   compatible = "fsl,ls1012a-dspi", 
"fsl,ls1021a-v1.0-dspi";
+   #address-cells = <1>;
+   #size-cells = <0>;
+   reg = <0x0 0x210 0x0 0x1>;
+   interrupts = <0 64 IRQ_TYPE_LEVEL_HIGH>;
+   clock-names = "dspi";
+   clocks = < 4 0>;
+   spi-num-chipselects = <5>;
+   big-endian;
+   status = "disabled";
+   };
+
duart0: serial@21c0500 {
compatible = "fsl,ns16550", "ns16550a";
reg = <0x00 0x21c0500 0x0 0x100>;
-- 
2.14.1



[PATCHv2 3/3] Documentation: dt: mtd: add sst25wf040b and en25s64 to the SPI NOR support list

2017-08-30 Thread Zhiqiang Hou
From: Yuan Yao 

The chip sst25wf040b and en25s64 are compatible with SPI NOR flash.

Signed-off-by: Yuan Yao 
Signed-off-by: Hou Zhiqiang 
Acked-by: Rob Herring 
---
V2:
 - Corrected the subject.

 Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt 
b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt
index 9ce35af8507c..4cab5d85cf6f 100644
--- a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt
+++ b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt
@@ -13,6 +13,7 @@ Required properties:
  at25df321a
  at25df641
  at26df081a
+ en25s64
  mr25h256
  mr25h10
  mr25h40
@@ -31,6 +32,7 @@ Required properties:
  s25fl008k
  s25fl064k
  sst25vf040b
+ sst25wf040b
  m25p40
  m25p80
  m25p16
-- 
2.14.1



[PATCHv2 1/2] PCI: Disable MSI for Freescale PCIe RC mode

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

The Freescale PCIe controller advertises the MSI/MSI-X capability
in both RC and Endpoint mode, but in RC mode it doesn't support
MSI/MSI-X by itself, it can only transfer MSI/MSI-X from downstream
devices. So add this quirk to prevent use of MSI/MSI-X in RC mode.

Signed-off-by: Hou Zhiqiang 
Acked-by: Minghuan Lian 
---
V2:
 - Fixed a typo in the commit message.

 drivers/pci/quirks.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index a4d33619a7bb..c1063a420f0c 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -4799,3 +4799,11 @@ static void quirk_no_ats(struct pci_dev *pdev)
 /* AMD Stoney platform GPU */
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x98e4, quirk_no_ats);
 #endif /* CONFIG_PCI_ATS */
+
+/* Freescale PCIe doesn't support MSI in RC mode */
+static void quirk_fsl_no_msi(struct pci_dev *pdev)
+{
+   if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT)
+   pdev->no_msi = 1;
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, quirk_fsl_no_msi);
-- 
2.14.1



[PATCHv2 0/2] PCI: layerscape: add fixes for layerscape-pcie errata

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

The [1/2] is to fix layerscape PCIe MSI/MSI-X capability errata.
The [2/2] is to change the default AXI system error response behavior
for PCI Express outbound non-posted requests.

Hou Zhiqiang (1):
  PCI: Disable MSI for Freescale PCIe RC mode

Minghuan Lian (1):
  pci/layerscape: change the default error response behavior

 drivers/pci/dwc/pci-layerscape.c | 11 +++
 drivers/pci/quirks.c |  8 
 2 files changed, 19 insertions(+)

-- 
2.14.1



[PATCHv2 2/2] pci/layerscape: change the default error response behavior

2017-10-12 Thread Zhiqiang Hou
From: Minghuan Lian 

By default, when the PCIe controller experiences an erroneous
completion from an external completer for its outbound non-posted
request, it always sends an OKAY response to the device's internal
AXI slave system interface. However, such default system error
response behavior cannot be used for other types of outbound
non-posted requests. For example, the outbound memory read
transaction requires an actual ERROR response, like UR completion
or completion timeout. The patch is to fix it by forwarding
the error response of the non-posted request.

Signed-off-by: Minghuan Lian 
Signed-off-by: Hou Zhiqiang 
---
V2:
 - Removed the parameter ls_pcie which is for debugging.

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

diff --git a/drivers/pci/dwc/pci-layerscape.c b/drivers/pci/dwc/pci-layerscape.c
index 87fa486bee2c..3a4277a5ab2c 100644
--- a/drivers/pci/dwc/pci-layerscape.c
+++ b/drivers/pci/dwc/pci-layerscape.c
@@ -33,6 +33,8 @@
 
 /* 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
 
@@ -124,6 +126,14 @@ 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);
@@ -135,6 +145,7 @@ 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.14.1



[PATCHv2 0/2] mtd: m25p80: restore the addressing mode when stop using the flash

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

To be compatible with legacy device, reset the addressing mode
to the default mode. Such as Freescale eSPI boot, it copies the
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 stop using it

 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



[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 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



[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 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



[PATCH 0/2] arm64: dts: Add ls1088a DSPI device tree nodes

2017-10-31 Thread Zhiqiang Hou
From: Hou Zhiqiang 

LS1088A reuse LS2085A DSPI driver, this patchset just adds device tree
nodes and adds compatible entry to documentation.

Hou Zhiqiang (2):
  arm64: dts: ls1088a: add DT nodes for DSPI support
  Documentation: fsl: dspi: Add a compatible string for ls1088a DSPI

 .../devicetree/bindings/spi/spi-fsl-dspi.txt   |  1 +
 arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts  | 28 ++
 arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi | 13 ++
 3 files changed, 42 insertions(+)

-- 
2.14.1



[PATCH 2/2] Documentation: fsl: dspi: Add a compatible string for ls1088a DSPI

2017-10-31 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Add a new compatible string "fsl,ls1088a-dspi".

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

diff --git a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt 
b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
index dcc7eaada511..5fc467211cc6 100644
--- a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
+++ b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
@@ -6,6 +6,7 @@ Required properties:
or
"fsl,ls2080a-dspi" followed by "fsl,ls2085a-dspi"
"fsl,ls1012a-dspi" followed by "fsl,ls1021a-v1.0-dspi"
+   "fsl,ls1088a-dspi" followed by "fsl,ls2085a-dspi"
 - reg : Offset and length of the register set for the device
 - interrupts : Should contain SPI controller interrupt
 - clocks: from common clock binding: handle to dspi clock.
-- 
2.14.1



[PATCH 1/2] arm64: dts: ls1088a: add DT nodes for DSPI support

2017-10-31 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Signed-off-by: Hou Zhiqiang 
---
 arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts | 28 +++
 arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi| 13 +++
 2 files changed, 41 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts 
b/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts
index 30128051d0c0..cf5b85b93ae6 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts
@@ -134,6 +134,34 @@
};
 };
 
+ {
+   status = "okay";
+
+   dflash0: n25q128a {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   compatible = "n25q128a11", "jedec,spi-nor";
+   reg = <0>;
+   spi-max-frequency = <300>;
+   };
+
+   dflash1: sst25wf040b {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   compatible = "sst,sst25wf040b", "jedec,spi-nor";
+   reg = <1>;
+   spi-max-frequency = <300>;
+   };
+
+   dflash2: en25s64 {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   compatible = "eon,en25s64", "jedec,spi-nor";
+   reg = <2>;
+   spi-max-frequency = <300>;
+   };
+};
+
  {
status = "okay";
 };
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
index bd80e9a2e67c..f5ed3878abb7 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
@@ -276,6 +276,19 @@
};
};
 
+   dspi: dspi@210 {
+   compatible = "fsl,ls1088a-dspi", "fsl,ls2085a-dspi";
+   #address-cells = <1>;
+   #size-cells = <0>;
+   reg = <0x0 0x210 0x0 0x1>;
+   interrupts = <0 26 0x4>; /* Level high type */
+   clocks = < 4 3>;
+   clock-names = "dspi";
+   spi-num-chipselects = <5>;
+   bus-num = <0>;
+   status = "disabled";
+   };
+
duart0: serial@21c0500 {
compatible = "fsl,ns16550", "ns16550a";
reg = <0x0 0x21c0500 0x0 0x100>;
-- 
2.14.1



[PATCH 2/2] pci/layerscape: change the default error response behavior

2017-09-22 Thread Zhiqiang Hou
From: Minghuan Lian 

By default, when the PCIe controller experiences an erroneous
completion from an external completer for its outbound non-posted
request, it always sends an OKAY response to the device's internal
AXI slave system interface. However, such default system error
response behavior cannot be used for other types of outbound
non-posted requests. For example, the outbound memory read
transaction requires an actual ERROR response, like UR completion
or completion timeout. The patch is to fix it by forwarding
the error response of the non-posted request.

Signed-off-by: Minghuan Lian 
Signed-off-by: Hou Zhiqiang 
---
 drivers/pci/dwc/pci-layerscape.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/drivers/pci/dwc/pci-layerscape.c b/drivers/pci/dwc/pci-layerscape.c
index 3b01e309a55e..a647090c140e 100644
--- a/drivers/pci/dwc/pci-layerscape.c
+++ b/drivers/pci/dwc/pci-layerscape.c
@@ -33,6 +33,8 @@
 
 /* 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
 
@@ -54,6 +56,19 @@ struct ls_pcie {
 
 #define to_ls_pcie(x)  dev_get_drvdata((x)->dev)
 
+static int err_response_flag = 1;
+
+static int __init ls_pcie_param(char *p)
+{
+   if (p && strncmp(p, "no-err-response", 15) == 0)
+   err_response_flag = 0;
+   else
+   err_response_flag = 1;
+
+   return 0;
+}
+early_param("ls_pcie", ls_pcie_param);
+
 static bool ls_pcie_is_bridge(struct ls_pcie *pcie)
 {
struct dw_pcie *pci = pcie->pci;
@@ -124,6 +139,14 @@ 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);
@@ -135,6 +158,8 @@ 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);
+   if (err_response_flag)
+   ls_pcie_fix_error_response(pcie);
 
dw_pcie_dbi_ro_wr_en(pci);
ls_pcie_clear_multifunction(pcie);
-- 
2.14.1



[PATCH 0/2] PCI: layerscape: add fixes for layerscape-pcie errata

2017-09-22 Thread Zhiqiang Hou
From: Hou Zhiqiang 

The [1/2] is to fix layerscape PCIe MSI/MSI-X capability errata.
The [2/2] is to change the default AXI system error response behavior
for PCI Express outbound non-posted requests.

Hou Zhiqiang (1):
  PCI: Disable MSI for Freescale PCIe RC mode

Minghuan Lian (1):
  pci/layerscape: change the default error response behavior

 drivers/pci/dwc/pci-layerscape.c | 25 +
 drivers/pci/quirks.c |  8 
 2 files changed, 33 insertions(+)

-- 
2.14.1



[PATCH 1/2] PCI: Disable MSI for Freescale PCIe RC mode

2017-09-22 Thread Zhiqiang Hou
From: Hou Zhiqiang 

The Freescale PCIe controller advertises the MSI/MSI-X capability
in both RC and Endpoint mode, but in RC mode it doesn't support
MSI/MSI-X by it self, it can only transfer MSI/MSI-X from downstream
devices. So add this quirk to prevent use of MSI/MSI-X in RC mode.

Signed-off-by: Hou Zhiqiang 
---
 drivers/pci/quirks.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index a4d33619a7bb..c1063a420f0c 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -4799,3 +4799,11 @@ static void quirk_no_ats(struct pci_dev *pdev)
 /* AMD Stoney platform GPU */
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x98e4, quirk_no_ats);
 #endif /* CONFIG_PCI_ATS */
+
+/* Freescale PCIe doesn't support MSI in RC mode */
+static void quirk_fsl_no_msi(struct pci_dev *pdev)
+{
+   if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT)
+   pdev->no_msi = 1;
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, quirk_fsl_no_msi);
-- 
2.14.1



[PATCH 0/5] arm64: add ls1012a and ls1046a pcie support

2017-09-19 Thread Zhiqiang Hou
From: Hou Zhiqiang 

This patch set adds ls1012a MSI and PCIe support, including driver
and device tree nodes. The ls1046a's MSI support patch and PCIe
driver patch has been applied, so only adds the PCIe device tree
nodes.

Hou Zhiqiang (5):
  irqchip/ls-scfg-msi: add LS1012a MSI support
  arm64: dts: ls1012a: Add MSI controller DT node
  PCI: layerscape: Add support for ls1012a
  arm64: dts: ls1012a: Add PCIe controller DT node
  arm64: dts: ls1046a: add PCIe controller DT nodes

 .../interrupt-controller/fsl,ls-scfg-msi.txt   |  1 +
 .../devicetree/bindings/pci/layerscape-pci.txt |  1 +
 arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi | 31 +
 arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 75 ++
 drivers/irqchip/irq-ls-scfg-msi.c  |  1 +
 drivers/pci/dwc/pci-layerscape.c   |  1 +
 6 files changed, 110 insertions(+)

-- 
2.14.1



[PATCH 3/5] PCI: layerscape: Add support for ls1012a

2017-09-19 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Signed-off-by: Hou Zhiqiang 
---
 Documentation/devicetree/bindings/pci/layerscape-pci.txt | 1 +
 drivers/pci/dwc/pci-layerscape.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/pci/layerscape-pci.txt 
b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
index c0484da0f20d..66df1e81e0b8 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,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
   entry for each entry in the interrupt-names property.
diff --git a/drivers/pci/dwc/pci-layerscape.c b/drivers/pci/dwc/pci-layerscape.c
index 87fa486bee2c..3b01e309a55e 100644
--- a/drivers/pci/dwc/pci-layerscape.c
+++ b/drivers/pci/dwc/pci-layerscape.c
@@ -253,6 +253,7 @@ static struct ls_pcie_drvdata ls2088_drvdata = {
 };
 
 static const struct of_device_id ls_pcie_of_match[] = {
+   { .compatible = "fsl,ls1012a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls1021a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls1043a-pcie", .data = _drvdata },
{ .compatible = "fsl,ls1046a-pcie", .data = _drvdata },
-- 
2.14.1



[PATCH 5/5] arm64: dts: ls1046a: add PCIe controller DT nodes

2017-09-19 Thread Zhiqiang Hou
From: Hou Zhiqiang 

LS1046a implements 3 PCIe 3.0 controllers.

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

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
index c8ff0baddf1d..eac8c32f64b0 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
@@ -661,6 +661,81 @@
 ;
};
 
+   pcie@340 {
+   compatible = "fsl,ls1046a-pcie", "snps,dw-pcie";
+   reg = <0x00 0x0340 0x0 0x0010   /* controller 
registers */
+  0x40 0x 0x0 0x2000>; /* 
configuration space */
+   reg-names = "regs", "config";
+   interrupts = , /* 
controller interrupt */
+; /* PME 
interrupt */
+   interrupt-names = "aer", "pme";
+   #address-cells = <3>;
+   #size-cells = <2>;
+   device_type = "pci";
+   dma-coherent;
+   num-lanes = <4>;
+   bus-range = <0x0 0xff>;
+   ranges = <0x8100 0x0 0x 0x40 0x0001 0x0 
0x0001   /* downstream I/O */
+ 0x8200 0x0 0x4000 0x40 0x4000 0x0 
0x4000>; /* non-prefetchable memory */
+   msi-parent = <>, <>, <>;
+   #interrupt-cells = <1>;
+   interrupt-map-mask = <0 0 0 7>;
+   interrupt-map = < 0 0 1  GIC_SPI 110 
IRQ_TYPE_LEVEL_HIGH>,
+   < 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>;
+   };
+
+   pcie@350 {
+   compatible = "fsl,ls1046a-pcie", "snps,dw-pcie";
+   reg = <0x00 0x0350 0x0 0x0010   /* controller 
registers */
+  0x48 0x 0x0 0x2000>; /* 
configuration space */
+   reg-names = "regs", "config";
+   interrupts = , /* 
controller interrupt */
+; /* PME 
interrupt */
+   interrupt-names = "aer", "pme";
+   #address-cells = <3>;
+   #size-cells = <2>;
+   device_type = "pci";
+   dma-coherent;
+   num-lanes = <2>;
+   bus-range = <0x0 0xff>;
+   ranges = <0x8100 0x0 0x 0x48 0x0001 0x0 
0x0001   /* downstream I/O */
+ 0x8200 0x0 0x4000 0x48 0x4000 0x0 
0x4000>; /* non-prefetchable memory */
+   msi-parent = <>, <>, <>;
+   #interrupt-cells = <1>;
+   interrupt-map-mask = <0 0 0 7>;
+   interrupt-map = < 0 0 1  GIC_SPI 120 
IRQ_TYPE_LEVEL_HIGH>,
+   < 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>;
+   };
+
+   pcie@360 {
+   compatible = "fsl,ls1046a-pcie", "snps,dw-pcie";
+   reg = <0x00 0x0360 0x0 0x0010   /* controller 
registers */
+  0x50 0x 0x0 0x2000>; /* 
configuration space */
+   reg-names = "regs", "config";
+   interrupts = , /* 
controller interrupt */
+; /* PME 
interrupt */
+   interrupt-names = "aer", "pme";
+   #address-cells = <3>;
+   #size-cells = <2>;
+   device_type = "pci";
+   dma-coherent;
+   num-lanes = <2>;
+   bus-range = <0x0 0xff>;
+   ranges = <0x8100 0x0 0x 0x50 0x0001 0x0 
0x0001   /* downstream I/O */
+ 0x8200 0x0 0x4000 0x50 0x4000 0x0 
0x4000>; /* non-prefetchable memory */
+   msi-parent = <>, <>, <>;
+   #interrupt-cells = <1>;
+   interrupt-map-mask = <0 0 0 7>;
+   interrupt-map = < 0 0 1  GIC_SPI 154 
IRQ_TYPE_LEVEL_HIGH>,
+   < 0 0 2  GIC_SPI 154 

[PATCH 2/5] arm64: dts: ls1012a: Add MSI controller DT node

2017-09-19 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Add MSI controller node for ls1012a platform.

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

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
index df83915d6ea6..a7698ac7264b 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
@@ -471,5 +471,12 @@
dr_mode = "host";
phy_type = "ulpi";
};
+
+   msi: msi-controller1@1572000 {
+   compatible = "fsl,ls1012a-msi";
+   reg = <0x0 0x1572000 0x0 0x8>;
+   msi-controller;
+   interrupts = <0 126 IRQ_TYPE_LEVEL_HIGH>;
+   };
};
 };
-- 
2.14.1



[PATCH 4/5] arm64: dts: ls1012a: Add PCIe controller DT node

2017-09-19 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Add PCIe controller node for ls1012a platform.

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

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
index a7698ac7264b..140570d45ff3 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
@@ -478,5 +478,29 @@
msi-controller;
interrupts = <0 126 IRQ_TYPE_LEVEL_HIGH>;
};
+
+   pcie@340 {
+   compatible = "fsl,ls1012a-pcie", "snps,dw-pcie";
+   reg = <0x00 0x0340 0x0 0x0010   /* controller 
registers */
+  0x40 0x 0x0 0x2000>; /* 
configuration space */
+   reg-names = "regs", "config";
+   interrupts = <0 118 0x4>, /* controller interrupt */
+<0 117 0x4>; /* PME interrupt */
+   interrupt-names = "aer", "pme";
+   #address-cells = <3>;
+   #size-cells = <2>;
+   device_type = "pci";
+   num-lanes = <4>;
+   bus-range = <0x0 0xff>;
+   ranges = <0x8100 0x0 0x 0x40 0x0001 0x0 
0x0001   /* downstream I/O */
+ 0x8200 0x0 0x4000 0x40 0x4000 0x0 
0x4000>; /* non-prefetchable memory */
+   msi-parent = <>;
+   #interrupt-cells = <1>;
+   interrupt-map-mask = <0 0 0 7>;
+   interrupt-map = < 0 0 1  0 110 
IRQ_TYPE_LEVEL_HIGH>,
+   < 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>;
+   };
};
 };
-- 
2.14.1



[PATCH 1/5] irqchip/ls-scfg-msi: add LS1012a MSI support

2017-09-19 Thread Zhiqiang Hou
From: Hou Zhiqiang 

The ls1012a implement only 1 msi controller, and it is the same as
ls1043a.

Signed-off-by: Hou Zhiqiang 
---
 .../devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt | 1 +
 drivers/irqchip/irq-ls-scfg-msi.c| 1 +
 2 files changed, 2 insertions(+)

diff --git 
a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt 
b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
index 49ccabbfa6f3..a4ff93d6b7f3 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
@@ -8,6 +8,7 @@ Required properties:
   "fsl,ls1043a-msi"
   "fsl,ls1046a-msi"
   "fsl,ls1043a-v1.1-msi"
+  "fsl,ls1012a-msi"
 - msi-controller: indicates that this is a PCIe MSI controller node
 - reg: physical base address of the controller and length of memory mapped.
 - interrupts: an interrupt to the parent interrupt controller.
diff --git a/drivers/irqchip/irq-ls-scfg-msi.c 
b/drivers/irqchip/irq-ls-scfg-msi.c
index 119f4ef0d421..57e3d900f19e 100644
--- a/drivers/irqchip/irq-ls-scfg-msi.c
+++ b/drivers/irqchip/irq-ls-scfg-msi.c
@@ -316,6 +316,7 @@ static const struct of_device_id ls_scfg_msi_id[] = {
{ .compatible = "fsl,1s1021a-msi", .data = _msi_cfg},
{ .compatible = "fsl,1s1043a-msi", .data = _msi_cfg},
 
+   { .compatible = "fsl,ls1012a-msi", .data = _msi_cfg },
{ .compatible = "fsl,ls1021a-msi", .data = _msi_cfg },
{ .compatible = "fsl,ls1043a-msi", .data = _msi_cfg },
{ .compatible = "fsl,ls1043a-v1.1-msi", .data = _v1_1_msi_cfg },
-- 
2.14.1



[PATCHv4 3/9] arm64: dts: ls1043a: fix typo of MSI compatible string

2017-07-05 Thread Zhiqiang Hou
From: Minghuan Lian 

"1" should be replaced by "l". This is a typo.
The patch is to fix it.

Signed-off-by: Minghuan Lian 
Signed-off-by: Hou Zhiqiang 
---
v4-v1:
 - None

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

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index 31fd77f..7ff98f4 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -653,21 +653,21 @@
};
 
msi1: msi-controller1@1571000 {
-   compatible = "fsl,1s1043a-msi";
+   compatible = "fsl,ls1043a-msi";
reg = <0x0 0x1571000 0x0 0x8>;
msi-controller;
interrupts = <0 116 0x4>;
};
 
msi2: msi-controller2@1572000 {
-   compatible = "fsl,1s1043a-msi";
+   compatible = "fsl,ls1043a-msi";
reg = <0x0 0x1572000 0x0 0x8>;
msi-controller;
interrupts = <0 126 0x4>;
};
 
msi3: msi-controller3@1573000 {
-   compatible = "fsl,1s1043a-msi";
+   compatible = "fsl,ls1043a-msi";
reg = <0x0 0x1573000 0x0 0x8>;
msi-controller;
interrupts = <0 160 0x4>;
-- 
2.1.0.27.g96db324



[PATCHv4 7/9] irqchip/ls-scfg-msi: add LS1046a MSI support

2017-07-05 Thread Zhiqiang Hou
From: Minghuan Lian 

LS1046a includes 4 MSIRs, each MSIR is assigned a dedicate GIC
SPI interrupt and provides 32 MSI interrupts. Compared to previous
MSI, LS1046a's IBS(interrupt bit select) shift is changed to 2 and
total MSI interrupt number is changed to 128.

The patch adds structure 'ls_scfg_msir' to describe MSIR setting and
'ibs_shift' to store the different value between the SoCs.

Signed-off-by: Minghuan Lian 
Signed-off-by: Hou Zhiqiang 
---
v4:
 - None
v3-v2:
 - keep the old misspelled compatible strings
v2-v1:
 - MSI dts node change has been merged into the patch 6/9

 drivers/irqchip/irq-ls-scfg-msi.c | 165 ++
 1 file changed, 130 insertions(+), 35 deletions(-)

diff --git a/drivers/irqchip/irq-ls-scfg-msi.c 
b/drivers/irqchip/irq-ls-scfg-msi.c
index cef67cc..0b1f34d 100644
--- a/drivers/irqchip/irq-ls-scfg-msi.c
+++ b/drivers/irqchip/irq-ls-scfg-msi.c
@@ -17,13 +17,24 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 
-#define MSI_MAX_IRQS   32
-#define MSI_IBS_SHIFT  3
-#define MSIR   4
+#define MSI_IRQS_PER_MSIR  32
+#define MSI_MSIR_OFFSET4
+
+struct ls_scfg_msi_cfg {
+   u32 ibs_shift; /* Shift of interrupt bit select */
+};
+
+struct ls_scfg_msir {
+   struct ls_scfg_msi *msi_data;
+   unsigned int index;
+   unsigned int gic_irq;
+   void __iomem *reg;
+};
 
 struct ls_scfg_msi {
spinlock_t  lock;
@@ -32,8 +43,11 @@ struct ls_scfg_msi {
struct irq_domain   *msi_domain;
void __iomem*regs;
phys_addr_t msiir_addr;
-   int irq;
-   DECLARE_BITMAP(used, MSI_MAX_IRQS);
+   struct ls_scfg_msi_cfg  *cfg;
+   u32 msir_num;
+   struct ls_scfg_msir *msir;
+   u32 irqs_num;
+   unsigned long   *used;
 };
 
 static struct irq_chip ls_scfg_msi_irq_chip = {
@@ -55,7 +69,7 @@ static void ls_scfg_msi_compose_msg(struct irq_data *data, 
struct msi_msg *msg)
 
msg->address_hi = upper_32_bits(msi_data->msiir_addr);
msg->address_lo = lower_32_bits(msi_data->msiir_addr);
-   msg->data = data->hwirq << MSI_IBS_SHIFT;
+   msg->data = data->hwirq;
 }
 
 static int ls_scfg_msi_set_affinity(struct irq_data *irq_data,
@@ -81,8 +95,8 @@ static int ls_scfg_msi_domain_irq_alloc(struct irq_domain 
*domain,
WARN_ON(nr_irqs != 1);
 
spin_lock(_data->lock);
-   pos = find_first_zero_bit(msi_data->used, MSI_MAX_IRQS);
-   if (pos < MSI_MAX_IRQS)
+   pos = find_first_zero_bit(msi_data->used, msi_data->irqs_num);
+   if (pos < msi_data->irqs_num)
__set_bit(pos, msi_data->used);
else
err = -ENOSPC;
@@ -106,7 +120,7 @@ static void ls_scfg_msi_domain_irq_free(struct irq_domain 
*domain,
int pos;
 
pos = d->hwirq;
-   if (pos < 0 || pos >= MSI_MAX_IRQS) {
+   if (pos < 0 || pos >= msi_data->irqs_num) {
pr_err("failed to teardown msi. Invalid hwirq %d\n", pos);
return;
}
@@ -123,15 +137,17 @@ static const struct irq_domain_ops ls_scfg_msi_domain_ops 
= {
 
 static void ls_scfg_msi_irq_handler(struct irq_desc *desc)
 {
-   struct ls_scfg_msi *msi_data = irq_desc_get_handler_data(desc);
+   struct ls_scfg_msir *msir = irq_desc_get_handler_data(desc);
+   struct ls_scfg_msi *msi_data = msir->msi_data;
unsigned long val;
-   int pos, virq;
+   int pos, virq, hwirq;
 
chained_irq_enter(irq_desc_get_chip(desc), desc);
 
-   val = ioread32be(msi_data->regs + MSIR);
-   for_each_set_bit(pos, , MSI_MAX_IRQS) {
-   virq = irq_find_mapping(msi_data->parent, (31 - pos));
+   val = ioread32be(msir->reg);
+   for_each_set_bit(pos, , MSI_IRQS_PER_MSIR) {
+   hwirq = ((31 - pos) << msi_data->cfg->ibs_shift) | msir->index;
+   virq = irq_find_mapping(msi_data->parent, hwirq);
if (virq)
generic_handle_irq(virq);
}
@@ -143,7 +159,7 @@ static int ls_scfg_msi_domains_init(struct ls_scfg_msi 
*msi_data)
 {
/* Initialize MSI domain parent */
msi_data->parent = irq_domain_add_linear(NULL,
-MSI_MAX_IRQS,
+msi_data->irqs_num,
 _scfg_msi_domain_ops,
 msi_data);
if (!msi_data->parent) {
@@ -164,16 +180,87 @@ static int ls_scfg_msi_domains_init(struct ls_scfg_msi 
*msi_data)
return 0;
 }
 
+static int ls_scfg_msi_setup_hwirq(struct ls_scfg_msi *msi_data, int index)
+{
+   struct ls_scfg_msir *msir;
+   int virq, i, hwirq;
+
+   virq = platform_get_irq(msi_data->pdev, index);
+   if (virq <= 0)
+   return -ENODEV;
+
+   msir = 

[PATCHv4 5/9] arm64: dts: ls1043a: share all MSIs

2017-07-05 Thread Zhiqiang Hou
From: Minghuan Lian 

In order to maximize the use of MSI, a PCIe controller will share
all MSI controllers. The patch changes "msi-parent" to refer to all
MSI controller dts nodes.

Signed-off-by: Minghuan Lian 
Signed-off-by: Hou Zhiqiang 
---
v4-v1:
 - None

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

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index 7ff98f4..d16b9cc 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -689,7 +689,7 @@
bus-range = <0x0 0xff>;
ranges = <0x8100 0x0 0x 0x40 0x0001 0x0 
0x0001   /* downstream I/O */
  0x8200 0x0 0x4000 0x40 0x4000 0x0 
0x4000>; /* non-prefetchable memory */
-   msi-parent = <>;
+   msi-parent = <>, <>, <>;
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = < 0 0 1  0 110 0x4>,
@@ -714,7 +714,7 @@
bus-range = <0x0 0xff>;
ranges = <0x8100 0x0 0x 0x48 0x0001 0x0 
0x0001   /* downstream I/O */
  0x8200 0x0 0x4000 0x48 0x4000 0x0 
0x4000>; /* non-prefetchable memory */
-   msi-parent = <>;
+   msi-parent = <>, <>, <>;
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = < 0 0 1  0 120  0x4>,
@@ -739,7 +739,7 @@
bus-range = <0x0 0xff>;
ranges = <0x8100 0x0 0x 0x50 0x0001 0x0 
0x0001   /* downstream I/O */
  0x8200 0x0 0x4000 0x50 0x4000 0x0 
0x4000>; /* non-prefetchable memory */
-   msi-parent = <>;
+   msi-parent = <>, <>, <>;
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = < 0 0 1  0 154 0x4>,
-- 
2.1.0.27.g96db324



[PATCHv4 2/9] arm: dts: ls1021a: fix typo of MSI compatible string

2017-07-05 Thread Zhiqiang Hou
From: Minghuan Lian 

"1" should be replaced by "l". This is a typo.
The patch is to fix it.

Signed-off-by: Minghuan Lian 
Signed-off-by: Hou Zhiqiang 
---
v4-v1:
 - None

 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 7bb9df2..51b0f69 100644
--- a/arch/arm/boot/dts/ls1021a.dtsi
+++ b/arch/arm/boot/dts/ls1021a.dtsi
@@ -129,14 +129,14 @@
};
 
msi1: msi-controller@1570e00 {
-   compatible = "fsl,1s1021a-msi";
+   compatible = "fsl,ls1021a-msi";
reg = <0x0 0x1570e00 0x0 0x8>;
msi-controller;
interrupts =  ;
};
 
msi2: msi-controller@1570e08 {
-   compatible = "fsl,1s1021a-msi";
+   compatible = "fsl,ls1021a-msi";
reg = <0x0 0x1570e08 0x0 0x8>;
msi-controller;
interrupts = ;
-- 
2.1.0.27.g96db324



[PATCHv4 9/9] irqchip/ls-scfg-msi: add MSI affinity support

2017-07-05 Thread Zhiqiang Hou
From: Minghuan Lian 

For LS1046a and LS1043a v1.1, the MSI controller has 4 MSIRs and 4 GIC
SPI interrupts which can be associated with different Core.
So we can support affinity to improve the performance.
The MSI message data is a byte for Layerscape MSI.
  76   5  4  3  2   1   0
| - |   IBS   |  SRS |
SRS bit0-1 is to select a MSIR which is associated with a CPU.
IBS bit2-6 of ls1046, bit2-4 of ls1043a v1.1 is to select bit of the
MSIR. With affinity, only bits of MSIR0(srs=0 cpu0) are available.
All other bits of the MSIR1-3(cpu1-3) are reserved. The MSI hwirq
always equals bit index of the MSIR0. When changing affinity, MSI
message data will be appended corresponding SRS then MSI will be
moved to the corresponding core.
But in affinity mode, there is only 8 MSI interrupts for a controller
of LS1043a v1.1. It cannot meet the requirement of the some PCIe
devices such as 4 ports Ethernet card. In contrast, without affinity,
all MSIRs can be used for core 0, the MSI interrupts can up to 32.
So the parameter is added to control affinity mode.
"lsmsi=no-affinity" will disable affinity and increase MSI
interrupt number.

Signed-off-by: Minghuan Lian 
Signed-off-by: Hou Zhiqiang 
---
v4:
 - None
v3-v2:
 - 1. update the description
 - 2. remove unnecessary msir_index checking
v2-v1:
 - None


 drivers/irqchip/irq-ls-scfg-msi.c | 68 ---
 1 file changed, 63 insertions(+), 5 deletions(-)

diff --git a/drivers/irqchip/irq-ls-scfg-msi.c 
b/drivers/irqchip/irq-ls-scfg-msi.c
index 8d57a59..119f4ef 100644
--- a/drivers/irqchip/irq-ls-scfg-msi.c
+++ b/drivers/irqchip/irq-ls-scfg-msi.c
@@ -40,6 +40,7 @@ struct ls_scfg_msir {
unsigned int gic_irq;
unsigned int bit_start;
unsigned int bit_end;
+   unsigned int srs; /* Shared interrupt register select */
void __iomem *reg;
 };
 
@@ -70,6 +71,19 @@ static struct msi_domain_info ls_scfg_msi_domain_info = {
.chip   = _scfg_msi_irq_chip,
 };
 
+static int msi_affinity_flag = 1;
+
+static int __init early_parse_ls_scfg_msi(char *p)
+{
+   if (p && strncmp(p, "no-affinity", 11) == 0)
+   msi_affinity_flag = 0;
+   else
+   msi_affinity_flag = 1;
+
+   return 0;
+}
+early_param("lsmsi", early_parse_ls_scfg_msi);
+
 static void ls_scfg_msi_compose_msg(struct irq_data *data, struct msi_msg *msg)
 {
struct ls_scfg_msi *msi_data = irq_data_get_irq_chip_data(data);
@@ -77,12 +91,36 @@ static void ls_scfg_msi_compose_msg(struct irq_data *data, 
struct msi_msg *msg)
msg->address_hi = upper_32_bits(msi_data->msiir_addr);
msg->address_lo = lower_32_bits(msi_data->msiir_addr);
msg->data = data->hwirq;
+
+   if (msi_affinity_flag)
+   msg->data |= cpumask_first(data->common->affinity);
 }
 
 static int ls_scfg_msi_set_affinity(struct irq_data *irq_data,
const struct cpumask *mask, bool force)
 {
-   return -EINVAL;
+   struct ls_scfg_msi *msi_data = irq_data_get_irq_chip_data(irq_data);
+   u32 cpu;
+
+   if (!msi_affinity_flag)
+   return -EINVAL;
+
+   if (!force)
+   cpu = cpumask_any_and(mask, cpu_online_mask);
+   else
+   cpu = cpumask_first(mask);
+
+   if (cpu >= msi_data->msir_num)
+   return -EINVAL;
+
+   if (msi_data->msir[cpu].gic_irq <= 0) {
+   pr_warn("cannot bind the irq to cpu%d\n", cpu);
+   return -EINVAL;
+   }
+
+   cpumask_copy(irq_data->common->affinity, mask);
+
+   return IRQ_SET_MASK_OK;
 }
 
 static struct irq_chip ls_scfg_msi_parent_chip = {
@@ -158,7 +196,7 @@ static void ls_scfg_msi_irq_handler(struct irq_desc *desc)
 
for_each_set_bit_from(pos, , size) {
hwirq = ((msir->bit_end - pos) << msi_data->cfg->ibs_shift) |
-   msir->index;
+   msir->srs;
virq = irq_find_mapping(msi_data->parent, hwirq);
if (virq)
generic_handle_irq(virq);
@@ -221,10 +259,19 @@ static int ls_scfg_msi_setup_hwirq(struct ls_scfg_msi 
*msi_data, int index)
 ls_scfg_msi_irq_handler,
 msir);
 
+   if (msi_affinity_flag) {
+   /* Associate MSIR interrupt to the cpu */
+   irq_set_affinity(msir->gic_irq, get_cpu_mask(index));
+   msir->srs = 0; /* This value is determined by the CPU */
+   } else
+   msir->srs = index;
+
/* Release the hwirqs corresponding to this MSIR */
-   for (i = 0; i < msi_data->cfg->msir_irqs; i++) {
-   hwirq = i << msi_data->cfg->ibs_shift | msir->index;
-   bitmap_clear(msi_data->used, hwirq, 1);
+   if (!msi_affinity_flag || msir->index == 0) {
+   for (i = 0; i < msi_data->cfg->msir_irqs; i++) {
+   hwirq = i << 

[PATCHv4 6/9] arm64: dts: ls1046a: add MSI dts node

2017-07-05 Thread Zhiqiang Hou
From: Minghuan Lian 

LS1046a includes 3 MSI controllers.
Each controller supports 128 interrupts.

Signed-off-by: Minghuan Lian 
Acked-by: Rob Herring 
Signed-off-by: Hou Zhiqiang 
---
v4:
 - rebased code
v3-v2:
 - None
v2-v1:
 - change whitespace number

 .../interrupt-controller/fsl,ls-scfg-msi.txt   |  1 +
 arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 31 ++
 2 files changed, 32 insertions(+)

diff --git 
a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt 
b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
index 2755cd1..dde4552 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
@@ -6,6 +6,7 @@ Required properties:
  Layerscape PCIe MSI controller block such as:
   "fsl,ls1021a-msi"
   "fsl,ls1043a-msi"
+  "fsl,ls1046a-msi"
 - msi-controller: indicates that this is a PCIe MSI controller node
 - reg: physical base address of the controller and length of memory mapped.
 - interrupts: an interrupt to the parent interrupt controller.
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
index dc1640b..c8ff0ba 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
@@ -630,6 +630,37 @@
interrupts = ;
clocks = < 4 1>;
};
+
+   msi1: msi-controller@158 {
+   compatible = "fsl,ls1046a-msi";
+   msi-controller;
+   reg = <0x0 0x158 0x0 0x1>;
+   interrupts = ,
+,
+,
+;
+   };
+
+   msi2: msi-controller@159 {
+   compatible = "fsl,ls1046a-msi";
+   msi-controller;
+   reg = <0x0 0x159 0x0 0x1>;
+   interrupts = ,
+,
+,
+;
+   };
+
+   msi3: msi-controller@15a {
+   compatible = "fsl,ls1046a-msi";
+   msi-controller;
+   reg = <0x0 0x15a 0x0 0x1>;
+   interrupts = ,
+,
+,
+;
+   };
+
};
 
reserved-memory {
-- 
2.1.0.27.g96db324



[PATCHv4 8/9] irqchip/ls-scfg-msi: add LS1043a v1.1 MSI support

2017-07-05 Thread Zhiqiang Hou
From: Minghuan Lian 

A MSI controller of LS1043a v1.0 only includes one MSIR and
is assigned one GIC interrupt. In order to support affinity,
LS1043a v1.1 MSI is assigned 4 MSIRs and 4 GIC interrupts.
But the MSIR has the different offset and only supports 8 MSIs.
The bits between variable bit_start and bit_end in structure
ls_scfg_msir are used to show 8 MSI interrupts. msir_irqs and
msir_base are added to describe the difference of MSI between
LS1043a v1.1 and other SoCs.

Signed-off-by: Minghuan Lian 
Acked-by: Rob Herring 
Signed-off-by: Hou Zhiqiang 
---
v4-v1:
 - None

 .../interrupt-controller/fsl,ls-scfg-msi.txt   |  1 +
 drivers/irqchip/irq-ls-scfg-msi.c  | 45 +++---
 2 files changed, 40 insertions(+), 6 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt 
b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
index dde4552..49ccabb 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
@@ -7,6 +7,7 @@ Required properties:
   "fsl,ls1021a-msi"
   "fsl,ls1043a-msi"
   "fsl,ls1046a-msi"
+  "fsl,ls1043a-v1.1-msi"
 - msi-controller: indicates that this is a PCIe MSI controller node
 - reg: physical base address of the controller and length of memory mapped.
 - interrupts: an interrupt to the parent interrupt controller.
diff --git a/drivers/irqchip/irq-ls-scfg-msi.c 
b/drivers/irqchip/irq-ls-scfg-msi.c
index 0b1f34d..8d57a59 100644
--- a/drivers/irqchip/irq-ls-scfg-msi.c
+++ b/drivers/irqchip/irq-ls-scfg-msi.c
@@ -25,14 +25,21 @@
 #define MSI_IRQS_PER_MSIR  32
 #define MSI_MSIR_OFFSET4
 
+#define MSI_LS1043V1_1_IRQS_PER_MSIR   8
+#define MSI_LS1043V1_1_MSIR_OFFSET 0x10
+
 struct ls_scfg_msi_cfg {
u32 ibs_shift; /* Shift of interrupt bit select */
+   u32 msir_irqs; /* The irq number per MSIR */
+   u32 msir_base; /* The base address of MSIR */
 };
 
 struct ls_scfg_msir {
struct ls_scfg_msi *msi_data;
unsigned int index;
unsigned int gic_irq;
+   unsigned int bit_start;
+   unsigned int bit_end;
void __iomem *reg;
 };
 
@@ -140,13 +147,18 @@ static void ls_scfg_msi_irq_handler(struct irq_desc *desc)
struct ls_scfg_msir *msir = irq_desc_get_handler_data(desc);
struct ls_scfg_msi *msi_data = msir->msi_data;
unsigned long val;
-   int pos, virq, hwirq;
+   int pos, size, virq, hwirq;
 
chained_irq_enter(irq_desc_get_chip(desc), desc);
 
val = ioread32be(msir->reg);
-   for_each_set_bit(pos, , MSI_IRQS_PER_MSIR) {
-   hwirq = ((31 - pos) << msi_data->cfg->ibs_shift) | msir->index;
+
+   pos = msir->bit_start;
+   size = msir->bit_end + 1;
+
+   for_each_set_bit_from(pos, , size) {
+   hwirq = ((msir->bit_end - pos) << msi_data->cfg->ibs_shift) |
+   msir->index;
virq = irq_find_mapping(msi_data->parent, hwirq);
if (virq)
generic_handle_irq(virq);
@@ -193,14 +205,24 @@ static int ls_scfg_msi_setup_hwirq(struct ls_scfg_msi 
*msi_data, int index)
msir->index = index;
msir->msi_data = msi_data;
msir->gic_irq = virq;
-   msir->reg = msi_data->regs + MSI_MSIR_OFFSET + 4 * index;
+   msir->reg = msi_data->regs + msi_data->cfg->msir_base + 4 * index;
+
+   if (msi_data->cfg->msir_irqs == MSI_LS1043V1_1_IRQS_PER_MSIR) {
+   msir->bit_start = 32 - ((msir->index + 1) *
+ MSI_LS1043V1_1_IRQS_PER_MSIR);
+   msir->bit_end = msir->bit_start +
+   MSI_LS1043V1_1_IRQS_PER_MSIR - 1;
+   } else {
+   msir->bit_start = 0;
+   msir->bit_end = msi_data->cfg->msir_irqs - 1;
+   }
 
irq_set_chained_handler_and_data(msir->gic_irq,
 ls_scfg_msi_irq_handler,
 msir);
 
/* Release the hwirqs corresponding to this MSIR */
-   for (i = 0; i < MSI_IRQS_PER_MSIR; i++) {
+   for (i = 0; i < msi_data->cfg->msir_irqs; i++) {
hwirq = i << msi_data->cfg->ibs_shift | msir->index;
bitmap_clear(msi_data->used, hwirq, 1);
}
@@ -216,7 +238,7 @@ static int ls_scfg_msi_teardown_hwirq(struct ls_scfg_msir 
*msir)
if (msir->gic_irq > 0)
irq_set_chained_handler_and_data(msir->gic_irq, NULL, NULL);
 
-   for (i = 0; i < MSI_IRQS_PER_MSIR; i++) {
+   for (i = 0; i < msi_data->cfg->msir_irqs; i++) {
hwirq = i << msi_data->cfg->ibs_shift | msir->index;
bitmap_set(msi_data->used, hwirq, 1);
}
@@ -226,10 +248,20 @@ static int ls_scfg_msi_teardown_hwirq(struct ls_scfg_msir 
*msir)
 
 static 

[PATCHv4 4/9] arm: dts: ls1021a: share all MSIs

2017-07-05 Thread Zhiqiang Hou
From: Minghuan Lian 

In order to maximize the use of MSI, a PCIe controller will share
all MSI controllers. The patch changes msi-parent to refer to all
MSI controller dts nodes.

Signed-off-by: Minghuan Lian 
Signed-off-by: Hou Zhiqiang 
---
v4-v1:
 - None

 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 51b0f69..9319e1f 100644
--- a/arch/arm/boot/dts/ls1021a.dtsi
+++ b/arch/arm/boot/dts/ls1021a.dtsi
@@ -699,7 +699,7 @@
bus-range = <0x0 0xff>;
ranges = <0x8100 0x0 0x 0x40 0x0001 0x0 
0x0001   /* downstream I/O */
  0x8200 0x0 0x4000 0x40 0x4000 0x0 
0x4000>; /* non-prefetchable memory */
-   msi-parent = <>;
+   msi-parent = <>, <>;
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = < 0 0 1  GIC_SPI 91  
IRQ_TYPE_LEVEL_HIGH>,
@@ -722,7 +722,7 @@
bus-range = <0x0 0xff>;
ranges = <0x8100 0x0 0x 0x48 0x0001 0x0 
0x0001   /* downstream I/O */
  0x8200 0x0 0x4000 0x48 0x4000 0x0 
0x4000>; /* non-prefetchable memory */
-   msi-parent = <>;
+   msi-parent = <>, <>;
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = < 0 0 1  GIC_SPI 92  
IRQ_TYPE_LEVEL_HIGH>,
-- 
2.1.0.27.g96db324



[PATCHv4 1/9] irqchip/ls-scfg-msi: fix typo of MSI compatible strings

2017-07-05 Thread Zhiqiang Hou
From: Minghuan Lian 

The patch is to fix typo of the Layerscape SCFG MSI dts compatible
strings. "1" is replaced by "l".

Signed-off-by: Minghuan Lian 
Acked-by: Rob Herring 
Signed-off-by: Hou Zhiqiang 
---
v4-v1:
 - None

 .../devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt| 6 +++---
 drivers/irqchip/irq-ls-scfg-msi.c   | 6 --
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt 
b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
index 9e38949..2755cd1 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
@@ -4,8 +4,8 @@ Required properties:
 
 - compatible: should be "fsl,-msi" to identify
  Layerscape PCIe MSI controller block such as:
-  "fsl,1s1021a-msi"
-  "fsl,1s1043a-msi"
+  "fsl,ls1021a-msi"
+  "fsl,ls1043a-msi"
 - msi-controller: indicates that this is a PCIe MSI controller node
 - reg: physical base address of the controller and length of memory mapped.
 - interrupts: an interrupt to the parent interrupt controller.
@@ -23,7 +23,7 @@ MSI controller node
 Examples:
 
msi1: msi-controller@1571000 {
-   compatible = "fsl,1s1043a-msi";
+   compatible = "fsl,ls1043a-msi";
reg = <0x0 0x1571000 0x0 0x8>,
msi-controller;
interrupts = <0 116 0x4>;
diff --git a/drivers/irqchip/irq-ls-scfg-msi.c 
b/drivers/irqchip/irq-ls-scfg-msi.c
index 02cca74c..cef67cc 100644
--- a/drivers/irqchip/irq-ls-scfg-msi.c
+++ b/drivers/irqchip/irq-ls-scfg-msi.c
@@ -219,8 +219,10 @@ static int ls_scfg_msi_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id ls_scfg_msi_id[] = {
-   { .compatible = "fsl,1s1021a-msi", },
-   { .compatible = "fsl,1s1043a-msi", },
+   { .compatible = "fsl,1s1021a-msi", }, /* a typo */
+   { .compatible = "fsl,1s1043a-msi", }, /* a typo */
+   { .compatible = "fsl,ls1021a-msi", },
+   { .compatible = "fsl,ls1043a-msi", },
{},
 };
 
-- 
2.1.0.27.g96db324



[PATCH 1/2] mtd: spi-nor: add a API to restore the addressing mode

2017-11-24 Thread Zhiqiang Hou
From: Hou Zhiqiang 

It's better to restore the addressing mode of the SPI flash
whenever remove the driver or reboot the system.

Signed-off-by: Hou Zhiqiang 
---
 drivers/mtd/spi-nor/spi-nor.c | 8 
 include/linux/mtd/spi-nor.h   | 1 +
 2 files changed, 9 insertions(+)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index bc266f70a15b..801cbe99b059 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -2713,6 +2713,14 @@ static void spi_nor_resume(struct mtd_info *mtd)
dev_err(dev, "resume() failed\n");
 }
 
+void spi_nor_restore_addr_mode(struct spi_nor *nor)
+{
+   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);
+}
+
 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..fe9357da2049 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -398,5 +398,6 @@ struct spi_nor_hwcaps {
  */
 int spi_nor_scan(struct spi_nor *nor, const char *name,
 const struct spi_nor_hwcaps *hwcaps);
+void spi_nor_restore_addr_mode(struct spi_nor *nor);
 
 #endif
-- 
2.14.1



[PATCH 0/2] mtd: m25p80: restore the addressing mode when stop using the flash

2017-11-24 Thread Zhiqiang Hou
From: Hou Zhiqiang 

To be compatible with legacy device, reset the addressing mode
to the default mode. Such as Freescale eSPI boot, it copies the
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 a API to restore the addressing mode
  mtd: m25p80: restore the addressing mode when stop using the flash

 drivers/mtd/devices/m25p80.c  | 8 
 drivers/mtd/spi-nor/spi-nor.c | 8 
 include/linux/mtd/spi-nor.h   | 1 +
 3 files changed, 17 insertions(+)

-- 
2.14.1



[PATCH 2/2] mtd: m25p80: restore the addressing mode when stop using the flash

2017-11-24 Thread Zhiqiang Hou
From: Hou Zhiqiang 

Add .shutdown function to restore the addressing mode in reboot
process, and add the same operation to the .remove function.

Signed-off-by: Hou Zhiqiang 
---
 drivers/mtd/devices/m25p80.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index dbe6a1de2bb8..867bd2d5a267 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -307,10 +307,17 @@ static int m25p_remove(struct spi_device *spi)
 {
struct m25p *flash = spi_get_drvdata(spi);
 
+   spi_nor_restore_addr_mode(>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_addr_mode(>spi_nor);
+}
 /*
  * Do NOT add to this array without reading the following:
  *
@@ -386,6 +393,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



[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



[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 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 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] 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



[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



[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 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 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 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 

[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



[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



  1   2   >