]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
spi: Update speed/mode on change
authorMarek Vasut <marex@denx.de>
Thu, 10 Jun 2021 12:00:00 +0000 (14:00 +0200)
committerTom Rini <trini@konsulko.com>
Wed, 30 Jun 2021 12:06:30 +0000 (08:06 -0400)
The spi_get_bus_and_cs() may be called on the same bus and chipselect
with different frequency or mode. This is valid usecase, but the code
fails to notify the controller of such a configuration change. Call
spi_set_speed_mode() in case bus frequency or bus mode changed to let
the controller update the configuration.

The problem can easily be triggered using the sspi command:
=> sspi 0:0@1000
=> sspi 0:0@2000
Without this patch, both transfers happen at 1000 Hz. With this patch,
the later transfer happens correctly at 2000 Hz.

Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Jagan Teki <jagan@amarulasolutions.com>
Cc: Patrick Delaunay <patrick.delaunay@foss.st.com>
drivers/spi/spi-uclass.c

index ee30110b5658c6b36212a28d69052f146d81f461..d867b278064f3f0dbaca04fd77cd8f0ab69016a2 100644 (file)
@@ -391,6 +391,8 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
        } else if (ret) {
                dev_err(bus, "Invalid chip select %d:%d (err=%d)\n", busnum, cs, ret);
                return ret;
+       } else if (dev) {
+               plat = dev_get_parent_plat(dev);
        }
 
        if (!device_active(dev)) {
@@ -416,12 +418,22 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
                        goto err;
        }
 
+       /* In case bus frequency or mode changed, update it. */
+       if ((speed && bus_data->speed && bus_data->speed != speed) ||
+           (plat && plat->mode != mode)) {
+               ret = spi_set_speed_mode(bus, speed, mode);
+               if (ret)
+                       goto err_speed_mode;
+       }
+
        *busp = bus;
        *devp = slave;
        log_debug("%s: bus=%p, slave=%p\n", __func__, bus, *devp);
 
        return 0;
 
+err_speed_mode:
+       spi_release_bus(slave);
 err:
        log_debug("%s: Error path, created=%d, device '%s'\n", __func__,
                  created, dev->name);