From 8d7c5395d15160ffc26e5490167c49dff511b74f Mon Sep 17 00:00:00 2001 From: Subhash Jadavani Date: Wed, 10 Aug 2011 11:16:01 +0530 Subject: [PATCH 1/9] mmc: sd: Handle SD3.0 cards not supporting UHS-I bus speed mode Here is Essential conditions to indicate Version 3.00 Card (SD_SPEC=2 and SD_SPEC3=1) : (1) The card shall support CMD6 (2) The card shall support CMD8 (3) The card shall support CMD42 (4) User area capacity shall be up to 2GB (SDSC) or 32GB (SDHC) User area capacity shall be more than or equal to 32GB and up to 2TB (SDXC) (5) Speed Class shall be supported (SDHC or SDXC) So even if SD card doesn't support any of the newly defined UHS-I bus speed mode, it can advertise itself as SD3.0 cards as long as it supports all the essential conditions of SD3.0 cards. Given this, these type of cards should atleast run in High Speed mode @50MHZ if it supports HS. But current initialization sequence for SD3.0 cards is such that these non-UHS-I SD3.0 cards runs in Default Speed mode @25MHz. This patch makes sure that these non-UHS-I SD3.0 cards run in High Speed Mode @50MHz. Tested this patch with SanDisk Extreme SDHC 8GB Class 10 card. Reported-by: "Hiremath, Vaibhav" Signed-off-by: Subhash Jadavani Signed-off-by: Chris Ball --- drivers/mmc/core/sd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 4c281a4bf0589d..c813ee3bda31e5 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -306,6 +306,9 @@ static int mmc_read_switch(struct mmc_card *card) goto out; } + if (status[13] & UHS_SDR50_BUS_SPEED) + card->sw_caps.hs_max_dtr = 50000000; + if (card->scr.sda_spec3) { card->sw_caps.sd3_bus_mode = status[13]; @@ -348,9 +351,6 @@ static int mmc_read_switch(struct mmc_card *card) } card->sw_caps.sd3_curr_limit = status[7]; - } else { - if (status[13] & 0x02) - card->sw_caps.hs_max_dtr = 50000000; } out: From 872a8ff772ded51403bd8a46f80b1bf9706b76cd Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Mon, 12 Mar 2012 10:58:00 -0600 Subject: [PATCH 2/9] mmc: use really long write timeout to deal with crappy cards mmc: use really long write timeout to deal with crappy cards Several people have noticed that crappy SD cards take much longer to complete multiple block writes than the 300ms that Linux specifies. Try to work around this by using a three second write timeout instead. This is a generalized version of a patch from Chase Maupin , whose patch description said: * With certain SD cards timeouts like the following have been seen due to an improper calculation of the dto value: mmcblk0: error -110 transferring data, sector 4126233, nr 8, card status 0xc00 * By removing the dto calculation and setting the timeout value to the maximum specified by the SD card specification part A2 section 2.2.15 these timeouts can be avoided. * This change has been used by beagleboard users as well as the Texas Instruments SDK without a negative impact. * There are multiple discussion threads about this but the most relevant ones are: * http://talk.maemo.org/showthread.php?p=1000707#post1000707 * http://www.mail-archive.com/linux-omap@vger.kernel.org/msg42213.html * Original proposal for this fix was done by Sukumar Ghoral of Texas Instruments * Tested using a Texas Instruments AM335x EVM Signed-off-by: Paul Walmsley Tested-by: Tony Lindgren Signed-off-by: Chris Ball --- drivers/mmc/core/core.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index d637982b0352bc..a14ddf966398c4 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -396,10 +396,14 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card) if (data->flags & MMC_DATA_WRITE) /* - * The limit is really 250 ms, but that is - * insufficient for some crappy cards. + * The MMC spec "It is strongly recommended + * for hosts to implement more than 500ms + * timeout value even if the card indicates + * the 250ms maximum busy length." Even the + * previous value of 300ms is known to be + * insufficient for some cards. */ - limit_us = 300000; + limit_us = 3000000; else limit_us = 100000; From f3320b75d0d51c9cca8df24369e34b664b235b7d Mon Sep 17 00:00:00 2001 From: Stefan Nilsson XK Date: Thu, 15 Sep 2011 17:50:38 +0200 Subject: [PATCH 3/9] mmc: core: Set correct bus mode before card init Earlier all cards where initiated with bus mode set as OPENDRAIN, and then later switched to PUSHPULL. According to the MMC/SD/SDIO specifications only MMC cards use OPENDRAIN during init. For both SD and SDIO the bus mode shall be PUSHPULL before attempting to init the card. The consequence of having incorrect bus mode can lead to not being able to detect the card. Therefore the default behavior have now been changed to PUSHPULL in mmc_power_up, and will only be temporarily switched when trying to attach or init a MMC card. Signed-off-by: Stefan Nilsson XK Signed-off-by: Ulf HANSSON Acked-by: Linus Walleij Signed-off-by: Chris Ball --- drivers/mmc/core/core.c | 8 +++----- drivers/mmc/core/mmc.c | 8 ++++++++ drivers/mmc/core/sd.c | 2 -- drivers/mmc/core/sdio.c | 2 -- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index a14ddf966398c4..04a141f99f4f0a 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1123,13 +1123,11 @@ static void mmc_power_up(struct mmc_host *host) bit = fls(host->ocr_avail) - 1; host->ios.vdd = bit; - if (mmc_host_is_spi(host)) { + if (mmc_host_is_spi(host)) host->ios.chip_select = MMC_CS_HIGH; - host->ios.bus_mode = MMC_BUSMODE_PUSHPULL; - } else { + else host->ios.chip_select = MMC_CS_DONTCARE; - host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; - } + host->ios.bus_mode = MMC_BUSMODE_PUSHPULL; host->ios.power_mode = MMC_POWER_UP; host->ios.bus_width = MMC_BUS_WIDTH_1; host->ios.timing = MMC_TIMING_LEGACY; diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 6952f778c294c9..89bb40d8c9b9c3 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -550,6 +550,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, BUG_ON(!host); WARN_ON(!host->claimed); + /* Set correct bus mode for MMC before attempting init */ + if (!mmc_host_is_spi(host)) + mmc_set_bus_mode(host, MMC_BUSMODE_OPENDRAIN); + /* * Since we're changing the OCR value, we seem to * need to tell some cards to go back to the idle @@ -1019,6 +1023,10 @@ int mmc_attach_mmc(struct mmc_host *host) BUG_ON(!host); WARN_ON(!host->claimed); + /* Set correct bus mode for MMC before attempting attach */ + if (!mmc_host_is_spi(host)) + mmc_set_bus_mode(host, MMC_BUSMODE_OPENDRAIN); + err = mmc_send_op_cond(host, 0, &ocr); if (err) return err; diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index c813ee3bda31e5..fd5522815aefd1 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -929,8 +929,6 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, err = mmc_send_relative_addr(host, &card->rca); if (err) return err; - - mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); } if (!oldcard) { diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index ac492ac974e164..698d813cff3b31 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -408,8 +408,6 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, */ if (oldcard) oldcard->rca = card->rca; - - mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); } /* From e4f6da232f57a77388881a9c6f5fd3e6f3d2708d Mon Sep 17 00:00:00 2001 From: Stefan Nilsson XK Date: Thu, 3 Nov 2011 09:44:12 +0100 Subject: [PATCH 4/9] mmc: core: Add quirk for long data read time Adds a quirk that sets the data read timeout to a fixed value instead of relying on the information in the CSD. The timeout value chosen is 300ms since that has proven enough for the problematic cards found, but could be increased if other cards require this. This patch also enables this quirk for certain Micron cards known to have this problem. Signed-off-by: Stefan Nilsson XK Signed-off-by: Ulf Hansson Acked-by: Linus Walleij Cc: Signed-off-by: Chris Ball --- drivers/mmc/card/block.c | 8 ++++++++ drivers/mmc/core/core.c | 12 ++++++++++++ include/linux/mmc/card.h | 6 ++++++ 3 files changed, 26 insertions(+) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 4c1a648d00fcfb..d62f4cd4b788f8 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -1492,6 +1492,14 @@ static const struct mmc_fixup blk_fixups[] = MMC_QUIRK_BLK_NO_CMD23), MMC_FIXUP("MMC32G", 0x11, CID_OEMID_ANY, add_quirk_mmc, MMC_QUIRK_BLK_NO_CMD23), + + /* + * Some Micron MMC cards needs longer data read timeout than + * indicated in CSD. + */ + MMC_FIXUP(CID_NAME_ANY, 0x13, 0x200, add_quirk_mmc, + MMC_QUIRK_LONG_READ_TIME), + END_FIXUP }; diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 04a141f99f4f0a..f5d2890e837383 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -415,6 +415,18 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card) data->timeout_clks = 0; } } + + /* + * Some cards require longer data read timeout than indicated in CSD. + * Address this by setting the read timeout to a "reasonably high" + * value. For the cards tested, 300ms has proven enough. If necessary, + * this value can be increased if other problematic cards require this. + */ + if (mmc_card_long_read_time(card) && data->flags & MMC_DATA_READ) { + data->timeout_ns = 300000000; + data->timeout_clks = 0; + } + /* * Some cards need very high timeouts if driven in SPI mode. * The worst observed timeout was 900ms after writing a diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index b460fc2af8a122..97c474098f0bd9 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -188,6 +188,7 @@ struct mmc_card { #define MMC_QUIRK_DISABLE_CD (1<<5) /* disconnect CD/DAT[3] resistor */ #define MMC_QUIRK_INAND_CMD38 (1<<6) /* iNAND devices have broken CMD38 */ #define MMC_QUIRK_BLK_NO_CMD23 (1<<7) /* Avoid CMD23 for regular multiblock */ +#define MMC_QUIRK_LONG_READ_TIME (1<<9) /* Data read time > CSD says */ unsigned int erase_size; /* erase size in sectors */ unsigned int erase_shift; /* if erase unit is power 2 */ @@ -377,6 +378,11 @@ static inline int mmc_card_nonstd_func_interface(const struct mmc_card *c) return c->quirks & MMC_QUIRK_NONSTD_FUNC_IF; } +static inline int mmc_card_long_read_time(const struct mmc_card *c) +{ + return c->quirks & MMC_QUIRK_LONG_READ_TIME; +} + #define mmc_card_name(c) ((c)->cid.prod_name) #define mmc_card_id(c) (dev_name(&(c)->dev)) From d64b84ca8c171596b68bf125d266c84306ac421c Mon Sep 17 00:00:00 2001 From: Grigori Goronzy Date: Mon, 4 Jun 2012 04:27:48 +0200 Subject: [PATCH 5/9] sdhci-bcm2708: speed up DMA sync Experiments show that it doesn't really take that long to sync, so we can reduce the poll interval slightly. Might improve performance a bit. --- drivers/mmc/host/sdhci-bcm2708.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-bcm2708.c b/drivers/mmc/host/sdhci-bcm2708.c index 7136998ad967db..9aebdfb6e7a074 100644 --- a/drivers/mmc/host/sdhci-bcm2708.c +++ b/drivers/mmc/host/sdhci-bcm2708.c @@ -907,7 +907,7 @@ static void sdhci_bcm2708_dma_complete_irq(struct sdhci_host *host, while (0 != (sdhci_bcm2708_raw_readl(host, SDHCI_PRESENT_STATE) & state_mask) && --timeout > 0) { - udelay(100); + udelay(30); continue; } if (timeout <= 0) From 9f144964006fb10db9436c5982c26d0ee9d8ec32 Mon Sep 17 00:00:00 2001 From: Grigori Goronzy Date: Mon, 11 Jun 2012 18:52:04 +0200 Subject: [PATCH 6/9] sdhci-bcm2708: remove custom clock handling The custom clock handling code is redundant and buggy. The MMC/SDHCI subsystem does a better job than it, so remove it for good. --- drivers/mmc/host/sdhci-bcm2708.c | 65 +------------------------------- 1 file changed, 1 insertion(+), 64 deletions(-) diff --git a/drivers/mmc/host/sdhci-bcm2708.c b/drivers/mmc/host/sdhci-bcm2708.c index 9aebdfb6e7a074..c96491185f88b6 100644 --- a/drivers/mmc/host/sdhci-bcm2708.c +++ b/drivers/mmc/host/sdhci-bcm2708.c @@ -359,68 +359,9 @@ void sdhci_bcm2708_writeb(struct sdhci_host *host, u8 val, int reg) static unsigned int sdhci_bcm2708_get_max_clock(struct sdhci_host *host) { - return 20000000; // this value is in Hz (20MHz) + return BCM2708_EMMC_CLOCK_FREQ; } -static unsigned int sdhci_bcm2708_get_timeout_clock(struct sdhci_host *host) -{ - if(host->clock) - return (host->clock / 1000); // this value is in kHz (100MHz) - else - return (sdhci_bcm2708_get_max_clock(host) / 1000); -} - -static void sdhci_bcm2708_set_clock(struct sdhci_host *host, unsigned int clock) -{ - int div = 0; - u16 clk = 0; - unsigned long timeout; - - if (clock == host->clock) - return; - - sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); - - if (clock == 0) - goto out; - - if (BCM2708_EMMC_CLOCK_FREQ <= clock) - div = 1; - else { - for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; div += 2) { - if ((BCM2708_EMMC_CLOCK_FREQ / div) <= clock) - break; - } - } - - DBG( "desired SD clock: %d, actual: %d\n", - clock, BCM2708_EMMC_CLOCK_FREQ / div); - - clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; - clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) - << SDHCI_DIVIDER_HI_SHIFT; - clk |= SDHCI_CLOCK_INT_EN; - - sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); - - timeout = 20; - while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) - & SDHCI_CLOCK_INT_STABLE)) { - if (timeout == 0) { - printk(KERN_ERR "%s: Internal clock never " - "stabilised.\n", mmc_hostname(host->mmc)); - return; - } - timeout--; - mdelay(1); - } - - clk |= SDHCI_CLOCK_CARD_EN; - sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); -out: - host->clock = clock; - } - /*****************************************************************************\ * * * DMA Operation * @@ -1307,11 +1248,7 @@ static struct sdhci_ops sdhci_bcm2708_ops = { #else #error The BCM2708 SDHCI driver needs CONFIG_MMC_SDHCI_IO_ACCESSORS to be set #endif - //.enable_dma = NULL, - .set_clock = sdhci_bcm2708_set_clock, .get_max_clock = sdhci_bcm2708_get_max_clock, - //.get_min_clock = NULL, - .get_timeout_clock = sdhci_bcm2708_get_timeout_clock, .enable = sdhci_bcm2708_enable, .disable = sdhci_bcm2708_disable, From 7a6fba9809c8d3a7fb1b2d0c40e0eae335127a6a Mon Sep 17 00:00:00 2001 From: Grigori Goronzy Date: Mon, 11 Jun 2012 18:53:59 +0200 Subject: [PATCH 7/9] sdhci-bcm2708: add additional quirks Some additional quirks are needed for correct operation. There's no SDHCI capabilities register documented, and it always reads zero, so add SDHCI_QUIRK_MISSING_CAPS. Apparently SDHCI_QUIRK_NO_HISPD_BIT is needed for many cards to work correctly in high-speed mode, so add it as well. --- drivers/mmc/host/sdhci-bcm2708.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-bcm2708.c b/drivers/mmc/host/sdhci-bcm2708.c index c96491185f88b6..16c918b0183c59 100644 --- a/drivers/mmc/host/sdhci-bcm2708.c +++ b/drivers/mmc/host/sdhci-bcm2708.c @@ -1311,7 +1311,9 @@ static int __devinit sdhci_bcm2708_probe(struct platform_device *pdev) host->quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION | SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | - SDHCI_QUIRK_NONSTANDARD_CLOCK; + SDHCI_QUIRK_MISSING_CAPS | + SDHCI_QUIRK_NO_HISPD_BIT; + #ifdef CONFIG_MMC_SDHCI_BCM2708_DMA host->flags = SDHCI_USE_PLATDMA; #endif From 420806e5adabd8343b362b4a1d7f64f22b394dbf Mon Sep 17 00:00:00 2001 From: Grigori Goronzy Date: Mon, 11 Jun 2012 18:57:13 +0200 Subject: [PATCH 8/9] sdhci-bcm2708: add allow_highspeed parameter Add a parameter to disable high-speed mode for the few cards that still might have problems. High-speed mode is enabled by default. --- drivers/mmc/host/sdhci-bcm2708.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-bcm2708.c b/drivers/mmc/host/sdhci-bcm2708.c index 16c918b0183c59..a8aae16957bb43 100644 --- a/drivers/mmc/host/sdhci-bcm2708.c +++ b/drivers/mmc/host/sdhci-bcm2708.c @@ -135,6 +135,8 @@ static inline unsigned long int since_ns(hptime_t t) return (unsigned long)((hptime() - t) * HPTIME_CLK_NS); } +static bool allow_highspeed = 1; + #if 0 static void hptime_test(void) { @@ -1381,7 +1383,8 @@ static int __devinit sdhci_bcm2708_probe(struct platform_device *pdev) host_priv->dma_chan, host_priv->dma_chan_base, host_priv->dma_irq); - host->mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; + if (allow_highspeed) + host->mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; #endif ret = sdhci_add_host(host); @@ -1487,8 +1490,12 @@ static void __exit sdhci_drv_exit(void) module_init(sdhci_drv_init); module_exit(sdhci_drv_exit); +module_param(allow_highspeed, bool, 0444); + MODULE_DESCRIPTION("Secure Digital Host Controller Interface platform driver"); MODULE_AUTHOR("Broadcom "); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:"DRIVER_NAME); +MODULE_PARM_DESC(allow_highspeed, "Allow high speed transfers modes"); + From f1a14aea8494dc019eb145a08f2f26022efd7731 Mon Sep 17 00:00:00 2001 From: Grigori Goronzy Date: Mon, 11 Jun 2012 18:58:40 +0200 Subject: [PATCH 9/9] sdhci-bcm2708: assume 50 MHz eMMC clock 80 MHz clock isnt't suited well to be dividable to get SD clocks of 25 MHz (default mode) or 50 MHz (high speed mode). 50 MHz are perfect to drive the SD interface at ideal frequencies. --- drivers/mmc/host/sdhci-bcm2708.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-bcm2708.c b/drivers/mmc/host/sdhci-bcm2708.c index a8aae16957bb43..64b956bb777afe 100644 --- a/drivers/mmc/host/sdhci-bcm2708.c +++ b/drivers/mmc/host/sdhci-bcm2708.c @@ -74,7 +74,7 @@ #define BCM2708_SDHCI_SLEEP_TIMEOUT 1000 /* msecs */ /* Mhz clock that the EMMC core is running at. Should match the platform clockman settings */ -#define BCM2708_EMMC_CLOCK_FREQ 80000000 +#define BCM2708_EMMC_CLOCK_FREQ 50000000 #define POWER_OFF 0 #define POWER_LAZY_OFF 1