aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/mpic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/sysdev/mpic.c')
-rw-r--r--arch/powerpc/sysdev/mpic.c84
1 files changed, 36 insertions, 48 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index ae24e2b82c5a..9513ea78e6c1 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -175,57 +175,57 @@ static inline int mpic_is_ht_interrupt(struct mpic *mpic, unsigned int source_no
175 return mpic->fixups[source_no].base != NULL; 175 return mpic->fixups[source_no].base != NULL;
176} 176}
177 177
178
178static inline void mpic_apic_end_irq(struct mpic *mpic, unsigned int source_no) 179static inline void mpic_apic_end_irq(struct mpic *mpic, unsigned int source_no)
179{ 180{
180 struct mpic_irq_fixup *fixup = &mpic->fixups[source_no]; 181 struct mpic_irq_fixup *fixup = &mpic->fixups[source_no];
181 u32 tmp;
182 182
183 spin_lock(&mpic->fixup_lock); 183 spin_lock(&mpic->fixup_lock);
184 writeb(0x11 + 2 * fixup->irq, fixup->base); 184 writeb(0x11 + 2 * fixup->irq, fixup->base + 2);
185 tmp = readl(fixup->base + 2); 185 writel(fixup->data, fixup->base + 4);
186 writel(tmp | 0x80000000ul, fixup->base + 2);
187 /* config writes shouldn't be posted but let's be safe ... */
188 (void)readl(fixup->base + 2);
189 spin_unlock(&mpic->fixup_lock); 186 spin_unlock(&mpic->fixup_lock);
190} 187}
191 188
192 189
193static void __init mpic_amd8111_read_irq(struct mpic *mpic, u8 __iomem *devbase) 190static void __init mpic_scan_ioapic(struct mpic *mpic, u8 __iomem *devbase)
194{ 191{
195 int i, irq; 192 int i, irq, n;
196 u32 tmp; 193 u32 tmp;
194 u8 pos;
197 195
198 printk(KERN_INFO "mpic: - Workarounds on AMD 8111 @ %p\n", devbase); 196 for (pos = readb(devbase + 0x34); pos; pos = readb(devbase + pos + 1)) {
197 u8 id = readb(devbase + pos);
199 198
200 for (i=0; i < 24; i++) { 199 if (id == 0x08) {
201 writeb(0x10 + 2*i, devbase + 0xf2); 200 id = readb(devbase + pos + 3);
202 tmp = readl(devbase + 0xf4); 201 if (id == 0x80)
203 if ((tmp & 0x1) || !(tmp & 0x20)) 202 break;
204 continue; 203 }
205 irq = (tmp >> 16) & 0xff;
206 mpic->fixups[irq].irq = i;
207 mpic->fixups[irq].base = devbase + 0xf2;
208 } 204 }
209} 205 if (pos == 0)
210 206 return;
211static void __init mpic_amd8131_read_irq(struct mpic *mpic, u8 __iomem *devbase) 207
212{ 208 printk(KERN_INFO "mpic: - Workarounds @ %p, pos = 0x%02x\n", devbase, pos);
213 int i, irq;
214 u32 tmp;
215 209
216 printk(KERN_INFO "mpic: - Workarounds on AMD 8131 @ %p\n", devbase); 210 devbase += pos;
217 211
218 for (i=0; i < 4; i++) { 212 writeb(0x01, devbase + 2);
219 writeb(0x10 + 2*i, devbase + 0xba); 213 n = (readl(devbase + 4) >> 16) & 0xff;
220 tmp = readl(devbase + 0xbc); 214
221 if ((tmp & 0x1) || !(tmp & 0x20)) 215 for (i = 0; i <= n; i++) {
216 writeb(0x10 + 2 * i, devbase + 2);
217 tmp = readl(devbase + 4);
218 if ((tmp & 0x21) != 0x20)
222 continue; 219 continue;
223 irq = (tmp >> 16) & 0xff; 220 irq = (tmp >> 16) & 0xff;
224 mpic->fixups[irq].irq = i; 221 mpic->fixups[irq].irq = i;
225 mpic->fixups[irq].base = devbase + 0xba; 222 mpic->fixups[irq].base = devbase;
223 writeb(0x11 + 2 * i, devbase + 2);
224 mpic->fixups[irq].data = readl(devbase + 4) | 0x80000000;
226 } 225 }
227} 226}
228 227
228
229static void __init mpic_scan_ioapics(struct mpic *mpic) 229static void __init mpic_scan_ioapics(struct mpic *mpic)
230{ 230{
231 unsigned int devfn; 231 unsigned int devfn;
@@ -241,21 +241,19 @@ static void __init mpic_scan_ioapics(struct mpic *mpic)
241 /* Init spinlock */ 241 /* Init spinlock */
242 spin_lock_init(&mpic->fixup_lock); 242 spin_lock_init(&mpic->fixup_lock);
243 243
244 /* Map u3 config space. We assume all IO-APICs are on the primary bus 244 /* Map U3 config space. We assume all IO-APICs are on the primary bus
245 * and slot will never be above "0xf" so we only need to map 32k 245 * so we only need to map 64kB.
246 */ 246 */
247 cfgspace = (unsigned char __iomem *)ioremap(0xf2000000, 0x8000); 247 cfgspace = ioremap(0xf2000000, 0x10000);
248 BUG_ON(cfgspace == NULL); 248 BUG_ON(cfgspace == NULL);
249 249
250 /* Now we scan all slots. We do a very quick scan, we read the header type, 250 /* Now we scan all slots. We do a very quick scan, we read the header type,
251 * vendor ID and device ID only, that's plenty enough 251 * vendor ID and device ID only, that's plenty enough
252 */ 252 */
253 for (devfn = 0; devfn < PCI_DEVFN(0x10,0); devfn ++) { 253 for (devfn = 0; devfn < 0x100; devfn++) {
254 u8 __iomem *devbase = cfgspace + (devfn << 8); 254 u8 __iomem *devbase = cfgspace + (devfn << 8);
255 u8 hdr_type = readb(devbase + PCI_HEADER_TYPE); 255 u8 hdr_type = readb(devbase + PCI_HEADER_TYPE);
256 u32 l = readl(devbase + PCI_VENDOR_ID); 256 u32 l = readl(devbase + PCI_VENDOR_ID);
257 u16 vendor_id, device_id;
258 int multifunc = 0;
259 257
260 DBG("devfn %x, l: %x\n", devfn, l); 258 DBG("devfn %x, l: %x\n", devfn, l);
261 259
@@ -264,21 +262,11 @@ static void __init mpic_scan_ioapics(struct mpic *mpic)
264 l == 0x0000ffff || l == 0xffff0000) 262 l == 0x0000ffff || l == 0xffff0000)
265 goto next; 263 goto next;
266 264
267 /* Check if it's a multifunction device (only really used 265 mpic_scan_ioapic(mpic, devbase);
268 * to function 0 though 266
269 */
270 multifunc = !!(hdr_type & 0x80);
271 vendor_id = l & 0xffff;
272 device_id = (l >> 16) & 0xffff;
273
274 /* If a known device, go to fixup setup code */
275 if (vendor_id == PCI_VENDOR_ID_AMD && device_id == 0x7460)
276 mpic_amd8111_read_irq(mpic, devbase);
277 if (vendor_id == PCI_VENDOR_ID_AMD && device_id == 0x7450)
278 mpic_amd8131_read_irq(mpic, devbase);
279 next: 267 next:
280 /* next device, if function 0 */ 268 /* next device, if function 0 */
281 if ((PCI_FUNC(devfn) == 0) && !multifunc) 269 if (PCI_FUNC(devfn) == 0 && (hdr_type & 0x80) == 0)
282 devfn += 7; 270 devfn += 7;
283 } 271 }
284} 272}