aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/pxamci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host/pxamci.c')
-rw-r--r--drivers/mmc/host/pxamci.c61
1 files changed, 45 insertions, 16 deletions
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 1654a3330340..1ea8482037bb 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -65,6 +65,8 @@ struct pxamci_host {
65 unsigned int dma_len; 65 unsigned int dma_len;
66 66
67 unsigned int dma_dir; 67 unsigned int dma_dir;
68 unsigned int dma_drcmrrx;
69 unsigned int dma_drcmrtx;
68}; 70};
69 71
70static void pxamci_stop_clock(struct pxamci_host *host) 72static void pxamci_stop_clock(struct pxamci_host *host)
@@ -131,13 +133,13 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
131 if (data->flags & MMC_DATA_READ) { 133 if (data->flags & MMC_DATA_READ) {
132 host->dma_dir = DMA_FROM_DEVICE; 134 host->dma_dir = DMA_FROM_DEVICE;
133 dcmd = DCMD_INCTRGADDR | DCMD_FLOWTRG; 135 dcmd = DCMD_INCTRGADDR | DCMD_FLOWTRG;
134 DRCMRTXMMC = 0; 136 DRCMR(host->dma_drcmrtx) = 0;
135 DRCMRRXMMC = host->dma | DRCMR_MAPVLD; 137 DRCMR(host->dma_drcmrrx) = host->dma | DRCMR_MAPVLD;
136 } else { 138 } else {
137 host->dma_dir = DMA_TO_DEVICE; 139 host->dma_dir = DMA_TO_DEVICE;
138 dcmd = DCMD_INCSRCADDR | DCMD_FLOWSRC; 140 dcmd = DCMD_INCSRCADDR | DCMD_FLOWSRC;
139 DRCMRRXMMC = 0; 141 DRCMR(host->dma_drcmrrx) = 0;
140 DRCMRTXMMC = host->dma | DRCMR_MAPVLD; 142 DRCMR(host->dma_drcmrtx) = host->dma | DRCMR_MAPVLD;
141 } 143 }
142 144
143 dcmd |= DCMD_BURST32 | DCMD_WIDTH1; 145 dcmd |= DCMD_BURST32 | DCMD_WIDTH1;
@@ -375,14 +377,23 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
375 if (host->clkrt == CLKRT_OFF) 377 if (host->clkrt == CLKRT_OFF)
376 clk_enable(host->clk); 378 clk_enable(host->clk);
377 379
378 /* 380 if (ios->clock == 26000000) {
379 * clk might result in a lower divisor than we 381 /* to support 26MHz on pxa300/pxa310 */
380 * desire. check for that condition and adjust 382 host->clkrt = 7;
381 * as appropriate. 383 } else {
382 */ 384 /* to handle (19.5MHz, 26MHz) */
383 if (rate / clk > ios->clock) 385 if (!clk)
384 clk <<= 1; 386 clk = 1;
385 host->clkrt = fls(clk) - 1; 387
388 /*
389 * clk might result in a lower divisor than we
390 * desire. check for that condition and adjust
391 * as appropriate.
392 */
393 if (rate / clk > ios->clock)
394 clk <<= 1;
395 host->clkrt = fls(clk) - 1;
396 }
386 397
387 /* 398 /*
388 * we write clkrt on the next command 399 * we write clkrt on the next command
@@ -459,7 +470,7 @@ static int pxamci_probe(struct platform_device *pdev)
459{ 470{
460 struct mmc_host *mmc; 471 struct mmc_host *mmc;
461 struct pxamci_host *host = NULL; 472 struct pxamci_host *host = NULL;
462 struct resource *r; 473 struct resource *r, *dmarx, *dmatx;
463 int ret, irq; 474 int ret, irq;
464 475
465 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 476 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -519,7 +530,8 @@ static int pxamci_probe(struct platform_device *pdev)
519 * Calculate minimum clock rate, rounding up. 530 * Calculate minimum clock rate, rounding up.
520 */ 531 */
521 mmc->f_min = (host->clkrate + 63) / 64; 532 mmc->f_min = (host->clkrate + 63) / 64;
522 mmc->f_max = host->clkrate; 533 mmc->f_max = (cpu_is_pxa300() || cpu_is_pxa310()) ? 26000000
534 : host->clkrate;
523 535
524 mmc->ocr_avail = host->pdata ? 536 mmc->ocr_avail = host->pdata ?
525 host->pdata->ocr_mask : 537 host->pdata->ocr_mask :
@@ -529,6 +541,9 @@ static int pxamci_probe(struct platform_device *pdev)
529 if (!cpu_is_pxa21x() && !cpu_is_pxa25x()) { 541 if (!cpu_is_pxa21x() && !cpu_is_pxa25x()) {
530 mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; 542 mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
531 host->cmdat |= CMDAT_SDIO_INT_EN; 543 host->cmdat |= CMDAT_SDIO_INT_EN;
544 if (cpu_is_pxa300() || cpu_is_pxa310())
545 mmc->caps |= MMC_CAP_MMC_HIGHSPEED |
546 MMC_CAP_SD_HIGHSPEED;
532 } 547 }
533 548
534 host->sg_cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE, &host->sg_dma, GFP_KERNEL); 549 host->sg_cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE, &host->sg_dma, GFP_KERNEL);
@@ -570,6 +585,20 @@ static int pxamci_probe(struct platform_device *pdev)
570 585
571 platform_set_drvdata(pdev, mmc); 586 platform_set_drvdata(pdev, mmc);
572 587
588 dmarx = platform_get_resource(pdev, IORESOURCE_DMA, 0);
589 if (!dmarx) {
590 ret = -ENXIO;
591 goto out;
592 }
593 host->dma_drcmrrx = dmarx->start;
594
595 dmatx = platform_get_resource(pdev, IORESOURCE_DMA, 1);
596 if (!dmatx) {
597 ret = -ENXIO;
598 goto out;
599 }
600 host->dma_drcmrtx = dmatx->start;
601
573 if (host->pdata && host->pdata->init) 602 if (host->pdata && host->pdata->init)
574 host->pdata->init(&pdev->dev, pxamci_detect_irq, mmc); 603 host->pdata->init(&pdev->dev, pxamci_detect_irq, mmc);
575 604
@@ -613,8 +642,8 @@ static int pxamci_remove(struct platform_device *pdev)
613 END_CMD_RES|PRG_DONE|DATA_TRAN_DONE, 642 END_CMD_RES|PRG_DONE|DATA_TRAN_DONE,
614 host->base + MMC_I_MASK); 643 host->base + MMC_I_MASK);
615 644
616 DRCMRRXMMC = 0; 645 DRCMR(host->dma_drcmrrx) = 0;
617 DRCMRTXMMC = 0; 646 DRCMR(host->dma_drcmrtx) = 0;
618 647
619 free_irq(host->irq, host); 648 free_irq(host->irq, host);
620 pxa_free_dma(host->dma); 649 pxa_free_dma(host->dma);