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