diff options
author | Linus Walleij <linus.walleij@stericsson.com> | 2010-10-19 07:43:58 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-11-10 08:15:19 -0500 |
commit | 34177802001894e064c857cac2759f68119550cd (patch) | |
tree | a0f441969ac73b1bc191d78f5d451974aeacad2e /drivers/mmc/host/mmci.c | |
parent | f20f8f21e0402c785c342547f7e49eafc42cfb52 (diff) |
ARM: 6438/2: mmci: add SDIO support for ST Variants
This adds some minor variant data and trickery to enable SDIO
on the ST Micro variants of MMCI/PL180.
Signed-off-by: Marcin Mielczarczyk <marcin.mielczarczyk@tieto.com>
Signed-off-by: Linus Walleij <linus.walleij@stericsson.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/mmc/host/mmci.c')
-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; |