aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/brcm2708/patches-3.10/0038-Lazy-CRC-quirk-Implemented-retrying-mechanisms-for-S.patch
diff options
context:
space:
mode:
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.patch227
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");
+
+