Skip to content

Commit 5f6d199

Browse files
Shenwei WangBartosz Golaszewski
authored andcommitted
gpio: mxc: release the parent IRQ in runtime suspend
Release the parent interrupt request during runtime suspend, allowing the parent interrupt controller to enter runtime suspend if there are no active users. This change may not have a visible impact if the parent controller is the GIC, but it can enable significant power savings for parent IRQ controllers like IRQSteer inside a subsystem on i.MX8 SoCs. Releasing the parent IRQ provides an opportunity for the subsystem to enter suspend states if there are no active users. Signed-off-by: Shenwei Wang <[email protected]> Reviewed-by: Andy Shevchenko <[email protected]> Signed-off-by: Bartosz Golaszewski <[email protected]>
1 parent b7df0f3 commit 5f6d199

File tree

1 file changed

+29
-12
lines changed

1 file changed

+29
-12
lines changed

drivers/gpio/gpio-mxc.c

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ struct mxc_gpio_port {
6262
struct clk *clk;
6363
int irq;
6464
int irq_high;
65+
void (*mx_irq_handler)(struct irq_desc *desc);
6566
struct irq_domain *domain;
6667
struct gpio_chip gc;
6768
struct device *dev;
@@ -399,6 +400,24 @@ static void mxc_gpio_free(struct gpio_chip *chip, unsigned int offset)
399400
pm_runtime_put(chip->parent);
400401
}
401402

403+
static void mxc_update_irq_chained_handler(struct mxc_gpio_port *port, bool enable)
404+
{
405+
if (enable)
406+
irq_set_chained_handler_and_data(port->irq, port->mx_irq_handler, port);
407+
else
408+
irq_set_chained_handler_and_data(port->irq, NULL, NULL);
409+
410+
/* setup handler for GPIO 16 to 31 */
411+
if (port->irq_high > 0) {
412+
if (enable)
413+
irq_set_chained_handler_and_data(port->irq_high,
414+
port->mx_irq_handler,
415+
port);
416+
else
417+
irq_set_chained_handler_and_data(port->irq_high, NULL, NULL);
418+
}
419+
}
420+
402421
static int mxc_gpio_probe(struct platform_device *pdev)
403422
{
404423
struct device_node *np = pdev->dev.of_node;
@@ -460,18 +479,12 @@ static int mxc_gpio_probe(struct platform_device *pdev)
460479
* the handler is needed only once, but doing it for every port
461480
* is more robust and easier.
462481
*/
463-
irq_set_chained_handler(port->irq, mx2_gpio_irq_handler);
464-
} else {
465-
/* setup one handler for each entry */
466-
irq_set_chained_handler_and_data(port->irq,
467-
mx3_gpio_irq_handler, port);
468-
if (port->irq_high > 0)
469-
/* setup handler for GPIO 16 to 31 */
470-
irq_set_chained_handler_and_data(port->irq_high,
471-
mx3_gpio_irq_handler,
472-
port);
473-
}
482+
port->irq_high = -1;
483+
port->mx_irq_handler = mx2_gpio_irq_handler;
484+
} else
485+
port->mx_irq_handler = mx3_gpio_irq_handler;
474486

487+
mxc_update_irq_chained_handler(port, true);
475488
err = bgpio_init(&port->gc, &pdev->dev, 4,
476489
port->base + GPIO_PSR,
477490
port->base + GPIO_DR, NULL,
@@ -604,6 +617,7 @@ static int mxc_gpio_runtime_suspend(struct device *dev)
604617

605618
mxc_gpio_save_regs(port);
606619
clk_disable_unprepare(port->clk);
620+
mxc_update_irq_chained_handler(port, false);
607621

608622
return 0;
609623
}
@@ -613,9 +627,12 @@ static int mxc_gpio_runtime_resume(struct device *dev)
613627
struct mxc_gpio_port *port = dev_get_drvdata(dev);
614628
int ret;
615629

630+
mxc_update_irq_chained_handler(port, true);
616631
ret = clk_prepare_enable(port->clk);
617-
if (ret)
632+
if (ret) {
633+
mxc_update_irq_chained_handler(port, false);
618634
return ret;
635+
}
619636

620637
mxc_gpio_restore_regs(port);
621638

0 commit comments

Comments
 (0)