aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pasemi/pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/pasemi/pci.c')
-rw-r--r--arch/powerpc/platforms/pasemi/pci.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/pasemi/pci.c b/arch/powerpc/platforms/pasemi/pci.c
index c3c64172482d..fdc839d93837 100644
--- a/arch/powerpc/platforms/pasemi/pci.c
+++ b/arch/powerpc/platforms/pasemi/pci.c
@@ -27,6 +27,7 @@
27#include <linux/pci.h> 27#include <linux/pci.h>
28 28
29#include <asm/pci-bridge.h> 29#include <asm/pci-bridge.h>
30#include <asm/isa-bridge.h>
30#include <asm/machdep.h> 31#include <asm/machdep.h>
31 32
32#include <asm/ppc-pci.h> 33#include <asm/ppc-pci.h>
@@ -108,6 +109,61 @@ static int workaround_5945(struct pci_bus *bus, unsigned int devfn,
108 return 1; 109 return 1;
109} 110}
110 111
112#ifdef CONFIG_PPC_PASEMI_NEMO
113#define PXP_ERR_CFG_REG 0x4
114#define PXP_IGNORE_PCIE_ERRORS 0x800
115#define SB600_BUS 5
116
117static void sb600_set_flag(int bus)
118{
119 static void __iomem *iob_mapbase = NULL;
120 struct resource res;
121 struct device_node *dn;
122 int err;
123
124 if (iob_mapbase == NULL) {
125 dn = of_find_compatible_node(NULL, "isa", "pasemi,1682m-iob");
126 if (!dn) {
127 pr_crit("NEMO SB600 missing iob node\n");
128 return;
129 }
130
131 err = of_address_to_resource(dn, 0, &res);
132 of_node_put(dn);
133
134 if (err) {
135 pr_crit("NEMO SB600 missing resource\n");
136 return;
137 }
138
139 pr_info("NEMO SB600 IOB base %08llx\n",res.start);
140
141 iob_mapbase = ioremap(res.start + 0x100, 0x94);
142 }
143
144 if (iob_mapbase != NULL) {
145 if (bus == SB600_BUS) {
146 /*
147 * This is the SB600's bus, tell the PCI-e root port
148 * to allow non-zero devices to enumerate.
149 */
150 out_le32(iob_mapbase + PXP_ERR_CFG_REG, in_le32(iob_mapbase + PXP_ERR_CFG_REG) | PXP_IGNORE_PCIE_ERRORS);
151 } else {
152 /*
153 * Only scan device 0 on other busses
154 */
155 out_le32(iob_mapbase + PXP_ERR_CFG_REG, in_le32(iob_mapbase + PXP_ERR_CFG_REG) & ~PXP_IGNORE_PCIE_ERRORS);
156 }
157 }
158}
159
160#else
161
162static void sb600_set_flag(int bus)
163{
164}
165#endif
166
111static int pa_pxp_read_config(struct pci_bus *bus, unsigned int devfn, 167static int pa_pxp_read_config(struct pci_bus *bus, unsigned int devfn,
112 int offset, int len, u32 *val) 168 int offset, int len, u32 *val)
113{ 169{
@@ -126,6 +182,8 @@ static int pa_pxp_read_config(struct pci_bus *bus, unsigned int devfn,
126 182
127 addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset); 183 addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset);
128 184
185 sb600_set_flag(bus->number);
186
129 /* 187 /*
130 * Note: the caller has already checked that offset is 188 * Note: the caller has already checked that offset is
131 * suitably aligned and that len is 1, 2 or 4. 189 * suitably aligned and that len is 1, 2 or 4.
@@ -160,6 +218,8 @@ static int pa_pxp_write_config(struct pci_bus *bus, unsigned int devfn,
160 218
161 addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset); 219 addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset);
162 220
221 sb600_set_flag(bus->number);
222
163 /* 223 /*
164 * Note: the caller has already checked that offset is 224 * Note: the caller has already checked that offset is
165 * suitably aligned and that len is 1, 2 or 4. 225 * suitably aligned and that len is 1, 2 or 4.
@@ -210,6 +270,12 @@ static int __init pas_add_bridge(struct device_node *dev)
210 /* Interpret the "ranges" property */ 270 /* Interpret the "ranges" property */
211 pci_process_bridge_OF_ranges(hose, dev, 1); 271 pci_process_bridge_OF_ranges(hose, dev, 1);
212 272
273 /*
274 * Scan for an isa bridge. This is needed to find the SB600 on the nemo
275 * and does nothing on machines without one.
276 */
277 isa_bridge_find_early(hose);
278
213 return 0; 279 return 0;
214} 280}
215 281