6171a621f6bf914a84b5fa1279df55dc396069ef
[openwrt/staging/pepe2k.git] /
1 From 7f38d09c9fd7906cea160e198299a7e378f9c796 Mon Sep 17 00:00:00 2001
2 From: Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
3 Date: Tue, 6 Nov 2018 09:44:05 +0800
4 Subject: [PATCH] PCI: mobiveil: ls_pcie_g4: add Workaround for A-011577
5
6 PCIe configuration access to non-existent function triggered
7 SERROR interrupt exception.
8
9 Workaround:
10 Disable error reporting on AXI bus during the Vendor ID read
11 transactions in enumeration.
12
13 This ERRATA is only for LX2160A Rev1.0, and it will be fixed
14 in Rev2.0.
15
16 Signed-off-by: Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
17 ---
18 .../pci/controller/mobiveil/pcie-layerscape-gen4.c | 36 ++++++++++++++++++++++
19 .../pci/controller/mobiveil/pcie-mobiveil-host.c | 17 +++++++++-
20 drivers/pci/controller/mobiveil/pcie-mobiveil.h | 3 ++
21 3 files changed, 55 insertions(+), 1 deletion(-)
22
23 --- a/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
24 +++ b/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
25 @@ -22,8 +22,12 @@
26
27 #include "pcie-mobiveil.h"
28
29 +#define REV_1_0 (0x10)
30 +
31 /* LUT and PF control registers */
32 #define PCIE_LUT_OFF 0x80000
33 +#define PCIE_LUT_GCR (0x28)
34 +#define PCIE_LUT_GCR_RRE (0)
35 #define PCIE_PF_OFF 0xc0000
36 #define PCIE_PF_INT_STAT 0x18
37 #define PF_INT_STAT_PABRST BIT(31)
38 @@ -40,6 +44,7 @@ struct ls_pcie_g4 {
39 struct mobiveil_pcie pci;
40 struct delayed_work dwork;
41 int irq;
42 + u8 rev;
43 };
44
45 static inline u32 ls_pcie_g4_lut_readl(struct ls_pcie_g4 *pcie, u32 off)
46 @@ -75,6 +80,15 @@ static bool ls_pcie_g4_is_bridge(struct
47 return header_type == PCI_HEADER_TYPE_BRIDGE;
48 }
49
50 +static int ls_pcie_g4_host_init(struct mobiveil_pcie *pci)
51 +{
52 + struct ls_pcie_g4 *pcie = to_ls_pcie_g4(pci);
53 +
54 + pcie->rev = csr_readb(pci, PCI_REVISION_ID);
55 +
56 + return 0;
57 +}
58 +
59 static int ls_pcie_g4_link_up(struct mobiveil_pcie *pci)
60 {
61 struct ls_pcie_g4 *pcie = to_ls_pcie_g4(pci);
62 @@ -206,12 +220,34 @@ static void ls_pcie_g4_reset(struct work
63 ls_pcie_g4_enable_interrupt(pcie);
64 }
65
66 +static int ls_pcie_g4_read_other_conf(struct pci_bus *bus, unsigned int devfn,
67 + int where, int size, u32 *val)
68 +{
69 + struct mobiveil_pcie *pci = bus->sysdata;
70 + struct ls_pcie_g4 *pcie = to_ls_pcie_g4(pci);
71 + int ret;
72 +
73 + if (pcie->rev == REV_1_0 && where == PCI_VENDOR_ID)
74 + ls_pcie_g4_lut_writel(pcie, PCIE_LUT_GCR,
75 + 0 << PCIE_LUT_GCR_RRE);
76 +
77 + ret = pci_generic_config_read(bus, devfn, where, size, val);
78 +
79 + if (pcie->rev == REV_1_0 && where == PCI_VENDOR_ID)
80 + ls_pcie_g4_lut_writel(pcie, PCIE_LUT_GCR,
81 + 1 << PCIE_LUT_GCR_RRE);
82 +
83 + return ret;
84 +}
85 +
86 static struct mobiveil_rp_ops ls_pcie_g4_rp_ops = {
87 .interrupt_init = ls_pcie_g4_interrupt_init,
88 + .read_other_conf = ls_pcie_g4_read_other_conf,
89 };
90
91 static const struct mobiveil_pab_ops ls_pcie_g4_pab_ops = {
92 .link_up = ls_pcie_g4_link_up,
93 + .host_init = ls_pcie_g4_host_init,
94 };
95
96 static int __init ls_pcie_g4_probe(struct platform_device *pdev)
97 --- a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
98 +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
99 @@ -77,9 +77,20 @@ static void __iomem *mobiveil_pcie_map_b
100 return pcie->rp.config_axi_slave_base + where;
101 }
102
103 +static int mobiveil_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
104 + int where, int size, u32 *val)
105 +{
106 + struct mobiveil_pcie *pcie = bus->sysdata;
107 + struct root_port *rp = &pcie->rp;
108 +
109 + if (bus->number > rp->root_bus_nr && rp->ops->read_other_conf)
110 + return rp->ops->read_other_conf(bus, devfn, where, size, val);
111 +
112 + return pci_generic_config_read(bus, devfn, where, size, val);
113 +}
114 static struct pci_ops mobiveil_pcie_ops = {
115 .map_bus = mobiveil_pcie_map_bus,
116 - .read = pci_generic_config_read,
117 + .read = mobiveil_pcie_config_read,
118 .write = pci_generic_config_write,
119 };
120
121 @@ -300,6 +311,10 @@ int mobiveil_host_init(struct mobiveil_p
122 value |= (PCI_CLASS_BRIDGE_PCI << 16);
123 csr_writel(pcie, value, PAB_INTP_AXI_PIO_CLASS);
124
125 + /* Platform specific host init */
126 + if (pcie->ops->host_init)
127 + return pcie->ops->host_init(pcie);
128 +
129 return 0;
130 }
131
132 --- a/drivers/pci/controller/mobiveil/pcie-mobiveil.h
133 +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
134 @@ -146,6 +146,8 @@ struct mobiveil_msi { /* MSI informati
135
136 struct mobiveil_rp_ops {
137 int (*interrupt_init)(struct mobiveil_pcie *pcie);
138 + int (*read_other_conf)(struct pci_bus *bus, unsigned int devfn,
139 + int where, int size, u32 *val);
140 };
141
142 struct root_port {
143 @@ -161,6 +163,7 @@ struct root_port {
144
145 struct mobiveil_pab_ops {
146 int (*link_up)(struct mobiveil_pcie *pcie);
147 + int (*host_init)(struct mobiveil_pcie *pcie);
148 };
149
150 struct mobiveil_pcie {