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 d500b6b21ea..08a33c33f6e 100644 --- a/drivers/mmc/at91_mci.c +++ b/drivers/mmc/at91_mci.c @@ -1,5 +1,5 @@ /* - * linux/drivers/mmc/at91_mci.c - ATMEL AT91RM9200 MCI Driver + * linux/drivers/mmc/at91_mci.c - ATMEL AT91 MCI Driver * * Copyright (C) 2005 Cougar Creek Computing Devices Ltd, All Rights Reserved * @@ -11,7 +11,7 @@ */ /* - This is the AT91RM9200 MCI driver that has been tested with both MMC cards + This is the AT91 MCI driver that has been tested with both MMC cards and SD-cards. Boards that support write protect are now supported. The CCAT91SBC001 board does not support SD cards. @@ -38,8 +38,8 @@ controller to manage the transfers. A read is done from the controller directly to the scatterlist passed in from the request. - Due to a bug in the controller, when a read is completed, all the words are byte - swapped in the scatterlist buffers. + Due to a bug in the AT91RM9200 controller, when a read is completed, all the words are byte + swapped in the scatterlist buffers. AT91SAM926x are not affected by this bug. The sequence of read interrupts is: ENDRX, RXBUFF, CMDRDY @@ -72,6 +72,7 @@ #include <asm/irq.h> #include <asm/mach/mmc.h> #include <asm/arch/board.h> +#include <asm/arch/cpu.h> #include <asm/arch/gpio.h> #include <asm/arch/at91_mci.h> #include <asm/arch/at91_pdc.h> @@ -147,7 +148,6 @@ static inline void at91mci_sg_to_dma(struct at91mci_host *host, struct mmc_data for (i = 0; i < len; i++) { struct scatterlist *sg; int amount; - int index; unsigned int *sgbuffer; sg = &data->sg[i]; @@ -155,10 +155,15 @@ static inline void at91mci_sg_to_dma(struct at91mci_host *host, struct mmc_data sgbuffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset; amount = min(size, sg->length); size -= amount; - amount /= 4; - for (index = 0; index < amount; index++) - *dmabuf++ = swab32(sgbuffer[index]); + if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */ + int index; + + for (index = 0; index < (amount / 4); index++) + *dmabuf++ = swab32(sgbuffer[index]); + } + else + memcpy(dmabuf, sgbuffer, amount); kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ); @@ -265,8 +270,6 @@ static void at91mci_post_dma_read(struct at91mci_host *host) while (host->in_use_index < host->transfer_index) { unsigned int *buffer; - int index; - int len; struct scatterlist *sg; @@ -284,11 +287,13 @@ static void at91mci_post_dma_read(struct at91mci_host *host) data->bytes_xfered += sg->length; - len = sg->length / 4; + if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */ + int index; - for (index = 0; index < len; index++) { - buffer[index] = swab32(buffer[index]); + for (index = 0; index < (sg->length / 4); index++) + buffer[index] = swab32(buffer[index]); } + kunmap_atomic(buffer, KM_BIO_SRC_IRQ); flush_dcache_page(sg->page); } @@ -339,7 +344,9 @@ static void at91_mci_enable(struct at91mci_host *host) at91_mci_write(host, AT91_MCI_IDR, 0xffffffff); at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC); at91_mci_write(host, AT91_MCI_MR, AT91_MCI_PDCMODE | 0x34a); - at91_mci_write(host, AT91_MCI_SDCR, 0); + + /* use Slot A or B (only one at same time) */ + at91_mci_write(host, AT91_MCI_SDCR, host->board->slot_b); } /* @@ -637,11 +644,11 @@ static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) if (host->board->vcc_pin) { switch (ios->power_mode) { case MMC_POWER_OFF: - at91_set_gpio_output(host->board->vcc_pin, 0); + at91_set_gpio_value(host->board->vcc_pin, 0); break; case MMC_POWER_UP: case MMC_POWER_ON: - at91_set_gpio_output(host->board->vcc_pin, 1); + at91_set_gpio_value(host->board->vcc_pin, 1); break; } } @@ -754,7 +761,7 @@ static irqreturn_t at91_mmc_det_irq(int irq, void *_host) present ? "insert" : "remove"); if (!present) { pr_debug("****** Resetting SD-card bus width ******\n"); - at91_mci_write(host, AT91_MCI_SDCR, 0); + at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS); } mmc_detect_change(host->mmc, msecs_to_jiffies(100)); } |