diff options
-rw-r--r-- | drivers/mmc/host/sdhci-of-esdhc.c | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index f8eb1fb0c921..ae5fcbfa1eef 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -21,6 +21,32 @@ #include "sdhci-pltfm.h" #include "sdhci-esdhc.h" +#define VENDOR_V_22 0x12 +static u32 esdhc_readl(struct sdhci_host *host, int reg) +{ + u32 ret; + + ret = in_be32(host->ioaddr + reg); + /* + * The bit of ADMA flag in eSDHC is not compatible with standard + * SDHC register, so set fake flag SDHCI_CAN_DO_ADMA2 when ADMA is + * supported by eSDHC. + * And for many FSL eSDHC controller, the reset value of field + * SDHCI_CAN_DO_ADMA1 is one, but some of them can't support ADMA, + * only these vendor version is greater than 2.2/0x12 support ADMA. + * For FSL eSDHC, must aligned 4-byte, so use 0xFC to read the + * the verdor version number, oxFE is SDHCI_HOST_VERSION. + */ + if ((reg == SDHCI_CAPABILITIES) && (ret & SDHCI_CAN_DO_ADMA1)) { + u32 tmp = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS); + tmp = (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT; + if (tmp > VENDOR_V_22) + ret |= SDHCI_CAN_DO_ADMA2; + } + + return ret; +} + static u16 esdhc_readw(struct sdhci_host *host, int reg) { u16 ret; @@ -144,7 +170,7 @@ static void esdhc_of_resume(struct sdhci_host *host) #endif static struct sdhci_ops sdhci_esdhc_ops = { - .read_l = sdhci_be32bs_readl, + .read_l = esdhc_readl, .read_w = esdhc_readw, .read_b = esdhc_readb, .write_l = sdhci_be32bs_writel, @@ -161,9 +187,13 @@ static struct sdhci_ops sdhci_esdhc_ops = { }; static struct sdhci_pltfm_data sdhci_esdhc_pdata = { - /* card detection could be handled via GPIO */ + /* + * card detection could be handled via GPIO + * eSDHC cannot support End Attribute in NOP ADMA descriptor + */ .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION - | SDHCI_QUIRK_NO_CARD_NO_RESET, + | SDHCI_QUIRK_NO_CARD_NO_RESET + | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, .ops = &sdhci_esdhc_ops, }; |