summaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi-img-spfi.c
diff options
context:
space:
mode:
authorSifan Naeem <sifan.naeem@imgtec.com>2015-07-29 06:55:26 -0400
committerMark Brown <broonie@kernel.org>2015-08-04 13:46:54 -0400
commitb03ba9e314c12b2127243145b5c1f41b2408de62 (patch)
treee909d33caf1fea825693ef42d3baec7778ea0ae6 /drivers/spi/spi-img-spfi.c
parent011710e2ab659c7ad6e5e554806414bd7a9508be (diff)
spi: img-spfi: fix multiple calls to request gpio
spfi_setup may be called many times by the spi framework, but gpio_request_one can only be called once without freeing, repeatedly calling gpio_request_one will cause an error to be thrown, which causes the request to spi_setup to be marked as failed. We can have a per-spi_device flag that indicates whether or not the gpio has been requested. If the gpio has already been requested use gpio_direction_output to set the direction of the gpio. Fixes: 8c2c8c03cdcb ("spi: img-spfi: Control CS lines with GPIO") Signed-off-by: Sifan Naeem <sifan.naeem@imgtec.com> Signed-off-by: Mark Brown <broonie@kernel.org> Cc: stable@vger.kernel.org
Diffstat (limited to 'drivers/spi/spi-img-spfi.c')
-rw-r--r--drivers/spi/spi-img-spfi.c49
1 files changed, 41 insertions, 8 deletions
diff --git a/drivers/spi/spi-img-spfi.c b/drivers/spi/spi-img-spfi.c
index 83b97418fc8d..1ba90562d72a 100644
--- a/drivers/spi/spi-img-spfi.c
+++ b/drivers/spi/spi-img-spfi.c
@@ -104,6 +104,10 @@ struct img_spfi {
104 bool rx_dma_busy; 104 bool rx_dma_busy;
105}; 105};
106 106
107struct img_spfi_device_data {
108 bool gpio_requested;
109};
110
107static inline u32 spfi_readl(struct img_spfi *spfi, u32 reg) 111static inline u32 spfi_readl(struct img_spfi *spfi, u32 reg)
108{ 112{
109 return readl(spfi->regs + reg); 113 return readl(spfi->regs + reg);
@@ -440,20 +444,49 @@ static int img_spfi_unprepare(struct spi_master *master,
440static int img_spfi_setup(struct spi_device *spi) 444static int img_spfi_setup(struct spi_device *spi)
441{ 445{
442 int ret; 446 int ret;
443 447 struct img_spfi_device_data *spfi_data = spi_get_ctldata(spi);
444 ret = gpio_request_one(spi->cs_gpio, (spi->mode & SPI_CS_HIGH) ? 448
445 GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH, 449 if (!spfi_data) {
446 dev_name(&spi->dev)); 450 spfi_data = kzalloc(sizeof(*spfi_data), GFP_KERNEL);
447 if (ret) 451 if (!spfi_data)
448 dev_err(&spi->dev, "can't request chipselect gpio %d\n", 452 return -ENOMEM;
453 spfi_data->gpio_requested = false;
454 spi_set_ctldata(spi, spfi_data);
455 }
456 if (!spfi_data->gpio_requested) {
457 ret = gpio_request_one(spi->cs_gpio,
458 (spi->mode & SPI_CS_HIGH) ?
459 GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH,
460 dev_name(&spi->dev));
461 if (ret)
462 dev_err(&spi->dev, "can't request chipselect gpio %d\n",
449 spi->cs_gpio); 463 spi->cs_gpio);
450 464 else
465 spfi_data->gpio_requested = true;
466 } else {
467 if (gpio_is_valid(spi->cs_gpio)) {
468 int mode = ((spi->mode & SPI_CS_HIGH) ?
469 GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH);
470
471 ret = gpio_direction_output(spi->cs_gpio, mode);
472 if (ret)
473 dev_err(&spi->dev, "chipselect gpio %d setup failed (%d)\n",
474 spi->cs_gpio, ret);
475 }
476 }
451 return ret; 477 return ret;
452} 478}
453 479
454static void img_spfi_cleanup(struct spi_device *spi) 480static void img_spfi_cleanup(struct spi_device *spi)
455{ 481{
456 gpio_free(spi->cs_gpio); 482 struct img_spfi_device_data *spfi_data = spi_get_ctldata(spi);
483
484 if (spfi_data) {
485 if (spfi_data->gpio_requested)
486 gpio_free(spi->cs_gpio);
487 kfree(spfi_data);
488 spi_set_ctldata(spi, NULL);
489 }
457} 490}
458 491
459static void img_spfi_config(struct spi_master *master, struct spi_device *spi, 492static void img_spfi_config(struct spi_master *master, struct spi_device *spi,