summaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
authorNagesh Penumarty <vpenumarty@nvidia.com>2010-01-29 19:43:06 +0530
committerNagesh Penumarty <vpenumarty@nvidia.com>2010-01-29 19:43:06 +0530
commit79fefc71bd02a800b7de14bcb5a3f0cfca79d098 (patch)
treee694461e82b86675b554ef5fb77b3b78319e3efb /drivers/mmc
parentbe2a66ed904211824cb577674ad531dbb557defb (diff)
Enabled ADMA in the mmc driver.
AP20 SDMMC controller has the following deviations from the specification. 1. Provides the specification version as 0 instead of 1. 2. Maximum allowed ADMA descriptor length is 32KB instead of 64KB. Enabled ADMA2 option in the MMC driver by adding the sw WARs for the above two issues. Tested on: Android Bug: 620234
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/sdhci-tegra.c4
-rw-r--r--drivers/mmc/host/sdhci.c25
-rwxr-xr-xdrivers/mmc/host/sdhci.h4
3 files changed, 32 insertions, 1 deletions
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 04280856ae69..07f365c2212d 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -298,6 +298,10 @@ int __init tegra_sdhci_probe(struct platform_device *pdev)
if (!pSdioCaps->EnableDmaSupport)
sdhost->quirks |= SDHCI_QUIRK_BROKEN_DMA;
+ else {
+ sdhost->quirks |= SDHCI_QUIRK_BROKEN_SPEC_VERSION;
+ sdhost->quirks |= SDHCI_QUIRK_32KB_MAX_ADMA_SIZE;
+ }
err1 = NvRmGetModuleInterfaceCapabilities(s_hRmGlobal,
NVRM_MODULE_ID(NvRmModuleID_Sdio, pdev->id),
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index a0591db8c152..bb5485aa4c08 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -411,6 +411,25 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
len -= offset;
}
+ if ((len == 0x10000) &&
+ (host->quirks & SDHCI_QUIRK_32KB_MAX_ADMA_SIZE)) {
+ len = 1 << 15;
+
+ desc[7] = (addr >> 24) & 0xff;
+ desc[6] = (addr >> 16) & 0xff;
+ desc[5] = (addr >> 8) & 0xff;
+ desc[4] = (addr >> 0) & 0xff;
+
+ desc[3] = (len >> 8) & 0xff;
+ desc[2] = (len >> 0) & 0xff;
+
+ desc[1] = 0x00;
+ desc[0] = 0x21; /* tran, valid */
+
+ desc += 8;
+ addr += len;
+ }
+
desc[7] = (addr >> 24) & 0xff;
desc[6] = (addr >> 16) & 0xff;
desc[5] = (addr >> 8) & 0xff;
@@ -696,7 +715,8 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
* (e.g. JMicron) can't do PIO properly when the selection
* is ADMA.
*/
- if (host->version >= SDHCI_SPEC_200) {
+ if ((host->version >= SDHCI_SPEC_200) ||
+ (host->quirks & SDHCI_QUIRK_BROKEN_SPEC_VERSION)) {
ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
ctrl &= ~SDHCI_CTRL_DMA_MASK;
if ((host->flags & SDHCI_REQ_USE_DMA) &&
@@ -1615,6 +1635,9 @@ int sdhci_add_host(struct sdhci_host *host)
if ((host->version >= SDHCI_SPEC_200) &&
(caps & SDHCI_CAN_DO_ADMA2))
host->flags |= SDHCI_USE_ADMA;
+ else if ((host->quirks & SDHCI_QUIRK_BROKEN_SPEC_VERSION) &&
+ (caps & SDHCI_CAN_DO_ADMA2))
+ host->flags |= SDHCI_USE_ADMA;
}
if ((host->quirks & SDHCI_QUIRK_BROKEN_ADMA) &&
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index fe800af6b7d0..fc746a0efeed 100755
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -217,6 +217,10 @@ struct sdhci_host {
#define SDHCI_QUIRK_ENABLE_INTERRUPT_AT_BLOCK_GAP (1<<16)
/* Controller should not program HIGH_SPEED_EN after switching to high speed */
#define SDHCI_QUIRK_BROKEN_CTRL_HISPD (1<<17)
+/* Controller provides an incorrect SPECIFICATION_VERSION_NUMBER */
+#define SDHCI_QUIRK_BROKEN_SPEC_VERSION (1<<18)
+/* Controller supports maximum ADMA size of 32 Kilo bytes. */
+#define SDHCI_QUIRK_32KB_MAX_ADMA_SIZE (1<<19)
int irq; /* Device IRQ */
void __iomem * ioaddr; /* Mapped address */