On 03-10-2026 02:59, Dave Klotz wrote:
The driver sets the io clock to the max-frequency the device tree gives
and fails the probe on any non-zero return from clk_set_rate(). Two
problems follow:

- clk_set_rate() returns the new rate on success and a negative error
   code on failure. The SpacemiT clock driver happens to return 0, but
   any clock driver that reports the rate makes the probe fail.
- A node without max-frequency asks for 0 Hz. On the K1 clock driver
   that picks no divider at all and writes whatever the calculation left
   behind into the io clock's divider field; host->max_clk is then 0,
   the capabilities register gives no base clock either, and the probe
   fails in sdhci_setup_cfg().

Treat only a negative return as an error. Without max-frequency, leave
the io clock as an earlier stage set it and run from its current rate.

Signed-off-by: Dave Klotz<[email protected]>
---
  drivers/mmc/spacemit_sdhci.c | 26 ++++++++++++++++++++++----
  1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c
index f5578f38bd..bbd49b76c6 100644
--- a/drivers/mmc/spacemit_sdhci.c
+++ b/drivers/mmc/spacemit_sdhci.c
@@ -606,10 +606,28 @@ static int spacemit_sdhci_probe(struct udevice *dev)
                goto err_reset;
        }
- ret = clk_set_rate(&clk, plat->cfg.f_max);
-       if (ret) {
-               log_err("Failed to set io clk: %d\n", ret);
-               goto err_reset;
+       /*
+        * Without max-frequency there is no rate to ask for: leave the io
+        * clock as an earlier stage set it and run from its current rate. The
+        * capabilities register gives no base clock on the K1, so it cannot
+        * stand in. clk_set_rate() returns the new rate on success, so only a
+        * negative value is an error.
+        */
+       if (plat->cfg.f_max) {
+               long rate = clk_set_rate(&clk, plat->cfg.f_max);

The clock API returns ulong; please use ulong rate with
IS_ERR_VALUE(rate) for consistency.

+
+               if (rate < 0) {
+                       ret = rate;
+                       log_err("Failed to set io clk: %d\n", ret);
+                       goto err_reset;
+               }
+       } else {
+               plat->cfg.f_max = clk_get_rate(&clk);

clk_get_rate() returns ulong, but f_max is uint. On RV64, assigning a
negative error first truncates it, so IS_ERR_VALUE(f_max) no longer
detects the error. Please validate the ulong rate before assigning it:

    rate = clk_get_rate(&clk);
    if (IS_ERR_VALUE(rate) || !rate) {
        ret = rate ? (int)rate : -EINVAL;
        goto err_reset;
    }
    plat->cfg.f_max = rate;

Reply via email to