summaryrefslogtreecommitdiff
path: root/drivers/irqchip/irq-renesas-irqc.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-07-08 11:01:13 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2019-07-08 11:01:13 -0700
commit2a1ccd31420a7b1acd6ca37b2bec2d723aa093e4 (patch)
tree43946f0c4afc7dce86fc055df48d661f8ed3999c /drivers/irqchip/irq-renesas-irqc.c
parente0e86b111bca6bbf746c03ec5cf3e6a61fa3f8e9 (diff)
parent3a1d24ca9573fbc74a3d32c972c333b161e0e9dc (diff)
downloadlinux-2a1ccd31420a7b1acd6ca37b2bec2d723aa093e4.tar.gz
linux-2a1ccd31420a7b1acd6ca37b2bec2d723aa093e4.tar.bz2
linux-2a1ccd31420a7b1acd6ca37b2bec2d723aa093e4.zip
Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq updates from Thomas Gleixner: "The irq departement provides the usual mixed bag: Core: - Further improvements to the irq timings code which aims to predict the next interrupt for power state selection to achieve better latency/power balance - Add interrupt statistics to the core NMI handlers - The usual small fixes and cleanups Drivers: - Support for Renesas RZ/A1, Annapurna Labs FIC, Meson-G12A SoC and Amazon Gravition AMR/GIC interrupt controllers. - Rework of the Renesas INTC controller driver - ACPI support for Socionext SoCs - Enhancements to the CSKY interrupt controller - The usual small fixes and cleanups" * 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (39 commits) irq/irqdomain: Fix comment typo genirq: Update irq stats from NMI handlers irqchip/gic-pm: Remove PM_CLK dependency irqchip/al-fic: Introduce Amazon's Annapurna Labs Fabric Interrupt Controller Driver dt-bindings: interrupt-controller: Add Amazon's Annapurna Labs FIC softirq: Use __this_cpu_write() in takeover_tasklets() irqchip/mbigen: Stop printing kernel addresses irqchip/gic: Add dependency for ARM_GIC_MAX_NR genirq/affinity: Remove unused argument from [__]irq_build_affinity_masks() genirq/timings: Add selftest for next event computation genirq/timings: Add selftest for irqs circular buffer genirq/timings: Add selftest for circular array genirq/timings: Encapsulate storing function genirq/timings: Encapsulate timings push genirq/timings: Optimize the period detection speed genirq/timings: Fix timings buffer inspection genirq/timings: Fix next event index function irqchip/qcom: Use struct_size() in devm_kzalloc() irqchip/irq-csky-mpintc: Remove unnecessary loop in interrupt handler dt-bindings: interrupt-controller: Update csky mpintc ...
Diffstat (limited to 'drivers/irqchip/irq-renesas-irqc.c')
-rw-r--r--drivers/irqchip/irq-renesas-irqc.c91
1 files changed, 32 insertions, 59 deletions
diff --git a/drivers/irqchip/irq-renesas-irqc.c b/drivers/irqchip/irq-renesas-irqc.c
index a449a7c839b3..11abc09ef76c 100644
--- a/drivers/irqchip/irq-renesas-irqc.c
+++ b/drivers/irqchip/irq-renesas-irqc.c
@@ -7,7 +7,6 @@
#include <linux/init.h>
#include <linux/platform_device.h>
-#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/io.h>
@@ -48,7 +47,7 @@ struct irqc_priv {
void __iomem *cpu_int_base;
struct irqc_irq irq[IRQC_IRQ_MAX];
unsigned int number_of_irqs;
- struct platform_device *pdev;
+ struct device *dev;
struct irq_chip_generic *gc;
struct irq_domain *irq_domain;
atomic_t wakeup_path;
@@ -61,8 +60,7 @@ static struct irqc_priv *irq_data_to_priv(struct irq_data *data)
static void irqc_dbg(struct irqc_irq *i, char *str)
{
- dev_dbg(&i->p->pdev->dev, "%s (%d:%d)\n",
- str, i->requested_irq, i->hw_irq);
+ dev_dbg(i->p->dev, "%s (%d:%d)\n", str, i->requested_irq, i->hw_irq);
}
static unsigned char irqc_sense[IRQ_TYPE_SENSE_MASK + 1] = {
@@ -125,33 +123,22 @@ static irqreturn_t irqc_irq_handler(int irq, void *dev_id)
static int irqc_probe(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
+ const char *name = dev_name(dev);
struct irqc_priv *p;
- struct resource *io;
struct resource *irq;
- 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 = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
- p->pdev = pdev;
+ p->dev = dev;
platform_set_drvdata(pdev, p);
- 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;
- }
+ pm_runtime_enable(dev);
+ pm_runtime_get_sync(dev);
/* allow any number of IRQs between 1 and IRQC_IRQ_MAX */
for (k = 0; k < IRQC_IRQ_MAX; k++) {
@@ -166,42 +153,41 @@ static int irqc_probe(struct platform_device *pdev)
p->number_of_irqs = k;
if (p->number_of_irqs < 1) {
- dev_err(&pdev->dev, "not enough IRQ resources\n");
+ dev_err(dev, "not enough IRQ resources\n");
ret = -EINVAL;
- goto err1;
+ goto err_runtime_pm_disable;
}
/* 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->iomem = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(p->iomem)) {
+ ret = PTR_ERR(p->iomem);
+ goto err_runtime_pm_disable;
}
p->cpu_int_base = p->iomem + IRQC_INT_CPU_BASE(0); /* SYS-SPI */
- p->irq_domain = irq_domain_add_linear(pdev->dev.of_node,
- p->number_of_irqs,
+ p->irq_domain = irq_domain_add_linear(dev->of_node, p->number_of_irqs,
&irq_generic_chip_ops, p);
if (!p->irq_domain) {
ret = -ENXIO;
- dev_err(&pdev->dev, "cannot initialize irq domain\n");
- goto err2;
+ dev_err(dev, "cannot initialize irq domain\n");
+ goto err_runtime_pm_disable;
}
ret = irq_alloc_domain_generic_chips(p->irq_domain, p->number_of_irqs,
- 1, name, handle_level_irq,
+ 1, "irqc", handle_level_irq,
0, 0, IRQ_GC_INIT_NESTED_LOCK);
if (ret) {
- dev_err(&pdev->dev, "cannot allocate generic chip\n");
- goto err3;
+ dev_err(dev, "cannot allocate generic chip\n");
+ goto err_remove_domain;
}
p->gc = irq_get_domain_generic_chip(p->irq_domain, 0);
p->gc->reg_base = p->cpu_int_base;
p->gc->chip_types[0].regs.enable = IRQC_EN_SET;
p->gc->chip_types[0].regs.disable = IRQC_EN_STS;
+ p->gc->chip_types[0].chip.parent_device = dev;
p->gc->chip_types[0].chip.irq_mask = irq_gc_mask_disable_reg;
p->gc->chip_types[0].chip.irq_unmask = irq_gc_unmask_enable_reg;
p->gc->chip_types[0].chip.irq_set_type = irqc_irq_set_type;
@@ -210,46 +196,33 @@ static int irqc_probe(struct platform_device *pdev)
/* 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");
+ if (devm_request_irq(dev, p->irq[k].requested_irq,
+ irqc_irq_handler, 0, name, &p->irq[k])) {
+ dev_err(dev, "failed to request IRQ\n");
ret = -ENOENT;
- goto err4;
+ goto err_remove_domain;
}
}
- dev_info(&pdev->dev, "driving %d irqs\n", p->number_of_irqs);
+ dev_info(dev, "driving %d irqs\n", p->number_of_irqs);
return 0;
-err4:
- while (--k >= 0)
- free_irq(p->irq[k].requested_irq, &p->irq[k]);
-err3:
+err_remove_domain:
irq_domain_remove(p->irq_domain);
-err2:
- iounmap(p->iomem);
-err1:
- pm_runtime_put(&pdev->dev);
- pm_runtime_disable(&pdev->dev);
- kfree(p);
-err0:
+err_runtime_pm_disable:
+ pm_runtime_put(dev);
+ pm_runtime_disable(dev);
return ret;
}
static int irqc_remove(struct platform_device *pdev)
{
struct irqc_priv *p = platform_get_drvdata(pdev);
- int k;
-
- for (k = 0; k < p->number_of_irqs; k++)
- free_irq(p->irq[k].requested_irq, &p->irq[k]);
irq_domain_remove(p->irq_domain);
- iounmap(p->iomem);
pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev);
- kfree(p);
return 0;
}