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 the review comments given on LKLM by 
Pierre Ossman.
Many thanks to David Brownell for his all support for review.

Signed-off-by: Vipin Bhandari <[email protected]>
Signed-off-by: Purushotam Kumar <[email protected]>
---
 drivers/mmc/host/davinci_mmc.c |  102 +++++++++++++++++++++------------------
 1 files changed, 55 insertions(+), 47 deletions(-)

diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
index 9b23802..c595934 100644
--- a/drivers/mmc/host/davinci_mmc.c
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -30,9 +30,9 @@
 #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>
 #include <mach/edma.h>
 
 /*
@@ -130,7 +130,7 @@
 #define MMCFIFOCTL_ACCWD_1    (3 << 3) /* access width of 1 byte     */
 
 
-/* MMCSD Init clock in Hz in opendain mode */
+/* MMCSD Init clock in Hz in opendrain mode */
 #define MMCSD_INIT_CLOCK               200000
 
 /*
@@ -194,21 +194,20 @@ struct mmc_davinci_host {
 
        /* For PIO we walk scatterlists one segment at a time. */
        unsigned int            sg_len;
-       int                     sg_idx;
+       struct scatterlist *sg;
 
        /* Version of the MMC/SD controller */
        u8 version;
+       /* for ns in one cycle calculation */
+       unsigned ns_in_one_cycle;
 };
 
 
 /* PIO only */
 static void mmc_davinci_sg_to_buf(struct mmc_davinci_host *host)
 {
-       struct scatterlist *sg;
-
-       sg = host->data->sg + host->sg_idx;
-       host->buffer_bytes_left = sg_dma_len(sg);
-       host->buffer = sg_virt(sg);
+       host->buffer_bytes_left = sg_dma_len(host->sg);
+       host->buffer = sg_virt(host->sg);
        if (host->buffer_bytes_left > host->bytes_left)
                host->buffer_bytes_left = host->bytes_left;
 }
@@ -220,8 +219,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->sg = sg_next(host->data->sg);
                mmc_davinci_sg_to_buf(host);
        }
 
@@ -312,10 +310,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 +334,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 +352,10 @@ 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);
+               davinci_fifo_data_trans(host, rw_threshold);
 
        writel(cmd->arg, host->base + DAVINCI_MMCARGHL);
        writel(cmd_reg,  host->base + DAVINCI_MMCCMD);
@@ -489,13 +483,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 +633,8 @@ 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 / host->ns_in_one_cycle);
        if (timeout > 0xffff)
                timeout = 0xffff;
 
@@ -686,8 +678,8 @@ 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;
+               host->sg = host->data->sg;
                mmc_davinci_sg_to_buf(host);
        }
 }
@@ -722,21 +714,30 @@ static void mmc_davinci_request(struct mmc_host *mmc, 
struct mmc_request *req)
 static unsigned int calculate_freq_for_card(struct mmc_davinci_host *host,
        unsigned int mmc_req_freq)
 {
-       unsigned int mmc_freq = 0, cpu_arm_clk = 0, mmc_push_pull = 0;
+       unsigned int mmc_freq = 0, cpu_arm_clk = 0, mmc_push_pull_divisor = 0;
 
        cpu_arm_clk = host->mmc_input_clk;
-       if (cpu_arm_clk > (2 * mmc_req_freq))
-               mmc_push_pull = ((unsigned int)cpu_arm_clk
+       if (mmc_req_freq && cpu_arm_clk > (2 * mmc_req_freq))
+               mmc_push_pull_divisor = ((unsigned int)cpu_arm_clk
                                / (2 * mmc_req_freq)) - 1;
        else
-               mmc_push_pull = 0;
+               mmc_push_pull_divisor = 0;
 
-       mmc_freq = (unsigned int)cpu_arm_clk / (2 * (mmc_push_pull + 1));
+       mmc_freq = (unsigned int)cpu_arm_clk
+                               / (2 * (mmc_push_pull_divisor + 1));
 
        if (mmc_freq > mmc_req_freq)
-               mmc_push_pull = mmc_push_pull + 1;
+               mmc_push_pull_divisor = mmc_push_pull_divisor + 1;
+
+       /* Convert ns to clock cycles */
+       if (mmc_req_freq < 400000)
+               host->ns_in_one_cycle = 1000000 / ((cpu_arm_clk
+                               / (2 * (mmc_push_pull_divisor + 1)))/1000);
+       else
+               host->ns_in_one_cycle = 1000000 / ((cpu_arm_clk
+                               / (2 * (mmc_push_pull_divisor + 1)))/1000000);
 
-       return mmc_push_pull;
+       return mmc_push_pull_divisor;
 }
 
 static void mmc_davinci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
@@ -762,11 +763,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 */
+               host->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 +875,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 +930,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 +992,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 +1053,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,
@@ -1076,7 +1082,7 @@ static int __init davinci_mmcsd_probe(struct 
platform_device *pdev)
                goto out;
 
        ret = -EBUSY;
-       mem_size = r->end - r->start + 1;
+       mem_size = resource_size(r);
        mem = request_mem_region(r->start, mem_size, pdev->name);
        if (!mem)
                goto out;
@@ -1111,6 +1117,7 @@ static int __init davinci_mmcsd_probe(struct 
platform_device *pdev)
                goto out;
        }
        clk_enable(host->clk);
+       host->ns_in_one_cycle = 1;
        host->mmc_input_clk = clk_get_rate(host->clk);
 
        init_mmcsd_host(host);
@@ -1132,9 +1139,9 @@ static int __init davinci_mmcsd_probe(struct 
platform_device *pdev)
        mmc->ops = &mmc_davinci_ops;
        mmc->f_min = 312500;
        mmc->f_max = 25000000;
-       if (pdata->max_freq)
+       if (pdata && pdata->max_freq)
                mmc->f_max = pdata->max_freq;
-       if (pdata->caps)
+       if (pdata && pdata->caps)
                mmc->caps |= pdata->caps;
        mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
 
@@ -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;
 
@@ -1267,5 +1274,6 @@ static void __exit davinci_mmcsd_exit(void)
 }
 module_exit(davinci_mmcsd_exit);
 
+MODULE_AUTHOR("Texas Instruments India <[email protected]>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("MMC/SD driver for Davinci MMC controller");
-- 
1.5.6

_______________________________________________
Davinci-linux-open-source mailing list
[email protected]
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source

Reply via email to