[U-Boot] [PATCH 1/4] mmc: Fix handling of bus widths and DDR card capabilities
Pantelis Antoniou
pantelis.antoniou at gmail.com
Fri Dec 12 20:12:46 CET 2014
Hi Andrew,
Looks good. I don’t have a DDR capable board to test, but at first glance
it’s fine.
> On Dec 1, 2014, at 14:59 , Andrew Gabbasov <andrew_gabbasov at mentor.com> wrote:
>
> If the MMC_MODE_DDR_52MHz flag is set in card capabilities bitmask,
> it is never cleared, even if switching to DDR mode fails, and if
> the controller driver uses this flag to check the DDR mode, it can
> take incorrect actions.
>
> Also, DDR related checks in mmc_startup() incorrectly handle the case
> when the host controller does not support some bus widths (e.g. can't
> support 8 bits), since the host_caps is checked for DDR bit, but not
> bus width bits.
>
> This fix clearly separates using of card_caps bitmask, having there
> the flags for the capabilities, that the card can support, and actual
> operation mode, described outside of card_caps (i.e. bus_width and
> ddr_mode fields in mmc structure). Separate host controller drivers
> may need to be updated to use the actual flags. Respectively,
> the capabilities checks in mmc_startup are made more correct and clear.
>
> Also, some clean up is made with errors handling and code syntax layout.
>
> Signed-off-by: Andrew Gabbasov <andrew_gabbasov at mentor.com>
> ---
> common/cmd_mmc.c | 3 ++-
> drivers/mmc/mmc.c | 52 +++++++++++++++++++++++++++++++---------------------
> include/mmc.h | 1 +
> 3 files changed, 34 insertions(+), 22 deletions(-)
>
> diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c
> index 4286e26..96478e4 100644
> --- a/common/cmd_mmc.c
> +++ b/common/cmd_mmc.c
> @@ -90,7 +90,8 @@ static void print_mmcinfo(struct mmc *mmc)
> puts("Capacity: ");
> print_size(mmc->capacity, "\n");
>
> - printf("Bus Width: %d-bit\n", mmc->bus_width);
> + printf("Bus Width: %d-bit%s\n", mmc->bus_width,
> + mmc->ddr_mode ? " DDR" : "");
> }
> static struct mmc *init_mmc_device(int dev, bool force_init)
> {
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index 44a4feb..4603a81 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -159,7 +159,7 @@ int mmc_set_blocklen(struct mmc *mmc, int len)
> {
> struct mmc_cmd cmd;
>
> - if (mmc->card_caps & MMC_MODE_DDR_52MHz)
> + if (mmc->ddr_mode)
> return 0;
>
> cmd.cmdidx = MMC_CMD_SET_BLOCKLEN;
> @@ -486,7 +486,7 @@ static int mmc_change_freq(struct mmc *mmc)
> char cardtype;
> int err;
>
> - mmc->card_caps = 0;
> + mmc->card_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
>
> if (mmc_host_is_spi(mmc))
> return 0;
> @@ -1103,8 +1103,10 @@ static int mmc_startup(struct mmc *mmc)
>
> /* An array to map CSD bus widths to host cap bits */
> static unsigned ext_to_hostcaps[] = {
> - [EXT_CSD_DDR_BUS_WIDTH_4] = MMC_MODE_DDR_52MHz,
> - [EXT_CSD_DDR_BUS_WIDTH_8] = MMC_MODE_DDR_52MHz,
> + [EXT_CSD_DDR_BUS_WIDTH_4] =
> + MMC_MODE_DDR_52MHz | MMC_MODE_4BIT,
> + [EXT_CSD_DDR_BUS_WIDTH_8] =
> + MMC_MODE_DDR_52MHz | MMC_MODE_8BIT,
> [EXT_CSD_BUS_WIDTH_4] = MMC_MODE_4BIT,
> [EXT_CSD_BUS_WIDTH_8] = MMC_MODE_8BIT,
> };
> @@ -1116,13 +1118,13 @@ static int mmc_startup(struct mmc *mmc)
>
> for (idx=0; idx < ARRAY_SIZE(ext_csd_bits); idx++) {
> unsigned int extw = ext_csd_bits[idx];
> + unsigned int caps = ext_to_hostcaps[extw];
>
> /*
> - * Check to make sure the controller supports
> - * this bus width, if it's more than 1
> + * Check to make sure the card and controller support
> + * these capabilities
> */
> - if (extw != EXT_CSD_BUS_WIDTH_1 &&
> - !(mmc->cfg->host_caps & ext_to_hostcaps[extw]))
> + if ((mmc->card_caps & caps) != caps)
> continue;
>
> err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
> @@ -1131,26 +1133,33 @@ static int mmc_startup(struct mmc *mmc)
> if (err)
> continue;
>
> + mmc->ddr_mode = (caps & MMC_MODE_DDR_52MHz) ? 1 : 0;
> mmc_set_bus_width(mmc, widths[idx]);
>
> err = mmc_send_ext_csd(mmc, test_csd);
> +
> + if (err)
> + continue;
> +
> /* Only compare read only fields */
> - if (!err && ext_csd[EXT_CSD_PARTITIONING_SUPPORT] \
> - == test_csd[EXT_CSD_PARTITIONING_SUPPORT]
> - && ext_csd[EXT_CSD_HC_WP_GRP_SIZE] \
> - == test_csd[EXT_CSD_HC_WP_GRP_SIZE] \
> - && ext_csd[EXT_CSD_REV] \
> - == test_csd[EXT_CSD_REV]
> - && ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] \
> - == test_csd[EXT_CSD_HC_ERASE_GRP_SIZE]
> - && memcmp(&ext_csd[EXT_CSD_SEC_CNT], \
> - &test_csd[EXT_CSD_SEC_CNT], 4) == 0) {
> -
> - mmc->card_caps |= ext_to_hostcaps[extw];
> + if (ext_csd[EXT_CSD_PARTITIONING_SUPPORT]
> + == test_csd[EXT_CSD_PARTITIONING_SUPPORT] &&
> + ext_csd[EXT_CSD_HC_WP_GRP_SIZE]
> + == test_csd[EXT_CSD_HC_WP_GRP_SIZE] &&
> + ext_csd[EXT_CSD_REV]
> + == test_csd[EXT_CSD_REV] &&
> + ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]
> + == test_csd[EXT_CSD_HC_ERASE_GRP_SIZE] &&
> + memcmp(&ext_csd[EXT_CSD_SEC_CNT],
> + &test_csd[EXT_CSD_SEC_CNT], 4) == 0)
> break;
> - }
> + else
> + err = SWITCH_ERR;
> }
>
> + if (err)
> + return err;
> +
> if (mmc->card_caps & MMC_MODE_HS) {
> if (mmc->card_caps & MMC_MODE_HS_52MHz)
> mmc->tran_speed = 52000000;
> @@ -1299,6 +1308,7 @@ int mmc_start_init(struct mmc *mmc)
> if (err)
> return err;
>
> + mmc->ddr_mode = 0;
> mmc_set_bus_width(mmc, 1);
> mmc_set_clock(mmc, 1);
>
> diff --git a/include/mmc.h b/include/mmc.h
> index d74a190..9c6d792 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -314,6 +314,7 @@ struct mmc {
> char init_in_progress; /* 1 if we have done mmc_start_init() */
> char preinit; /* start init as early as possible */
> uint op_cond_response; /* the response byte from the last op_cond */
> + int ddr_mode;
> };
>
> int mmc_register(struct mmc *mmc);
> --
> 2.1.0
Applied, thanks.
— Pantelis
More information about the U-Boot
mailing list