[PATCH] spi: gpio: Use core CS GPIO handling for everything

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The SPI core can handle all CS GPIOs without any problem.
As can be seen from the code in spi_get_gpio_descs()
the core will just get a bunch of chip selects from
the device.

When using GPIO descriptors from a board file, the
process is not any different.

However we need to be carefule about one thing:
devm_gpiod_get_index_optional() passes GPIOD_OUT_LOW
in the core and GPIOD_OUT_HIGH in the spi-gpio driver.
This is because the driver assumes the polarity
inversion is not handled by the core.

We need to revisit commit 9b00bc7b901f
("spi: spi-gpio: Rewrite to use GPIO descriptors")
and make sure all passed descriptors are flagged as
active low for the core, because now they are passed
in as active high and inverted by the driver instead.
The device tree core will enforce active low on
CS gpios, but board files are not that forgiving.

Cc: Andrey Smirnov <andrew.smirnov@xxxxxxxxx>
Signed-off-by: Linus Walleij <linus.walleij@xxxxxxxxxx>
---
 arch/arm/mach-pxa/cm-x300.c            |  2 +-
 arch/arm/mach-s3c24xx/mach-jive.c      |  4 +-
 arch/arm/mach-s3c24xx/mach-qt2410.c    |  2 +-
 arch/arm/mach-s3c64xx/mach-smartq.c    |  2 +-
 arch/mips/alchemy/devboards/db1000.c   |  2 +-
 arch/mips/jz4740/board-qi_lb60.c       |  2 +-
 drivers/misc/eeprom/digsy_mtc_eeprom.c |  2 +-
 drivers/spi/spi-gpio.c                 | 59 ++------------------------
 8 files changed, 12 insertions(+), 63 deletions(-)

diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index 425855f456f2..60ebc5f4041e 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -362,7 +362,7 @@ static struct gpiod_lookup_table cm_x300_spi_gpiod_table = {
 		GPIO_LOOKUP("gpio-pxa", GPIO_LCD_DOUT,
 			    "miso", GPIO_ACTIVE_HIGH),
 		GPIO_LOOKUP("gpio-pxa", GPIO_LCD_CS,
-			    "cs", GPIO_ACTIVE_HIGH),
+			    "cs", GPIO_ACTIVE_LOW),
 		{ },
 	},
 };
diff --git a/arch/arm/mach-s3c24xx/mach-jive.c b/arch/arm/mach-s3c24xx/mach-jive.c
index 885e8f12e4b9..66c38472111d 100644
--- a/arch/arm/mach-s3c24xx/mach-jive.c
+++ b/arch/arm/mach-s3c24xx/mach-jive.c
@@ -406,7 +406,7 @@ static struct gpiod_lookup_table jive_lcdspi_gpiod_table = {
 		GPIO_LOOKUP("GPIOB", 8,
 			    "mosi", GPIO_ACTIVE_HIGH),
 		GPIO_LOOKUP("GPIOB", 7,
-			    "cs", GPIO_ACTIVE_HIGH),
+			    "cs", GPIO_ACTIVE_LOW),
 		{ },
 	},
 };
@@ -431,7 +431,7 @@ static struct gpiod_lookup_table jive_wm8750_gpiod_table = {
 		GPIO_LOOKUP("GPIOB", 9,
 			    "mosi", GPIO_ACTIVE_HIGH),
 		GPIO_LOOKUP("GPIOH", 10,
-			    "cs", GPIO_ACTIVE_HIGH),
+			    "cs", GPIO_ACTIVE_LOW),
 		{ },
 	},
 };
diff --git a/arch/arm/mach-s3c24xx/mach-qt2410.c b/arch/arm/mach-s3c24xx/mach-qt2410.c
index 5d48e5b6e738..61fbd3694257 100644
--- a/arch/arm/mach-s3c24xx/mach-qt2410.c
+++ b/arch/arm/mach-s3c24xx/mach-qt2410.c
@@ -214,7 +214,7 @@ static struct gpiod_lookup_table qt2410_spi_gpiod_table = {
 		GPIO_LOOKUP("GPIOG", 5,
 			    "miso", GPIO_ACTIVE_HIGH),
 		GPIO_LOOKUP("GPIOB", 5,
-			    "cs", GPIO_ACTIVE_HIGH),
+			    "cs", GPIO_ACTIVE_LOW),
 		{ },
 	},
 };
diff --git a/arch/arm/mach-s3c64xx/mach-smartq.c b/arch/arm/mach-s3c64xx/mach-smartq.c
index 951208f168e7..f81a85c75247 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq.c
@@ -225,7 +225,7 @@ static struct gpiod_lookup_table smartq_lcd_control_gpiod_table = {
 		GPIO_LOOKUP("GPIOM", 3,
 			    "miso", GPIO_ACTIVE_HIGH),
 		GPIO_LOOKUP("GPIOM", 0,
-			    "cs", GPIO_ACTIVE_HIGH),
+			    "cs", GPIO_ACTIVE_LOW),
 		{ },
 	},
 };
diff --git a/arch/mips/alchemy/devboards/db1000.c b/arch/mips/alchemy/devboards/db1000.c
index 2c52ee27b4f2..aa3b5b3d81aa 100644
--- a/arch/mips/alchemy/devboards/db1000.c
+++ b/arch/mips/alchemy/devboards/db1000.c
@@ -424,7 +424,7 @@ static struct gpiod_lookup_table db1100_spi_gpiod_table = {
 		GPIO_LOOKUP("alchemy-gpio2", 7,
 			    "miso", GPIO_ACTIVE_HIGH),
 		GPIO_LOOKUP("alchemy-gpio2", 10,
-			    "cs", GPIO_ACTIVE_HIGH),
+			    "cs", GPIO_ACTIVE_LOW),
 		{ },
 	},
 };
diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c
index 071e9d94eea7..9ea53398c0f1 100644
--- a/arch/mips/jz4740/board-qi_lb60.c
+++ b/arch/mips/jz4740/board-qi_lb60.c
@@ -328,7 +328,7 @@ static struct gpiod_lookup_table qi_lb60_spigpio_gpio_table = {
 		GPIO_LOOKUP("GPIOC", 22,
 			    "mosi", GPIO_ACTIVE_HIGH),
 		GPIO_LOOKUP("GPIOC", 21,
-			    "cs", GPIO_ACTIVE_HIGH),
+			    "cs", GPIO_ACTIVE_LOW),
 		{ },
 	},
 };
diff --git a/drivers/misc/eeprom/digsy_mtc_eeprom.c b/drivers/misc/eeprom/digsy_mtc_eeprom.c
index f1f766b70965..c058eaff0385 100644
--- a/drivers/misc/eeprom/digsy_mtc_eeprom.c
+++ b/drivers/misc/eeprom/digsy_mtc_eeprom.c
@@ -69,7 +69,7 @@ static struct gpiod_lookup_table eeprom_spi_gpiod_table = {
 		GPIO_LOOKUP("gpio@b00", GPIO_EEPROM_DO,
 			    "miso", GPIO_ACTIVE_HIGH),
 		GPIO_LOOKUP("gpio@b00", GPIO_EEPROM_CS,
-			    "cs", GPIO_ACTIVE_HIGH),
+			    "cs", GPIO_ACTIVE_LOW),
 		{ },
 	},
 };
diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c
index 9eb82150666e..4309832221b1 100644
--- a/drivers/spi/spi-gpio.c
+++ b/drivers/spi/spi-gpio.c
@@ -35,7 +35,6 @@ struct spi_gpio {
 	struct gpio_desc		*sck;
 	struct gpio_desc		*miso;
 	struct gpio_desc		*mosi;
-	struct gpio_desc		**cs_gpios;
 };
 
 /*----------------------------------------------------------------------*/
@@ -203,37 +202,6 @@ static void spi_gpio_chipselect(struct spi_device *spi, int is_active)
 	/* set initial clock line level */
 	if (is_active)
 		gpiod_set_value_cansleep(spi_gpio->sck, spi->mode & SPI_CPOL);
-
-	/* Drive chip select line, if we have one */
-	if (spi_gpio->cs_gpios) {
-		struct gpio_desc *cs = spi_gpio->cs_gpios[spi->chip_select];
-
-		/* SPI chip selects are normally active-low */
-		gpiod_set_value_cansleep(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
-	}
-}
-
-static int spi_gpio_setup(struct spi_device *spi)
-{
-	struct gpio_desc	*cs;
-	int			status = 0;
-	struct spi_gpio		*spi_gpio = spi_to_spi_gpio(spi);
-
-	/*
-	 * The CS GPIOs have already been
-	 * initialized from the descriptor lookup.
-	 */
-	if (spi_gpio->cs_gpios) {
-		cs = spi_gpio->cs_gpios[spi->chip_select];
-		if (!spi->controller_state && cs)
-			status = gpiod_direction_output(cs,
-						  !(spi->mode & SPI_CS_HIGH));
-	}
-
-	if (!status)
-		status = spi_bitbang_setup(spi);
-
-	return status;
 }
 
 static int spi_gpio_set_direction(struct spi_device *spi, bool output)
@@ -264,11 +232,6 @@ static int spi_gpio_set_direction(struct spi_device *spi, bool output)
 	return 0;
 }
 
-static void spi_gpio_cleanup(struct spi_device *spi)
-{
-	spi_bitbang_cleanup(spi);
-}
-
 /*
  * It can be convenient to use this driver with pins that have alternate
  * functions associated with a "native" SPI controller if a driver for that
@@ -324,8 +287,6 @@ static int spi_gpio_probe_pdata(struct platform_device *pdev,
 {
 	struct device *dev = &pdev->dev;
 	struct spi_gpio_platform_data *pdata = dev_get_platdata(dev);
-	struct spi_gpio *spi_gpio = spi_master_get_devdata(master);
-	int i;
 
 #ifdef GENERIC_BITBANG
 	if (!pdata || !pdata->num_chipselect)
@@ -335,20 +296,8 @@ static int spi_gpio_probe_pdata(struct platform_device *pdev,
 	 * The master needs to think there is a chipselect even if not
 	 * connected
 	 */
-	master->num_chipselect = pdata->num_chipselect ?: 1;
-
-	spi_gpio->cs_gpios = devm_kcalloc(dev, master->num_chipselect,
-					  sizeof(*spi_gpio->cs_gpios),
-					  GFP_KERNEL);
-	if (!spi_gpio->cs_gpios)
-		return -ENOMEM;
-
-	for (i = 0; i < master->num_chipselect; i++) {
-		spi_gpio->cs_gpios[i] = devm_gpiod_get_index(dev, "cs", i,
-							     GPIOD_OUT_HIGH);
-		if (IS_ERR(spi_gpio->cs_gpios[i]))
-			return PTR_ERR(spi_gpio->cs_gpios[i]);
-	}
+	master->num_chipselect = pdata->num_chipselect ? : 1;
+	master->use_gpio_descriptors = true;
 
 	return 0;
 }
@@ -405,8 +354,8 @@ static int spi_gpio_probe(struct platform_device *pdev)
 	}
 
 	master->bus_num = pdev->id;
-	master->setup = spi_gpio_setup;
-	master->cleanup = spi_gpio_cleanup;
+	master->setup = spi_bitbang_setup;
+	master->cleanup = spi_bitbang_cleanup;
 
 	bb = &spi_gpio->bitbang;
 	bb->master = master;
-- 
2.21.0




[Index of Archives]     [Linux SPI]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux