Messages in this thread Patch in this message | | | From | Stephen Warren <> | Subject | [PATCH] mfd: arizona: simplify use of shared IRQ | Date | Wed, 1 Aug 2012 14:37:35 -0600 |
| |
From: Stephen Warren <swarren@nvidia.com>
The Arizona core contains a shared IRQ line driven by multiple blocks, each represented as a separate regmap_irq_chip in the kernel.
The existing code avoids calling request_threaded_irq() with no handler multiple times on this shared interrupt line (which apparently wasn't supported or didn't work in the past) by using a handler that manually distributes the shared interrupt to each regmap_irq_chip. Since the IRQ core appears to support this now, simplify the code by removing the open-coded handler.
This also removes the top-level IRQ domain for the Arizona core. In theory, such a change would prevent this driver acting as an interrupt controller when instantiated from device tree. However, I don't believe that worked before, since the IRQ domain only contained the two virtual interrupts needed to invoke the regmap_irq_chip handlers, and hence did not allow the child interrupts to be translated anyway. Hence, this is unlikely to be a regression.
Signed-off-by: Stephen Warren <swarren@nvidia.com> --- One outstanding issue with this change is that it removes the pm_runtime calls from the interrupt handler thread. Equivalent code should presumably be added to regmap_irq_thread(). However, I haven't attempted this yet since I understand some pm_runtime support has already been added to regmap, so don't want to duplicate anything, although I haven't seen those changes yet to be sure.
Note: I have only compile-tested this particular change. However, I have runtime tested the same shared-interrupt logic in the MAX8907 driver which has a similar HW setup. --- drivers/mfd/arizona-irq.c | 101 ++++---------------------------------- include/linux/mfd/arizona/core.h | 1 - 2 files changed, 10 insertions(+), 92 deletions(-)
diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c index 98ac345..6b97876 100644 --- a/drivers/mfd/arizona-irq.c +++ b/drivers/mfd/arizona-irq.c @@ -91,66 +91,6 @@ static irqreturn_t arizona_ctrlif_err(int irq, void *data) return IRQ_HANDLED; } -static irqreturn_t arizona_irq_thread(int irq, void *data) -{ - struct arizona *arizona = data; - int i, ret; - - ret = pm_runtime_get_sync(arizona->dev); - if (ret < 0) { - dev_err(arizona->dev, "Failed to resume device: %d\n", ret); - return IRQ_NONE; - } - - /* Check both domains */ - for (i = 0; i < 2; i++) - handle_nested_irq(irq_find_mapping(arizona->virq, i)); - - pm_runtime_mark_last_busy(arizona->dev); - pm_runtime_put_autosuspend(arizona->dev); - - return IRQ_HANDLED; -} - -static void arizona_irq_enable(struct irq_data *data) -{ -} - -static void arizona_irq_disable(struct irq_data *data) -{ -} - -static struct irq_chip arizona_irq_chip = { - .name = "arizona", - .irq_disable = arizona_irq_disable, - .irq_enable = arizona_irq_enable, -}; - -static int arizona_irq_map(struct irq_domain *h, unsigned int virq, - irq_hw_number_t hw) -{ - struct regmap_irq_chip_data *data = h->host_data; - - irq_set_chip_data(virq, data); - irq_set_chip_and_handler(virq, &arizona_irq_chip, handle_edge_irq); - irq_set_nested_thread(virq, 1); - - /* ARM needs us to explicitly flag the IRQ as valid - * and will set them noprobe when we do so. */ -#ifdef CONFIG_ARM - set_irq_flags(virq, IRQF_VALID); -#else - irq_set_noprobe(virq); -#endif - - return 0; -} - -static struct irq_domain_ops arizona_domain_ops = { - .map = arizona_irq_map, - .xlate = irq_domain_xlate_twocell, -}; - int arizona_irq_init(struct arizona *arizona) { int flags = IRQF_ONESHOT; @@ -189,26 +129,18 @@ int arizona_irq_init(struct arizona *arizona) flags |= IRQF_TRIGGER_LOW; } - /* Allocate a virtual IRQ domain to distribute to the regmap domains */ - arizona->virq = irq_domain_add_linear(NULL, 2, &arizona_domain_ops, - arizona); - if (!arizona->virq) { - ret = -EINVAL; - goto err; - } + irq_set_status_flags(arizona->irq, IRQ_NOAUTOEN); - ret = regmap_add_irq_chip(arizona->regmap, - irq_create_mapping(arizona->virq, 0), - IRQF_ONESHOT, -1, aod, + ret = regmap_add_irq_chip(arizona->regmap, arizona->irq, + IRQF_ONESHOT | IRQF_SHARED, -1, aod, &arizona->aod_irq_chip); if (ret != 0) { dev_err(arizona->dev, "Failed to add AOD IRQs: %d\n", ret); goto err_domain; } - ret = regmap_add_irq_chip(arizona->regmap, - irq_create_mapping(arizona->virq, 1), - IRQF_ONESHOT, -1, irq, + ret = regmap_add_irq_chip(arizona->regmap, arizona->irq, + IRQF_ONESHOT | IRQF_SHARED, -1, irq, &arizona->irq_chip); if (ret != 0) { dev_err(arizona->dev, "Failed to add AOD IRQs: %d\n", ret); @@ -235,27 +167,16 @@ int arizona_irq_init(struct arizona *arizona) goto err_ctrlif; } - ret = request_threaded_irq(arizona->irq, NULL, arizona_irq_thread, - flags, "arizona", arizona); - - if (ret != 0) { - dev_err(arizona->dev, "Failed to request IRQ %d: %d\n", - arizona->irq, ret); - goto err_main_irq; - } + enable_irq(arizona->irq); return 0; -err_main_irq: - free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR), arizona); err_ctrlif: free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_BOOT_DONE), arizona); err_boot_done: - regmap_del_irq_chip(irq_create_mapping(arizona->virq, 1), - arizona->irq_chip); + regmap_del_irq_chip(arizona->irq, arizona->irq_chip); err_aod: - regmap_del_irq_chip(irq_create_mapping(arizona->virq, 0), - arizona->aod_irq_chip); + regmap_del_irq_chip(arizona->irq, arizona->aod_irq_chip); err_domain: err: return ret; @@ -265,10 +186,8 @@ int arizona_irq_exit(struct arizona *arizona) { free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR), arizona); free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_BOOT_DONE), arizona); - regmap_del_irq_chip(irq_create_mapping(arizona->virq, 1), - arizona->irq_chip); - regmap_del_irq_chip(irq_create_mapping(arizona->virq, 0), - arizona->aod_irq_chip); + regmap_del_irq_chip(arizona->irq, arizona->irq_chip); + regmap_del_irq_chip(arizona->irq, arizona->aod_irq_chip); free_irq(arizona->irq, arizona); return 0; diff --git a/include/linux/mfd/arizona/core.h b/include/linux/mfd/arizona/core.h index dd231ac..b9e758b 100644 --- a/include/linux/mfd/arizona/core.h +++ b/include/linux/mfd/arizona/core.h @@ -92,7 +92,6 @@ struct arizona { struct arizona_pdata pdata; int irq; - struct irq_domain *virq; struct regmap_irq_chip_data *aod_irq_chip; struct regmap_irq_chip_data *irq_chip; -- 1.7.0.4
| |