aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/mpic.c
diff options
context:
space:
mode:
authorMichael Ellerman <michael@ellerman.id.au>2007-05-07 22:58:36 -0400
committerPaul Mackerras <paulus@samba.org>2007-05-07 23:42:27 -0400
commit812fd1fd63caf2d72906603ebb9c6049a19ef4d2 (patch)
tree3bb831135adc67b4bc05d582b61ef5dfe63ac7bf /arch/powerpc/sysdev/mpic.c
parent014dad902aad6f5efbd65d0524b2e99304d2b07e (diff)
[POWERPC] Enable MSI mappings for MPIC
On some Apple machines the HT MSI mappings are not enabled by firmware, so we need to do it by hand. We can't use the pci routines as this code runs too early. Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/sysdev/mpic.c')
-rw-r--r--arch/powerpc/sysdev/mpic.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index e88bbd5ec4c8..33ecf89702d4 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -389,6 +389,50 @@ static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source,
389#endif 389#endif
390} 390}
391 391
392#ifdef CONFIG_PCI_MSI
393static void __init mpic_scan_ht_msi(struct mpic *mpic, u8 __iomem *devbase,
394 unsigned int devfn)
395{
396 u8 __iomem *base;
397 u8 pos, flags;
398 u64 addr = 0;
399
400 for (pos = readb(devbase + PCI_CAPABILITY_LIST); pos != 0;
401 pos = readb(devbase + pos + PCI_CAP_LIST_NEXT)) {
402 u8 id = readb(devbase + pos + PCI_CAP_LIST_ID);
403 if (id == PCI_CAP_ID_HT) {
404 id = readb(devbase + pos + 3);
405 if ((id & HT_5BIT_CAP_MASK) == HT_CAPTYPE_MSI_MAPPING)
406 break;
407 }
408 }
409
410 if (pos == 0)
411 return;
412
413 base = devbase + pos;
414
415 flags = readb(base + HT_MSI_FLAGS);
416 if (!(flags & HT_MSI_FLAGS_FIXED)) {
417 addr = readl(base + HT_MSI_ADDR_LO) & HT_MSI_ADDR_LO_MASK;
418 addr = addr | ((u64)readl(base + HT_MSI_ADDR_HI) << 32);
419 }
420
421 printk(KERN_DEBUG "mpic: - HT:%02x.%x %s MSI mapping found @ 0x%lx\n",
422 PCI_SLOT(devfn), PCI_FUNC(devfn),
423 flags & HT_MSI_FLAGS_ENABLE ? "enabled" : "disabled", addr);
424
425 if (!(flags & HT_MSI_FLAGS_ENABLE))
426 writeb(flags | HT_MSI_FLAGS_ENABLE, base + HT_MSI_FLAGS);
427}
428#else
429static void __init mpic_scan_ht_msi(struct mpic *mpic, u8 __iomem *devbase,
430 unsigned int devfn)
431{
432 return;
433}
434#endif
435
392static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase, 436static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase,
393 unsigned int devfn, u32 vdid) 437 unsigned int devfn, u32 vdid)
394{ 438{
@@ -480,6 +524,7 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic)
480 goto next; 524 goto next;
481 525
482 mpic_scan_ht_pic(mpic, devbase, devfn, l); 526 mpic_scan_ht_pic(mpic, devbase, devfn, l);
527 mpic_scan_ht_msi(mpic, devbase, devfn);
483 528
484 next: 529 next:
485 /* next device, if function 0 */ 530 /* next device, if function 0 */