From: Carlos Song <carlos.song@xxxxxxx> Request the parent interrupt during runtime resume and release the parent interrupt dunring runtime suspend for allowing the parent interrupt controller to enter runtime suspend if there are no active users. No visible impact if the parent controller is the GIC, but it has 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: Carlos Song <carlos.song@xxxxxxx> Signed-off-by: Frank Li <Frank.Li@xxxxxxx> --- drivers/i2c/busses/i2c-imx-lpi2c.c | 40 ++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c index 23f83f10d5f6..0159ade235ef 100644 --- a/drivers/i2c/busses/i2c-imx-lpi2c.c +++ b/drivers/i2c/busses/i2c-imx-lpi2c.c @@ -168,6 +168,7 @@ struct lpi2c_imx_struct { struct i2c_adapter adapter; int num_clks; struct clk_bulk_data *clks; + int irq; void __iomem *base; __u8 *rx_buf; __u8 *tx_buf; @@ -1252,6 +1253,27 @@ static int lpi2c_dma_init(struct device *dev, dma_addr_t phy_addr) return ret; } +static int lpi2c_manage_irq_handler(struct lpi2c_imx_struct *lpi2c_imx, bool enable) +{ + int ret; + + if (enable) { + ret = devm_request_irq(lpi2c_imx->adapter.dev.parent, lpi2c_imx->irq, + lpi2c_imx_isr, IRQF_NO_SUSPEND, + dev_name(lpi2c_imx->adapter.dev.parent), + lpi2c_imx); + if (ret) { + dev_err(lpi2c_imx->adapter.dev.parent, "can't claim irq %d\n", + lpi2c_imx->irq); + return ret; + } + } else { + devm_free_irq(lpi2c_imx->adapter.dev.parent, lpi2c_imx->irq, lpi2c_imx); + } + + return 0; +} + static u32 lpi2c_imx_func(struct i2c_adapter *adapter) { return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | @@ -1277,7 +1299,7 @@ static int lpi2c_imx_probe(struct platform_device *pdev) struct resource *res; dma_addr_t phy_addr; unsigned int temp; - int irq, ret; + int ret; lpi2c_imx = devm_kzalloc(&pdev->dev, sizeof(*lpi2c_imx), GFP_KERNEL); if (!lpi2c_imx) @@ -1287,9 +1309,9 @@ static int lpi2c_imx_probe(struct platform_device *pdev) if (IS_ERR(lpi2c_imx->base)) return PTR_ERR(lpi2c_imx->base); - irq = platform_get_irq(pdev, 0); - if (irq < 0) - return irq; + lpi2c_imx->irq = platform_get_irq(pdev, 0); + if (lpi2c_imx->irq < 0) + return lpi2c_imx->irq; lpi2c_imx->adapter.owner = THIS_MODULE; lpi2c_imx->adapter.algo = &lpi2c_imx_algo; @@ -1309,10 +1331,9 @@ static int lpi2c_imx_probe(struct platform_device *pdev) if (ret) lpi2c_imx->bitrate = I2C_MAX_STANDARD_MODE_FREQ; - ret = devm_request_irq(&pdev->dev, irq, lpi2c_imx_isr, IRQF_NO_SUSPEND, - pdev->name, lpi2c_imx); + ret = lpi2c_manage_irq_handler(lpi2c_imx, true); if (ret) - return dev_err_probe(&pdev->dev, ret, "can't claim irq %d\n", irq); + return ret; i2c_set_adapdata(&lpi2c_imx->adapter, lpi2c_imx); platform_set_drvdata(pdev, lpi2c_imx); @@ -1392,6 +1413,7 @@ static int __maybe_unused lpi2c_runtime_suspend(struct device *dev) { struct lpi2c_imx_struct *lpi2c_imx = dev_get_drvdata(dev); + lpi2c_manage_irq_handler(lpi2c_imx, false); clk_bulk_disable(lpi2c_imx->num_clks, lpi2c_imx->clks); pinctrl_pm_select_sleep_state(dev); @@ -1410,6 +1432,10 @@ static int __maybe_unused lpi2c_runtime_resume(struct device *dev) return ret; } + ret = lpi2c_manage_irq_handler(lpi2c_imx, true); + if (ret) + return ret; + return 0; } -- 2.34.1