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]> Changes in v2: - Use ulong and IS_ERR_VALUE() for the clock API return values. - Validate clk_get_rate() before narrowing to cfg.f_max and retain the error. --- drivers/mmc/spacemit_sdhci.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c index f5578f38bd..6488ae0fdb 100644 --- a/drivers/mmc/spacemit_sdhci.c +++ b/drivers/mmc/spacemit_sdhci.c @@ -606,10 +606,30 @@ 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) { + ulong rate = clk_set_rate(&clk, plat->cfg.f_max); + + if (IS_ERR_VALUE(rate)) { + ret = (int)rate; + log_err("Failed to set io clk: %d\n", ret); + goto err_reset; + } + } else { + ulong rate = clk_get_rate(&clk); + + if (IS_ERR_VALUE(rate) || !rate) { + ret = rate ? (int)rate : -EINVAL; + log_err("No max-frequency and no io clk rate\n"); + goto err_reset; + } + plat->cfg.f_max = rate; } /* Set quirks */ -- 2.55.0
