Skip to content

Commit 4262df2

Browse files
NXP-CarlosSongAndi Shyti
authored andcommitted
i2c: imx-lpi2c: make controller available until the system enters suspend_noirq() and from resume_noirq().
This is a general i2c controller feature. Some I2C devices may need the I2C controller to remain active during resume_noirq() or suspend_noirq(). If the controller is autosuspended, there is no way to wake it up once runtime PM disabled (in suspend_late()). During system resume, the I2C controller will be available only after runtime PM is re-enabled (in resume_early()). However, this may be too late for some devices. Wake up the controller in the suspend() callback while runtime PM is still enabled. The I2C controller will remain available until the suspend_noirq() callback (pm_runtime_force_suspend()) is called. During resume, the I2C controller can be restored by the resume_noirq() callback (pm_runtime_force_resume()). Finally, the resume() callback re-enables autosuspend. As a result, the I2C controller can remain available until the system enters suspend_noirq() and from resume_noirq(). Signed-off-by: Carlos Song <carlos.song@nxp.com> Link: https://lore.kernel.org/r/20241227084736.1323943-1-carlos.song@nxp.com Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
1 parent 8abbc71 commit 4262df2

File tree

1 file changed

+35
-1
lines changed

1 file changed

+35
-1
lines changed

drivers/i2c/busses/i2c-imx-lpi2c.c

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1318,7 +1318,7 @@ static int lpi2c_imx_probe(struct platform_device *pdev)
13181318
if (ret)
13191319
lpi2c_imx->bitrate = I2C_MAX_STANDARD_MODE_FREQ;
13201320

1321-
ret = devm_request_irq(&pdev->dev, irq, lpi2c_imx_isr, 0,
1321+
ret = devm_request_irq(&pdev->dev, irq, lpi2c_imx_isr, IRQF_NO_SUSPEND,
13221322
pdev->name, lpi2c_imx);
13231323
if (ret)
13241324
return dev_err_probe(&pdev->dev, ret, "can't claim irq %d\n", irq);
@@ -1447,9 +1447,43 @@ static int __maybe_unused lpi2c_resume_noirq(struct device *dev)
14471447
return 0;
14481448
}
14491449

1450+
static int lpi2c_suspend(struct device *dev)
1451+
{
1452+
/*
1453+
* Some I2C devices may need the I2C controller to remain active
1454+
* during resume_noirq() or suspend_noirq(). If the controller is
1455+
* autosuspended, there is no way to wake it up once runtime PM is
1456+
* disabled (in suspend_late()).
1457+
*
1458+
* During system resume, the I2C controller will be available only
1459+
* after runtime PM is re-enabled (in resume_early()). However, this
1460+
* may be too late for some devices.
1461+
*
1462+
* Wake up the controller in the suspend() callback while runtime PM
1463+
* is still enabled. The I2C controller will remain available until
1464+
* the suspend_noirq() callback (pm_runtime_force_suspend()) is
1465+
* called. During resume, the I2C controller can be restored by the
1466+
* resume_noirq() callback (pm_runtime_force_resume()).
1467+
*
1468+
* Finally, the resume() callback re-enables autosuspend, ensuring
1469+
* the I2C controller remains available until the system enters
1470+
* suspend_noirq() and from resume_noirq().
1471+
*/
1472+
return pm_runtime_resume_and_get(dev);
1473+
}
1474+
1475+
static int lpi2c_resume(struct device *dev)
1476+
{
1477+
pm_runtime_mark_last_busy(dev);
1478+
pm_runtime_put_autosuspend(dev);
1479+
1480+
return 0;
1481+
}
1482+
14501483
static const struct dev_pm_ops lpi2c_pm_ops = {
14511484
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(lpi2c_suspend_noirq,
14521485
lpi2c_resume_noirq)
1486+
SYSTEM_SLEEP_PM_OPS(lpi2c_suspend, lpi2c_resume)
14531487
SET_RUNTIME_PM_OPS(lpi2c_runtime_suspend,
14541488
lpi2c_runtime_resume, NULL)
14551489
};

0 commit comments

Comments
 (0)