static int irqc_probe(struct platform_device *pdev) { struct renesas_irqc_config *pdata = pdev->dev.platform_data; struct irqc_priv *p; struct resource *io; struct resource *irq; struct irq_chip *irq_chip; const char *name = dev_name(&pdev->dev); int ret; int k; p = kzalloc(sizeof(*p), GFP_KERNEL); if (!p) { dev_err(&pdev->dev, "failed to allocate driver data\n"); ret = -ENOMEM; goto err0; } /* deal with driver instance configuration */ if (pdata) memcpy(&p->config, pdata, sizeof(*pdata)); p->pdev = pdev; platform_set_drvdata(pdev, p); /* get hold of manadatory IOMEM */ io = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!io) { dev_err(&pdev->dev, "not enough IOMEM resources\n"); ret = -EINVAL; goto err1; } /* allow any number of IRQs between 1 and IRQC_IRQ_MAX */ for (k = 0; k < IRQC_IRQ_MAX; k++) { irq = platform_get_resource(pdev, IORESOURCE_IRQ, k); if (!irq) break; p->irq[k].p = p; p->irq[k].requested_irq = irq->start; } p->number_of_irqs = k; if (p->number_of_irqs < 1) { dev_err(&pdev->dev, "not enough IRQ resources\n"); ret = -EINVAL; goto err1; } /* ioremap IOMEM and setup read/write callbacks */ p->iomem = ioremap_nocache(io->start, resource_size(io)); if (!p->iomem) { dev_err(&pdev->dev, "failed to remap IOMEM\n"); ret = -ENXIO; goto err2; } p->cpu_int_base = p->iomem + IRQC_INT_CPU_BASE(0); /* SYS-SPI */ irq_chip = &p->irq_chip; irq_chip->name = name; irq_chip->irq_mask = irqc_irq_disable; irq_chip->irq_unmask = irqc_irq_enable; irq_chip->irq_enable = irqc_irq_enable; irq_chip->irq_disable = irqc_irq_disable; irq_chip->irq_set_type = irqc_irq_set_type; irq_chip->flags = IRQCHIP_SKIP_SET_WAKE; p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, p->number_of_irqs, p->config.irq_base, &irqc_irq_domain_ops, p); if (!p->irq_domain) { ret = -ENXIO; dev_err(&pdev->dev, "cannot initialize irq domain\n"); goto err2; } /* request interrupts one by one */ for (k = 0; k < p->number_of_irqs; k++) { if (request_irq(p->irq[k].requested_irq, irqc_irq_handler, 0, name, &p->irq[k])) { dev_err(&pdev->dev, "failed to request IRQ\n"); ret = -ENOENT; goto err3; } } dev_info(&pdev->dev, "driving %d irqs\n", p->number_of_irqs); /* warn in case of mismatch if irq base is specified */ if (p->config.irq_base) { if (p->config.irq_base != p->irq[0].domain_irq) dev_warn(&pdev->dev, "irq base mismatch (%d/%d)\n", p->config.irq_base, p->irq[0].domain_irq); } return 0; err3: for (; k >= 0; k--) free_irq(p->irq[k - 1].requested_irq, &p->irq[k - 1]); irq_domain_remove(p->irq_domain); err2: iounmap(p->iomem); err1: kfree(p); err0: return ret; }
static int irqc_probe(struct platform_device *pdev) { struct irqc_priv *p; struct resource *io; struct resource *irq; struct irq_chip *irq_chip; const char *name = dev_name(&pdev->dev); int ret; int k; p = kzalloc(sizeof(*p), GFP_KERNEL); if (!p) { dev_err(&pdev->dev, "failed to allocate driver data\n"); ret = -ENOMEM; goto err0; } p->pdev = pdev; platform_set_drvdata(pdev, p); p->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(p->clk)) { dev_warn(&pdev->dev, "unable to get clock\n"); p->clk = NULL; } pm_runtime_enable(&pdev->dev); pm_runtime_get_sync(&pdev->dev); /* get hold of manadatory IOMEM */ io = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!io) { dev_err(&pdev->dev, "not enough IOMEM resources\n"); ret = -EINVAL; goto err1; } /* allow any number of IRQs between 1 and IRQC_IRQ_MAX */ for (k = 0; k < IRQC_IRQ_MAX; k++) { irq = platform_get_resource(pdev, IORESOURCE_IRQ, k); if (!irq) break; p->irq[k].p = p; p->irq[k].requested_irq = irq->start; } p->number_of_irqs = k; if (p->number_of_irqs < 1) { dev_err(&pdev->dev, "not enough IRQ resources\n"); ret = -EINVAL; goto err1; } /* ioremap IOMEM and setup read/write callbacks */ p->iomem = ioremap_nocache(io->start, resource_size(io)); if (!p->iomem) { dev_err(&pdev->dev, "failed to remap IOMEM\n"); ret = -ENXIO; goto err2; } p->cpu_int_base = p->iomem + IRQC_INT_CPU_BASE(0); /* SYS-SPI */ irq_chip = &p->irq_chip; irq_chip->name = name; irq_chip->irq_mask = irqc_irq_disable; irq_chip->irq_unmask = irqc_irq_enable; irq_chip->irq_set_type = irqc_irq_set_type; irq_chip->irq_set_wake = irqc_irq_set_wake; irq_chip->flags = IRQCHIP_MASK_ON_SUSPEND; p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, p->number_of_irqs, 0, &irqc_irq_domain_ops, p); if (!p->irq_domain) { ret = -ENXIO; dev_err(&pdev->dev, "cannot initialize irq domain\n"); goto err2; } /* request interrupts one by one */ for (k = 0; k < p->number_of_irqs; k++) { if (request_irq(p->irq[k].requested_irq, irqc_irq_handler, 0, name, &p->irq[k])) { dev_err(&pdev->dev, "failed to request IRQ\n"); ret = -ENOENT; goto err3; } } dev_info(&pdev->dev, "driving %d irqs\n", p->number_of_irqs); return 0; err3: while (--k >= 0) free_irq(p->irq[k].requested_irq, &p->irq[k]); irq_domain_remove(p->irq_domain); err2: iounmap(p->iomem); err1: pm_runtime_put(&pdev->dev); pm_runtime_disable(&pdev->dev); kfree(p); err0: return ret; }