diff options
Diffstat (limited to 'target/linux/brcm2708/patches-3.10/0038-Lazy-CRC-quirk-Implemented-retrying-mechanisms-for-S.patch')
-rw-r--r-- | target/linux/brcm2708/patches-3.10/0038-Lazy-CRC-quirk-Implemented-retrying-mechanisms-for-S.patch | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/target/linux/brcm2708/patches-3.10/0038-Lazy-CRC-quirk-Implemented-retrying-mechanisms-for-S.patch b/target/linux/brcm2708/patches-3.10/0038-Lazy-CRC-quirk-Implemented-retrying-mechanisms-for-S.patch new file mode 100644 index 0000000000..b21e62bcba --- /dev/null +++ b/target/linux/brcm2708/patches-3.10/0038-Lazy-CRC-quirk-Implemented-retrying-mechanisms-for-S.patch @@ -0,0 +1,227 @@ +From d6442f505a7bf1bebe9bd4689d021f007a269cd6 Mon Sep 17 00:00:00 2001 +From: dero <de@ro> +Date: Mon, 19 Nov 2012 12:46:06 +0100 +Subject: [PATCH 038/174] Lazy CRC quirk: Implemented retrying mechanisms for + SD SSR and SCR, disabled missing_status and spurious CRC ACMD51 quirks by + default (should be fixed by the retrying-mechanishm) + +--- + drivers/mmc/core/sd.c | 115 +++++++++++++++++++++++++++++++++------ + drivers/mmc/host/sdhci-bcm2708.c | 11 +++- + 2 files changed, 108 insertions(+), 18 deletions(-) + +--- a/drivers/mmc/core/sd.c ++++ b/drivers/mmc/core/sd.c +@@ -13,6 +13,8 @@ + #include <linux/err.h> + #include <linux/slab.h> + #include <linux/stat.h> ++#include <linux/jiffies.h> ++#include <linux/nmi.h> + + #include <linux/mmc/host.h> + #include <linux/mmc/card.h> +@@ -58,6 +60,15 @@ static const unsigned int tacc_mant[] = + __res & __mask; \ + }) + ++// timeout for tries ++static const unsigned long retry_timeout_ms= 10*1000; ++ ++// try at least 10 times, even if timeout is reached ++static const int retry_min_tries= 10; ++ ++// delay between tries ++static const unsigned long retry_delay_ms= 10; ++ + /* + * Given the decoded CSD structure, decode the raw CID to our CID structure. + */ +@@ -210,12 +221,62 @@ static int mmc_decode_scr(struct mmc_car + } + + /* +- * Fetch and process SD Status register. ++ * Fetch and process SD Configuration Register. ++ */ ++static int mmc_read_scr(struct mmc_card *card) ++{ ++ unsigned long timeout_at; ++ int err, tries; ++ ++ timeout_at= jiffies + msecs_to_jiffies( retry_timeout_ms ); ++ tries= 0; ++ ++ while( tries < retry_min_tries || time_before( jiffies, timeout_at ) ) ++ { ++ unsigned long delay_at; ++ tries++; ++ ++ err = mmc_app_send_scr(card, card->raw_scr); ++ if( !err ) ++ break; // sucess!!! ++ ++ touch_nmi_watchdog(); // we are still alive! ++ ++ // delay ++ delay_at= jiffies + msecs_to_jiffies( retry_delay_ms ); ++ while( time_before( jiffies, delay_at ) ) ++ { ++ mdelay( 1 ); ++ touch_nmi_watchdog(); // we are still alive! ++ } ++ } ++ ++ if( err) ++ { ++ pr_err("%s: failed to read SD Configuration register (SCR) after %d tries during %lu ms, error %d\n", mmc_hostname(card->host), tries, retry_timeout_ms, err ); ++ return err; ++ } ++ ++ if( tries > 1 ) ++ { ++ pr_info("%s: could read SD Configuration register (SCR) at the %dth attempt\n", mmc_hostname(card->host), tries ); ++ } ++ ++ err = mmc_decode_scr(card); ++ if (err) ++ return err; ++ ++ return err; ++} ++ ++/* ++ * Fetch and process SD Status Register. + */ + static int mmc_read_ssr(struct mmc_card *card) + { ++ unsigned long timeout_at; + unsigned int au, es, et, eo; +- int err, i; ++ int err, i, tries; + u32 *ssr; + + if (!(card->csd.cmdclass & CCC_APP_SPEC)) { +@@ -227,15 +288,41 @@ static int mmc_read_ssr(struct mmc_card + ssr = kmalloc(64, GFP_KERNEL); + if (!ssr) + return -ENOMEM; +- +- err = mmc_app_sd_status(card, ssr); +- if (err) { +- pr_warning("%s: problem reading SD Status " +- "register.\n", mmc_hostname(card->host)); +- err = 0; ++ ++ timeout_at= jiffies + msecs_to_jiffies( retry_timeout_ms ); ++ tries= 0; ++ ++ while( tries < retry_min_tries || time_before( jiffies, timeout_at ) ) ++ { ++ unsigned long delay_at; ++ tries++; ++ ++ err= mmc_app_sd_status(card, ssr); ++ if( !err ) ++ break; // sucess!!! ++ ++ touch_nmi_watchdog(); // we are still alive! ++ ++ // delay ++ delay_at= jiffies + msecs_to_jiffies( retry_delay_ms ); ++ while( time_before( jiffies, delay_at ) ) ++ { ++ mdelay( 1 ); ++ touch_nmi_watchdog(); // we are still alive! ++ } ++ } ++ ++ if( err) ++ { ++ pr_err("%s: failed to read SD Status register (SSR) after %d tries during %lu ms, error %d\n", mmc_hostname(card->host), tries, retry_timeout_ms, err ); + goto out; + } + ++ if( tries > 1 ) ++ { ++ pr_info("%s: could read SD Status register (SSR) at the %dth attempt\n", mmc_hostname(card->host), tries ); ++ } ++ + for (i = 0; i < 16; i++) + ssr[i] = be32_to_cpu(ssr[i]); + +@@ -808,15 +895,11 @@ int mmc_sd_setup_card(struct mmc_host *h + + if (!reinit) { + /* +- * Fetch SCR from card. ++ * Fetch and decode SD Configuration register. + */ +- err = mmc_app_send_scr(card, card->raw_scr); +- if (err) +- return err; +- +- err = mmc_decode_scr(card); +- if (err) +- return err; ++ err = mmc_read_scr(card); ++ if( err ) ++ return err; + + /* + * Fetch and process SD Status register. +--- a/drivers/mmc/host/sdhci-bcm2708.c ++++ b/drivers/mmc/host/sdhci-bcm2708.c +@@ -137,6 +137,7 @@ static bool allow_highspeed = 1; + static int emmc_clock_freq = BCM2708_EMMC_CLOCK_FREQ; + static bool sync_after_dma = 1; + static bool missing_status = 1; ++static bool spurious_crc_acmd51 = 0; + bool enable_llm = 1; + + #if 0 +@@ -1103,7 +1104,7 @@ static unsigned int sdhci_bcm2708_quirk_ + return 1; + } + +-static unsigned int sdhci_bcm2708_quirk_spurious_crc(struct sdhci_host *host) ++static unsigned int sdhci_bcm2708_quirk_spurious_crc_acmd51(struct sdhci_host *host) + { + return 1; + } +@@ -1149,7 +1150,6 @@ static struct sdhci_ops sdhci_bcm2708_op + .pdma_reset = sdhci_bcm2708_platdma_reset, + #endif + .extra_ints = sdhci_bcm2708_quirk_extra_ints, +- .spurious_crc_acmd51 = sdhci_bcm2708_quirk_spurious_crc, + .voltage_broken = sdhci_bcm2708_quirk_voltage_broken, + .uhs_broken = sdhci_bcm2708_uhs_broken, + }; +@@ -1194,6 +1194,11 @@ static int sdhci_bcm2708_probe(struct pl + sdhci_bcm2708_ops.missing_status = sdhci_bcm2708_missing_status; + } + ++ if( spurious_crc_acmd51 ) { ++ sdhci_bcm2708_ops.spurious_crc_acmd51 = sdhci_bcm2708_quirk_spurious_crc_acmd51; ++ } ++ ++ + printk("sdhci: %s low-latency mode\n",enable_llm?"Enable":"Disable"); + + host->hw_name = "BCM2708_Arasan"; +@@ -1389,6 +1394,7 @@ module_param(allow_highspeed, bool, 0444 + module_param(emmc_clock_freq, int, 0444); + module_param(sync_after_dma, bool, 0444); + module_param(missing_status, bool, 0444); ++module_param(spurious_crc_acmd51, bool, 0444); + module_param(enable_llm, bool, 0444); + module_param(cycle_delay, int, 0444); + +@@ -1401,6 +1407,7 @@ MODULE_PARM_DESC(allow_highspeed, "Allow + MODULE_PARM_DESC(emmc_clock_freq, "Specify the speed of emmc clock"); + MODULE_PARM_DESC(sync_after_dma, "Block in driver until dma complete"); + MODULE_PARM_DESC(missing_status, "Use the missing status quirk"); ++MODULE_PARM_DESC(spurious_crc_acmd51, "Use the spurious crc quirk for reading SCR (ACMD51)"); + MODULE_PARM_DESC(enable_llm, "Enable low-latency mode"); + + |