AT91 MMC update for 2.6.19
authorAndrew Victor <andrew@sanpeople.com>
Mon, 11 Dec 2006 11:40:23 +0000 (12:40 +0100)
committerPierre Ossman <drzeus@drzeus.cx>
Mon, 11 Dec 2006 11:43:35 +0000 (12:43 +0100)
The driver is usable on the newer SAM9 processors so replace all text
references to AT91RM9200 with just AT91.

The controller bug where all the words are byte-swapped is fixed on the
AT91SAM9 processors.  The byte-swapping work-around therefore only needs
to be done if cpu_is_at91rm9200().
[Original patch from Wojtek Kaniewski]

The AT91RM9200 and AT91SAM9260 processors support two MMC/SD slots - the
slot which is connected is now passed via the platform_data and the
correct slot selected in the AT91_MCI_SDCR register.

The driver should not be calling at91_set_gpio_output() since the VCC
pin should have already been configured as an output in the
processor/board setup code.  The driver should call
at91_set_gpio_value().

Signed-off-by: Andrew Victor <andrew@sanpeople.com>
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
drivers/mmc/at91_mci.c

index d500b6b21ea053bd3849d5de483963d7197dc98f..08a33c33f6edbb98ddd1dbd044f4f3848123bde4 100644 (file)
@@ -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));
        }