spi_qsd: GPIO configuration changes for SPI chip-select line
The chip-select GPIO's pertaining to each slave remains in suspended
configuration until the first transfer is intiated by the slave.
Change-Id: I3aa8555289be7ce457b91a969cf03909be0965d7
Signed-off-by: Harini Jayaraman <harinij@codeaurora.org>
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index 4896556..aaeb790 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.c
@@ -172,11 +172,17 @@
static char const * const spi_rsrcs[] = {
"spi_clk",
- "spi_cs",
"spi_miso",
"spi_mosi"
};
+static char const * const spi_cs_rsrcs[] = {
+ "spi_cs",
+ "spi_cs1",
+ "spi_cs2",
+ "spi_cs3",
+};
+
enum msm_spi_mode {
SPI_FIFO_MODE = 0x0, /* 00 */
SPI_BLOCK_MODE = 0x1, /* 01 */
@@ -184,6 +190,12 @@
SPI_MODE_NONE = 0xFF, /* invalid value */
};
+/* Structure for SPI CS GPIOs */
+struct spi_cs_gpio {
+ int gpio_num;
+ bool valid;
+};
+
/* Structures for Data Mover */
struct spi_dmov_cmd {
dmov_box box; /* data aligned to max(dm_burst_size, block_size)
@@ -330,8 +342,10 @@
struct spi_transfer *cur_rx_transfer;
/* Temporary buffer used for WR-WR or WR-RD transfers */
u8 *temp_buf;
- /* GPIO pin numbers for SPI clk, cs, miso and mosi */
+ /* GPIO pin numbers for SPI clk, miso and mosi */
int spi_gpios[ARRAY_SIZE(spi_rsrcs)];
+ /* SPI CS GPIOs for each slave */
+ struct spi_cs_gpio cs_gpios[ARRAY_SIZE(spi_cs_rsrcs)];
};
/* Forward declaration */
@@ -635,8 +649,8 @@
if (dd->spi_gpios[i] >= 0) {
result = gpio_request(dd->spi_gpios[i], spi_rsrcs[i]);
if (result) {
- pr_err("%s: gpio_request for pin %d failed\
- with error%d\n", __func__,
+ dev_err(dd->dev, "%s: gpio_request for pin %d "
+ "failed with error %d\n", __func__,
dd->spi_gpios[i], result);
goto error;
}
@@ -660,6 +674,13 @@
if (dd->spi_gpios[i] >= 0)
gpio_free(dd->spi_gpios[i]);
}
+
+ for (i = 0; i < ARRAY_SIZE(spi_cs_rsrcs); ++i) {
+ if (dd->cs_gpios[i].valid) {
+ gpio_free(dd->cs_gpios[i].gpio_num);
+ dd->cs_gpios[i].valid = 0;
+ }
+ }
}
static void msm_spi_clock_set(struct msm_spi *dd, int speed)
@@ -1652,7 +1673,24 @@
static void msm_spi_process_message(struct msm_spi *dd)
{
int xfrs_grped = 0;
+ int cs_num;
+ int rc;
+
dd->write_xfr_cnt = dd->read_xfr_cnt = 0;
+ cs_num = dd->cur_msg->spi->chip_select;
+ if ((!(dd->cur_msg->spi->mode & SPI_LOOP)) &&
+ (!(dd->cs_gpios[cs_num].valid)) &&
+ (dd->cs_gpios[cs_num].gpio_num >= 0)) {
+ rc = gpio_request(dd->cs_gpios[cs_num].gpio_num,
+ spi_cs_rsrcs[cs_num]);
+ if (rc) {
+ dev_err(dd->dev, "gpio_request for pin %d failed with "
+ "error %d\n", dd->cs_gpios[cs_num].gpio_num,
+ rc);
+ return;
+ }
+ dd->cs_gpios[cs_num].valid = 1;
+ }
dd->cur_transfer = list_first_entry(&dd->cur_msg->transfers,
struct spi_transfer,
@@ -1664,7 +1702,7 @@
&dd->cur_msg->transfers,
transfer_list) {
if (!dd->cur_transfer->len)
- return;
+ goto error;
if (xfrs_grped) {
xfrs_grped--;
continue;
@@ -1686,12 +1724,20 @@
int ret = msm_spi_map_dma_buffers(dd);
if (ret < 0) {
dd->cur_msg->status = ret;
- return;
+ goto error;
}
}
dd->cur_tx_transfer = dd->cur_rx_transfer = dd->cur_transfer;
msm_spi_process_transfer(dd);
}
+
+ return;
+
+error:
+ if (dd->cs_gpios[cs_num].valid) {
+ gpio_free(dd->cs_gpios[cs_num].gpio_num);
+ dd->cs_gpios[cs_num].valid = 0;
+ }
}
/* workqueue - pull messages from queue & process */
@@ -2257,9 +2303,17 @@
dd->spi_gpios[i] = resource ? resource->start : -1;
}
+ for (i = 0; i < ARRAY_SIZE(spi_cs_rsrcs); ++i) {
+ resource = platform_get_resource_byname(pdev, IORESOURCE_IO,
+ spi_cs_rsrcs[i]);
+ dd->cs_gpios[i].gpio_num = resource ? resource->start : -1;
+ dd->cs_gpios[i].valid = 0;
+ }
+
rc = msm_spi_request_gpios(dd);
if (rc)
goto err_probe_gpio;
+
spin_lock_init(&dd->queue_lock);
mutex_init(&dd->core_lock);
INIT_LIST_HEAD(&dd->queue);