]> err.no Git - linux-2.6/blobdiff - drivers/mmc/host/at91_mci.c
Merge branch 'core-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6] / drivers / mmc / host / at91_mci.c
index e1f91a42d521002a99d9c6e623a15636aea293cb..f15e2064305cd227ab93f7fdaaa8006ceb684e36 100644 (file)
@@ -198,9 +198,14 @@ static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data
        unsigned int len, i, size;
        unsigned *dmabuf = host->buffer;
 
-       size = host->total_length;
+       size = data->blksz * data->blocks;
        len = data->sg_len;
 
+       /* AT91SAM926[0/3] Data Write Operation and number of bytes erratum */
+       if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
+               if (host->total_length == 12)
+                       memset(dmabuf, 0, 12);
+
        /*
         * Just loop through all entries. Size might not
         * be the entire list though so make sure that
@@ -222,9 +227,10 @@ static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data
 
                        for (index = 0; index < (amount / 4); index++)
                                *dmabuf++ = swab32(sgbuffer[index]);
-               }
-               else
+               } else {
                        memcpy(dmabuf, sgbuffer, amount);
+                       dmabuf += amount;
+               }
 
                kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ);
 
@@ -417,7 +423,7 @@ static void at91_mci_update_bytes_xfered(struct at91mci_host *host)
                        /* card is in IDLE mode now */
                        pr_debug("-> bytes_xfered %d, total_length = %d\n",
                                data->bytes_xfered, host->total_length);
-                       data->bytes_xfered = host->total_length;
+                       data->bytes_xfered = data->blksz * data->blocks;
                }
        }
 }
@@ -514,11 +520,19 @@ static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command
 
        if (data) {
 
-               if ( cpu_is_at91rm9200() && (data->blksz & 0x3) ) {
-                       pr_debug("Unsupported block size\n");
-                       cmd->error = -EINVAL;
-                       mmc_request_done(host->mmc, host->request);
-                       return;
+               if (cpu_is_at91rm9200() || cpu_is_at91sam9261()) {
+                       if (data->blksz & 0x3) {
+                               pr_debug("Unsupported block size\n");
+                               cmd->error = -EINVAL;
+                               mmc_request_done(host->mmc, host->request);
+                               return;
+                       }
+                       if (data->flags & MMC_DATA_STREAM) {
+                               pr_debug("Stream commands not supported\n");
+                               cmd->error = -EINVAL;
+                               mmc_request_done(host->mmc, host->request);
+                               return;
+                       }
                }
 
                block_length = data->blksz;
@@ -565,13 +579,13 @@ static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command
                ier = AT91_MCI_CMDRDY;
        } else {
                /* zero block length and PDC mode */
-               mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff;
+               mr = at91_mci_read(host, AT91_MCI_MR) & 0x5fff;
                mr |= (data->blksz & 0x3) ? AT91_MCI_PDCFBYTE : 0;
                mr |= (block_length << 16);
                mr |= AT91_MCI_PDCMODE;
                at91_mci_write(host, AT91_MCI_MR, mr);
 
-               if (!cpu_is_at91rm9200())
+               if (!(cpu_is_at91rm9200() || cpu_is_at91sam9261()))
                        at91_mci_write(host, AT91_MCI_BLKR,
                                AT91_MCI_BLKR_BCNT(blocks) |
                                AT91_MCI_BLKR_BLKLEN(block_length));
@@ -600,6 +614,13 @@ static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command
                                 * Handle a write
                                 */
                                host->total_length = block_length * blocks;
+                               /*
+                                * AT91SAM926[0/3] Data Write Operation and
+                                * number of bytes erratum
+                                */
+                               if (cpu_is_at91sam9260 () || cpu_is_at91sam9263())
+                                       if (host->total_length < 12)
+                                               host->total_length = 12;
                                host->buffer = dma_alloc_coherent(NULL,
                                                host->total_length,
                                                &host->physical_address, GFP_KERNEL);
@@ -663,6 +684,7 @@ static void at91_mci_process_next(struct at91mci_host *host)
 static void at91_mci_completed_command(struct at91mci_host *host, unsigned int status)
 {
        struct mmc_command *cmd = host->cmd;
+       struct mmc_data *data = cmd->data;
 
        at91_mci_write(host, AT91_MCI_IDR, 0xffffffff & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));
 
@@ -685,15 +707,25 @@ static void at91_mci_completed_command(struct at91mci_host *host, unsigned int s
                        cmd->error = 0;
                }
                else {
-                       if (status & (AT91_MCI_RTOE | AT91_MCI_DTOE))
-                               cmd->error = -ETIMEDOUT;
-                       else if (status & (AT91_MCI_RCRCE | AT91_MCI_DCRCE))
-                               cmd->error = -EILSEQ;
-                       else
-                               cmd->error = -EIO;
+                       if (status & (AT91_MCI_DTOE | AT91_MCI_DCRCE)) {
+                               if (data) {
+                                       if (status & AT91_MCI_DTOE)
+                                               data->error = -ETIMEDOUT;
+                                       else if (status & AT91_MCI_DCRCE)
+                                               data->error = -EILSEQ;
+                               }
+                       } else {
+                               if (status & AT91_MCI_RTOE)
+                                       cmd->error = -ETIMEDOUT;
+                               else if (status & AT91_MCI_RCRCE)
+                                       cmd->error = -EILSEQ;
+                               else
+                                       cmd->error = -EIO;
+                       }
 
-                       pr_debug("Error detected and set to %d (cmd = %d, retries = %d)\n",
-                                cmd->error, cmd->opcode, cmd->retries);
+                       pr_debug("Error detected and set to %d/%d (cmd = %d, retries = %d)\n",
+                               cmd->error, data ? data->error : 0,
+                                cmd->opcode, cmd->retries);
                }
        }
        else
@@ -963,7 +995,7 @@ static int __init at91_mci_probe(struct platform_device *pdev)
        mmc->f_min = 375000;
        mmc->f_max = 25000000;
        mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
-       mmc->caps = MMC_CAP_MULTIWRITE | MMC_CAP_SDIO_IRQ;
+       mmc->caps = MMC_CAP_SDIO_IRQ;
 
        mmc->max_blk_size = 4095;
        mmc->max_blk_count = mmc->max_req_size;