spi_qsd: Runtime configuration of spi gpio's

Configure the spi clk, mosi, miso, cs gpio's on per
transaction basis and unconfigure otherwise.
It will remove the conflicts if same gpio's are
being used by different modules if no SPI device
is present.

CRs-Fixed: 387043
Change-Id: Ib5c3bfbd13681f4aee0c4a815b19f423c586e160
Signed-off-by: Alok Chauhan <alokc@codeaurora.org>
(cherry picked from commit 66554a1317d40fbacd1a7e1e3210de8fb947ad57)

Signed-off-by: Sudhir Sharma <sudsha@codeaurora.org>
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index 9f3327a..18bc936 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.c
@@ -1294,6 +1294,7 @@
 		container_of(work, struct msm_spi, work_data);
 	unsigned long        flags;
 	u32                  status_error = 0;
+	int                  rc = 0;
 
 	mutex_lock(&dd->core_lock);
 
@@ -1304,6 +1305,21 @@
 	if (dd->use_rlock)
 		remote_mutex_lock(&dd->r_lock);
 
+	/* Configure the spi clk, miso, mosi and cs gpio */
+	if (dd->pdata->gpio_config) {
+		rc = dd->pdata->gpio_config();
+		if (rc) {
+			dev_err(dd->dev,
+					"%s: error configuring GPIOs\n",
+					__func__);
+			status_error = 1;
+		}
+	}
+
+	rc = msm_spi_request_gpios(dd);
+	if (rc)
+		status_error = 1;
+
 	clk_prepare_enable(dd->clk);
 	clk_prepare_enable(dd->pclk);
 	msm_spi_enable_irqs(dd);
@@ -1335,6 +1351,12 @@
 	clk_disable_unprepare(dd->clk);
 	clk_disable_unprepare(dd->pclk);
 
+	/* Free  the spi clk, miso, mosi, cs gpio */
+	if (!rc && dd->pdata && dd->pdata->gpio_release)
+		dd->pdata->gpio_release();
+	if (!rc)
+		msm_spi_free_gpios(dd);
+
 	if (dd->use_rlock)
 		remote_mutex_unlock(&dd->r_lock);
 
@@ -1421,6 +1443,24 @@
 	if (dd->use_rlock)
 		remote_mutex_lock(&dd->r_lock);
 
+	/* Configure the spi clk, miso, mosi, cs gpio */
+	if (dd->pdata->gpio_config) {
+		rc = dd->pdata->gpio_config();
+		if (rc) {
+			dev_err(&spi->dev,
+					"%s: error configuring GPIOs\n",
+					__func__);
+			rc = -ENXIO;
+			goto err_setup_gpio;
+		}
+	}
+
+	rc = msm_spi_request_gpios(dd);
+	if (rc) {
+		rc = -ENXIO;
+		goto err_setup_gpio;
+	}
+
 	clk_prepare_enable(dd->clk);
 	clk_prepare_enable(dd->pclk);
 
@@ -1453,10 +1493,15 @@
 	clk_disable_unprepare(dd->clk);
 	clk_disable_unprepare(dd->pclk);
 
+	/* Free  the spi clk, miso, mosi, cs gpio */
+	if (dd->pdata && dd->pdata->gpio_release)
+		dd->pdata->gpio_release();
+	msm_spi_free_gpios(dd);
+
+err_setup_gpio:
 	if (dd->use_rlock)
 		remote_mutex_unlock(&dd->r_lock);
 	mutex_unlock(&dd->core_lock);
-
 err_setup_exit:
 	return rc;
 }
@@ -1893,22 +1938,9 @@
 			dd->use_dma = 1;
 			master->dma_alignment =	dma_get_cache_alignment();
 		}
-
-skip_dma_resources:
-		if (pdata->gpio_config) {
-			rc = pdata->gpio_config();
-			if (rc) {
-				dev_err(&pdev->dev,
-					"%s: error configuring GPIOs\n",
-					__func__);
-				goto err_probe_gpio;
-			}
-		}
 	}
 
-	rc = msm_spi_request_gpios(dd);
-	if (rc)
-		goto err_probe_gpio;
+skip_dma_resources:
 
 	spin_lock_init(&dd->queue_lock);
 	mutex_init(&dd->core_lock);
@@ -1947,8 +1979,8 @@
 
 		dd->use_rlock = 1;
 		dd->pm_lat = pdata->pm_lat;
-		pm_qos_add_request(&qos_req_list, PM_QOS_CPU_DMA_LATENCY, 
-					    	 PM_QOS_DEFAULT_VALUE);
+		pm_qos_add_request(&qos_req_list, PM_QOS_CPU_DMA_LATENCY,
+					PM_QOS_DEFAULT_VALUE);
 	}
 
 	mutex_lock(&dd->core_lock);
@@ -2077,10 +2109,6 @@
 err_probe_reqmem:
 	destroy_workqueue(dd->workqueue);
 err_probe_workq:
-	msm_spi_free_gpios(dd);
-err_probe_gpio:
-	if (pdata && pdata->gpio_release)
-		pdata->gpio_release();
 err_probe_res:
 	spi_master_put(master);
 err_probe_exit:
@@ -2107,7 +2135,6 @@
 
 	/* Wait for transactions to end, or time out */
 	wait_event_interruptible(dd->continue_suspend, !dd->transfer_pending);
-	msm_spi_free_gpios(dd);
 
 suspend_exit:
 	return 0;
@@ -2124,7 +2151,6 @@
 	if (!dd)
 		goto resume_exit;
 
-	BUG_ON(msm_spi_request_gpios(dd) != 0);
 	dd->suspended = 0;
 resume_exit:
 	return 0;
@@ -2138,17 +2164,13 @@
 {
 	struct spi_master *master = platform_get_drvdata(pdev);
 	struct msm_spi    *dd = spi_master_get_devdata(master);
-	struct msm_spi_platform_data *pdata = pdev->dev.platform_data;
 
 	pm_qos_remove_request(&qos_req_list);
 	spi_debugfs_exit(dd);
 	sysfs_remove_group(&pdev->dev.kobj, &dev_attr_grp);
 
 	msm_spi_teardown_dma(dd);
-	if (pdata && pdata->gpio_release)
-		pdata->gpio_release();
 
-	msm_spi_free_gpios(dd);
 	clk_put(dd->clk);
 	clk_put(dd->pclk);
 	destroy_workqueue(dd->workqueue);