i2c: qcom: geni: Turn off resources during system-suspend if needed
I2C clients may need the bus to do transactions while system suspend
is in progress. While Runtime-PM resume turns on resources
successfully for such transactions, runtime-suspend callback is not
called by put_sync method to avoid race between runtime PM and system
PM frameworks.
Turn off resources if this condition is detected during I2C bus
system suspend callback, and set the runtime-PM status to be
consistent with the hardware. If however, transaction is still
ongoing during noirq suspend callback, abort suspend by returning
-EBUSY.
Change-Id: Id93afa765bf97babcb6a9c6922d25f108afdc7f3
Signed-off-by: Sagar Dharia <sdharia@codeaurora.org>
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c
index 7e9999b..2460ba7 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -910,8 +910,23 @@
static int geni_i2c_suspend_noirq(struct device *device)
{
- if (!pm_runtime_status_suspended(device))
+ struct geni_i2c_dev *gi2c = dev_get_drvdata(device);
+ int ret;
+
+ /* Make sure no transactions are pending */
+ ret = i2c_trylock_bus(&gi2c->adap, I2C_LOCK_SEGMENT);
+ if (!ret) {
+ GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
+ "late I2C transaction request\n");
return -EBUSY;
+ }
+ if (!pm_runtime_status_suspended(device)) {
+ geni_i2c_runtime_suspend(device);
+ pm_runtime_disable(device);
+ pm_runtime_set_suspended(device);
+ pm_runtime_enable(device);
+ }
+ i2c_unlock_bus(&gi2c->adap, I2C_LOCK_SEGMENT);
return 0;
}
#else