diff options
Diffstat (limited to 'arch/powerpc/sysdev/fsl_msi.c')
| -rw-r--r-- | arch/powerpc/sysdev/fsl_msi.c | 28 |
1 files changed, 19 insertions, 9 deletions
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c index 419a77239bd7..e5c344d336ea 100644 --- a/arch/powerpc/sysdev/fsl_msi.c +++ b/arch/powerpc/sysdev/fsl_msi.c | |||
| @@ -30,7 +30,7 @@ LIST_HEAD(msi_head); | |||
| 30 | 30 | ||
| 31 | struct fsl_msi_feature { | 31 | struct fsl_msi_feature { |
| 32 | u32 fsl_pic_ip; | 32 | u32 fsl_pic_ip; |
| 33 | u32 msiir_offset; | 33 | u32 msiir_offset; /* Offset of MSIIR, relative to start of MSIR bank */ |
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| 36 | struct fsl_msi_cascade_data { | 36 | struct fsl_msi_cascade_data { |
| @@ -126,10 +126,19 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq, | |||
| 126 | { | 126 | { |
| 127 | struct fsl_msi *msi_data = fsl_msi_data; | 127 | struct fsl_msi *msi_data = fsl_msi_data; |
| 128 | struct pci_controller *hose = pci_bus_to_host(pdev->bus); | 128 | struct pci_controller *hose = pci_bus_to_host(pdev->bus); |
| 129 | u64 base = fsl_pci_immrbar_base(hose); | 129 | u64 address; /* Physical address of the MSIIR */ |
| 130 | int len; | ||
| 131 | const u64 *reg; | ||
| 132 | |||
| 133 | /* If the msi-address-64 property exists, then use it */ | ||
| 134 | reg = of_get_property(hose->dn, "msi-address-64", &len); | ||
| 135 | if (reg && (len == sizeof(u64))) | ||
| 136 | address = be64_to_cpup(reg); | ||
| 137 | else | ||
| 138 | address = fsl_pci_immrbar_base(hose) + msi_data->msiir_offset; | ||
| 130 | 139 | ||
| 131 | msg->address_lo = msi_data->msi_addr_lo + lower_32_bits(base); | 140 | msg->address_lo = lower_32_bits(address); |
| 132 | msg->address_hi = msi_data->msi_addr_hi + upper_32_bits(base); | 141 | msg->address_hi = upper_32_bits(address); |
| 133 | 142 | ||
| 134 | msg->data = hwirq; | 143 | msg->data = hwirq; |
| 135 | 144 | ||
| @@ -296,7 +305,7 @@ static int __devinit fsl_msi_setup_hwirq(struct fsl_msi *msi, | |||
| 296 | } | 305 | } |
| 297 | 306 | ||
| 298 | msi->msi_virqs[irq_index] = virt_msir; | 307 | msi->msi_virqs[irq_index] = virt_msir; |
| 299 | cascade_data->index = offset + irq_index; | 308 | cascade_data->index = offset; |
| 300 | cascade_data->msi_data = msi; | 309 | cascade_data->msi_data = msi; |
| 301 | irq_set_handler_data(virt_msir, cascade_data); | 310 | irq_set_handler_data(virt_msir, cascade_data); |
| 302 | irq_set_chained_handler(virt_msir, fsl_msi_cascade); | 311 | irq_set_chained_handler(virt_msir, fsl_msi_cascade); |
| @@ -359,8 +368,7 @@ static int __devinit fsl_of_msi_probe(struct platform_device *dev) | |||
| 359 | 368 | ||
| 360 | msi->irqhost->host_data = msi; | 369 | msi->irqhost->host_data = msi; |
| 361 | 370 | ||
| 362 | msi->msi_addr_hi = 0x0; | 371 | msi->msiir_offset = features->msiir_offset + (res.start & 0xfffff); |
| 363 | msi->msi_addr_lo = features->msiir_offset + (res.start & 0xfffff); | ||
| 364 | 372 | ||
| 365 | rc = fsl_msi_init_allocator(msi); | 373 | rc = fsl_msi_init_allocator(msi); |
| 366 | if (rc) { | 374 | if (rc) { |
| @@ -376,8 +384,10 @@ static int __devinit fsl_of_msi_probe(struct platform_device *dev) | |||
| 376 | goto error_out; | 384 | goto error_out; |
| 377 | } | 385 | } |
| 378 | 386 | ||
| 379 | if (!p) | 387 | if (!p) { |
| 380 | p = all_avail; | 388 | p = all_avail; |
| 389 | len = sizeof(all_avail); | ||
| 390 | } | ||
| 381 | 391 | ||
| 382 | for (irq_index = 0, i = 0; i < len / (2 * sizeof(u32)); i++) { | 392 | for (irq_index = 0, i = 0; i < len / (2 * sizeof(u32)); i++) { |
| 383 | if (p[i * 2] % IRQS_PER_MSI_REG || | 393 | if (p[i * 2] % IRQS_PER_MSI_REG || |
| @@ -393,7 +403,7 @@ static int __devinit fsl_of_msi_probe(struct platform_device *dev) | |||
| 393 | count = p[i * 2 + 1] / IRQS_PER_MSI_REG; | 403 | count = p[i * 2 + 1] / IRQS_PER_MSI_REG; |
| 394 | 404 | ||
| 395 | for (j = 0; j < count; j++, irq_index++) { | 405 | for (j = 0; j < count; j++, irq_index++) { |
| 396 | err = fsl_msi_setup_hwirq(msi, dev, offset, irq_index); | 406 | err = fsl_msi_setup_hwirq(msi, dev, offset + j, irq_index); |
| 397 | if (err) | 407 | if (err) |
| 398 | goto error_out; | 408 | goto error_out; |
| 399 | } | 409 | } |
