Skip to content

Commit 6fe71bf

Browse files
committed
WORKAROUND: i2c: qcom-geni: Fix -EACCES error during system resume
When other drivers attempt I2C transfers during early resume phase, the I2C controller is still runtime suspended, causing pm_runtime_get_sync() to fail with -EACCES (-13): [ 101.914202] geni_i2c 980000.i2c: error turning SE resources:-13 The PM runtime core returns -EACCES when runtime PM is disabled (dev->power.disable_depth > 0). This occurs because: 1. During suspend_noirq, I2C driver calls geni_i2c_runtime_suspend() and then pm_runtime_disable() 2. I2C driver's noirq_resume only marks adapter as resumed but doesn't re-enable runtime PM or power up the hardware 3. Other drivers resuming later attempt I2C transfers 4. pm_runtime_get_sync() returns -EACCES because runtime PM is still disabled Fix this by calling pm_runtime_force_resume() in geni_i2c_resume_noirq() to properly resume the hardware and re-enable runtime PM during the noirq phase. This ensures the I2C controller is powered and ready for use when other drivers need it during resume. Upstream-Status: Pending Signed-off-by: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com> Signed-off-by: Mukesh Kumar Savaliya <mukesh.savaliya@oss.qualcomm.com>
1 parent d00f474 commit 6fe71bf

1 file changed

Lines changed: 22 additions & 2 deletions

File tree

drivers/i2c/busses/i2c-qcom-geni.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,8 +1064,14 @@ static int geni_i2c_probe(struct platform_device *pdev)
10641064
spin_lock_init(&gi2c->lock);
10651065
platform_set_drvdata(pdev, gi2c);
10661066

1067-
/* Keep interrupts disabled initially to allow for low-power modes */
1068-
ret = devm_request_irq(dev, gi2c->irq, geni_i2c_irq, IRQF_NO_AUTOEN,
1067+
/*
1068+
* Keep interrupts disabled initially to allow for low-power modes.
1069+
* IRQF_NO_SUSPEND: Keep IRQ enabled during suspend to handle I2C transfers
1070+
* in noirq phase (e.g., from PCIe driver's noirq_resume).
1071+
* IRQF_EARLY_RESUME: Enable IRQ early during resume sequence.
1072+
*/
1073+
ret = devm_request_irq(dev, gi2c->irq, geni_i2c_irq,
1074+
IRQF_NO_AUTOEN | IRQF_NO_SUSPEND | IRQF_EARLY_RESUME,
10691075
dev_name(dev), gi2c);
10701076
if (ret)
10711077
return dev_err_probe(dev, ret,
@@ -1283,6 +1289,20 @@ static int __maybe_unused geni_i2c_suspend_noirq(struct device *dev)
12831289
static int __maybe_unused geni_i2c_resume_noirq(struct device *dev)
12841290
{
12851291
struct geni_i2c_dev *gi2c = dev_get_drvdata(dev);
1292+
int ret = 0;
1293+
1294+
/*
1295+
* Resume hardware to handle I2C transfers from other drivers'
1296+
* noirq_resume callbacks (e.g., PCIe driver).
1297+
* pm_runtime_force_resume() properly handles PM state and usage_count.
1298+
*/
1299+
if (gi2c->suspended) {
1300+
ret = pm_runtime_force_resume(dev);
1301+
if (ret) {
1302+
dev_err(dev, "Failed to resume I2C during noirq: %d\n", ret);
1303+
return ret;
1304+
}
1305+
}
12861306

12871307
i2c_mark_adapter_resumed(&gi2c->adap);
12881308
return 0;

0 commit comments

Comments
 (0)