[U-Boot] [PATCH v2 1/3] mmc: sdhci: fix the wrong operation when response type is R1b

Lei Wen adrian.wenl at gmail.com
Fri Mar 30 05:33:06 CEST 2012


Hi Jaehoon,

On Fri, Mar 30, 2012 at 10:39 AM, Jaehoon Chung <jh80.chung at samsung.com> wrote:
> When response type is R1b, mask value is added the SDHCI_INT_DAT_END.
> but in while(), didn't check that flag.
> So sdhci controller didn't work fine.
> CMD6 didn't always complete.

Could you elaborate it more in details?
        do {
                stat = sdhci_readl(host, SDHCI_INT_STATUS);
                if (stat & SDHCI_INT_ERROR)
                        break;
        } while ((stat & mask) != mask);
Here in the while condition, if the status read out don't contain all mask,
then the looping would continue.
Do you mean you just need a retry max time set here?


>
> Signed-off-by: Jaehoon Chung <jh80.chung at samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
> ---
>  drivers/mmc/sdhci.c |   33 +++++++++++++++++++++++----------
>  1 files changed, 23 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
> index fc904b5..0dd08b9 100644
> --- a/drivers/mmc/sdhci.c
> +++ b/drivers/mmc/sdhci.c
> @@ -124,10 +124,11 @@ int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
>  {
>        struct sdhci_host *host = (struct sdhci_host *)mmc->priv;
>        unsigned int stat = 0;
> -       int ret = 0;
> +       int i, ret = 0;
>        int trans_bytes = 0, is_aligned = 1;
>        u32 mask, flags, mode;
>        unsigned int timeout, start_addr = 0;
> +       unsigned int retry = 10000;
>
>        /* Wait max 10 ms */
>        timeout = 10;
> @@ -206,19 +207,31 @@ int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
>        flush_cache(start_addr, trans_bytes);
>  #endif
>        sdhci_writew(host, SDHCI_MAKE_CMD(cmd->cmdidx, flags), SDHCI_COMMAND);
> -       do {
> +
> +       for (i = 0; i < retry; i++) {
>                stat = sdhci_readl(host, SDHCI_INT_STATUS);
> -               if (stat & SDHCI_INT_ERROR)
> +               if (stat & (SDHCI_INT_RESPONSE | SDHCI_INT_DATA_END)) {
> +                       sdhci_cmd_done(host, cmd);
> +                       sdhci_writel(host, mask, SDHCI_INT_STATUS);
> +                       if (!data) {
> +                               sdhci_writel(host, stat,  SDHCI_INT_STATUS);

Why do two write?

> +                       }
>                        break;
> -       } while ((stat & mask) != mask);
> +               }
> +       }
>
> -       if ((stat & (SDHCI_INT_ERROR | mask)) == mask) {
> -               sdhci_cmd_done(host, cmd);
> -               sdhci_writel(host, mask, SDHCI_INT_STATUS);
> -       } else
> -               ret = -1;
> +       if (i == retry) {
> +               printf("%s: waiting for status update\n",__func__);
> +               return TIMEOUT;
> +       }
> +
> +       if (stat & SDHCI_INT_TIMEOUT) {
> +               return TIMEOUT;
> +       } else if (stat & SDHCI_INT_ERROR) {
> +               return -1;
> +       }
>
> -       if (!ret && data)
> +       if (data)
>                ret = sdhci_transfer_data(host, data, start_addr);
>
>        stat = sdhci_readl(host, SDHCI_INT_STATUS);


Thanks,
Lei


More information about the U-Boot mailing list