From afdce7686371191dbe85b0ec3814abc364a22205 Mon Sep 17 00:00:00 2001 From: Emanuele Ghidoli Date: Tue, 2 Jul 2024 21:54:29 +0200 Subject: [PATCH] mmc: am654_sdhci: Add the quirk to set TESTCD bit The ARASAN MMC controller on Keystone 3 class of devices need the SDCD line to be connected for proper functioning. In cases where this can't be connected, add a quirk to force the controller into test mode and set the TESTCD bit. Use the flag "ti,fails-without-test-cd", to implement this above quirk when required. Additionally, this quirk also avoids waiting for the controller debounce time. This commit is similar to linux kernel commit c7666240ec76 ("drivers: mmc: sdhci_am654: Add the quirk to set TESTCD bit"). Signed-off-by: Emanuele Ghidoli --- drivers/mmc/am654_sdhci.c | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c index 48fac7a11b..b4c60a48d2 100644 --- a/drivers/mmc/am654_sdhci.c +++ b/drivers/mmc/am654_sdhci.c @@ -105,6 +105,8 @@ struct am654_sdhci_plat { #define FREQSEL_2_BIT BIT(2) #define STRBSEL_4_BIT BIT(3) #define DLL_CALIB BIT(4) + u32 quirks; +#define SDHCI_AM654_QUIRK_FORCE_CDTEST BIT(0) }; struct timing_data { @@ -350,10 +352,8 @@ int am654_sdhci_init(struct am654_sdhci_plat *plat) } #define MAX_SDCD_DEBOUNCE_TIME 2000 -static int am654_sdhci_deferred_probe(struct sdhci_host *host) +static int am654_sdhci_cd_poll(struct mmc *mmc) { - struct udevice *dev = host->mmc->dev; - struct am654_sdhci_plat *plat = dev_get_plat(dev); unsigned long start; int val; @@ -368,12 +368,35 @@ static int am654_sdhci_deferred_probe(struct sdhci_host *host) if (get_timer(start) > MAX_SDCD_DEBOUNCE_TIME) return -ENOMEDIUM; - val = mmc_getcd(host->mmc); + val = mmc_getcd(mmc); } while (!val); + return 0; +} + +static int am654_sdhci_deferred_probe(struct sdhci_host *host) +{ + struct udevice *dev = host->mmc->dev; + struct am654_sdhci_plat *plat = dev_get_plat(dev); + int ret; + + if (!(plat->quirks & SDHCI_AM654_QUIRK_FORCE_CDTEST)) { + if (am654_sdhci_cd_poll(host->mmc)) + return -ENOMEDIUM; + } + am654_sdhci_init(plat); - return sdhci_probe(dev); + ret = sdhci_probe(dev); + + if (plat->quirks & SDHCI_AM654_QUIRK_FORCE_CDTEST) { + u8 hostctrlreg = sdhci_readb(host, SDHCI_HOST_CONTROL); + + hostctrlreg |= SDHCI_CTRL_CD_TEST_INS | SDHCI_CTRL_CD_TEST; + sdhci_writeb(host, hostctrlreg, SDHCI_HOST_CONTROL); + } + + return ret; } static void am654_sdhci_write_b(struct sdhci_host *host, u8 val, int reg) @@ -679,6 +702,9 @@ static int am654_sdhci_probe(struct udevice *dev) regmap_init_mem_index(dev_ofnode(dev), &plat->base, 1); + if (plat->quirks & SDHCI_AM654_QUIRK_FORCE_CDTEST) + am654_sdhci_deferred_probe(host); + return 0; } @@ -728,6 +754,8 @@ static int am654_sdhci_of_to_plat(struct udevice *dev) dev_read_u32(dev, "ti,strobe-sel", &plat->strb_sel); dev_read_u32(dev, "ti,clkbuf-sel", &plat->clkbuf_sel); + if (dev_read_bool(dev, "ti,fails-without-test-cd")) + plat->quirks |= SDHCI_AM654_QUIRK_FORCE_CDTEST; ret = mmc_of_parse(dev, cfg); if (ret) -- 2.39.5