This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Omap-L138 Davinci host MMC Linux driver and MMC data timeout

Other Parts Discussed in Thread: OMAP-L138

Hi, 

We have observed something that could be problematic in the way Davinci MMC Linux driver sets data timeout requested by Linux MMC core driver.

To give some context, we are working on an Omap-L138 based board on which we run Linux 3.1-rc4. On this system, we use an SDCard that has very high read/write busy time. For this reason, we have modified mmc_set_data_timeout() in drivers/mmc/core/core.c by adjusting data->timeout_ns/data->timeout_clks to obtain what we call software timeout. This modification has the following effects:

- Davinci MMC driver computes this software timeout as data->timeout_clks + convert_to_clks(data->timeout_ns) (see mmc_davinci_prepare_data() in drivers/mmc/host/davinci_mmc.c)

- this software timeout cannot be more than 0xFFFF

- this software timeout is then write to DAVINCI_MMCTOD register

As its is implemented in Davinci MMC driver, value in DAVINCI_MMCTOD only constitutes the lower bits of what we call the hardware timeout. The upper bits of this hardware timeout are found in TOD_25_16 bits of DAVINCI_MMCTOR register. Currently, TOD_25_16 bits contains fixed value 0x1F. This means that 0x1F FFFF is the maximum timeout that we can obtain with Davinci MMC driver code.

The problem is that hardware timeout (set in MMC controller by Davinci MMC driver) may not be equal to requested software timeout (set in Linux MMC core code, ie data->timeout_ns and data->timeout_clks).

In my opinion, this is really problematic especially when hardware timeout ends up being set less than requested software timeout. This situation may only be tolerate if the software timeout is bigger than the max possible hardware timeout which is 0x3FF FFFF (and not 0x1F FFFF as forced by Davinci MMC driver). To obtain the requested software timeout, the Davinci MMC driver must adjust both the value in DAVINCI_MMCTOD and in TOD_25_16 bits of DAVINCI_MMCTOR.

This situation is also present in Davinci MMC driver of Linux kernel 3.18.

What do you think about this observation? Do I miss something?

Regards,

Fabrice

  • Hi Fabrice,

    Apologize for the delayed response on this.


    To give some context, we are working on an Omap-L138 based board on which we run Linux 3.1-rc4. On this system, we use an SDCard that has very high read/write busy time. For this reason, we have modified mmc_set_data_timeout() in drivers/mmc/core/core.c by adjusting data->timeout_ns/data->timeout_clks to obtain what we call software timeout. This modification has the following effects:


    What problem are you facing when you used the default hw timeout even though MMC was in high read/write busy ?

    Could you attach the code changes if any to reproduce the issue at my end.

    Also, have you increased the hardware timeout to maximum ?

    Try to modify like below and let us know the status.

    drivers/mmc/host/davinci_mmc.c

    static void __init init_mmcsd_host(struct mmc_davinci_host *host)
    {

        mmc_davinci_reset_ctrl(host, 1);

        writel(0, host->base + DAVINCI_MMCCLK);
        writel(MMCCLK_CLKEN, host->base + DAVINCI_MMCCLK);

    /*
        writel(0x1FFF, host->base + DAVINCI_MMCTOR);
        writel(0xFFFF, host->base + DAVINCI_MMCTOD);
    */

        /* Titus : Setting maximum hw timeout to 0x3FF FFFF */
        writel(0x3FFFF, host->base + DAVINCI_MMCTOR);
        writel(0xFFFF, host->base + DAVINCI_MMCTOD);


        mmc_davinci_reset_ctrl(host, 0);
    }

  • Hi Titus,

    Thanks for replying. Below, I am adding more information as requested.

    What problem are you facing when you used the default hw timeout even though MMC was in high read/write busy ?

    Regarding this question, here follows what I obtained from kernel log (this shows the issue with the default hw timeout):

    mmcblk0: retrying using single block read
    mmcblk0: error -110 transferring data, sector 7774080, nr 8, cmd response 0x900, card status 0x0
    end_request: I/O error, dev mmcblk0, sector 7774080
    mmcblk0: timed out sending r/w cmd command, card status 0x400b00
    mmcblk0: error -110 transferring data, sector 7774081, nr 7, cmd response 0x900, card status 0x0
    end_request: I/O error, dev mmcblk0, sector 7774081
    mmcblk0: timed out sending r/w cmd command, card status 0x400b00
    mmcblk0: error -110 transferring data, sector 7774082, nr 6, cmd response 0x900, card status 0x0
    end_request: I/O error, dev mmcblk0, sector 7774082
    mmcblk0: timed out sending r/w cmd command, card status 0x400b00
    mmcblk0: error -110 transferring data, sector 7774083, nr 5, cmd response 0x900, card status 0x0
    end_request: I/O error, dev mmcblk0, sector 7774083
    mmcblk0: timed out sending r/w cmd command, card status 0x400b00
    mmcblk0: error -110 transferring data, sector 7774084, nr 4, cmd response 0x900, card status 0x0
    end_request: I/O error, dev mmcblk0, sector 7774084
    mmcblk0: timed out sending r/w cmd command, card status 0x400b00

    Also, have you increased the hardware timeout to maximum ?

    Yes, I increased this timeout to its max value as you can see in the patch below. After that the card worked properly.

    diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
    index 91a0a74..02fd8de 100644
    --- a/drivers/mmc/core/core.c
    +++ b/drivers/mmc/core/core.c
    @@ -410,6 +410,29 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)
                            data->timeout_ns = limit_us * 1000;
                            data->timeout_clks = 0;
                    }
    +
    +                data->timeout_clks = 0xFFFF;
    +                data->timeout_ns = 0;
            }
            /*
             * Some cards need very high timeouts if driven in SPI mode.
    diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
    index 0076c74..1001bd1 100644
    --- a/drivers/mmc/host/davinci_mmc.c
    +++ b/drivers/mmc/host/davinci_mmc.c
    @@ -351,7 +351,15 @@ static void mmc_davinci_start_command(struct mmc_davinci_host *host,
                    cmd_reg |= MMCCMD_PPLEN;
     
            /* set Command timeout */
    -       writel(0x1FFF, host->base + DAVINCI_MMCTOR);
    +       writel(0x3FFFF, host->base + DAVINCI_MMCTOR);
     
            /* Enable interrupt (calculate here, defer until FIFO is stuffed). */
            im_val =  MMCST0_RSPDNE | MMCST0_CRCRS | MMCST0_TOUTRS;
    @@ -1197,7 +1205,15 @@ 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(0x1FFF, host->base + DAVINCI_MMCTOR);
    +       writel(0x3FFFF, host->base + DAVINCI_MMCTOR);
            writel(0xFFFF, host->base + DAVINCI_MMCTOD);
     
            mmc_davinci_reset_ctrl(host, 0);

    Could you attach the code changes if any to reproduce the issue at my end?

    I did NO code changes for the issue to show up. The only changes that I did are those in the above patch.

    Kind regards,

    Fabrice

  • Hi Fabrice,

    You meant that your problem got resolved ?
  • Hi Titus,

    Yes, I have solved the problem by setting hardware timeout to its max value. But I think the best would be to correctly adjust values in hardware registers (DAVINCI_MMCTOR and DAVINCI_MMCTOD) to match requested software timeout. That is these registers should be set to match values in data->timeout_clks and data->timeout_ns (set in drivers/mmc/core/core.c).

    As I mentioned in my first post, I think it would be good if you correctly set these registers instead of setting fixed value if DAVINCI_MMCTOR and some variable value in DAVINCI_MMCTOD. This is why I am reporting this issue.

    Regards,

    Fabrice