diff options
| -rw-r--r-- | drivers/mmc/host/mmci.c | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 976c9d0e8080..0814b88b44d6 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/highmem.h> | 19 | #include <linux/highmem.h> |
| 20 | #include <linux/log2.h> | 20 | #include <linux/log2.h> |
| 21 | #include <linux/mmc/host.h> | 21 | #include <linux/mmc/host.h> |
| 22 | #include <linux/mmc/card.h> | ||
| 22 | #include <linux/amba/bus.h> | 23 | #include <linux/amba/bus.h> |
| 23 | #include <linux/clk.h> | 24 | #include <linux/clk.h> |
| 24 | #include <linux/scatterlist.h> | 25 | #include <linux/scatterlist.h> |
| @@ -49,6 +50,7 @@ static unsigned int fmax = 515633; | |||
| 49 | * and will not work at all. | 50 | * and will not work at all. |
| 50 | * @broken_blockend_dma: the MCI_DATABLOCKEND is broken on the hardware when | 51 | * @broken_blockend_dma: the MCI_DATABLOCKEND is broken on the hardware when |
| 51 | * using DMA. | 52 | * using DMA. |
| 53 | * @sdio: variant supports SDIO | ||
| 52 | */ | 54 | */ |
| 53 | struct variant_data { | 55 | struct variant_data { |
| 54 | unsigned int clkreg; | 56 | unsigned int clkreg; |
| @@ -58,6 +60,7 @@ struct variant_data { | |||
| 58 | unsigned int fifohalfsize; | 60 | unsigned int fifohalfsize; |
| 59 | bool broken_blockend; | 61 | bool broken_blockend; |
| 60 | bool broken_blockend_dma; | 62 | bool broken_blockend_dma; |
| 63 | bool sdio; | ||
| 61 | }; | 64 | }; |
| 62 | 65 | ||
| 63 | static struct variant_data variant_arm = { | 66 | static struct variant_data variant_arm = { |
| @@ -72,6 +75,7 @@ static struct variant_data variant_u300 = { | |||
| 72 | .clkreg_enable = 1 << 13, /* HWFCEN */ | 75 | .clkreg_enable = 1 << 13, /* HWFCEN */ |
| 73 | .datalength_bits = 16, | 76 | .datalength_bits = 16, |
| 74 | .broken_blockend_dma = true, | 77 | .broken_blockend_dma = true, |
| 78 | .sdio = true, | ||
| 75 | }; | 79 | }; |
| 76 | 80 | ||
| 77 | static struct variant_data variant_ux500 = { | 81 | static struct variant_data variant_ux500 = { |
| @@ -81,6 +85,7 @@ static struct variant_data variant_ux500 = { | |||
| 81 | .clkreg_enable = 1 << 14, /* HWFCEN */ | 85 | .clkreg_enable = 1 << 14, /* HWFCEN */ |
| 82 | .datalength_bits = 24, | 86 | .datalength_bits = 24, |
| 83 | .broken_blockend = true, | 87 | .broken_blockend = true, |
| 88 | .sdio = true, | ||
| 84 | }; | 89 | }; |
| 85 | /* | 90 | /* |
| 86 | * This must be called with host->lock held | 91 | * This must be called with host->lock held |
| @@ -222,6 +227,11 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) | |||
| 222 | irqmask = MCI_TXFIFOHALFEMPTYMASK; | 227 | irqmask = MCI_TXFIFOHALFEMPTYMASK; |
| 223 | } | 228 | } |
| 224 | 229 | ||
| 230 | /* The ST Micro variants has a special bit to enable SDIO */ | ||
| 231 | if (variant->sdio && host->mmc->card) | ||
| 232 | if (mmc_card_sdio(host->mmc->card)) | ||
| 233 | datactrl |= MCI_ST_DPSM_SDIOEN; | ||
| 234 | |||
| 225 | writel(datactrl, base + MMCIDATACTRL); | 235 | writel(datactrl, base + MMCIDATACTRL); |
| 226 | writel(readl(base + MMCIMASK0) & ~MCI_DATAENDMASK, base + MMCIMASK0); | 236 | writel(readl(base + MMCIMASK0) & ~MCI_DATAENDMASK, base + MMCIMASK0); |
| 227 | mmci_set_mask1(host, irqmask); | 237 | mmci_set_mask1(host, irqmask); |
| @@ -429,7 +439,32 @@ static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int rem | |||
| 429 | variant->fifosize : variant->fifohalfsize; | 439 | variant->fifosize : variant->fifohalfsize; |
| 430 | count = min(remain, maxcnt); | 440 | count = min(remain, maxcnt); |
| 431 | 441 | ||
| 432 | writesl(base + MMCIFIFO, ptr, count >> 2); | 442 | /* |
| 443 | * The ST Micro variant for SDIO transfer sizes | ||
| 444 | * less then 8 bytes should have clock H/W flow | ||
| 445 | * control disabled. | ||
| 446 | */ | ||
| 447 | if (variant->sdio && | ||
| 448 | mmc_card_sdio(host->mmc->card)) { | ||
| 449 | if (count < 8) | ||
| 450 | writel(readl(host->base + MMCICLOCK) & | ||
| 451 | ~variant->clkreg_enable, | ||
| 452 | host->base + MMCICLOCK); | ||
| 453 | else | ||
| 454 | writel(readl(host->base + MMCICLOCK) | | ||
| 455 | variant->clkreg_enable, | ||
| 456 | host->base + MMCICLOCK); | ||
| 457 | } | ||
| 458 | |||
| 459 | /* | ||
| 460 | * SDIO especially may want to send something that is | ||
| 461 | * not divisible by 4 (as opposed to card sectors | ||
| 462 | * etc), and the FIFO only accept full 32-bit writes. | ||
| 463 | * So compensate by adding +3 on the count, a single | ||
| 464 | * byte become a 32bit write, 7 bytes will be two | ||
| 465 | * 32bit writes etc. | ||
| 466 | */ | ||
| 467 | writesl(base + MMCIFIFO, ptr, (count + 3) >> 2); | ||
| 433 | 468 | ||
| 434 | ptr += count; | 469 | ptr += count; |
| 435 | remain -= count; | 470 | remain -= count; |
