Vipin Bhandari <[email protected]> writes:

> 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]>

Pierre has had some more questions/comments on LKML.  Are you planning
to address those and re-submit upstream?

I'd like to see this driver get re-submitted upstream before pulling
into DaVinci git.

Kevin

> ---
>  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

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

Reply via email to