From: Igor Velkov <[email protected]> `sf probe <bus>:<cs> <speed>` ignores the speed for a flash that has a device tree node. _spi_get_bus_and_cs() probes the device, and with it the flash reads its JEDEC ID, at spi-max-frequency from the device tree. The requested speed is set only after the probe, and the slave keeps max_hz from the device tree, so the next claim of the bus goes back to that frequency.
A device bound without a device tree node already gets the requested speed and mode before the probe. Do the same for a device from the device tree, for the duration of the probe. On ROCK Pi 4A the device tree sets spi-max-frequency = <108000000> and the flash does not answer at the resulting clock, at any requested speed: => sf probe 1:0 1000000 jedec_spi_nor flash@0: unrecognized JEDEC id bytes: ff, ff, ff With this change: => sf probe 1:0 1000000 SF: Detected xt25f32 with page size 256 Bytes, erase size 4 KiB, total 4 MiB Add a sandbox test for it. Signed-off-by: Igor Velkov <[email protected]> --- Tested in sandbox (the new test fails without the change) and on ROCK Pi 4A with U-Boot proper chainloaded from the running one. --- drivers/spi/spi-uclass.c | 9 +++++++++ test/dm/spi.c | 20 ++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c index 120565df149..097c1ae665e 100644 --- a/drivers/spi/spi-uclass.c +++ b/drivers/spi/spi-uclass.c @@ -517,8 +517,17 @@ int _spi_get_bus_and_cs(int busnum, int cs, int speed, int mode, if (!device_active(dev)) { struct spi_slave *slave; + uint dt_max_hz = plat->max_hz; + uint dt_mode = plat->mode; + /* Probe at the caller's speed and mode: a flash reads its ID here */ + if (speed && !created) { + plat->max_hz = speed; + plat->mode = mode; + } ret = device_probe(dev); + plat->max_hz = dt_max_hz; + plat->mode = dt_mode; if (ret) goto err; slave = dev_get_parent_priv(dev); diff --git a/test/dm/spi.c b/test/dm/spi.c index a89ba06274f..4ea4bcd1196 100644 --- a/test/dm/spi.c +++ b/test/dm/spi.c @@ -91,6 +91,26 @@ static int dm_test_spi_find(struct unit_test_state *uts) } DM_TEST(dm_test_spi_find, UTF_SCAN_PDATA | UTF_SCAN_FDT); +/* Test that the first probe of a device from the DT uses the caller's speed */ +static int dm_test_spi_probe_speed(struct unit_test_state *uts) +{ + const int busnum = 0, cs = 0, mode = 0, speed = 1000000; + struct spi_slave *slave; + struct udevice *bus; + + /* spi.bin@0 has spi-max-frequency = <40000000> */ + ut_assertok(_spi_get_bus_and_cs(busnum, cs, speed, mode, NULL, NULL, + &bus, &slave)); + ut_asserteq(speed, slave->max_hz); + + ut_assertok(spi_claim_bus(slave)); + ut_asserteq(speed, sandbox_spi_get_speed(bus)); + spi_release_bus(slave); + + return 0; +} +DM_TEST(dm_test_spi_probe_speed, UTF_SCAN_PDATA | UTF_SCAN_FDT); + /* dm_test_spi_switch_slaves - Helper function to check whether spi_claim_bus * operates correctly with two spi slaves. * --- base-commit: f8eb3469e1a17c79b047b3fd38ae820e8816a115 change-id: 20260930-spi-probe-speed-1628c684e624 Best regards, -- Igor Velkov <[email protected]>
