diff options
-rw-r--r-- | drivers/mmc/at91_mci.c | 41 |
1 files changed, 24 insertions, 17 deletions
diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c index d500b6b21ea0..08a33c33f6ed 100644 --- a/drivers/mmc/at91_mci.c +++ b/drivers/mmc/at91_mci.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/mmc/at91_mci.c - ATMEL AT91RM9200 MCI Driver | 2 | * linux/drivers/mmc/at91_mci.c - ATMEL AT91 MCI Driver |
3 | * | 3 | * |
4 | * Copyright (C) 2005 Cougar Creek Computing Devices Ltd, All Rights Reserved | 4 | * Copyright (C) 2005 Cougar Creek Computing Devices Ltd, All Rights Reserved |
5 | * | 5 | * |
@@ -11,7 +11,7 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | /* | 13 | /* |
14 | This is the AT91RM9200 MCI driver that has been tested with both MMC cards | 14 | This is the AT91 MCI driver that has been tested with both MMC cards |
15 | and SD-cards. Boards that support write protect are now supported. | 15 | and SD-cards. Boards that support write protect are now supported. |
16 | The CCAT91SBC001 board does not support SD cards. | 16 | The CCAT91SBC001 board does not support SD cards. |
17 | 17 | ||
@@ -38,8 +38,8 @@ | |||
38 | controller to manage the transfers. | 38 | controller to manage the transfers. |
39 | 39 | ||
40 | A read is done from the controller directly to the scatterlist passed in from the request. | 40 | A read is done from the controller directly to the scatterlist passed in from the request. |
41 | Due to a bug in the controller, when a read is completed, all the words are byte | 41 | Due to a bug in the AT91RM9200 controller, when a read is completed, all the words are byte |
42 | swapped in the scatterlist buffers. | 42 | swapped in the scatterlist buffers. AT91SAM926x are not affected by this bug. |
43 | 43 | ||
44 | The sequence of read interrupts is: ENDRX, RXBUFF, CMDRDY | 44 | The sequence of read interrupts is: ENDRX, RXBUFF, CMDRDY |
45 | 45 | ||
@@ -72,6 +72,7 @@ | |||
72 | #include <asm/irq.h> | 72 | #include <asm/irq.h> |
73 | #include <asm/mach/mmc.h> | 73 | #include <asm/mach/mmc.h> |
74 | #include <asm/arch/board.h> | 74 | #include <asm/arch/board.h> |
75 | #include <asm/arch/cpu.h> | ||
75 | #include <asm/arch/gpio.h> | 76 | #include <asm/arch/gpio.h> |
76 | #include <asm/arch/at91_mci.h> | 77 | #include <asm/arch/at91_mci.h> |
77 | #include <asm/arch/at91_pdc.h> | 78 | #include <asm/arch/at91_pdc.h> |
@@ -147,7 +148,6 @@ static inline void at91mci_sg_to_dma(struct at91mci_host *host, struct mmc_data | |||
147 | for (i = 0; i < len; i++) { | 148 | for (i = 0; i < len; i++) { |
148 | struct scatterlist *sg; | 149 | struct scatterlist *sg; |
149 | int amount; | 150 | int amount; |
150 | int index; | ||
151 | unsigned int *sgbuffer; | 151 | unsigned int *sgbuffer; |
152 | 152 | ||
153 | sg = &data->sg[i]; | 153 | sg = &data->sg[i]; |
@@ -155,10 +155,15 @@ static inline void at91mci_sg_to_dma(struct at91mci_host *host, struct mmc_data | |||
155 | sgbuffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset; | 155 | sgbuffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset; |
156 | amount = min(size, sg->length); | 156 | amount = min(size, sg->length); |
157 | size -= amount; | 157 | size -= amount; |
158 | amount /= 4; | ||
159 | 158 | ||
160 | for (index = 0; index < amount; index++) | 159 | if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */ |
161 | *dmabuf++ = swab32(sgbuffer[index]); | 160 | int index; |
161 | |||
162 | for (index = 0; index < (amount / 4); index++) | ||
163 | *dmabuf++ = swab32(sgbuffer[index]); | ||
164 | } | ||
165 | else | ||
166 | memcpy(dmabuf, sgbuffer, amount); | ||
162 | 167 | ||
163 | kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ); | 168 | kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ); |
164 | 169 | ||
@@ -265,8 +270,6 @@ static void at91mci_post_dma_read(struct at91mci_host *host) | |||
265 | 270 | ||
266 | while (host->in_use_index < host->transfer_index) { | 271 | while (host->in_use_index < host->transfer_index) { |
267 | unsigned int *buffer; | 272 | unsigned int *buffer; |
268 | int index; | ||
269 | int len; | ||
270 | 273 | ||
271 | struct scatterlist *sg; | 274 | struct scatterlist *sg; |
272 | 275 | ||
@@ -284,11 +287,13 @@ static void at91mci_post_dma_read(struct at91mci_host *host) | |||
284 | 287 | ||
285 | data->bytes_xfered += sg->length; | 288 | data->bytes_xfered += sg->length; |
286 | 289 | ||
287 | len = sg->length / 4; | 290 | if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */ |
291 | int index; | ||
288 | 292 | ||
289 | for (index = 0; index < len; index++) { | 293 | for (index = 0; index < (sg->length / 4); index++) |
290 | buffer[index] = swab32(buffer[index]); | 294 | buffer[index] = swab32(buffer[index]); |
291 | } | 295 | } |
296 | |||
292 | kunmap_atomic(buffer, KM_BIO_SRC_IRQ); | 297 | kunmap_atomic(buffer, KM_BIO_SRC_IRQ); |
293 | flush_dcache_page(sg->page); | 298 | flush_dcache_page(sg->page); |
294 | } | 299 | } |
@@ -339,7 +344,9 @@ static void at91_mci_enable(struct at91mci_host *host) | |||
339 | at91_mci_write(host, AT91_MCI_IDR, 0xffffffff); | 344 | at91_mci_write(host, AT91_MCI_IDR, 0xffffffff); |
340 | at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC); | 345 | at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC); |
341 | at91_mci_write(host, AT91_MCI_MR, AT91_MCI_PDCMODE | 0x34a); | 346 | at91_mci_write(host, AT91_MCI_MR, AT91_MCI_PDCMODE | 0x34a); |
342 | at91_mci_write(host, AT91_MCI_SDCR, 0); | 347 | |
348 | /* use Slot A or B (only one at same time) */ | ||
349 | at91_mci_write(host, AT91_MCI_SDCR, host->board->slot_b); | ||
343 | } | 350 | } |
344 | 351 | ||
345 | /* | 352 | /* |
@@ -637,11 +644,11 @@ static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
637 | if (host->board->vcc_pin) { | 644 | if (host->board->vcc_pin) { |
638 | switch (ios->power_mode) { | 645 | switch (ios->power_mode) { |
639 | case MMC_POWER_OFF: | 646 | case MMC_POWER_OFF: |
640 | at91_set_gpio_output(host->board->vcc_pin, 0); | 647 | at91_set_gpio_value(host->board->vcc_pin, 0); |
641 | break; | 648 | break; |
642 | case MMC_POWER_UP: | 649 | case MMC_POWER_UP: |
643 | case MMC_POWER_ON: | 650 | case MMC_POWER_ON: |
644 | at91_set_gpio_output(host->board->vcc_pin, 1); | 651 | at91_set_gpio_value(host->board->vcc_pin, 1); |
645 | break; | 652 | break; |
646 | } | 653 | } |
647 | } | 654 | } |
@@ -754,7 +761,7 @@ static irqreturn_t at91_mmc_det_irq(int irq, void *_host) | |||
754 | present ? "insert" : "remove"); | 761 | present ? "insert" : "remove"); |
755 | if (!present) { | 762 | if (!present) { |
756 | pr_debug("****** Resetting SD-card bus width ******\n"); | 763 | pr_debug("****** Resetting SD-card bus width ******\n"); |
757 | at91_mci_write(host, AT91_MCI_SDCR, 0); | 764 | at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS); |
758 | } | 765 | } |
759 | mmc_detect_change(host->mmc, msecs_to_jiffies(100)); | 766 | mmc_detect_change(host->mmc, msecs_to_jiffies(100)); |
760 | } | 767 | } |