int of_irq_to_resource(struct device_node *dev, int index, struct resource *r) { struct of_irq out_irq; int irq; int res; res = of_irq_map_one(dev, index, &out_irq); /* Get irq for the device */ if (res) { pr_debug("IRQ not found... code = %d", res); return NO_IRQ; } /* Assuming single interrupt controller... */ irq = out_irq.specifier[0]; pr_debug("IRQ found = %d", irq); /* Only dereference the resource if both the * resource and the irq are valid. */ if (r && irq != NO_IRQ) { r->start = r->end = irq; r->flags = IORESOURCE_IRQ; } return irq; }
static int __init spu_map_interrupts(struct spu *spu, struct device_node *np) { struct of_irq oirq; int ret; int i; for (i=0; i < 3; i++) { ret = of_irq_map_one(np, i, &oirq); if (ret) { pr_debug("spu_new: failed to get irq %d\n", i); goto err; } ret = -EINVAL; pr_debug(" irq %d no 0x%x on %s\n", i, oirq.specifier[0], oirq.controller->full_name); spu->irqs[i] = irq_create_of_mapping(oirq.controller, oirq.specifier, oirq.size); if (spu->irqs[i] == NO_IRQ) { pr_debug("spu_new: failed to map it !\n"); goto err; } } return 0; err: pr_debug("failed to map irq %x for spu %s\n", *oirq.specifier, spu->name); for (; i >= 0; i--) { if (spu->irqs[i] != NO_IRQ) irq_dispose_mapping(spu->irqs[i]); } return ret; }
unsigned int irq_of_parse_and_map(struct device_node *dev, int index) { struct of_irq oirq; if (of_irq_map_one(dev, index, &oirq)) return NO_IRQ; return oirq.specifier[0]; }
static void request_ras_irqs(struct device_node *np, irqreturn_t (*handler)(int, void *, struct pt_regs *), const char *name) { int i, index, count = 0; struct of_irq oirq; u32 *opicprop; unsigned int opicplen; unsigned int virqs[16]; /* Check for obsolete "open-pic-interrupt" property. If present, then * map those interrupts using the default interrupt host and default * trigger */ opicprop = (u32 *)get_property(np, "open-pic-interrupt", &opicplen); if (opicprop) { opicplen /= sizeof(u32); for (i = 0; i < opicplen; i++) { if (count > 15) break; virqs[count] = irq_create_mapping(NULL, *(opicprop++)); if (virqs[count] == NO_IRQ) printk(KERN_ERR "Unable to allocate interrupt " "number for %s\n", np->full_name); else count++; } } /* Else use normal interrupt tree parsing */ else { /* First try to do a proper OF tree parsing */ for (index = 0; of_irq_map_one(np, index, &oirq) == 0; index++) { if (count > 15) break; virqs[count] = irq_create_of_mapping(oirq.controller, oirq.specifier, oirq.size); if (virqs[count] == NO_IRQ) printk(KERN_ERR "Unable to allocate interrupt " "number for %s\n", np->full_name); else count++; } } /* Now request them */ for (i = 0; i < count; i++) { if (request_irq(virqs[i], handler, 0, name, NULL)) { printk(KERN_ERR "Unable to request interrupt %d for " "%s\n", virqs[i], np->full_name); return; } } }
unsigned int irq_of_parse_and_map(struct device_node *dev, int index) { struct of_irq oirq; if (of_irq_map_one(dev, index, &oirq)) return 0; return irq_create_of_mapping(oirq.controller, oirq.specifier, oirq.size); }
static void __init msm_dt_timer_init(void) { struct device_node *node; struct resource res; struct of_irq oirq; node = of_find_compatible_node(NULL, NULL, "qcom,msm-qtimer"); if (!node) { pr_err("no matching timer node found\n"); return; } if (of_irq_map_one(node, 0, &oirq)) { pr_err("interrupt not specified in timer node\n"); } else { res.start = res.end = oirq.specifier[0]; res.flags = IORESOURCE_IRQ; arch_timer_register(&res, 1); } of_node_put(node); }
static int of_isp1760_probe(struct platform_device *dev) { struct isp1760 *drvdata; struct device_node *dp = dev->dev.of_node; struct resource *res; struct resource memory; struct of_irq oirq; int virq; resource_size_t res_len; int ret; const unsigned int *prop; unsigned int devflags = 0; enum of_gpio_flags gpio_flags; drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL); if (!drvdata) return -ENOMEM; ret = of_address_to_resource(dp, 0, &memory); if (ret) return -ENXIO; res_len = resource_size(&memory); res = request_mem_region(memory.start, res_len, dev_name(&dev->dev)); if (!res) return -EBUSY; if (of_irq_map_one(dp, 0, &oirq)) { ret = -ENODEV; goto release_reg; } virq = irq_create_of_mapping(oirq.controller, oirq.specifier, oirq.size); if (of_device_is_compatible(dp, "nxp,usb-isp1761")) devflags |= ISP1760_FLAG_ISP1761; /* Some systems wire up only 16 of the 32 data lines */ prop = of_get_property(dp, "bus-width", NULL); if (prop && *prop == 16) devflags |= ISP1760_FLAG_BUS_WIDTH_16; if (of_get_property(dp, "port1-otg", NULL) != NULL) devflags |= ISP1760_FLAG_OTG_EN; if (of_get_property(dp, "analog-oc", NULL) != NULL) devflags |= ISP1760_FLAG_ANALOG_OC; if (of_get_property(dp, "dack-polarity", NULL) != NULL) devflags |= ISP1760_FLAG_DACK_POL_HIGH; if (of_get_property(dp, "dreq-polarity", NULL) != NULL) devflags |= ISP1760_FLAG_DREQ_POL_HIGH; drvdata->rst_gpio = of_get_gpio_flags(dp, 0, &gpio_flags); if (gpio_is_valid(drvdata->rst_gpio)) { ret = gpio_request(drvdata->rst_gpio, dev_name(&dev->dev)); if (!ret) { if (!(gpio_flags & OF_GPIO_ACTIVE_LOW)) { devflags |= ISP1760_FLAG_RESET_ACTIVE_HIGH; gpio_direction_output(drvdata->rst_gpio, 0); } else { gpio_direction_output(drvdata->rst_gpio, 1); } } else { drvdata->rst_gpio = ret; } } drvdata->hcd = isp1760_register(memory.start, res_len, virq, IRQF_SHARED, drvdata->rst_gpio, &dev->dev, dev_name(&dev->dev), devflags); if (IS_ERR(drvdata->hcd)) { ret = PTR_ERR(drvdata->hcd); goto free_gpio; } dev_set_drvdata(&dev->dev, drvdata); return ret; free_gpio: if (gpio_is_valid(drvdata->rst_gpio)) gpio_free(drvdata->rst_gpio); release_reg: release_mem_region(memory.start, res_len); kfree(drvdata); return ret; }
int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq) { struct device_node *dn, *ppnode; struct pci_dev *ppdev; u32 lspec; u32 laddr[3]; u8 pin; int rc; /* Check if we have a device node, if yes, fallback to standard OF * parsing */ dn = pci_device_to_OF_node(pdev); if (dn) return of_irq_map_one(dn, 0, out_irq); /* Ok, we don't, time to have fun. Let's start by building up an * interrupt spec. we assume #interrupt-cells is 1, which is standard * for PCI. If you do different, then don't use that routine. */ rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin); if (rc != 0) return rc; /* No pin, exit */ if (pin == 0) return -ENODEV; /* Now we walk up the PCI tree */ lspec = pin; for (;;) { /* Get the pci_dev of our parent */ ppdev = pdev->bus->self; /* Ouch, it's a host bridge... */ if (ppdev == NULL) { struct pci_controller *host; host = pci_bus_to_host(pdev->bus); ppnode = host ? host->dn : NULL; /* No node for host bridge ? give up */ if (ppnode == NULL) return -EINVAL; } else /* We found a P2P bridge, check if it has a node */ ppnode = pci_device_to_OF_node(ppdev); /* Ok, we have found a parent with a device-node, hand over to * the OF parsing code. * We build a unit address from the linux device to be used for * resolution. Note that we use the linux bus number which may * not match your firmware bus numbering. * Fortunately, in most cases, interrupt-map-mask doesn't * include the bus number as part of the matching. * You should still be careful about that though if you intend * to rely on this function (you ship a firmware that doesn't * create device nodes for all PCI devices). */ if (ppnode) break; /* We can only get here if we hit a P2P bridge with no node, * let's do standard swizzling and try again */ lspec = pci_swizzle_interrupt_pin(pdev, lspec); pdev = ppdev; } laddr[0] = (pdev->bus->number << 16) | (pdev->devfn << 8); laddr[1] = laddr[2] = 0; return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq); }
static int of_isp1760_probe(struct platform_device *dev, const struct of_device_id *match) { struct usb_hcd *hcd; struct device_node *dp = dev->dev.of_node; struct resource *res; struct resource memory; struct of_irq oirq; int virq; resource_size_t res_len; int ret; const unsigned int *prop; unsigned int devflags = 0; ret = of_address_to_resource(dp, 0, &memory); if (ret) return -ENXIO; res_len = resource_size(&memory); res = request_mem_region(memory.start, res_len, dev_name(&dev->dev)); if (!res) return -EBUSY; if (of_irq_map_one(dp, 0, &oirq)) { ret = -ENODEV; goto release_reg; } virq = irq_create_of_mapping(oirq.controller, oirq.specifier, oirq.size); if (of_device_is_compatible(dp, "nxp,usb-isp1761")) devflags |= ISP1760_FLAG_ISP1761; /* Some systems wire up only 16 of the 32 data lines */ prop = of_get_property(dp, "bus-width", NULL); if (prop && *prop == 16) devflags |= ISP1760_FLAG_BUS_WIDTH_16; if (of_get_property(dp, "port1-otg", NULL) != NULL) devflags |= ISP1760_FLAG_OTG_EN; if (of_get_property(dp, "analog-oc", NULL) != NULL) devflags |= ISP1760_FLAG_ANALOG_OC; if (of_get_property(dp, "dack-polarity", NULL) != NULL) devflags |= ISP1760_FLAG_DACK_POL_HIGH; if (of_get_property(dp, "dreq-polarity", NULL) != NULL) devflags |= ISP1760_FLAG_DREQ_POL_HIGH; hcd = isp1760_register(memory.start, res_len, virq, IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev), devflags); if (IS_ERR(hcd)) { ret = PTR_ERR(hcd); goto release_reg; } dev_set_drvdata(&dev->dev, hcd); return ret; release_reg: release_mem_region(memory.start, res_len); return ret; }
void request_event_sources_irqs(struct device_node *np, irq_handler_t handler, const char *name) { int i, index, count = 0; struct of_irq oirq; const u32 *opicprop; unsigned int opicplen; unsigned int virqs[16]; /* */ opicprop = of_get_property(np, "open-pic-interrupt", &opicplen); if (opicprop) { opicplen /= sizeof(u32); for (i = 0; i < opicplen; i++) { if (count > 15) break; virqs[count] = irq_create_mapping(NULL, *(opicprop++)); if (virqs[count] == NO_IRQ) { pr_err("event-sources: Unable to allocate " "interrupt number for %s\n", np->full_name); WARN_ON(1); } else count++; } } /* */ else { /* */ for (index = 0; of_irq_map_one(np, index, &oirq) == 0; index++) { if (count > 15) break; virqs[count] = irq_create_of_mapping(oirq.controller, oirq.specifier, oirq.size); if (virqs[count] == NO_IRQ) { pr_err("event-sources: Unable to allocate " "interrupt number for %s\n", np->full_name); WARN_ON(1); } else count++; } } /* */ for (i = 0; i < count; i++) { if (request_irq(virqs[i], handler, 0, name, NULL)) { pr_err("event-sources: Unable to request interrupt " "%d for %s\n", virqs[i], np->full_name); WARN_ON(1); return; } } }