The scatterlist traversal is made proper. The patch has some minor comments
modification and also sets the value written to the DAVINCI_MMCTOR register
properly. The timeout calculation is made proper by deriving it from the
clock values.

This patch incorporates most of review comments given on LKLM by
Pierre Ossman.

Signed-off-by: Vipin Bhandari <vipin.bhand...@ti.com>
---
 drivers/mmc/host/davinci_mmc.c |   73 ++++++++++++++++++++++------------------
 1 files changed, 40 insertions(+), 33 deletions(-)

diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
index 9b23802..d2193ca 100644
--- a/drivers/mmc/host/davinci_mmc.c
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -30,6 +30,7 @@
 #include <linux/irq.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
+#include <linux/mmc/mmc.h>
 
 #include <mach/mmc.h>
 #include <mach/cpu.h>
@@ -145,7 +146,9 @@
 
 #define NR_SG          16
 
+#define DAVINCI_MMC_FIFO_SIZE_BYTE 32
 static unsigned rw_threshold = 32;
+static unsigned ns_in_one_cycle = 1;
 module_param(rw_threshold, uint, S_IRUGO);
 MODULE_PARM_DESC(rw_threshold,
                "Read/Write threshold. Default = 32");
@@ -194,7 +197,6 @@ struct mmc_davinci_host {
 
        /* For PIO we walk scatterlists one segment at a time. */
        unsigned int            sg_len;
-       int                     sg_idx;
 
        /* Version of the MMC/SD controller */
        u8 version;
@@ -205,8 +207,7 @@ struct mmc_davinci_host {
 static void mmc_davinci_sg_to_buf(struct mmc_davinci_host *host)
 {
        struct scatterlist *sg;
-
-       sg = host->data->sg + host->sg_idx;
+       sg = host->data->sg;
        host->buffer_bytes_left = sg_dma_len(sg);
        host->buffer = sg_virt(sg);
        if (host->buffer_bytes_left > host->bytes_left)
@@ -220,8 +221,7 @@ static void davinci_fifo_data_trans(struct mmc_davinci_host 
*host,
        unsigned int i;
 
        if (host->buffer_bytes_left == 0) {
-               host->sg_idx++;
-               BUG_ON(host->sg_idx == host->sg_len);
+               host->data->sg = sg_next(host->data->sg);
                mmc_davinci_sg_to_buf(host);
        }
 
@@ -312,10 +312,6 @@ static void mmc_davinci_start_command(struct 
mmc_davinci_host *host,
        /* Set command index */
        cmd_reg |= cmd->opcode;
 
-       /* Setting initialize clock */
-       if (cmd->opcode == 0)
-               cmd_reg |= MMCCMD_INITCK;
-
        /* Enable EDMA transfer triggers */
        if (host->do_dma)
                cmd_reg |= MMCCMD_DMATRIG;
@@ -340,7 +336,7 @@ static void mmc_davinci_start_command(struct 
mmc_davinci_host *host,
                cmd_reg |= MMCCMD_PPLEN;
 
        /* set Command timeout */
-       writel(0xFFFF, host->base + DAVINCI_MMCTOR);
+       writel(0x1FFF, host->base + DAVINCI_MMCTOR);
 
        /* Enable interrupt (calculate here, defer until FIFO is stuffed). */
        im_val =  MMCST0_RSPDNE | MMCST0_CRCRS | MMCST0_TOUTRS;
@@ -358,10 +354,12 @@ static void mmc_davinci_start_command(struct 
mmc_davinci_host *host,
 
        /*
         * Before non-DMA WRITE commands the controller needs priming:
-        * FIFO should be populated with 32 bytes
+        * FIFO should be populated with 32 bytes i.e. whatever is the FIFO size
         */
-       if (!host->do_dma && (host->data_dir == DAVINCI_MMC_DATADIR_WRITE))
-               davinci_fifo_data_trans(host, 32);
+       if (!host->do_dma && (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) &&
+               ((cmd->opcode == MMC_WRITE_BLOCK) ||
+               (cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK)))
+               davinci_fifo_data_trans(host, DAVINCI_MMC_FIFO_SIZE_BYTE);
 
        writel(cmd->arg, host->base + DAVINCI_MMCARGHL);
        writel(cmd_reg,  host->base + DAVINCI_MMCCMD);
@@ -489,13 +487,14 @@ static void mmc_davinci_send_dma_request(struct 
mmc_davinci_host *host,
        }
 
        /* We know sg_len and ccnt will never be out of range because
-        * we told the block layer to ensure that it only hands us one
-        * scatterlist segment per EDMA PARAM entry.  Update the PARAM
+        * we told the mmc layer which in turn tells the block layer
+        * to ensure that it only hands us one scatterlist segment
+        * per EDMA PARAM entry.  Update the PARAM
         * entries needed for each segment of this scatterlist.
         */
        for (slot = channel, link = 0, sg = data->sg, sg_len = host->sg_len;
                        sg_len-- != 0 && bytes_left;
-                       sg++, slot = host->links[link++]) {
+                       sg = sg_next(sg), slot = host->links[link++]) {
                u32             buf = sg_dma_address(sg);
                unsigned        count = sg_dma_len(sg);
 
@@ -638,11 +637,7 @@ mmc_davinci_prepare_data(struct mmc_davinci_host *host, 
struct mmc_request *req)
                data->blocks, data->blksz);
        dev_dbg(mmc_dev(host->mmc), "  DTO %d cycles + %d ns\n",
                data->timeout_clks, data->timeout_ns);
-
-       /* Convert ns to clock cycles by assuming 20MHz frequency
-        * 1 cycle at 20MHz = 500 ns
-        */
-       timeout = data->timeout_clks + data->timeout_ns / 500;
+       timeout = data->timeout_clks + data->timeout_ns / ns_in_one_cycle;
        if (timeout > 0xffff)
                timeout = 0xffff;
 
@@ -686,7 +681,6 @@ mmc_davinci_prepare_data(struct mmc_davinci_host *host, 
struct mmc_request *req)
                host->bytes_left = 0;
        } else {
                /* Revert to CPU Copy */
-               host->sg_idx = 0;
                host->sg_len = data->sg_len;
                mmc_davinci_sg_to_buf(host);
        }
@@ -736,6 +730,14 @@ static unsigned int calculate_freq_for_card(struct 
mmc_davinci_host *host,
        if (mmc_freq > mmc_req_freq)
                mmc_push_pull = mmc_push_pull + 1;
 
+       /* Convert ns to clock cycles */
+       if (mmc_req_freq < 400000)
+               ns_in_one_cycle = 1000000 / ((cpu_arm_clk
+                                       / (2 * (mmc_push_pull + 1)))/1000);
+       else
+               ns_in_one_cycle = 1000000 / ((cpu_arm_clk
+                                       / (2 * (mmc_push_pull + 1)))/1000000);
+
        return mmc_push_pull;
 }
 
@@ -762,11 +764,22 @@ static void mmc_davinci_set_ios(struct mmc_host *mmc, 
struct mmc_ios *ios)
 
        if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) {
                u32 temp;
+
+               /* Ignoring the init clock value passed for fixing the inter
+                * operability with different cards.
+                */
                open_drain_freq = ((unsigned int)cpu_arm_clk
                                / (2 * MMCSD_INIT_CLOCK)) - 1;
-               temp = readl(host->base + DAVINCI_MMCCLK) & ~0xFF;
+
+               if (open_drain_freq > 0xFF)
+                       open_drain_freq = 0xFF;
+
+               temp = readl(host->base + DAVINCI_MMCCLK) & ~MMCCLK_CLKRT_MASK;
                temp |= open_drain_freq;
                writel(temp, host->base + DAVINCI_MMCCLK);
+
+               /* Convert ns to clock cycles */
+               ns_in_one_cycle = (1000000) / (MMCSD_INIT_CLOCK/1000);
        } else {
                u32 temp;
                mmc_push_pull_freq = calculate_freq_for_card(host, ios->clock);
@@ -863,10 +876,6 @@ davinci_abort_data(struct mmc_davinci_host *host, struct 
mmc_data *data)
 {
        u32 temp;
 
-       /* record how much data we transferred */
-       temp = readl(host->base + DAVINCI_MMCNBLC);
-       data->bytes_xfered += (data->blocks - temp) * data->blksz;
-
        /* reset command and data state machines */
        temp = readl(host->base + DAVINCI_MMCCTL);
        writel(temp | MMCCTL_CMDRST | MMCCTL_DATRST,
@@ -922,7 +931,7 @@ static irqreturn_t mmc_davinci_irq(int irq, void *dev_id)
                                davinci_fifo_data_trans(host, host->bytes_left);
                        }
                        end_transfer = 1;
-                       data->bytes_xfered += data->blocks * data->blksz;
+                       data->bytes_xfered = data->blocks * data->blksz;
                } else {
                        dev_err(mmc_dev(host->mmc),
                                        "DATDNE with no host->data\n");
@@ -984,9 +993,7 @@ static irqreturn_t mmc_davinci_irq(int irq, void *dev_id)
                /* Command CRC error */
                dev_dbg(mmc_dev(host->mmc), "Command CRC error\n");
                if (host->cmd) {
-                       /* Ignore CMD CRC errors during high speed operation */
-                       if (host->mmc->ios.clock <= 25000000)
-                               host->cmd->error = -EILSEQ;
+                       host->cmd->error = -EILSEQ;
                        end_command = 1;
                }
        }
@@ -1047,7 +1054,7 @@ static void __init init_mmcsd_host(struct 
mmc_davinci_host *host)
        writel(0, host->base + DAVINCI_MMCCLK);
        writel(MMCCLK_CLKEN, host->base + DAVINCI_MMCCLK);
 
-       writel(0xFFFF, host->base + DAVINCI_MMCTOR);
+       writel(0x1FFF, host->base + DAVINCI_MMCTOR);
        writel(0xFFFF, host->base + DAVINCI_MMCTOD);
 
        writel(readl(host->base + DAVINCI_MMCCTL) & ~MMCCTL_DATRST,
@@ -1149,7 +1156,7 @@ static int __init davinci_mmcsd_probe(struct 
platform_device *pdev)
        mmc->max_seg_size       = MAX_CCNT * rw_threshold;
 
        /* MMC/SD controller limits for multiblock requests */
-       mmc->max_blk_size       = 4095;  /* BLEN is 11 bits */
+       mmc->max_blk_size       = 4095;  /* BLEN is 12 bits */
        mmc->max_blk_count      = 65535; /* NBLK is 16 bits */
        mmc->max_req_size       = mmc->max_blk_size * mmc->max_blk_count;
 
-- 
1.5.6

_______________________________________________
Davinci-linux-open-source mailing list
Davinci-linux-open-source@linux.davincidsp.com
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source

Reply via email to