]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/mmc/mmci.c
[PATCH] I2C: Resurrect i2c_smbus_write_i2c_block_data.
[linux-2.6-omap-h63xx.git] / drivers / mmc / mmci.c
index 166c9b0ad04ef7a43be4e63f6f5e66483cbdd80a..37ee7f8dc82fe305195472e0ad5dd281e5c5f219 100644 (file)
 #include <linux/highmem.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/protocol.h>
+#include <linux/amba/bus.h>
+#include <linux/clk.h>
 
+#include <asm/cacheflush.h>
 #include <asm/div64.h>
 #include <asm/io.h>
 #include <asm/scatterlist.h>
 #include <asm/sizes.h>
-#include <asm/hardware/amba.h>
-#include <asm/hardware/clock.h>
 #include <asm/mach/mmc.h>
 
 #include "mmci.h"
@@ -123,15 +124,10 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c)
        }
 
        c |= cmd->opcode | MCI_CPSM_ENABLE;
-       switch (cmd->flags & MMC_RSP_MASK) {
-       case MMC_RSP_NONE:
-       default:
-               break;
-       case MMC_RSP_LONG:
-               c |= MCI_CPSM_LONGRSP;
-       case MMC_RSP_SHORT:
+       if (cmd->flags & MMC_RSP_PRESENT) {
+               if (cmd->flags & MMC_RSP_136)
+                       c |= MCI_CPSM_LONGRSP;
                c |= MCI_CPSM_RESPONSE;
-               break;
        }
        if (/*interrupt*/0)
                c |= MCI_CPSM_INTERRUPT;
@@ -157,6 +153,13 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
                else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN))
                        data->error = MMC_ERR_FIFO;
                status |= MCI_DATAEND;
+
+               /*
+                * We hit an error condition.  Ensure that any data
+                * partially written to a page is properly coherent.
+                */
+               if (host->sg_len && data->flags & MMC_DATA_READ)
+                       flush_dcache_page(host->sg_ptr->page);
        }
        if (status & MCI_DATAEND) {
                mmci_stop_data(host);
@@ -292,7 +295,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id, struct pt_regs *regs)
                /*
                 * Unmap the buffer.
                 */
-               mmci_kunmap_atomic(host, &flags);
+               mmci_kunmap_atomic(host, buffer, &flags);
 
                host->sg_off += len;
                host->size -= len;
@@ -301,6 +304,13 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id, struct pt_regs *regs)
                if (remain)
                        break;
 
+               /*
+                * If we were reading, and we have completed this
+                * page, ensure that the data cache is coherent.
+                */
+               if (status & MCI_RXACTIVE)
+                       flush_dcache_page(host->sg_ptr->page);
+
                if (!mmci_next_sg(host))
                        break;
 
@@ -479,13 +489,9 @@ static int mmci_probe(struct amba_device *dev, void *id)
                goto host_free;
        }
 
-       ret = clk_use(host->clk);
-       if (ret)
-               goto clk_free;
-
        ret = clk_enable(host->clk);
        if (ret)
-               goto clk_unuse;
+               goto clk_free;
 
        host->plat = plat;
        host->mclk = clk_get_rate(host->clk);
@@ -558,8 +564,6 @@ static int mmci_probe(struct amba_device *dev, void *id)
        iounmap(host->base);
  clk_disable:
        clk_disable(host->clk);
- clk_unuse:
-       clk_unuse(host->clk);
  clk_free:
        clk_put(host->clk);
  host_free:
@@ -594,7 +598,6 @@ static int mmci_remove(struct amba_device *dev)
 
                iounmap(host->base);
                clk_disable(host->clk);
-               clk_unuse(host->clk);
                clk_put(host->clk);
 
                mmc_free_host(mmc);