[U-Boot] [RFC 1/3] mmc: checking status after commands with R1b response

Lei Wen adrian.wenl at gmail.com
Thu Mar 10 08:45:58 CET 2011


Hi Raffaele,

On Thu, Mar 10, 2011 at 12:51 AM, Raffaele Recalcati
<lamiaposta71 at gmail.com> wrote:
> From: Raffaele Recalcati <raffaele.recalcati at bticino.it>
>
> It is a recommended to check card status after these kind of commands.
> This is done using CMD13 (SEND_STATUS) JEDEC command.
> In case of error the previous command is issued again.
>
> Signed-off-by: Raffaele Recalcati <raffaele.recalcati at bticino.it>
> ---
>  drivers/mmc/mmc.c |  106 +++++++++++++++++++++++++++++++++++++++--------------
>  include/mmc.h     |    4 ++
>  2 files changed, 82 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index 6805b33..53ed36f 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -48,6 +48,32 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
>        return mmc->send_cmd(mmc, cmd, data);
>  }
>
> +int mmc_send_status(struct mmc *mmc)
> +{
> +       struct mmc_cmd cmd;
> +       int err;
> +       int timeout = 1000;
> +       int status;
> +
> +       cmd.cmdidx = MMC_CMD_SEND_STATUS;
> +       cmd.resp_type = MMC_RSP_R1;
> +       cmd.cmdarg = 0;
> +       cmd.flags = 0;
> +
> +       do {
> +               err = mmc_send_cmd(mmc, &cmd, NULL);
> +               if (err)
> +                       return err;
> +               udelay(1000);
> +               if (cmd.response[0] & MMC_STATUS_MASK) {
> +                       printf("Status Error: 0x%08X\n", cmd.response[0]);
> +                       return 1;
> +               }
> +       } while (!(cmd.response[0] & MMC_STATUS_RDY_FOR_DATA) && timeout--);
> +
> +       return 0;
> +}
> +
>  int mmc_set_blocklen(struct mmc *mmc, int len)
>  {
>        struct mmc_cmd cmd;
> @@ -82,6 +108,7 @@ mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)
>  {
>        struct mmc_cmd cmd;
>        struct mmc_data data;
> +       int timeout = 1000;
>
>        if ((start + blkcnt) > mmc->block_dev.lba) {
>                printf("MMC: block number 0x%lx exceeds max(0x%lx)\n",
> @@ -113,14 +140,22 @@ mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)
>        }
>
>        if (blkcnt > 1) {
> -               cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
> -               cmd.cmdarg = 0;
> -               cmd.resp_type = MMC_RSP_R1b;
> -               cmd.flags = 0;
> -               if (mmc_send_cmd(mmc, &cmd, NULL)) {
> -                       printf("mmc fail to send stop cmd\n");
> -                       return 0;
> -               }
> +               do {
> +                       cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
> +                       cmd.cmdarg = 0;
> +                       cmd.resp_type = MMC_RSP_R1b;
> +                       cmd.flags = 0;
> +                       if (mmc_send_cmd(mmc, &cmd, NULL)) {
> +                               printf("mmc fail to send stop cmd\n");
> +                               return 0;
> +                       }
> +
> +                       udelay(1000);
> +
> +               } while (mmc_send_status(mmc) && timeout--);

I apply your patch and test on my board and find this patch mess my sd card...
Why you need to keep send the stop command (Also the other command in
this patch)
if mmc_send_status fail? As my understanding, the command should only send once,
and then start to call the mmc_send_status till the status stable.

This is also what kernel does. You could refer to
drivers/mmc/core/mmc_ops.c in the linux kernel.

Best regards,
Lei


More information about the U-Boot mailing list