lkml.org 
[lkml]   [2008]   [Jun]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[PATCH 2/2] [OLPC] sdhci: add quirk for the Marvell CaFe's interrupt timeout
[Note that this is against Pierre's mmc/next branch]


The CaFe chip has a hardware bug that ends up with us getting a timeout
value that's too small, causing the following sorts of problems:

[ 60.525138] mmcblk0: error -110 transferring data
[ 60.531477] end_request: I/O error, dev mmcblk0, sector 1484353
[ 60.533371] Buffer I/O error on device mmcblk0p2, logical block 181632
[ 60.533371] lost page write due to I/O error on mmcblk0p2

To play it safe, we simply set the timeout to the max possible value
(0xE), and that works. It also breaks the timeout calculation logic
out into a separate function.

Mitch verified that using 0xE instead of 0xC in OFW fixed timeout
problems for a user with an 8GB card, as well.

Signed-off-by: Andres Salomon <dilinger@debian.org>
---
drivers/mmc/host/sdhci-pci.c | 3 +-
drivers/mmc/host/sdhci.c | 43 +++++++++++++++++++++++++++++------------
drivers/mmc/host/sdhci.h | 2 +
3 files changed, 34 insertions(+), 14 deletions(-)

diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index ec375b8..70c0c78 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -105,7 +105,8 @@ static const struct sdhci_pci_fixes sdhci_ene_714 = {
};

static const struct sdhci_pci_fixes sdhci_cafe = {
- .quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER,
+ .quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER |
+ SDHCI_QUIRK_BROKEN_TIMEOUT_VAL,
};

static int jmicron_pmos(struct sdhci_pci_chip *chip, int on)
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 5f1c1bf..228457c 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -314,23 +314,19 @@ static void sdhci_transfer_pio(struct sdhci_host *host)
DBG("PIO transfer complete.\n");
}

-static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
+static u8 calculate_timeout(struct sdhci_host *host, struct mmc_data *data)
{
u8 count;
unsigned target_timeout, current_timeout;

- WARN_ON(host->data);
-
- if (data == NULL)
- return;
-
- /* Sanity checks */
- BUG_ON(data->blksz * data->blocks > 524288);
- BUG_ON(data->blksz > host->mmc->max_blk_size);
- BUG_ON(data->blocks > 65535);
-
- host->data = data;
- host->data_early = 0;
+ /*
+ * If the host controller provides us with an incorrect timeout
+ * value, just skip the check and use 0xE. The hardware may take
+ * longer to time out, but that's much better than having a too-short
+ * timeout value.
+ */
+ if ((host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL))
+ return 0xE;

/* timeout in us */
target_timeout = data->timeout_ns / 1000 +
@@ -361,6 +357,27 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
count = 0xE;
}

+ return count;
+}
+
+static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
+{
+ u8 count;
+
+ WARN_ON(host->data);
+
+ if (data == NULL)
+ return;
+
+ /* Sanity checks */
+ BUG_ON(data->blksz * data->blocks > 524288);
+ BUG_ON(data->blksz > host->mmc->max_blk_size);
+ BUG_ON(data->blocks > 65535);
+
+ host->data = data;
+ host->data_early = 0;
+
+ count = calculate_timeout(host, data);
writeb(count, host->ioaddr + SDHCI_TIMEOUT_CONTROL);

if (host->flags & SDHCI_USE_DMA)
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 37ae056..7c30251 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -178,6 +178,8 @@ struct sdhci_host {
#define SDHCI_QUIRK_RESET_AFTER_REQUEST (1<<8)
/* Controller needs voltage and power writes to happen separately */
#define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER (1<<9)
+/* Controller provides an incorrect timeout value for transfers */
+#define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1<<10)

int irq; /* Device IRQ */
void __iomem * ioaddr; /* Mapped address */
--
1.5.5.3


\
 
 \ /
  Last update: 2008-06-27 22:25    [W:1.240 / U:0.460 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site