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 <emanuele.ghidoli@toradex.com>
This commit is contained in:
Emanuele Ghidoli 2024-07-02 21:54:29 +02:00 committed by Tom Rini
parent 9945a30e2e
commit afdce76863

View file

@ -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)