Commit 99eeb8df authored by Andrew Victor's avatar Andrew Victor Committed by Pierre Ossman

AT91 MMC update for 2.6.19

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: default avatarAndrew Victor <andrew@sanpeople.com>
Signed-off-by: default avatarPierre Ossman <drzeus@drzeus.cx>
parent a98087cf
/* /*
* 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 * Copyright (C) 2005 Cougar Creek Computing Devices Ltd, All Rights Reserved
* *
...@@ -11,7 +11,7 @@ ...@@ -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. and SD-cards. Boards that support write protect are now supported.
The CCAT91SBC001 board does not support SD cards. The CCAT91SBC001 board does not support SD cards.
...@@ -38,8 +38,8 @@ ...@@ -38,8 +38,8 @@
controller to manage the transfers. controller to manage the transfers.
A read is done from the controller directly to the scatterlist passed in from the request. 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 Due to a bug in the AT91RM9200 controller, when a read is completed, all the words are byte
swapped in the scatterlist buffers. swapped in the scatterlist buffers. AT91SAM926x are not affected by this bug.
The sequence of read interrupts is: ENDRX, RXBUFF, CMDRDY The sequence of read interrupts is: ENDRX, RXBUFF, CMDRDY
...@@ -72,6 +72,7 @@ ...@@ -72,6 +72,7 @@
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/mach/mmc.h> #include <asm/mach/mmc.h>
#include <asm/arch/board.h> #include <asm/arch/board.h>
#include <asm/arch/cpu.h>
#include <asm/arch/gpio.h> #include <asm/arch/gpio.h>
#include <asm/arch/at91_mci.h> #include <asm/arch/at91_mci.h>
#include <asm/arch/at91_pdc.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 ...@@ -147,7 +148,6 @@ static inline void at91mci_sg_to_dma(struct at91mci_host *host, struct mmc_data
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
struct scatterlist *sg; struct scatterlist *sg;
int amount; int amount;
int index;
unsigned int *sgbuffer; unsigned int *sgbuffer;
sg = &data->sg[i]; sg = &data->sg[i];
...@@ -155,10 +155,15 @@ static inline void at91mci_sg_to_dma(struct at91mci_host *host, struct mmc_data ...@@ -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; sgbuffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
amount = min(size, sg->length); amount = min(size, sg->length);
size -= amount; size -= amount;
amount /= 4;
for (index = 0; index < amount; index++) if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */
*dmabuf++ = swab32(sgbuffer[index]); 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); kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ);
...@@ -265,8 +270,6 @@ static void at91mci_post_dma_read(struct at91mci_host *host) ...@@ -265,8 +270,6 @@ static void at91mci_post_dma_read(struct at91mci_host *host)
while (host->in_use_index < host->transfer_index) { while (host->in_use_index < host->transfer_index) {
unsigned int *buffer; unsigned int *buffer;
int index;
int len;
struct scatterlist *sg; struct scatterlist *sg;
...@@ -284,11 +287,13 @@ static void at91mci_post_dma_read(struct at91mci_host *host) ...@@ -284,11 +287,13 @@ static void at91mci_post_dma_read(struct at91mci_host *host)
data->bytes_xfered += sg->length; data->bytes_xfered += sg->length;
len = sg->length / 4; if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */
int index;
for (index = 0; index < len; index++) { for (index = 0; index < (sg->length / 4); index++)
buffer[index] = swab32(buffer[index]); buffer[index] = swab32(buffer[index]);
} }
kunmap_atomic(buffer, KM_BIO_SRC_IRQ); kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
flush_dcache_page(sg->page); flush_dcache_page(sg->page);
} }
...@@ -339,7 +344,9 @@ static void at91_mci_enable(struct at91mci_host *host) ...@@ -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_IDR, 0xffffffff);
at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC); 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_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) ...@@ -637,11 +644,11 @@ static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
if (host->board->vcc_pin) { if (host->board->vcc_pin) {
switch (ios->power_mode) { switch (ios->power_mode) {
case MMC_POWER_OFF: case MMC_POWER_OFF:
at91_set_gpio_output(host->board->vcc_pin, 0); at91_set_gpio_value(host->board->vcc_pin, 0);
break; break;
case MMC_POWER_UP: case MMC_POWER_UP:
case MMC_POWER_ON: case MMC_POWER_ON:
at91_set_gpio_output(host->board->vcc_pin, 1); at91_set_gpio_value(host->board->vcc_pin, 1);
break; break;
} }
} }
...@@ -754,7 +761,7 @@ static irqreturn_t at91_mmc_det_irq(int irq, void *_host) ...@@ -754,7 +761,7 @@ static irqreturn_t at91_mmc_det_irq(int irq, void *_host)
present ? "insert" : "remove"); present ? "insert" : "remove");
if (!present) { if (!present) {
pr_debug("****** Resetting SD-card bus width ******\n"); 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)); mmc_detect_change(host->mmc, msecs_to_jiffies(100));
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment