Check for available pinctrl states before selecting them in the
SpacemiT SDHCI driver.

Skip pinctrl selection when the device does not define a default
state, allowing eMMC configurations without pinctrl properties
to work without spurious pinctrl errors.

Select the UHS pinctrl state only when it is defined, and log
errors when pinctrl state selection fails.

Cc: Dave Klotz <[email protected]>
Cc: Eric Chung <[email protected]>
Cc: Hung-Chun Tseng <[email protected]>
Cc: E Shattow <[email protected]>
Cc: Yixun Lan <[email protected]>
Signed-off-by: Anand Moon <[email protected]>
---
 drivers/mmc/spacemit_sdhci.c | 33 ++++++++++++++++++++++++++++++---
 1 file changed, 30 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c
index 836201ce83c..668555b94e1 100644
--- a/drivers/mmc/spacemit_sdhci.c
+++ b/drivers/mmc/spacemit_sdhci.c
@@ -355,10 +355,27 @@ static int spacemit_sdhci_get_b_max(struct udevice *dev, 
void *dst,
        return mmc->cfg->b_max;
 }
 
+static bool spacemit_sdhci_has_pinctrl_state(struct udevice *dev,
+                                            const char *state_name)
+{
+       char propname[20];
+       int state;
+
+       state = dev_read_stringlist_search(dev, "pinctrl-names",
+                                          state_name);
+       if (state < 0)
+               return false;
+
+       snprintf(propname, sizeof(propname), "pinctrl-%d", state);
+
+       return !!dev_read_prop(dev, propname, NULL);
+}
+
 static void spacemit_sdhci_set_control_reg(struct sdhci_host *host)
 {
        struct mmc *mmc = host->mmc;
        u32 reg;
+       int ret;
 
        spacemit_sdhci_set_voltage(host);
 
@@ -383,16 +400,26 @@ static void spacemit_sdhci_set_control_reg(struct 
sdhci_host *host)
        sdhci_writel(host, reg, SPACEMIT_SDHC_TX_CFG_REG);
 
        /* Set pinctrl state based on selected timing mode */
-       if (IS_ENABLED(CONFIG_PINCTRL)) {
+       if (IS_ENABLED(CONFIG_PINCTRL) &&
+           spacemit_sdhci_has_pinctrl_state(mmc->dev, "default")) {
                switch (mmc->selected_mode) {
                case UHS_SDR12:
                case UHS_SDR25:
                case UHS_SDR50:
                case UHS_SDR104:
-                       pinctrl_select_state(mmc->dev, "uhs");
+                       if (spacemit_sdhci_has_pinctrl_state(mmc->dev, "uhs")) {
+                               ret = pinctrl_select_state(mmc->dev, "uhs");
+                               if (ret)
+                                       log_err("SDHCI %s: uhs pinctrl 
selection failed: %d\n",
+                                               mmc->dev->name, ret);
+                       }
                        break;
+
                default:
-                       pinctrl_select_state(mmc->dev, "default");
+                       ret = pinctrl_select_state(mmc->dev, "default");
+                       if (ret)
+                               log_err("SDHCI %s: default pinctrl selection 
failed: %d\n",
+                                       mmc->dev->name, ret);
                        break;
                }
        }
-- 
2.56.0

Reply via email to