Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions drivers/i2c/busses/i2c-qcom-geni.c
Original file line number Diff line number Diff line change
Expand Up @@ -831,8 +831,14 @@ static int geni_i2c_probe(struct platform_device *pdev)
spin_lock_init(&gi2c->lock);
platform_set_drvdata(pdev, gi2c);

/* Keep interrupts disabled initially to allow for low-power modes */
ret = devm_request_irq(dev, gi2c->irq, geni_i2c_irq, IRQF_NO_AUTOEN,
/*
* Keep interrupts disabled initially to allow for low-power modes.
* IRQF_NO_SUSPEND: Keep IRQ enabled during suspend to handle I2C transfers
* in noirq phase (e.g., from PCIe driver's noirq_resume).
* IRQF_EARLY_RESUME: Enable IRQ early during resume sequence.
*/
ret = devm_request_irq(dev, gi2c->irq, geni_i2c_irq,
IRQF_NO_AUTOEN | IRQF_NO_SUSPEND | IRQF_EARLY_RESUME,
dev_name(dev), gi2c);
if (ret)
return dev_err_probe(dev, ret,
Expand Down Expand Up @@ -1044,6 +1050,20 @@ static int __maybe_unused geni_i2c_suspend_noirq(struct device *dev)
static int __maybe_unused geni_i2c_resume_noirq(struct device *dev)
{
struct geni_i2c_dev *gi2c = dev_get_drvdata(dev);
int ret = 0;

/*
* Resume hardware to handle I2C transfers from other drivers'
* noirq_resume callbacks (e.g., PCIe driver).
* pm_runtime_force_resume() properly handles PM state and usage_count.
*/
if (gi2c->suspended) {
ret = pm_runtime_force_resume(dev);
if (ret) {
dev_err(dev, "Failed to resume I2C during noirq: %d\n", ret);
return ret;
}
}

i2c_mark_adapter_resumed(&gi2c->adap);
return 0;
Expand Down