aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/fsl_msi.c
diff options
context:
space:
mode:
authorTimur Tabi <timur@freescale.com>2011-12-13 15:51:59 -0500
committerKumar Gala <galak@kernel.crashing.org>2012-01-04 16:47:44 -0500
commit446bc1ffe4f2cac228909fe0ac48884d12700d81 (patch)
treeebc83802cd7f4c140159384c2b7e6e492080891f /arch/powerpc/sysdev/fsl_msi.c
parentc6ca52ad32cb9a4b9b331a60966ffa4d00ce3f37 (diff)
powerpc/fsl: add MSI support for the Freescale hypervisor
Add support for vmpic-msi nodes to the fsl_msi driver. The MSI is virtualized by the hypervisor, so the vmpic-msi does not contain a 'reg' property. Instead, the driver uses hcalls. Add support for the "msi-address-64" property to the fsl_pci driver. The Freescale hypervisor typically puts the virtualized MSIIR register in the page after the end of DDR, so we extend the DDR ATMU to cover it. Any other location for MSIIR is not supported, for now. Signed-off-by: Timur Tabi <timur@freescale.com> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/sysdev/fsl_msi.c')
-rw-r--r--arch/powerpc/sysdev/fsl_msi.c68
1 files changed, 48 insertions, 20 deletions
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 89548e07ddeb..ecb5c1946d22 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -23,6 +23,8 @@
23#include <asm/hw_irq.h> 23#include <asm/hw_irq.h>
24#include <asm/ppc-pci.h> 24#include <asm/ppc-pci.h>
25#include <asm/mpic.h> 25#include <asm/mpic.h>
26#include <asm/fsl_hcalls.h>
27
26#include "fsl_msi.h" 28#include "fsl_msi.h"
27#include "fsl_pci.h" 29#include "fsl_pci.h"
28 30
@@ -163,11 +165,13 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
163 */ 165 */
164 np = of_parse_phandle(hose->dn, "fsl,msi", 0); 166 np = of_parse_phandle(hose->dn, "fsl,msi", 0);
165 if (np) { 167 if (np) {
166 if (of_device_is_compatible(np, "fsl,mpic-msi")) 168 if (of_device_is_compatible(np, "fsl,mpic-msi") ||
169 of_device_is_compatible(np, "fsl,vmpic-msi"))
167 phandle = np->phandle; 170 phandle = np->phandle;
168 else { 171 else {
169 dev_err(&pdev->dev, "node %s has an invalid fsl,msi" 172 dev_err(&pdev->dev,
170 " phandle\n", hose->dn->full_name); 173 "node %s has an invalid fsl,msi phandle %u\n",
174 hose->dn->full_name, np->phandle);
171 return -EINVAL; 175 return -EINVAL;
172 } 176 }
173 } 177 }
@@ -196,16 +200,14 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
196 200
197 if (hwirq < 0) { 201 if (hwirq < 0) {
198 rc = hwirq; 202 rc = hwirq;
199 pr_debug("%s: fail allocating msi interrupt\n", 203 dev_err(&pdev->dev, "could not allocate MSI interrupt\n");
200 __func__);
201 goto out_free; 204 goto out_free;
202 } 205 }
203 206
204 virq = irq_create_mapping(msi_data->irqhost, hwirq); 207 virq = irq_create_mapping(msi_data->irqhost, hwirq);
205 208
206 if (virq == NO_IRQ) { 209 if (virq == NO_IRQ) {
207 pr_debug("%s: fail mapping hwirq 0x%x\n", 210 dev_err(&pdev->dev, "fail mapping hwirq %i\n", hwirq);
208 __func__, hwirq);
209 msi_bitmap_free_hwirqs(&msi_data->bitmap, hwirq, 1); 211 msi_bitmap_free_hwirqs(&msi_data->bitmap, hwirq, 1);
210 rc = -ENOSPC; 212 rc = -ENOSPC;
211 goto out_free; 213 goto out_free;
@@ -234,6 +236,7 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
234 u32 intr_index; 236 u32 intr_index;
235 u32 have_shift = 0; 237 u32 have_shift = 0;
236 struct fsl_msi_cascade_data *cascade_data; 238 struct fsl_msi_cascade_data *cascade_data;
239 unsigned int ret;
237 240
238 cascade_data = irq_get_handler_data(irq); 241 cascade_data = irq_get_handler_data(irq);
239 msi_data = cascade_data->msi_data; 242 msi_data = cascade_data->msi_data;
@@ -265,6 +268,14 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
265 case FSL_PIC_IP_IPIC: 268 case FSL_PIC_IP_IPIC:
266 msir_value = fsl_msi_read(msi_data->msi_regs, msir_index * 0x4); 269 msir_value = fsl_msi_read(msi_data->msi_regs, msir_index * 0x4);
267 break; 270 break;
271 case FSL_PIC_IP_VMPIC:
272 ret = fh_vmpic_get_msir(virq_to_hw(irq), &msir_value);
273 if (ret) {
274 pr_err("fsl-msi: fh_vmpic_get_msir() failed for "
275 "irq %u (ret=%u)\n", irq, ret);
276 msir_value = 0;
277 }
278 break;
268 } 279 }
269 280
270 while (msir_value) { 281 while (msir_value) {
@@ -282,6 +293,7 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
282 293
283 switch (msi_data->feature & FSL_PIC_IP_MASK) { 294 switch (msi_data->feature & FSL_PIC_IP_MASK) {
284 case FSL_PIC_IP_MPIC: 295 case FSL_PIC_IP_MPIC:
296 case FSL_PIC_IP_VMPIC:
285 chip->irq_eoi(idata); 297 chip->irq_eoi(idata);
286 break; 298 break;
287 case FSL_PIC_IP_IPIC: 299 case FSL_PIC_IP_IPIC:
@@ -311,7 +323,8 @@ static int fsl_of_msi_remove(struct platform_device *ofdev)
311 } 323 }
312 if (msi->bitmap.bitmap) 324 if (msi->bitmap.bitmap)
313 msi_bitmap_free(&msi->bitmap); 325 msi_bitmap_free(&msi->bitmap);
314 iounmap(msi->msi_regs); 326 if ((msi->feature & FSL_PIC_IP_MASK) != FSL_PIC_IP_VMPIC)
327 iounmap(msi->msi_regs);
315 kfree(msi); 328 kfree(msi);
316 329
317 return 0; 330 return 0;
@@ -383,26 +396,32 @@ static int __devinit fsl_of_msi_probe(struct platform_device *dev)
383 goto error_out; 396 goto error_out;
384 } 397 }
385 398
386 /* Get the MSI reg base */ 399 /*
387 err = of_address_to_resource(dev->dev.of_node, 0, &res); 400 * Under the Freescale hypervisor, the msi nodes don't have a 'reg'
388 if (err) { 401 * property. Instead, we use hypercalls to access the MSI.
389 dev_err(&dev->dev, "%s resource error!\n", 402 */
403 if ((features->fsl_pic_ip & FSL_PIC_IP_MASK) != FSL_PIC_IP_VMPIC) {
404 err = of_address_to_resource(dev->dev.of_node, 0, &res);
405 if (err) {
406 dev_err(&dev->dev, "invalid resource for node %s\n",
390 dev->dev.of_node->full_name); 407 dev->dev.of_node->full_name);
391 goto error_out; 408 goto error_out;
392 } 409 }
393 410
394 msi->msi_regs = ioremap(res.start, resource_size(&res)); 411 msi->msi_regs = ioremap(res.start, resource_size(&res));
395 if (!msi->msi_regs) { 412 if (!msi->msi_regs) {
396 dev_err(&dev->dev, "ioremap problem failed\n"); 413 dev_err(&dev->dev, "could not map node %s\n",
397 goto error_out; 414 dev->dev.of_node->full_name);
415 goto error_out;
416 }
417 msi->msiir_offset =
418 features->msiir_offset + (res.start & 0xfffff);
398 } 419 }
399 420
400 msi->feature = features->fsl_pic_ip; 421 msi->feature = features->fsl_pic_ip;
401 422
402 msi->irqhost->host_data = msi; 423 msi->irqhost->host_data = msi;
403 424
404 msi->msiir_offset = features->msiir_offset + (res.start & 0xfffff);
405
406 /* 425 /*
407 * Remember the phandle, so that we can match with any PCI nodes 426 * Remember the phandle, so that we can match with any PCI nodes
408 * that have an "fsl,msi" property. 427 * that have an "fsl,msi" property.
@@ -476,6 +495,11 @@ static const struct fsl_msi_feature ipic_msi_feature = {
476 .msiir_offset = 0x38, 495 .msiir_offset = 0x38,
477}; 496};
478 497
498static const struct fsl_msi_feature vmpic_msi_feature = {
499 .fsl_pic_ip = FSL_PIC_IP_VMPIC,
500 .msiir_offset = 0,
501};
502
479static const struct of_device_id fsl_of_msi_ids[] = { 503static const struct of_device_id fsl_of_msi_ids[] = {
480 { 504 {
481 .compatible = "fsl,mpic-msi", 505 .compatible = "fsl,mpic-msi",
@@ -485,6 +509,10 @@ static const struct of_device_id fsl_of_msi_ids[] = {
485 .compatible = "fsl,ipic-msi", 509 .compatible = "fsl,ipic-msi",
486 .data = (void *)&ipic_msi_feature, 510 .data = (void *)&ipic_msi_feature,
487 }, 511 },
512 {
513 .compatible = "fsl,vmpic-msi",
514 .data = (void *)&vmpic_msi_feature,
515 },
488 {} 516 {}
489}; 517};
490 518