Lines Matching +full:msi +full:- +full:ranges

2  * Copyright (C) 2007-2011 Freescale Semiconductor, Inc.
17 #include <linux/msi.h>
24 #include <asm/ppc-pci.h>
50 * in the cascade interrupt. So, this MSI interrupt has been acked
60 .name = "FSL-MSI",
66 struct fsl_msi *msi_data = h->host_data; in fsl_msi_host_map()
85 rc = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS, in fsl_msi_init_allocator()
86 msi_data->irqhost->of_node); in fsl_msi_init_allocator()
90 rc = msi_bitmap_reserve_dt_hwirqs(&msi_data->bitmap); in fsl_msi_init_allocator()
92 msi_bitmap_free(&msi_data->bitmap); in fsl_msi_init_allocator()
102 pr_debug("fslmsi: MSI-X untested, trying anyway.\n"); in fsl_msi_check_device()
112 list_for_each_entry(entry, &pdev->msi_list, list) { in fsl_teardown_msi_irqs()
113 if (entry->irq == NO_IRQ) in fsl_teardown_msi_irqs()
115 msi_data = irq_get_chip_data(entry->irq); in fsl_teardown_msi_irqs()
116 irq_set_msi_desc(entry->irq, NULL); in fsl_teardown_msi_irqs()
117 msi_bitmap_free_hwirqs(&msi_data->bitmap, in fsl_teardown_msi_irqs()
118 virq_to_hw(entry->irq), 1); in fsl_teardown_msi_irqs()
119 irq_dispose_mapping(entry->irq); in fsl_teardown_msi_irqs()
130 struct pci_controller *hose = pci_bus_to_host(pdev->bus); in fsl_compose_msi_msg()
135 /* If the msi-address-64 property exists, then use it */ in fsl_compose_msi_msg()
136 reg = of_get_property(hose->dn, "msi-address-64", &len); in fsl_compose_msi_msg()
140 address = fsl_pci_immrbar_base(hose) + msi_data->msiir_offset; in fsl_compose_msi_msg()
142 msg->address_lo = lower_32_bits(address); in fsl_compose_msi_msg()
143 msg->address_hi = upper_32_bits(address); in fsl_compose_msi_msg()
145 msg->data = hwirq; in fsl_compose_msi_msg()
153 struct pci_controller *hose = pci_bus_to_host(pdev->bus); in fsl_setup_msi_irqs()
156 int rc, hwirq = -ENOMEM; in fsl_setup_msi_irqs()
163 * If the PCI node has an fsl,msi property, then we need to use it in fsl_setup_msi_irqs()
164 * to find the specific MSI. in fsl_setup_msi_irqs()
166 np = of_parse_phandle(hose->dn, "fsl,msi", 0); in fsl_setup_msi_irqs()
168 if (of_device_is_compatible(np, "fsl,mpic-msi") || in fsl_setup_msi_irqs()
169 of_device_is_compatible(np, "fsl,vmpic-msi")) in fsl_setup_msi_irqs()
170 phandle = np->phandle; in fsl_setup_msi_irqs()
172 dev_err(&pdev->dev, in fsl_setup_msi_irqs()
173 "node %s has an invalid fsl,msi phandle %u\n", in fsl_setup_msi_irqs()
174 hose->dn->full_name, np->phandle); in fsl_setup_msi_irqs()
175 return -EINVAL; in fsl_setup_msi_irqs()
179 list_for_each_entry(entry, &pdev->msi_list, list) { in fsl_setup_msi_irqs()
181 * Loop over all the MSI devices until we find one that has an in fsl_setup_msi_irqs()
186 * If the PCI node has an fsl,msi property, then we in fsl_setup_msi_irqs()
187 * restrict our search to the corresponding MSI node. in fsl_setup_msi_irqs()
188 * The simplest way is to skip over MSI nodes with the in fsl_setup_msi_irqs()
190 * has the additional benefit of skipping over MSI in fsl_setup_msi_irqs()
193 if (phandle && (phandle != msi_data->phandle)) in fsl_setup_msi_irqs()
196 hwirq = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1); in fsl_setup_msi_irqs()
203 dev_err(&pdev->dev, "could not allocate MSI interrupt\n"); in fsl_setup_msi_irqs()
207 virq = irq_create_mapping(msi_data->irqhost, hwirq); in fsl_setup_msi_irqs()
210 dev_err(&pdev->dev, "fail mapping hwirq %i\n", hwirq); in fsl_setup_msi_irqs()
211 msi_bitmap_free_hwirqs(&msi_data->bitmap, hwirq, 1); in fsl_setup_msi_irqs()
212 rc = -ENOSPC; in fsl_setup_msi_irqs()
215 /* chip_data is msi_data via host->hostdata in host->map() */ in fsl_setup_msi_irqs()
234 int msir_index = -1; in fsl_msi_cascade()
242 msi_data = cascade_data->msi_data; in fsl_msi_cascade()
244 raw_spin_lock(&desc->lock); in fsl_msi_cascade()
245 if ((msi_data->feature & FSL_PIC_IP_MASK) == FSL_PIC_IP_IPIC) { in fsl_msi_cascade()
246 if (chip->irq_mask_ack) in fsl_msi_cascade()
247 chip->irq_mask_ack(idata); in fsl_msi_cascade()
249 chip->irq_mask(idata); in fsl_msi_cascade()
250 chip->irq_ack(idata); in fsl_msi_cascade()
257 msir_index = cascade_data->index; in fsl_msi_cascade()
263 switch (msi_data->feature & FSL_PIC_IP_MASK) { in fsl_msi_cascade()
265 msir_value = fsl_msi_read(msi_data->msi_regs, in fsl_msi_cascade()
269 msir_value = fsl_msi_read(msi_data->msi_regs, msir_index * 0x4); in fsl_msi_cascade()
274 pr_err("fsl-msi: fh_vmpic_get_msir() failed for " in fsl_msi_cascade()
282 intr_index = ffs(msir_value) - 1; in fsl_msi_cascade()
284 cascade_irq = irq_linear_revmap(msi_data->irqhost, in fsl_msi_cascade()
294 switch (msi_data->feature & FSL_PIC_IP_MASK) { in fsl_msi_cascade()
297 chip->irq_eoi(idata); in fsl_msi_cascade()
300 if (!irqd_irq_disabled(idata) && chip->irq_unmask) in fsl_msi_cascade()
301 chip->irq_unmask(idata); in fsl_msi_cascade()
305 raw_spin_unlock(&desc->lock); in fsl_msi_cascade()
310 struct fsl_msi *msi = platform_get_drvdata(ofdev); in fsl_of_msi_remove() local
314 if (msi->list.prev != NULL) in fsl_of_msi_remove()
315 list_del(&msi->list); in fsl_of_msi_remove()
317 virq = msi->msi_virqs[i]; in fsl_of_msi_remove()
324 if (msi->bitmap.bitmap) in fsl_of_msi_remove()
325 msi_bitmap_free(&msi->bitmap); in fsl_of_msi_remove()
326 if ((msi->feature & FSL_PIC_IP_MASK) != FSL_PIC_IP_VMPIC) in fsl_of_msi_remove()
327 iounmap(msi->msi_regs); in fsl_of_msi_remove()
328 kfree(msi); in fsl_of_msi_remove()
333 static int __devinit fsl_msi_setup_hwirq(struct fsl_msi *msi, in fsl_msi_setup_hwirq() argument
340 virt_msir = irq_of_parse_and_map(dev->dev.of_node, irq_index); in fsl_msi_setup_hwirq()
342 dev_err(&dev->dev, "%s: Cannot translate IRQ index %d\n", in fsl_msi_setup_hwirq()
349 dev_err(&dev->dev, "No memory for MSI cascade data\n"); in fsl_msi_setup_hwirq()
350 return -ENOMEM; in fsl_msi_setup_hwirq()
353 msi->msi_virqs[irq_index] = virt_msir; in fsl_msi_setup_hwirq()
354 cascade_data->index = offset; in fsl_msi_setup_hwirq()
355 cascade_data->msi_data = msi; in fsl_msi_setup_hwirq()
366 struct fsl_msi *msi; in fsl_of_msi_probe() local
376 match = of_match_device(fsl_of_msi_ids, &dev->dev); in fsl_of_msi_probe()
378 return -EINVAL; in fsl_of_msi_probe()
379 features = match->data; in fsl_of_msi_probe()
381 printk(KERN_DEBUG "Setting up Freescale MSI support\n"); in fsl_of_msi_probe()
383 msi = kzalloc(sizeof(struct fsl_msi), GFP_KERNEL); in fsl_of_msi_probe()
384 if (!msi) { in fsl_of_msi_probe()
385 dev_err(&dev->dev, "No memory for MSI structure\n"); in fsl_of_msi_probe()
386 return -ENOMEM; in fsl_of_msi_probe()
388 platform_set_drvdata(dev, msi); in fsl_of_msi_probe()
390 msi->irqhost = irq_alloc_host(dev->dev.of_node, IRQ_HOST_MAP_LINEAR, in fsl_of_msi_probe()
393 if (msi->irqhost == NULL) { in fsl_of_msi_probe()
394 dev_err(&dev->dev, "No memory for MSI irqhost\n"); in fsl_of_msi_probe()
395 err = -ENOMEM; in fsl_of_msi_probe()
400 * Under the Freescale hypervisor, the msi nodes don't have a 'reg' in fsl_of_msi_probe()
401 * property. Instead, we use hypercalls to access the MSI. in fsl_of_msi_probe()
403 if ((features->fsl_pic_ip & FSL_PIC_IP_MASK) != FSL_PIC_IP_VMPIC) { in fsl_of_msi_probe()
404 err = of_address_to_resource(dev->dev.of_node, 0, &res); in fsl_of_msi_probe()
406 dev_err(&dev->dev, "invalid resource for node %s\n", in fsl_of_msi_probe()
407 dev->dev.of_node->full_name); in fsl_of_msi_probe()
411 msi->msi_regs = ioremap(res.start, resource_size(&res)); in fsl_of_msi_probe()
412 if (!msi->msi_regs) { in fsl_of_msi_probe()
413 dev_err(&dev->dev, "could not map node %s\n", in fsl_of_msi_probe()
414 dev->dev.of_node->full_name); in fsl_of_msi_probe()
417 msi->msiir_offset = in fsl_of_msi_probe()
418 features->msiir_offset + (res.start & 0xfffff); in fsl_of_msi_probe()
421 msi->feature = features->fsl_pic_ip; in fsl_of_msi_probe()
423 msi->irqhost->host_data = msi; in fsl_of_msi_probe()
427 * that have an "fsl,msi" property. in fsl_of_msi_probe()
429 msi->phandle = dev->dev.of_node->phandle; in fsl_of_msi_probe()
431 rc = fsl_msi_init_allocator(msi); in fsl_of_msi_probe()
433 dev_err(&dev->dev, "Error allocating MSI bitmap\n"); in fsl_of_msi_probe()
437 p = of_get_property(dev->dev.of_node, "msi-available-ranges", &len); in fsl_of_msi_probe()
439 dev_err(&dev->dev, "%s: Malformed msi-available-ranges property\n", in fsl_of_msi_probe()
441 err = -EINVAL; in fsl_of_msi_probe()
453 printk(KERN_WARNING "%s: %s: msi available range of %u at %u is not IRQ-aligned\n", in fsl_of_msi_probe()
454 __func__, dev->dev.of_node->full_name, in fsl_of_msi_probe()
456 err = -EINVAL; in fsl_of_msi_probe()
464 err = fsl_msi_setup_hwirq(msi, dev, offset + j, irq_index); in fsl_of_msi_probe()
470 list_add_tail(&msi->list, &msi_head); in fsl_of_msi_probe()
478 dev_err(&dev->dev, "Different MSI driver already installed!\n"); in fsl_of_msi_probe()
479 err = -ENODEV; in fsl_of_msi_probe()
505 .compatible = "fsl,mpic-msi",
509 .compatible = "fsl,ipic-msi",
513 .compatible = "fsl,vmpic-msi",
521 .name = "fsl-msi",