Skip to content

Commit 766c6b6

Browse files
Sven Van Asbroeckbroonie
authored andcommitted
spi: fix client driver breakages when using GPIO descriptors
Commit f3186dd ("spi: Optionally use GPIO descriptors for CS GPIOs") introduced the optional use of GPIO descriptors for chip selects. A side-effect of this change: when a SPI bus uses GPIO descriptors, all its client devices have SPI_CS_HIGH set in spi->mode. This flag is required for the SPI bus to operate correctly. This unfortunately breaks many client drivers, which use the following pattern to configure their underlying SPI bus: static int client_device_probe(struct spi_device *spi) { ... spi->mode = SPI_MODE_0; spi->bits_per_word = 8; err = spi_setup(spi); .. } In short, many client drivers overwrite the SPI_CS_HIGH bit in spi->mode, and break the underlying SPI bus driver. This is especially true for Freescale/NXP imx ecspi, where large numbers of spi client drivers now no longer work. Proposed fix: ------------- When using gpio descriptors, depend on gpiolib to handle CS polarity. Existing quirks in gpiolib ensure that this is handled correctly. Existing gpiolib behaviour will force the polarity of any chip-select gpiod to active-high (if 'spi-active-high' devicetree prop present) or active-low (if 'spi-active-high' absent). Irrespective of whether the gpio is marked GPIO_ACTIVE_[HIGH|LOW] in the devicetree. Loose ends: ----------- If this fix is applied: - is commit 138c9c3 ("spi: spidev: Fix CS polarity if GPIO descriptors are used") still necessary / correct ? Fixes: f3186dd ("spi: Optionally use GPIO descriptors for CS GPIOs") Signed-off-by: Sven Van Asbroeck <thesven73@gmail.com> Acked-by: Linus Walleij <linus.walleij@linaro.org> Link: https://lore.kernel.org/r/20201106150706.29089-1-TheSven73@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent bc7f2cd commit 766c6b6

1 file changed

Lines changed: 6 additions & 17 deletions

File tree

drivers/spi/spi.c

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -812,18 +812,16 @@ static void spi_set_cs(struct spi_device *spi, bool enable)
812812
enable = !enable;
813813

814814
if (spi->cs_gpiod || gpio_is_valid(spi->cs_gpio)) {
815-
/*
816-
* Honour the SPI_NO_CS flag and invert the enable line, as
817-
* active low is default for SPI. Execution paths that handle
818-
* polarity inversion in gpiolib (such as device tree) will
819-
* enforce active high using the SPI_CS_HIGH resulting in a
820-
* double inversion through the code above.
821-
*/
822815
if (!(spi->mode & SPI_NO_CS)) {
823816
if (spi->cs_gpiod)
817+
/* polarity handled by gpiolib */
824818
gpiod_set_value_cansleep(spi->cs_gpiod,
825-
!enable);
819+
enable1);
826820
else
821+
/*
822+
* invert the enable line, as active low is
823+
* default for SPI.
824+
*/
827825
gpio_set_value_cansleep(spi->cs_gpio, !enable);
828826
}
829827
/* Some SPI masters need both GPIO CS & slave_select */
@@ -1992,15 +1990,6 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
19921990
}
19931991
spi->chip_select = value;
19941992

1995-
/*
1996-
* For descriptors associated with the device, polarity inversion is
1997-
* handled in the gpiolib, so all gpio chip selects are "active high"
1998-
* in the logical sense, the gpiolib will invert the line if need be.
1999-
*/
2000-
if ((ctlr->use_gpio_descriptors) && ctlr->cs_gpiods &&
2001-
ctlr->cs_gpiods[spi->chip_select])
2002-
spi->mode |= SPI_CS_HIGH;
2003-
20041993
/* Device speed */
20051994
if (!of_property_read_u32(nc, "spi-max-frequency", &value))
20061995
spi->max_speed_hz = value;

0 commit comments

Comments
 (0)