[PATCH V2] spi: Update speed/mode on change

Marek Vasut marex at denx.de
Thu Jun 10 14:00:00 CEST 2021


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 at 1000
=> sspi 0:0 at 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 at denx.de>
Cc: Jagan Teki <jagan at amarulasolutions.com>
Cc: Patrick Delaunay <patrick.delaunay at foss.st.com>
---
V2: Set plat in case it is NULL
---
 drivers/spi/spi-uclass.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index ee30110b56..d867b27806 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -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);
-- 
2.30.2



More information about the U-Boot mailing list