diff options
Diffstat (limited to 'drivers/irqchip/irq-imx-irqsteer.c')
-rw-r--r-- | drivers/irqchip/irq-imx-irqsteer.c | 42 |
1 files changed, 31 insertions, 11 deletions
diff --git a/drivers/irqchip/irq-imx-irqsteer.c b/drivers/irqchip/irq-imx-irqsteer.c index 20cf7a9e9ece..6dc9ac48fee5 100644 --- a/drivers/irqchip/irq-imx-irqsteer.c +++ b/drivers/irqchip/irq-imx-irqsteer.c @@ -24,7 +24,7 @@ #define CHAN_MINTDIS(t) (CTRL_STRIDE_OFF(t, 3) + 0x4) #define CHAN_MASTRSTAT(t) (CTRL_STRIDE_OFF(t, 3) + 0x8) -#define CHAN_MAX_OUTPUT_INT 0x8 +#define CHAN_MAX_OUTPUT_INT 0xF struct irqsteer_data { void __iomem *regs; @@ -36,6 +36,7 @@ struct irqsteer_data { int channel; struct irq_domain *domain; u32 *saved_reg; + struct device *dev; }; static int imx_irqsteer_get_reg_index(struct irqsteer_data *data, @@ -72,10 +73,26 @@ static void imx_irqsteer_irq_mask(struct irq_data *d) raw_spin_unlock_irqrestore(&data->lock, flags); } +static void imx_irqsteer_irq_bus_lock(struct irq_data *d) +{ + struct irqsteer_data *data = d->chip_data; + + pm_runtime_get_sync(data->dev); +} + +static void imx_irqsteer_irq_bus_sync_unlock(struct irq_data *d) +{ + struct irqsteer_data *data = d->chip_data; + + pm_runtime_put_autosuspend(data->dev); +} + static const struct irq_chip imx_irqsteer_irq_chip = { - .name = "irqsteer", - .irq_mask = imx_irqsteer_irq_mask, - .irq_unmask = imx_irqsteer_irq_unmask, + .name = "irqsteer", + .irq_mask = imx_irqsteer_irq_mask, + .irq_unmask = imx_irqsteer_irq_unmask, + .irq_bus_lock = imx_irqsteer_irq_bus_lock, + .irq_bus_sync_unlock = imx_irqsteer_irq_bus_sync_unlock, }; static int imx_irqsteer_irq_map(struct irq_domain *h, unsigned int irq, @@ -150,6 +167,7 @@ static int imx_irqsteer_probe(struct platform_device *pdev) if (!data) return -ENOMEM; + data->dev = &pdev->dev; data->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(data->regs)) { dev_err(&pdev->dev, "failed to initialize reg\n"); @@ -194,7 +212,7 @@ static int imx_irqsteer_probe(struct platform_device *pdev) /* steer all IRQs into configured channel */ writel_relaxed(BIT(data->channel), data->regs + CHANCTRL); - data->domain = irq_domain_add_linear(np, data->reg_num * 32, + data->domain = irq_domain_create_linear(of_fwnode_handle(np), data->reg_num * 32, &imx_irqsteer_domain_ops, data); if (!data->domain) { dev_err(&pdev->dev, "failed to create IRQ domain\n"); @@ -210,10 +228,8 @@ static int imx_irqsteer_probe(struct platform_device *pdev) for (i = 0; i < data->irq_count; i++) { data->irq[i] = irq_of_parse_and_map(np, i); - if (!data->irq[i]) { - ret = -EINVAL; - goto out; - } + if (!data->irq[i]) + break; irq_set_chained_handler_and_data(data->irq[i], imx_irqsteer_irq_handler, @@ -236,9 +252,13 @@ static void imx_irqsteer_remove(struct platform_device *pdev) struct irqsteer_data *irqsteer_data = platform_get_drvdata(pdev); int i; - for (i = 0; i < irqsteer_data->irq_count; i++) + for (i = 0; i < irqsteer_data->irq_count; i++) { + if (!irqsteer_data->irq[i]) + break; + irq_set_chained_handler_and_data(irqsteer_data->irq[i], NULL, NULL); + } irq_domain_remove(irqsteer_data->domain); @@ -310,6 +330,6 @@ static struct platform_driver imx_irqsteer_driver = { .pm = &imx_irqsteer_pm_ops, }, .probe = imx_irqsteer_probe, - .remove_new = imx_irqsteer_remove, + .remove = imx_irqsteer_remove, }; builtin_platform_driver(imx_irqsteer_driver); |