diff options
Diffstat (limited to 'arch/powerpc/platforms/pasemi/pci.c')
-rw-r--r-- | arch/powerpc/platforms/pasemi/pci.c | 66 |
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 | |||
117 | static 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 | |||
162 | static void sb600_set_flag(int bus) | ||
163 | { | ||
164 | } | ||
165 | #endif | ||
166 | |||
111 | static int pa_pxp_read_config(struct pci_bus *bus, unsigned int devfn, | 167 | static 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 | ||