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
6 PCIe configuration access to non-existent function triggered
7 SERROR interrupt exception.
10 Disable error reporting on AXI bus during the Vendor ID read
11 transactions in enumeration.
13 This ERRATA is only for LX2160A Rev1.0, and it will be fixed
16 Signed-off-by: Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
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(-)
23 --- a/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
24 +++ b/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
27 #include "pcie-mobiveil.h"
29 +#define REV_1_0 (0x10)
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;
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;
50 +static int ls_pcie_g4_host_init(struct mobiveil_pcie *pci)
52 + struct ls_pcie_g4 *pcie = to_ls_pcie_g4(pci);
54 + pcie->rev = csr_readb(pci, PCI_REVISION_ID);
59 static int ls_pcie_g4_link_up(struct mobiveil_pcie *pci)
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);
66 +static int ls_pcie_g4_read_other_conf(struct pci_bus *bus, unsigned int devfn,
67 + int where, int size, u32 *val)
69 + struct mobiveil_pcie *pci = bus->sysdata;
70 + struct ls_pcie_g4 *pcie = to_ls_pcie_g4(pci);
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);
77 + ret = pci_generic_config_read(bus, devfn, where, size, val);
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);
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,
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,
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;
103 +static int mobiveil_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
104 + int where, int size, u32 *val)
106 + struct mobiveil_pcie *pcie = bus->sysdata;
107 + struct root_port *rp = &pcie->rp;
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);
112 + return pci_generic_config_read(bus, devfn, where, size, val);
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,
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);
125 + /* Platform specific host init */
126 + if (pcie->ops->host_init)
127 + return pcie->ops->host_init(pcie);
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
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);
143 @@ -161,6 +163,7 @@ struct root_port {
145 struct mobiveil_pab_ops {
146 int (*link_up)(struct mobiveil_pcie *pcie);
147 + int (*host_init)(struct mobiveil_pcie *pcie);
150 struct mobiveil_pcie {