[U-Boot] [PATCH] mmc: add setdsr support
Pantelis Antoniou
panto at antoniou-consulting.com
Mon Dec 16 15:46:13 CET 2013
Hi Markus,
On Dec 16, 2013, at 4:52 PM, Markus Niebel wrote:
> From: Markus Niebel <Markus.Niebel at tqs.de>
>
> The eMMC and the SD-Card specifications describe the optional SET_DSR command.
> During measurements at our lab we found that some cards implementing this feature
> having really strong driver strengts per default. This can lead to voltage peaks
> above the specification of the host on signal edges for data sent from a card to
> the host.
>
> Since availability of a given card type may be shorter than the time a certain
> hardware will be produced it is useful to have support for this command (Alternative
> would be changing termination resistors and adapting the driver strength of the
> host to the used card.)
>
> Following proposal for an implementation:
>
> - new field that reflects CSD field DSR_IMP in struct mmc
> - new field for design specific DSR value in struct mmc
> - board code can set DSR value in mmc struct just after registering an controller
> - mmc_startup sends the the stored DSR value before selecting a card, if DSR_IMP is set
>
> Additionally the mmc command is extended to make is possible to play around with different
> DSR values.
>
> The concept was tested on a i.MX53 based platform using a Micron eMMC card where the default
> DSR is 0x0400 (12mA) but in our design 0x0100 (0x0100) were enough. To use this feature for
> instance on a mx53loco one have to add a call to mmc_set_dsr() in board_mmc_init() after
> calling fsl_esdhc_initialize() for the eMMC.
>
> Signed-off-by: Markus Niebel <Markus.Niebel at tqs.de>
> ---
> changes for V2:
> - extend documentation according to the comments from Pantelis Antoniou
> changes for V3:
> - correct formatting of if condition in mmc_startup as sugested by Pantelis Antoniou
> the stray new line comment for V1 of patch is left as is since the patch doesn't
> bring in an new line. (simply overlooked the comments, sorry for that)
>
> common/cmd_mmc.c | 23 +++++++++++++++++++++++
> drivers/mmc/mmc.c | 18 ++++++++++++++++++
> include/mmc.h | 3 +++
> 3 files changed, 44 insertions(+)
>
> diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c
> index 67a94a7..da5fef9 100644
> --- a/common/cmd_mmc.c
> +++ b/common/cmd_mmc.c
> @@ -340,6 +340,28 @@ static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> }
> #endif /* CONFIG_SUPPORT_EMMC_BOOT */
> }
> +
> + else if (argc == 3 && strcmp(argv[1], "setdsr") == 0) {
> + struct mmc *mmc = find_mmc_device(curr_device);
> + u32 val = simple_strtoul(argv[2], NULL, 16);
> + int ret;
> +
> + if (!mmc) {
> + printf("no mmc device at slot %x\n", curr_device);
> + return 1;
> + }
> + ret = mmc_set_dsr(mmc, val);
> + printf("set dsr %s\n", (!ret) ? "OK, force rescan" : "ERROR");
> + if (!ret) {
> + mmc->has_init = 0;
> + if (mmc_init(mmc))
> + return 1;
> + else
> + return 0;
> + }
> + return ret;
> + }
> +
> state = MMC_INVALID;
> if (argc == 5 && strcmp(argv[1], "read") == 0)
> state = MMC_READ;
> @@ -423,5 +445,6 @@ U_BOOT_CMD(
> "mmc bootpart <device num> <boot part size MB> <RPMB part size MB>\n"
> " - change sizes of boot and RPMB partitions of specified device\n"
> #endif
> + "mmc setdsr - set DSR register value\n"
> );
> #endif /* !CONFIG_GENERIC_MMC */
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index e1461a9..85eb89c 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -877,6 +877,7 @@ static int mmc_startup(struct mmc *mmc)
>
> mmc->tran_speed = freq * mult;
>
> + mmc->dsr_imp = ((cmd.response[1] >> 12) & 0x1);
> mmc->read_bl_len = 1 << ((cmd.response[1] >> 16) & 0xf);
>
> if (IS_SD(mmc))
> @@ -907,6 +908,14 @@ static int mmc_startup(struct mmc *mmc)
> if (mmc->write_bl_len > MMC_MAX_BLOCK_LEN)
> mmc->write_bl_len = MMC_MAX_BLOCK_LEN;
>
> + if (mmc->dsr_imp && mmc->dsr != 0xffffffff) {
> + cmd.cmdidx = MMC_CMD_SET_DSR;
> + cmd.cmdarg = (mmc->dsr & 0xffff) << 16;
> + cmd.resp_type = MMC_RSP_NONE;
> + if (mmc_send_cmd(mmc, &cmd, NULL))
> + printf("MMC: SET_DSR failed\n");
> + }
> +
> /* Select the card, and put it into Transfer Mode */
> if (!mmc_host_is_spi(mmc)) { /* cmd not supported in spi */
> cmd.cmdidx = MMC_CMD_SELECT_CARD;
> @@ -1163,6 +1172,9 @@ static int mmc_send_if_cond(struct mmc *mmc)
>
> int mmc_register(struct mmc *mmc)
> {
> + /* Setup dsr related values */
> + mmc->dsr_imp = 0;
> + mmc->dsr = 0xffffffff;
> /* Setup the universal parts of the block interface just once */
> mmc->block_dev.if_type = IF_TYPE_MMC;
> mmc->block_dev.dev = cur_dev_num++;
> @@ -1280,6 +1292,12 @@ int mmc_init(struct mmc *mmc)
> return err;
> }
>
> +int mmc_set_dsr(struct mmc *mmc, u16 val)
> +{
> + mmc->dsr = val;
> + return 0;
> +}
> +
> /*
> * CPU and board-specific MMC initializations. Aliased function
> * signals caller to move on
> diff --git a/include/mmc.h b/include/mmc.h
> index cb558da..facb819 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -262,6 +262,8 @@ struct mmc {
> uint card_caps;
> uint host_caps;
> uint ocr;
> + uint dsr;
> + uint dsr_imp;
> uint scr[2];
> uint csd[4];
> uint cid[4];
> @@ -304,6 +306,7 @@ int board_mmc_getcd(struct mmc *mmc);
> int mmc_switch_part(int dev_num, unsigned int part_num);
> int mmc_getcd(struct mmc *mmc);
> int mmc_getwp(struct mmc *mmc);
> +int mmc_set_dsr(struct mmc *mmc, u16 val);
> void spl_mmc_load(void) __noreturn;
> /* Function to change the size of boot partition and rpmb partitions */
> int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
> --
> 1.7.9.5
>
Acked-by: Pantelis Antoniou <panto at antoniou-consulting.com>
Thanks
-- Pantelis
More information about the U-Boot
mailing list