aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/fsl_msi.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/sysdev/fsl_msi.c')
-rw-r--r--arch/powerpc/sysdev/fsl_msi.c28
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
31struct fsl_msi_feature { 31struct 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
36struct fsl_msi_cascade_data { 36struct 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 }