diff options
Diffstat (limited to 'arch/powerpc/sysdev/mpic.c')
| -rw-r--r-- | arch/powerpc/sysdev/mpic.c | 45 |
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 | ||
| 393 | static 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 | ||
| 429 | static void __init mpic_scan_ht_msi(struct mpic *mpic, u8 __iomem *devbase, | ||
| 430 | unsigned int devfn) | ||
| 431 | { | ||
| 432 | return; | ||
| 433 | } | ||
| 434 | #endif | ||
| 435 | |||
| 392 | static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase, | 436 | static 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 */ |
