diff options
author | Jason Jin <Jason.jin@freescale.com> | 2012-08-10 18:23:10 +0800 |
---|---|---|
committer | Justin Waters <justin.waters@timesys.com> | 2012-09-12 16:50:07 -0400 |
commit | e4204d37dfbfae5e176f6564242f33e7a7b59fe2 (patch) | |
tree | d92cc6ba77c1fe23003dbd3c541c734bf9a80bd7 /drivers | |
parent | 8b207089bcbf20474355e29395e5631f96886c66 (diff) |
ENGR00212262-3: Faraday:Enable the ADMA2 function for SDHC
This patch enable the ADMA2 function for the SDHC module used
on Faraday board. Please note that the ADMA address should be 16
bytes aligned other than 4 byte in the spec.
This patch also increased the SDHC module frequency to 200MHz.
Signed-off-by: Jason Jin <Jason.jin@freescale.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mmc/host/sdhci-esdhc-imx.c | 16 | ||||
-rwxr-xr-x | drivers/mmc/host/sdhci.c | 47 |
2 files changed, 44 insertions, 19 deletions
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 2296eb8d1c18..3dcfcb043ef0 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -134,6 +134,16 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg) val |= SDHCI_CARD_PRESENT; } + if (reg == SDHCI_CAPABILITIES && cpu_is_mvf()) + { + if (val & SDHCI_CAN_DO_ADMA1) { + u32 tmp = readl(host->ioaddr + SDHCI_SLOT_INT_STATUS); + tmp = (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT; + if (tmp >= 0x12) + val |= SDHCI_CAN_DO_ADMA2; + } + } + if (reg == SDHCI_INT_STATUS && cpu_is_mx6() && mx6q_revision() == IMX_CHIP_REVISION_1_0) { /* @@ -786,10 +796,16 @@ static void esdhc_pltfm_exit(struct sdhci_host *host) } struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { +#ifdef CONFIG_ARCH_MVF + .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION + | SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_NO_CARD_NO_RESET + | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC, +#else .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_BROKEN_CARD_DETECTION | SDHCI_QUIRK_NO_HISPD_BIT, /* ADMA has issues. Might be fixable */ +#endif .ops = &sdhci_esdhc_ops, .init = esdhc_pltfm_init, .exit = esdhc_pltfm_exit, diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 82afe0522ecc..189dff37e84e 100755 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2,6 +2,7 @@ * linux/drivers/mmc/host/sdhci.c - Secure Digital Host Controller Interface driver * * Copyright (C) 2005-2011 Pierre Ossman, All Rights Reserved. + * Copyright 2012 Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -42,6 +43,12 @@ #define MAX_TUNING_LOOP 40 +#ifdef CONFIG_ARCH_MVF +#define ADDR_ALIGNED 0xF +#else +#define ADDR_ALIGNED 0x3 +#endif + static unsigned int debug_quirks = 0; static void sdhci_finish_data(struct sdhci_host *); @@ -497,10 +504,10 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, */ host->align_addr = dma_map_single(mmc_dev(host->mmc), - host->align_buffer, 128 * 4, direction); + host->align_buffer, 128 * (ADDR_ALIGNED + 1), direction); if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr)) goto fail; - BUG_ON(host->align_addr & 0x3); + BUG_ON(host->align_addr & ADDR_ALIGNED); host->sg_count = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, direction); @@ -523,22 +530,22 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, * the (up to three) bytes that screw up the * alignment. */ - offset = (4 - (addr & 0x3)) & 0x3; + offset = ((ADDR_ALIGNED + 1) - (addr & ADDR_ALIGNED)) & ADDR_ALIGNED; if (offset) { if (data->flags & MMC_DATA_WRITE) { buffer = sdhci_kmap_atomic(sg, &flags); - WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3)); + WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - ADDR_ALIGNED)); memcpy(align, buffer, offset); sdhci_kunmap_atomic(buffer, &flags); } /* tran, valid */ - sdhci_set_adma_desc(desc, align_addr, offset, 0x21); + sdhci_set_adma_desc(desc, align_addr, (len - offset) ? offset : len, 0x21); BUG_ON(offset > 65536); - align += 4; - align_addr += 4; + align += (ADDR_ALIGNED + 1); + align_addr += (ADDR_ALIGNED + 1); desc += 8; @@ -549,8 +556,10 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, BUG_ON(len > 65536); /* tran, valid */ - sdhci_set_adma_desc(desc, addr, len, 0x21); - desc += 8; + if (len > 0) { + sdhci_set_adma_desc(desc, addr, len, 0x21); + desc += 8; + } /* * If this triggers then we have a calculation bug @@ -581,14 +590,14 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, */ if (data->flags & MMC_DATA_WRITE) { dma_sync_single_for_device(mmc_dev(host->mmc), - host->align_addr, 128 * 4, direction); + host->align_addr, 128 * (ADDR_ALIGNED + 1), direction); } host->adma_addr = dma_map_single(mmc_dev(host->mmc), host->adma_desc, (128 * 2 + 1) * 4, DMA_TO_DEVICE); if (dma_mapping_error(mmc_dev(host->mmc), host->adma_addr)) goto unmap_entries; - BUG_ON(host->adma_addr & 0x3); + BUG_ON(host->adma_addr & ADDR_ALIGNED); return 0; @@ -597,7 +606,7 @@ unmap_entries: data->sg_len, direction); unmap_align: dma_unmap_single(mmc_dev(host->mmc), host->align_addr, - 128 * 4, direction); + 128 * (ADDR_ALIGNED + 1), direction); fail: return -EINVAL; } @@ -622,7 +631,7 @@ static void sdhci_adma_table_post(struct sdhci_host *host, (128 * 2 + 1) * 4, DMA_TO_DEVICE); dma_unmap_single(mmc_dev(host->mmc), host->align_addr, - 128 * 4, direction); + 128 * (ADDR_ALIGNED + 1), direction); if (data->flags & MMC_DATA_READ) { dma_sync_sg_for_cpu(mmc_dev(host->mmc), data->sg, @@ -631,15 +640,15 @@ static void sdhci_adma_table_post(struct sdhci_host *host, align = host->align_buffer; for_each_sg(data->sg, sg, host->sg_count, i) { - if (sg_dma_address(sg) & 0x3) { - size = 4 - (sg_dma_address(sg) & 0x3); + if (sg_dma_address(sg) & ADDR_ALIGNED) { + size = (ADDR_ALIGNED + 1) - (sg_dma_address(sg) & ADDR_ALIGNED); buffer = sdhci_kmap_atomic(sg, &flags); - WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3)); - memcpy(buffer, align, size); + WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - ADDR_ALIGNED)); + memcpy(buffer, align, (size - data->sg->length) ? data->sg->length : size); sdhci_kunmap_atomic(buffer, &flags); - align += 4; + align += (ADDR_ALIGNED + 1); } } } @@ -2559,7 +2568,7 @@ int sdhci_add_host(struct sdhci_host *host) * each of those entries. */ host->adma_desc = kmalloc((128 * 2 + 1) * 4, GFP_KERNEL); - host->align_buffer = kmalloc(128 * 4, GFP_KERNEL); + host->align_buffer = kmalloc(128 * (ADDR_ALIGNED + 1), GFP_KERNEL); if (!host->adma_desc || !host->align_buffer) { kfree(host->adma_desc); kfree(host->align_buffer); |