diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c index 6e0c5fb10efad..93ec0fb872539 100644 --- a/drivers/soundwire/qcom.c +++ b/drivers/soundwire/qcom.c @@ -21,6 +21,41 @@ #include #include #include "bus.h" +#include + +/* + * Local helper: bounded retry for deferred clock providers. + * Clock-provider registration does not trigger deferred-probe retries, + * so a consumer that loses the probe-order race stays deferred forever. + * Wait up to 30s for providers that are registered milliseconds later. + */ +static struct clk *clk_get_retry(struct device *dev, const char *id) +{ + struct clk *c; + int i; + + for (i = 0; i < 60; i++) { + c = devm_clk_get(dev, id); + if (!IS_ERR(c) || PTR_ERR(c) != -EPROBE_DEFER) + return c; + msleep(500); + } + return c; +} + +static struct clk *clk_get_retry_optional(struct device *dev, const char *id) +{ + struct clk *c; + int i; + + for (i = 0; i < 60; i++) { + c = devm_clk_get_optional(dev, id); + if (!IS_ERR(c) || PTR_ERR(c) != -EPROBE_DEFER) + return c; + msleep(500); + } + return c; +} #define SWRM_COMP_SW_RESET 0x008 #define SWRM_COMP_STATUS 0x014 @@ -1669,7 +1704,7 @@ static int qcom_swrm_probe(struct platform_device *pdev) goto err_init; } - ctrl->hclk = devm_clk_get(dev, "iface"); + ctrl->hclk = clk_get_retry(dev, "iface"); if (IS_ERR(ctrl->hclk)) { ret = dev_err_probe(dev, PTR_ERR(ctrl->hclk), "unable to get iface clock\n"); goto err_init; diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index c41eb8de61609..3198ba6412833 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -18,6 +18,41 @@ #include #include "lpass-macro-common.h" +#include + +/* + * Local helper: bounded retry for deferred clock providers. + * Clock-provider registration does not trigger deferred-probe retries, + * so a consumer that loses the probe-order race stays deferred forever. + * Wait up to 30s for providers that are registered milliseconds later. + */ +static struct clk *clk_get_retry(struct device *dev, const char *id) +{ + struct clk *c; + int i; + + for (i = 0; i < 60; i++) { + c = devm_clk_get(dev, id); + if (!IS_ERR(c) || PTR_ERR(c) != -EPROBE_DEFER) + return c; + msleep(500); + } + return c; +} + +static struct clk *clk_get_retry_optional(struct device *dev, const char *id) +{ + struct clk *c; + int i; + + for (i = 0; i < 60; i++) { + c = devm_clk_get_optional(dev, id); + if (!IS_ERR(c) || PTR_ERR(c) != -EPROBE_DEFER) + return c; + msleep(500); + } + return c; +} #define CDC_RX_TOP_TOP_CFG0 (0x0000) #define CDC_RX_TOP_SWR_CTRL (0x0008) @@ -3780,25 +3815,25 @@ static int rx_macro_probe(struct platform_device *pdev) if (!rx) return -ENOMEM; - rx->macro = devm_clk_get_optional(dev, "macro"); + rx->macro = clk_get_retry_optional(dev, "macro"); if (IS_ERR(rx->macro)) return dev_err_probe(dev, PTR_ERR(rx->macro), "unable to get macro clock\n"); - rx->dcodec = devm_clk_get_optional(dev, "dcodec"); + rx->dcodec = clk_get_retry_optional(dev, "dcodec"); if (IS_ERR(rx->dcodec)) return dev_err_probe(dev, PTR_ERR(rx->dcodec), "unable to get dcodec clock\n"); - rx->mclk = devm_clk_get(dev, "mclk"); + rx->mclk = clk_get_retry(dev, "mclk"); if (IS_ERR(rx->mclk)) return dev_err_probe(dev, PTR_ERR(rx->mclk), "unable to get mclk clock\n"); if (flags & LPASS_MACRO_FLAG_HAS_NPL_CLOCK) { - rx->npl = devm_clk_get(dev, "npl"); + rx->npl = clk_get_retry(dev, "npl"); if (IS_ERR(rx->npl)) return dev_err_probe(dev, PTR_ERR(rx->npl), "unable to get npl clock\n"); } - rx->fsgen = devm_clk_get(dev, "fsgen"); + rx->fsgen = clk_get_retry(dev, "fsgen"); if (IS_ERR(rx->fsgen)) return dev_err_probe(dev, PTR_ERR(rx->fsgen), "unable to get fsgen clock\n"); diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c index 6deaaabe43afa..f3a6c5d9fa17a 100644 --- a/sound/soc/codecs/lpass-tx-macro.c +++ b/sound/soc/codecs/lpass-tx-macro.c @@ -16,6 +16,41 @@ #include #include "lpass-macro-common.h" +#include + +/* + * Local helper: bounded retry for deferred clock providers. + * Clock-provider registration does not trigger deferred-probe retries, + * so a consumer that loses the probe-order race stays deferred forever. + * Wait up to 30s for providers that are registered milliseconds later. + */ +static struct clk *clk_get_retry(struct device *dev, const char *id) +{ + struct clk *c; + int i; + + for (i = 0; i < 60; i++) { + c = devm_clk_get(dev, id); + if (!IS_ERR(c) || PTR_ERR(c) != -EPROBE_DEFER) + return c; + msleep(500); + } + return c; +} + +static struct clk *clk_get_retry_optional(struct device *dev, const char *id) +{ + struct clk *c; + int i; + + for (i = 0; i < 60; i++) { + c = devm_clk_get_optional(dev, id); + if (!IS_ERR(c) || PTR_ERR(c) != -EPROBE_DEFER) + return c; + msleep(500); + } + return c; +} #define CDC_TX_CLK_RST_CTRL_MCLK_CONTROL (0x0000) #define CDC_TX_MCLK_EN_MASK BIT(0) @@ -2258,25 +2293,25 @@ static int tx_macro_probe(struct platform_device *pdev) tx->data = device_get_match_data(dev); - tx->macro = devm_clk_get_optional(dev, "macro"); + tx->macro = clk_get_retry_optional(dev, "macro"); if (IS_ERR(tx->macro)) return dev_err_probe(dev, PTR_ERR(tx->macro), "unable to get macro clock\n"); - tx->dcodec = devm_clk_get_optional(dev, "dcodec"); + tx->dcodec = clk_get_retry_optional(dev, "dcodec"); if (IS_ERR(tx->dcodec)) return dev_err_probe(dev, PTR_ERR(tx->dcodec), "unable to get dcodec clock\n"); - tx->mclk = devm_clk_get(dev, "mclk"); + tx->mclk = clk_get_retry(dev, "mclk"); if (IS_ERR(tx->mclk)) return dev_err_probe(dev, PTR_ERR(tx->mclk), "unable to get mclk clock\n"); if (tx->data->flags & LPASS_MACRO_FLAG_HAS_NPL_CLOCK) { - tx->npl = devm_clk_get(dev, "npl"); + tx->npl = clk_get_retry(dev, "npl"); if (IS_ERR(tx->npl)) return dev_err_probe(dev, PTR_ERR(tx->npl), "unable to get npl clock\n"); } - tx->fsgen = devm_clk_get(dev, "fsgen"); + tx->fsgen = clk_get_retry(dev, "fsgen"); if (IS_ERR(tx->fsgen)) return dev_err_probe(dev, PTR_ERR(tx->fsgen), "unable to get fsgen clock\n"); diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c index 03d6434a4a126..61f9f6cf676be 100644 --- a/sound/soc/codecs/lpass-va-macro.c +++ b/sound/soc/codecs/lpass-va-macro.c @@ -19,6 +19,41 @@ #include #include "lpass-macro-common.h" +#include + +/* + * Local helper: bounded retry for deferred clock providers. + * Clock-provider registration does not trigger deferred-probe retries, + * so a consumer that loses the probe-order race stays deferred forever. + * Wait up to 30s for providers that are registered milliseconds later. + */ +static struct clk *clk_get_retry(struct device *dev, const char *id) +{ + struct clk *c; + int i; + + for (i = 0; i < 60; i++) { + c = devm_clk_get(dev, id); + if (!IS_ERR(c) || PTR_ERR(c) != -EPROBE_DEFER) + return c; + msleep(500); + } + return c; +} + +static struct clk *clk_get_retry_optional(struct device *dev, const char *id) +{ + struct clk *c; + int i; + + for (i = 0; i < 60; i++) { + c = devm_clk_get_optional(dev, id); + if (!IS_ERR(c) || PTR_ERR(c) != -EPROBE_DEFER) + return c; + msleep(500); + } + return c; +} /* VA macro registers */ #define CDC_VA_CLK_RST_CTRL_MCLK_CONTROL (0x0000) @@ -1557,15 +1592,15 @@ static int va_macro_probe(struct platform_device *pdev) va->dev = dev; - va->macro = devm_clk_get_optional(dev, "macro"); + va->macro = clk_get_retry_optional(dev, "macro"); if (IS_ERR(va->macro)) return dev_err_probe(dev, PTR_ERR(va->macro), "unable to get macro clock\n"); - va->dcodec = devm_clk_get_optional(dev, "dcodec"); + va->dcodec = clk_get_retry_optional(dev, "dcodec"); if (IS_ERR(va->dcodec)) return dev_err_probe(dev, PTR_ERR(va->dcodec), "unable to get dcodec clock\n"); - va->mclk = devm_clk_get(dev, "mclk"); + va->mclk = clk_get_retry(dev, "mclk"); if (IS_ERR(va->mclk)) return dev_err_probe(dev, PTR_ERR(va->mclk), "unable to get mclk clock\n"); @@ -1610,7 +1645,7 @@ static int va_macro_probe(struct platform_device *pdev) goto err; if (va->has_npl_clk) { - va->npl = devm_clk_get(dev, "npl"); + va->npl = clk_get_retry(dev, "npl"); if (IS_ERR(va->npl)) { ret = PTR_ERR(va->npl); goto err; diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index 899c8bee4645f..314e83cc1bf92 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -19,6 +19,41 @@ #include "lpass-macro-common.h" #include "lpass-wsa-macro.h" +#include + +/* + * Local helper: bounded retry for deferred clock providers. + * Clock-provider registration does not trigger deferred-probe retries, + * so a consumer that loses the probe-order race stays deferred forever. + * Wait up to 30s for providers that are registered milliseconds later. + */ +static struct clk *clk_get_retry(struct device *dev, const char *id) +{ + struct clk *c; + int i; + + for (i = 0; i < 60; i++) { + c = devm_clk_get(dev, id); + if (!IS_ERR(c) || PTR_ERR(c) != -EPROBE_DEFER) + return c; + msleep(500); + } + return c; +} + +static struct clk *clk_get_retry_optional(struct device *dev, const char *id) +{ + struct clk *c; + int i; + + for (i = 0; i < 60; i++) { + c = devm_clk_get_optional(dev, id); + if (!IS_ERR(c) || PTR_ERR(c) != -EPROBE_DEFER) + return c; + msleep(500); + } + return c; +} #define CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL (0x0000) #define CDC_WSA_MCLK_EN_MASK BIT(0) @@ -2701,25 +2736,25 @@ static int wsa_macro_probe(struct platform_device *pdev) if (!wsa) return -ENOMEM; - wsa->macro = devm_clk_get_optional(dev, "macro"); + wsa->macro = clk_get_retry_optional(dev, "macro"); if (IS_ERR(wsa->macro)) return dev_err_probe(dev, PTR_ERR(wsa->macro), "unable to get macro clock\n"); - wsa->dcodec = devm_clk_get_optional(dev, "dcodec"); + wsa->dcodec = clk_get_retry_optional(dev, "dcodec"); if (IS_ERR(wsa->dcodec)) return dev_err_probe(dev, PTR_ERR(wsa->dcodec), "unable to get dcodec clock\n"); - wsa->mclk = devm_clk_get(dev, "mclk"); + wsa->mclk = clk_get_retry(dev, "mclk"); if (IS_ERR(wsa->mclk)) return dev_err_probe(dev, PTR_ERR(wsa->mclk), "unable to get mclk clock\n"); if (flags & LPASS_MACRO_FLAG_HAS_NPL_CLOCK) { - wsa->npl = devm_clk_get(dev, "npl"); + wsa->npl = clk_get_retry(dev, "npl"); if (IS_ERR(wsa->npl)) return dev_err_probe(dev, PTR_ERR(wsa->npl), "unable to get npl clock\n"); } - wsa->fsgen = devm_clk_get(dev, "fsgen"); + wsa->fsgen = clk_get_retry(dev, "fsgen"); if (IS_ERR(wsa->fsgen)) return dev_err_probe(dev, PTR_ERR(wsa->fsgen), "unable to get fsgen clock\n");