qup_i2c: Manage gpio configuration from runtime pm.
Due to gpio_request and gpio_free calls are made from
multiple places in i2c driver code and can cause erroneous
condition where same gpios are assigned/freed multiple times.
Move the gpio reques/free calls under runtime pm to
manage better.
CRs-Fixed: 432971
Change-Id: Ic44202e0743fa56806a0612243d3b800bad1433f
Signed-off-by: Alok Chauhan <alokc@codeaurora.org>
Signed-off-by: Manish Kumar <manishku@codeaurora.org>
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 92d162b..b562350 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -163,7 +163,7 @@
int wr_sz;
struct msm_i2c_platform_data *pdata;
int suspended;
- int clk_state;
+ int pwr_state;
struct mutex mlock;
void *complete;
int i2c_gpios[ARRAY_SIZE(i2c_rsrcs)];
@@ -327,7 +327,7 @@
static void
qup_i2c_pwr_mgmt(struct qup_i2c_dev *dev, unsigned int state)
{
- dev->clk_state = state;
+ dev->pwr_state = state;
if (state != 0) {
clk_prepare_enable(dev->clk);
if (!dev->pdata->keep_ahb_clk_on)
@@ -1228,10 +1228,6 @@
dev->i2c_gpios[i] = res ? res->start : -1;
}
- ret = qup_i2c_request_gpios(dev);
- if (ret)
- goto err_request_gpio_failed;
-
platform_set_drvdata(pdev, dev);
dev->one_bit_t = (USEC_PER_SEC/pdata->clk_freq) + 1;
@@ -1313,7 +1309,7 @@
pdata->msm_i2c_config_gpio(dev->adapter.nr, 1);
mutex_init(&dev->mlock);
- dev->clk_state = 0;
+ dev->pwr_state = 0;
/* If the same AHB clock is used on Modem side
* switch it on here itself and don't switch it
* on and off during suspend and resume.
@@ -1343,13 +1339,11 @@
err_request_irq_failed:
- qup_i2c_free_gpios(dev);
if (dev->gsbi)
iounmap(dev->gsbi);
err_reset_failed:
clk_disable_unprepare(dev->clk);
clk_disable_unprepare(dev->pclk);
-err_request_gpio_failed:
err_gsbi_failed:
iounmap(dev->base);
err_ioremap_failed:
@@ -1380,8 +1374,10 @@
dev->suspended = 1;
mutex_unlock(&dev->mlock);
mutex_destroy(&dev->mlock);
- if (dev->clk_state != 0)
+ if (dev->pwr_state != 0) {
qup_i2c_pwr_mgmt(dev, 0);
+ qup_i2c_free_gpios(dev);
+ }
platform_set_drvdata(pdev, NULL);
if (dev->num_irqs == 3) {
free_irq(dev->out_irq, dev);
@@ -1393,7 +1389,6 @@
clk_put(dev->pclk);
}
clk_put(dev->clk);
- qup_i2c_free_gpios(dev);
if (dev->gsbi)
iounmap(dev->gsbi);
iounmap(dev->base);
@@ -1425,9 +1420,10 @@
mutex_lock(&dev->mlock);
dev->suspended = 1;
mutex_unlock(&dev->mlock);
- if (dev->clk_state != 0)
+ if (dev->pwr_state != 0) {
qup_i2c_pwr_mgmt(dev, 0);
- qup_i2c_free_gpios(dev);
+ qup_i2c_free_gpios(dev);
+ }
return 0;
}
@@ -1435,10 +1431,14 @@
{
struct platform_device *pdev = to_platform_device(device);
struct qup_i2c_dev *dev = platform_get_drvdata(pdev);
+ int ret = 0;
dev_dbg(device, "pm_runtime: resuming...\n");
- BUG_ON(qup_i2c_request_gpios(dev) != 0);
- if (dev->clk_state == 0)
+ if (dev->pwr_state == 0) {
+ ret = qup_i2c_request_gpios(dev);
+ if (ret != 0)
+ return ret;
qup_i2c_pwr_mgmt(dev, 1);
+ }
dev->suspended = 0;
return 0;
}
@@ -1454,11 +1454,15 @@
static int qup_i2c_resume(struct device *device)
{
+ int ret = 0;
if (!pm_runtime_enabled(device) || !pm_runtime_suspended(device)) {
dev_dbg(device, "system resume");
- i2c_qup_pm_resume_runtime(device);
- pm_runtime_mark_last_busy(device);
- pm_request_autosuspend(device);
+ ret = i2c_qup_pm_resume_runtime(device);
+ if (!ret) {
+ pm_runtime_mark_last_busy(device);
+ pm_request_autosuspend(device);
+ }
+ return ret;
}
return 0;
}