浏览代码

spi: davinci: request cs_gpio's from probe

Now CS GPIOs are requested from struct spi_master.setup() callback
and that causes failures when Client SPI device is getting accessed
through SPIDEV driver. The failure happens, because .setup() callback
may be called many times from IOCTL handler and when it's called
second time gpio_request() will fail and return -EBUSY.

Hence, fix it by moving CS GPIOs requesting code in .probe().

Reported-by: Murali Karicheri <m-karicheri2@ti.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Grygorii Strashko 11 年之前
父节点
当前提交
8936decdd9
共有 1 个文件被更改,包括 25 次插入9 次删除
  1. 25 9
      drivers/spi/spi-davinci.c

+ 25 - 9
drivers/spi/spi-davinci.c

@@ -397,24 +397,21 @@ static int davinci_spi_setup(struct spi_device *spi)
 	struct spi_master *master = spi->master;
 	struct spi_master *master = spi->master;
 	struct device_node *np = spi->dev.of_node;
 	struct device_node *np = spi->dev.of_node;
 	bool internal_cs = true;
 	bool internal_cs = true;
-	unsigned long flags = GPIOF_DIR_OUT;
 
 
 	dspi = spi_master_get_devdata(spi->master);
 	dspi = spi_master_get_devdata(spi->master);
 	pdata = &dspi->pdata;
 	pdata = &dspi->pdata;
 
 
-	flags |= (spi->mode & SPI_CS_HIGH) ? GPIOF_INIT_LOW : GPIOF_INIT_HIGH;
-
 	if (!(spi->mode & SPI_NO_CS)) {
 	if (!(spi->mode & SPI_NO_CS)) {
 		if (np && (master->cs_gpios != NULL) && (spi->cs_gpio >= 0)) {
 		if (np && (master->cs_gpios != NULL) && (spi->cs_gpio >= 0)) {
-			retval = gpio_request_one(spi->cs_gpio,
-						  flags, dev_name(&spi->dev));
+			retval = gpio_direction_output(
+				      spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
 			internal_cs = false;
 			internal_cs = false;
 		} else if (pdata->chip_sel &&
 		} else if (pdata->chip_sel &&
 			   spi->chip_select < pdata->num_chipselect &&
 			   spi->chip_select < pdata->num_chipselect &&
 			   pdata->chip_sel[spi->chip_select] != SPI_INTERN_CS) {
 			   pdata->chip_sel[spi->chip_select] != SPI_INTERN_CS) {
 			spi->cs_gpio = pdata->chip_sel[spi->chip_select];
 			spi->cs_gpio = pdata->chip_sel[spi->chip_select];
-			retval = gpio_request_one(spi->cs_gpio,
-						  flags, dev_name(&spi->dev));
+			retval = gpio_direction_output(
+				      spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
 			internal_cs = false;
 			internal_cs = false;
 		}
 		}
 	}
 	}
@@ -441,8 +438,6 @@ static int davinci_spi_setup(struct spi_device *spi)
 
 
 static void davinci_spi_cleanup(struct spi_device *spi)
 static void davinci_spi_cleanup(struct spi_device *spi)
 {
 {
-	if (spi->cs_gpio >= 0)
-		gpio_free(spi->cs_gpio);
 }
 }
 
 
 static int davinci_spi_check_error(struct davinci_spi *dspi, int int_status)
 static int davinci_spi_check_error(struct davinci_spi *dspi, int int_status)
@@ -967,6 +962,27 @@ static int davinci_spi_probe(struct platform_device *pdev)
 	if (dspi->version == SPI_VERSION_2)
 	if (dspi->version == SPI_VERSION_2)
 		dspi->bitbang.flags |= SPI_READY;
 		dspi->bitbang.flags |= SPI_READY;
 
 
+	if (pdev->dev.of_node) {
+		int i;
+
+		for (i = 0; i < pdata->num_chipselect; i++) {
+			int cs_gpio = of_get_named_gpio(pdev->dev.of_node,
+							"cs-gpios", i);
+
+			if (cs_gpio == -EPROBE_DEFER) {
+				ret = cs_gpio;
+				goto free_clk;
+			}
+
+			if (gpio_is_valid(cs_gpio)) {
+				ret = devm_gpio_request(&pdev->dev, cs_gpio,
+							dev_name(&pdev->dev));
+				if (ret)
+					goto free_clk;
+			}
+		}
+	}
+
 	r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
 	r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
 	if (r)
 	if (r)
 		dma_rx_chan = r->start;
 		dma_rx_chan = r->start;