Skip to content

Commit

Permalink
sdhci: support for ADMA only hosts
Browse files Browse the repository at this point in the history
Add support for ADMA on SDHCI hosts, not supporting SDMA.

According to the SDHCI specifications a host can support ADMA but not SDMA

Signed-off-by: Richard Röjfors <richard.rojfors@mocean-labs.com>
Cc: <linux-mmc@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Richard Röjfors authored and Linus Torvalds committed Sep 23, 2009
1 parent 996ad56 commit a13abc7
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 23 deletions.
2 changes: 1 addition & 1 deletion drivers/mmc/host/sdhci-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ static int sdhci_pci_enable_dma(struct sdhci_host *host)

if (((pdev->class & 0xFFFF00) == (PCI_CLASS_SYSTEM_SDHCI << 8)) &&
((pdev->class & 0x0000FF) != PCI_SDHCI_IFDMA) &&
(host->flags & SDHCI_USE_DMA)) {
(host->flags & SDHCI_USE_SDMA)) {
dev_warn(&pdev->dev, "Will use DMA mode even though HW "
"doesn't fully claim to support it.\n");
}
Expand Down
38 changes: 18 additions & 20 deletions drivers/mmc/host/sdhci.c
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
count = sdhci_calc_timeout(host, data);
sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL);

if (host->flags & SDHCI_USE_DMA)
if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA))
host->flags |= SDHCI_REQ_USE_DMA;

/*
Expand Down Expand Up @@ -1600,7 +1600,7 @@ int sdhci_resume_host(struct sdhci_host *host)
{
int ret;

if (host->flags & SDHCI_USE_DMA) {
if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
if (host->ops->enable_dma)
host->ops->enable_dma(host);
}
Expand Down Expand Up @@ -1681,37 +1681,35 @@ int sdhci_add_host(struct sdhci_host *host)
caps = sdhci_readl(host, SDHCI_CAPABILITIES);

if (host->quirks & SDHCI_QUIRK_FORCE_DMA)
host->flags |= SDHCI_USE_DMA;
else if (!(caps & SDHCI_CAN_DO_DMA))
DBG("Controller doesn't have DMA capability\n");
host->flags |= SDHCI_USE_SDMA;
else if (!(caps & SDHCI_CAN_DO_SDMA))
DBG("Controller doesn't have SDMA capability\n");
else
host->flags |= SDHCI_USE_DMA;
host->flags |= SDHCI_USE_SDMA;

if ((host->quirks & SDHCI_QUIRK_BROKEN_DMA) &&
(host->flags & SDHCI_USE_DMA)) {
(host->flags & SDHCI_USE_SDMA)) {
DBG("Disabling DMA as it is marked broken\n");
host->flags &= ~SDHCI_USE_DMA;
host->flags &= ~SDHCI_USE_SDMA;
}

if (host->flags & SDHCI_USE_DMA) {
if ((host->version >= SDHCI_SPEC_200) &&
(caps & SDHCI_CAN_DO_ADMA2))
host->flags |= SDHCI_USE_ADMA;
}
if ((host->version >= SDHCI_SPEC_200) && (caps & SDHCI_CAN_DO_ADMA2))
host->flags |= SDHCI_USE_ADMA;

if ((host->quirks & SDHCI_QUIRK_BROKEN_ADMA) &&
(host->flags & SDHCI_USE_ADMA)) {
DBG("Disabling ADMA as it is marked broken\n");
host->flags &= ~SDHCI_USE_ADMA;
}

if (host->flags & SDHCI_USE_DMA) {
if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
if (host->ops->enable_dma) {
if (host->ops->enable_dma(host)) {
printk(KERN_WARNING "%s: No suitable DMA "
"available. Falling back to PIO.\n",
mmc_hostname(mmc));
host->flags &= ~(SDHCI_USE_DMA | SDHCI_USE_ADMA);
host->flags &=
~(SDHCI_USE_SDMA | SDHCI_USE_ADMA);
}
}
}
Expand Down Expand Up @@ -1739,7 +1737,7 @@ int sdhci_add_host(struct sdhci_host *host)
* mask, but PIO does not need the hw shim so we set a new
* mask here in that case.
*/
if (!(host->flags & SDHCI_USE_DMA)) {
if (!(host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA))) {
host->dma_mask = DMA_BIT_MASK(64);
mmc_dev(host->mmc)->dma_mask = &host->dma_mask;
}
Expand Down Expand Up @@ -1816,7 +1814,7 @@ int sdhci_add_host(struct sdhci_host *host)
*/
if (host->flags & SDHCI_USE_ADMA)
mmc->max_hw_segs = 128;
else if (host->flags & SDHCI_USE_DMA)
else if (host->flags & SDHCI_USE_SDMA)
mmc->max_hw_segs = 1;
else /* PIO */
mmc->max_hw_segs = 128;
Expand Down Expand Up @@ -1899,10 +1897,10 @@ int sdhci_add_host(struct sdhci_host *host)

mmc_add_host(mmc);

printk(KERN_INFO "%s: SDHCI controller on %s [%s] using %s%s\n",
printk(KERN_INFO "%s: SDHCI controller on %s [%s] using %s\n",
mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)),
(host->flags & SDHCI_USE_ADMA)?"A":"",
(host->flags & SDHCI_USE_DMA)?"DMA":"PIO");
(host->flags & SDHCI_USE_ADMA) ? "ADMA" :
(host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO");

sdhci_enable_card_detection(host);

Expand Down
4 changes: 2 additions & 2 deletions drivers/mmc/host/sdhci.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@
#define SDHCI_CAN_DO_ADMA2 0x00080000
#define SDHCI_CAN_DO_ADMA1 0x00100000
#define SDHCI_CAN_DO_HISPD 0x00200000
#define SDHCI_CAN_DO_DMA 0x00400000
#define SDHCI_CAN_DO_SDMA 0x00400000
#define SDHCI_CAN_VDD_330 0x01000000
#define SDHCI_CAN_VDD_300 0x02000000
#define SDHCI_CAN_VDD_180 0x04000000
Expand Down Expand Up @@ -252,7 +252,7 @@ struct sdhci_host {
spinlock_t lock; /* Mutex */

int flags; /* Host attributes */
#define SDHCI_USE_DMA (1<<0) /* Host is DMA capable */
#define SDHCI_USE_SDMA (1<<0) /* Host is SDMA capable */
#define SDHCI_USE_ADMA (1<<1) /* Host is ADMA capable */
#define SDHCI_REQ_USE_DMA (1<<2) /* Use DMA for this req. */
#define SDHCI_DEVICE_DEAD (1<<3) /* Device unresponsive */
Expand Down

0 comments on commit a13abc7

Please sign in to comment.