Vipin Bhandari <vipin.bhand...@ti.com> 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 most of review comments given on LKLM by
> Pierre Ossman.
>
> Signed-off-by: Vipin Bhandari <vipin.bhand...@ti.com>

Thanks, pushing today.

Kevin

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

_______________________________________________
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