From f0710a557cb17746b09234f01073a2cdafe4f4a5 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Mon, 6 May 2013 12:17:32 +0300 Subject: mmc: sdhci: add ability to stay runtime-resumed if the card is powered up If card power is dependent on SD bus power then the host controller must not be runtime suspended while the card is powered up. Add the ability to stay runtime-resumed in that case and enable it with a new quirk SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON. Signed-off-by: Adrian Hunter Signed-off-by: Chris Ball --- include/linux/mmc/sdhci.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux/mmc/sdhci.h') diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index b838ffc49e4..ba35bdb87d9 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h @@ -95,6 +95,7 @@ struct sdhci_host { /* The system physically doesn't support 1.8v, even if the host does */ #define SDHCI_QUIRK2_NO_1_8_V (1<<2) #define SDHCI_QUIRK2_PRESET_VALUE_BROKEN (1<<3) +#define SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON (1<<4) int irq; /* Device IRQ */ void __iomem *ioaddr; /* Mapped address */ @@ -139,6 +140,7 @@ struct sdhci_host { u8 pwr; /* Current voltage */ bool runtime_suspended; /* Host is runtime suspended */ + bool bus_on; /* Bus power prevents runtime suspend */ struct mmc_request *mrq; /* Current request */ struct mmc_command *cmd; /* Current command */ -- cgit v1.2.3-70-g09d2 From 156e14b126ffb6f040bc6f1aff3c51077e42a744 Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Wed, 12 Jun 2013 08:16:38 +0200 Subject: mmc: sdhci: fix caps2 for HS200 Although the HC supports HS200 (eMMC) the caps2 are always zero; this means there's no way to use the super speed mode (when init the card). If the HC support SDR104, for SD3.0, so it also supports HS200 for eMMC and this patch just sets the MMC_CAP2_HS200 in the host caps2 field. Reported-by: Youssef Triki Signed-off-by: Giuseppe Cavallaro Reviewed-by: Philip Rakity Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci.c | 14 +++++++++----- include/linux/mmc/sdhci.h | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'include/linux/mmc/sdhci.h') diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index eadb3adf446..9bd6ab20384 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1863,7 +1863,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) */ if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) && (host->flags & SDHCI_SDR50_NEEDS_TUNING || - host->flags & SDHCI_HS200_NEEDS_TUNING)) + host->flags & SDHCI_SDR104_NEEDS_TUNING)) requires_tuning_nonuhs = true; if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR104) || @@ -2994,9 +2994,13 @@ int sdhci_add_host(struct sdhci_host *host) mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25; /* SDR104 supports also implies SDR50 support */ - if (caps[1] & SDHCI_SUPPORT_SDR104) + if (caps[1] & SDHCI_SUPPORT_SDR104) { mmc->caps |= MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50; - else if (caps[1] & SDHCI_SUPPORT_SDR50) + /* SD3.0: SDR104 is supported so (for eMMC) the caps2 + * field can be promoted to support HS200. + */ + mmc->caps2 |= MMC_CAP2_HS200; + } else if (caps[1] & SDHCI_SUPPORT_SDR50) mmc->caps |= MMC_CAP_UHS_SDR50; if (caps[1] & SDHCI_SUPPORT_DDR50) @@ -3006,9 +3010,9 @@ int sdhci_add_host(struct sdhci_host *host) if (caps[1] & SDHCI_USE_SDR50_TUNING) host->flags |= SDHCI_SDR50_NEEDS_TUNING; - /* Does the host need tuning for HS200? */ + /* Does the host need tuning for SDR104 / HS200? */ if (mmc->caps2 & MMC_CAP2_HS200) - host->flags |= SDHCI_HS200_NEEDS_TUNING; + host->flags |= SDHCI_SDR104_NEEDS_TUNING; /* Driver Type(s) (A, C, D) supported by the host */ if (caps[1] & SDHCI_DRIVER_TYPE_A) diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index ba35bdb87d9..a7451800909 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h @@ -127,7 +127,7 @@ struct sdhci_host { #define SDHCI_AUTO_CMD23 (1<<7) /* Auto CMD23 support */ #define SDHCI_PV_ENABLED (1<<8) /* Preset value enabled */ #define SDHCI_SDIO_IRQ_ENABLED (1<<9) /* SDIO irq enabled */ -#define SDHCI_HS200_NEEDS_TUNING (1<<10) /* HS200 needs tuning */ +#define SDHCI_SDR104_NEEDS_TUNING (1<<10) /* SDR104/HS200 needs tuning */ #define SDHCI_USING_RETUNING_TIMER (1<<11) /* Host is using a retuning timer for the card */ unsigned int version; /* SDHCI spec. version */ -- cgit v1.2.3-70-g09d2 From dcaff04d36fd7f22973bf4fc108912ce19bcef4f Mon Sep 17 00:00:00 2001 From: Oded Gabbay Date: Fri, 5 Jul 2013 12:48:35 -0400 Subject: mmc: esdhc: Fix bug when writing to SDHCI_HOST_CONTROL register The P2020 has a non-standard implementation of the SDHCI_HOST_CONTROL register. This patch adds a QUIRK in the SDHCI header to signal that a host controller has a non-standard SDHCI_HOST_CONTROL register. The patch adds a check to the function esdhc_writeb in file sdhci-of-esdhc.c, where it checks if the write is done to the SDHCI_HOST_CONTROL register and th host has the above mentioned QUIRK, then the function simply returns instead of writing to the register. The patch also detects if the processor is P2020 (by looking in dev tree) and if so, adds the QUIRK to the host->quirk2 Signed-off-by: Oded Gabbay Reviewed-by: Anton Vorontsov Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-of-esdhc.c | 17 +++++++++++++++++ include/linux/mmc/sdhci.h | 2 ++ 2 files changed, 19 insertions(+) (limited to 'include/linux/mmc/sdhci.h') diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index b2a635e73ae..15039e2d1c1 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -121,6 +121,13 @@ static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg) if (reg == SDHCI_HOST_CONTROL) { u32 dma_bits; + /* + * If host control register is not standard, exit + * this function + */ + if (host->quirks2 & SDHCI_QUIRK2_BROKEN_HOST_CONTROL) + return; + /* DMA select is 22,23 bits in Protocol Control Register */ dma_bits = (val & SDHCI_CTRL_DMA_MASK) << 5; clrsetbits_be32(host->ioaddr + reg , SDHCI_CTRL_DMA_MASK << 5, @@ -289,6 +296,7 @@ static const struct sdhci_pltfm_data sdhci_esdhc_pdata = { static int sdhci_esdhc_probe(struct platform_device *pdev) { struct sdhci_host *host; + struct device_node *np; int ret; host = sdhci_pltfm_init(pdev, &sdhci_esdhc_pdata, 0); @@ -297,6 +305,15 @@ static int sdhci_esdhc_probe(struct platform_device *pdev) sdhci_get_of_property(pdev); + np = pdev->dev.of_node; + if (of_device_is_compatible(np, "fsl,p2020-esdhc")) { + /* + * Freescale messed up with P2020 as it has a non-standard + * host control register + */ + host->quirks2 |= SDHCI_QUIRK2_BROKEN_HOST_CONTROL; + } + /* call to generic mmc_of_parse to support additional capabilities */ mmc_of_parse(host->mmc); diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index a7451800909..e3c6a74d980 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h @@ -96,6 +96,8 @@ struct sdhci_host { #define SDHCI_QUIRK2_NO_1_8_V (1<<2) #define SDHCI_QUIRK2_PRESET_VALUE_BROKEN (1<<3) #define SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON (1<<4) +/* Controller has a non-standard host control register */ +#define SDHCI_QUIRK2_BROKEN_HOST_CONTROL (1<<5) int irq; /* Device IRQ */ void __iomem *ioaddr; /* Mapped address */ -- cgit v1.2.3-70-g09d2