]> git.itanic.dy.fi Git - linux-stable/commitdiff
spi: Restore delays for non-GPIO chip select
authorJanne Grunau <j@jannau.net>
Mon, 11 Mar 2024 22:53:17 +0000 (23:53 +0100)
committerSasha Levin <sashal@kernel.org>
Tue, 26 Mar 2024 22:17:31 +0000 (18:17 -0400)
[ Upstream commit aa0162dc0dd95c3bf248e3c78068760094e8f64b ]

SPI controller with integrated chip select handling still need to adhere
to SPI device's CS setup, hold and inactive delays. For controller
without set_cs_timing spi core shall handle the delays to avoid
duplicated delay handling in each controller driver.
Fixes a regression for the out of tree SPI controller and SPI HID
transport on Apple M1/M1 Pro/Max notebooks.

Fixes: 4d8ff6b0991d ("spi: Add multi-cs memories support in SPI core")
Signed-off-by: Janne Grunau <j@jannau.net>
Link: https://msgid.link/r/20240311-spi-cs-delays-regression-v1-1-0075020a90b2@jannau.net
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/spi/spi.c

index d1b297f438f145ebb9e9507e570f9995b85db00f..46f1535487608353d0250ca60f4e842c92943261 100644 (file)
@@ -1042,10 +1042,14 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force)
        if (spi->mode & SPI_CS_HIGH)
                enable = !enable;
 
-       if (spi_is_csgpiod(spi)) {
-               if (!spi->controller->set_cs_timing && !activate)
-                       spi_delay_exec(&spi->cs_hold, NULL);
+       /*
+        * Handle chip select delays for GPIO based CS or controllers without
+        * programmable chip select timing.
+        */
+       if ((spi_is_csgpiod(spi) || !spi->controller->set_cs_timing) && !activate)
+               spi_delay_exec(&spi->cs_hold, NULL);
 
+       if (spi_is_csgpiod(spi)) {
                if (!(spi->mode & SPI_NO_CS)) {
                        /*
                         * Historically ACPI has no means of the GPIO polarity and
@@ -1079,16 +1083,16 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force)
                if ((spi->controller->flags & SPI_CONTROLLER_GPIO_SS) &&
                    spi->controller->set_cs)
                        spi->controller->set_cs(spi, !enable);
-
-               if (!spi->controller->set_cs_timing) {
-                       if (activate)
-                               spi_delay_exec(&spi->cs_setup, NULL);
-                       else
-                               spi_delay_exec(&spi->cs_inactive, NULL);
-               }
        } else if (spi->controller->set_cs) {
                spi->controller->set_cs(spi, !enable);
        }
+
+       if (spi_is_csgpiod(spi) || !spi->controller->set_cs_timing) {
+               if (activate)
+                       spi_delay_exec(&spi->cs_setup, NULL);
+               else
+                       spi_delay_exec(&spi->cs_inactive, NULL);
+       }
 }
 
 #ifdef CONFIG_HAS_DMA