[U-Boot] [PATCH v2 0/9] reduce the size of the mmc core

This series applies on u-boot/next
It aims at reducing the size taken by the mmc core in the SPL. Recent changes (for which I'm to blame) have bloated the mmc core and have broken platforms that were already tight on code space. This is achieved mostly by compiling out parts of the initialization process that are not required when the SD/MMC write operations are not used.
Using am335x_hs_evm_config and Linaro GCC 6.2-2016.11 toolchain, this series saves 624 bytes of sram (512 bytes of code and 112 bytes of rodata). This doesn't looks like much but it allows building the platform without removing features from its config file (tested with commit d2ac491 ("am335x_hs_evm: Trim options in SPL to reduce binary size") reverted)
Changes in v2: - atmel_mci: fixed v1 bug by setting the block length before each transfer. - atmel_mci: removed loop to read/write dummy data as it is not needed anymore - compile out code for HS200 in mmc_get_capabilities() - fixed usage of CONFIG_IS_ENABLED() in the definition of mmc_blk_ops - default SPL_MMC_WRITE to 'n' - removed patch 'mmc: remove unneeded verification in mmc_set_card_speed()'
Jean-Jacques Hiblot (9): common: do not compile common fastboot code when building the SPL mmc: atmel: when sending a data command, use the provided block size mmc: compile out more code if support for UHS and HS200 is not enabled mmc: reworked version lookup in mmc_startup_v4 mmc: add a Kconfig option to enable the support for MMC write operations mmc: read ssr only if MMC write support is enabled mmc: compile out erase and write mmc commands if write operations are not enabled mmc: don't read the size of eMMC enhanced user data area in SPL mmc: remove hc_wp_grp_size from struct mmc if not needed
cmd/mmc.c | 10 +++++ cmd/mvebu/bubt.c | 2 +- common/Makefile | 2 + common/spl/Kconfig | 9 +++++ drivers/mmc/Kconfig | 7 ++++ drivers/mmc/Makefile | 4 +- drivers/mmc/gen_atmel_mci.c | 42 +++++++++---------- drivers/mmc/mmc-uclass.c | 2 +- drivers/mmc/mmc.c | 99 +++++++++++++++++++++++++++------------------ drivers/mmc/mmc_private.h | 4 +- include/mmc.h | 8 ++++ 11 files changed, 121 insertions(+), 68 deletions(-)

This is not required as fastboot can't be started from SPL.
Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com ---
Changes in v2: None
common/Makefile | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/common/Makefile b/common/Makefile index 1416620..c7bde23 100644 --- a/common/Makefile +++ b/common/Makefile @@ -109,6 +109,7 @@ obj-$(CONFIG_IO_TRACE) += iotrace.o obj-y += memsize.o obj-y += stdio.o
+ifndef CONFIG_SPL_BUILD # This option is not just y/n - it can have a numeric value ifdef CONFIG_FASTBOOT_FLASH obj-y += image-sparse.o @@ -119,6 +120,7 @@ ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV obj-y += fb_nand.o endif endif +endif
ifdef CONFIG_CMD_EEPROM_LAYOUT obj-y += eeprom/eeprom_field.o eeprom/eeprom_layout.o

struct mmc_data contains the block size to use for the data transfer. Use this information instead of using the default value or the block length information stored in struct mmc.
Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com
--- Tested on a SAM9x35-EK
Changes in v2: - atmel_mci: fixed v1 bug by setting the block length before each transfer. - atmel_mci: removed loop to read/write dummy data as it is not needed anymore
drivers/mmc/gen_atmel_mci.c | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-)
diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c index 22154d1..1c108b5 100644 --- a/drivers/mmc/gen_atmel_mci.c +++ b/drivers/mmc/gen_atmel_mci.c @@ -74,6 +74,20 @@ static void dump_cmd(u32 cmdr, u32 arg, u32 status, const char* msg) cmdr, cmdr & 0x3F, arg, status, msg); }
+static inline void mci_set_blklen(atmel_mci_t *mci, int blklen) +{ + unsigned int version = atmel_mci_get_version(mci); + + blklen &= 0xfffc; + + /* MCI IP version >= 0x200 has blkr */ + if (version >= 0x200) + writel(MMCI_BFINS(BLKLEN, blklen, readl(&mci->blkr)), + &mci->blkr); + else + writel(MMCI_BFINS(BLKLEN, blklen, readl(&mci->mr)), &mci->mr); +} + /* Setup for MCI Clock and Block Size */ #ifdef CONFIG_DM_MMC static void mci_set_mode(struct udevice *dev, u32 hz, u32 blklen) @@ -124,7 +138,6 @@ static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen) priv->curr_clk = bus_hz / (clkdiv * 2 + clkodd + 2); else priv->curr_clk = (bus_hz / (clkdiv + 1)) / 2; - blklen &= 0xfffc;
mr = MMCI_BF(CLKDIV, clkdiv);
@@ -138,14 +151,10 @@ static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen) */ if (version >= 0x500) mr |= MMCI_BF(CLKODD, clkodd); - else - mr |= MMCI_BF(BLKLEN, blklen);
writel(mr, &mci->mr);
- /* MCI IP version >= 0x200 has blkr */ - if (version >= 0x200) - writel(MMCI_BF(BLKLEN, blklen), &mci->blkr); + mci_set_blklen(mci, blklen);
if (mmc->card_caps & mmc->cfg->host_caps & MMC_MODE_HS) writel(MMCI_BIT(HSMODE), &mci->cfg); @@ -236,7 +245,6 @@ static int atmel_mci_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, { struct atmel_mci_plat *plat = dev_get_platdata(dev); struct atmel_mci_priv *priv = dev_get_priv(dev); - struct mmc *mmc = mmc_get_mmc_dev(dev); atmel_mci_t *mci = plat->mci; #else static int @@ -257,11 +265,13 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) /* Figure out the transfer arguments */ cmdr = mci_encode_cmd(cmd, data, &error_flags);
+ mci_set_blklen(mci, data->blocksize); + /* For multi blocks read/write, set the block register */ if ((cmd->cmdidx == MMC_CMD_READ_MULTIPLE_BLOCK) || (cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK)) - writel(data->blocks | MMCI_BF(BLKLEN, mmc->read_bl_len), - &mci->blkr); + writel(data->blocks | MMCI_BF(BLKLEN, data->blocksize), + &mci->blkr);
/* Send the command */ writel(cmd->cmdarg, &mci->argr); @@ -295,17 +305,15 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) if (data) { u32 word_count, block_count; u32* ioptr; - u32 sys_blocksize, dummy, i; + u32 i; u32 (*mci_data_op) (atmel_mci_t *mci, u32* data, u32 error_flags);
if (data->flags & MMC_DATA_READ) { mci_data_op = mci_data_read; - sys_blocksize = mmc->read_bl_len; ioptr = (u32*)data->dest; } else { mci_data_op = mci_data_write; - sys_blocksize = mmc->write_bl_len; ioptr = (u32*)data->src; }
@@ -328,16 +336,6 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) 1, cnt, 0); } #endif -#ifdef DEBUG - if (!status && word_count < (sys_blocksize / 4)) - printf("filling rest of block...\n"); -#endif - /* fill the rest of a full block */ - while (!status && word_count < (sys_blocksize / 4)) { - status = mci_data_op(mci, &dummy, - error_flags); - word_count++; - } if (status) { dump_cmd(cmdr, cmd->cmdarg, status, "Data Transfer Failed");

Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com
---
Changes in v2: - compile out code for HS200 in mmc_get_capabilities()
drivers/mmc/mmc.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 67d05c5..18d202d 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -799,9 +799,11 @@ static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode) case MMC_DDR_52: speed_bits = EXT_CSD_TIMING_HS; break; +#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) case MMC_HS_200: speed_bits = EXT_CSD_TIMING_HS200; break; +#endif case MMC_LEGACY: speed_bits = EXT_CSD_TIMING_LEGACY; break; @@ -851,10 +853,12 @@ static int mmc_get_capabilities(struct mmc *mmc) cardtype = ext_csd[EXT_CSD_CARD_TYPE] & 0x3f; mmc->cardtype = cardtype;
+#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) if (cardtype & (EXT_CSD_CARD_TYPE_HS200_1_2V | EXT_CSD_CARD_TYPE_HS200_1_8V)) { mmc->card_caps |= MMC_MODE_HS200; } +#endif if (cardtype & EXT_CSD_CARD_TYPE_52) { if (cardtype & EXT_CSD_CARD_TYPE_DDR_52) mmc->card_caps |= MMC_MODE_DDR_52MHz; @@ -1307,10 +1311,15 @@ static int sd_set_card_speed(struct mmc *mmc, enum bus_mode mode)
switch (mode) { case SD_LEGACY: - case UHS_SDR12: speed = UHS_SDR12_BUS_SPEED; break; case SD_HS: + speed = HIGH_SPEED_BUS_SPEED; + break; +#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) + case UHS_SDR12: + speed = UHS_SDR12_BUS_SPEED; + break; case UHS_SDR25: speed = UHS_SDR25_BUS_SPEED; break; @@ -1323,6 +1332,7 @@ static int sd_set_card_speed(struct mmc *mmc, enum bus_mode mode) case UHS_SDR104: speed = UHS_SDR104_BUS_SPEED; break; +#endif default: return -EINVAL; }

Using a table versus a switch() structure saves a bit of space
Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com ---
Changes in v2: None
drivers/mmc/mmc.c | 42 +++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 25 deletions(-)
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 18d202d..5255c0d 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1940,6 +1940,17 @@ static int mmc_startup_v4(struct mmc *mmc) u64 capacity; bool has_parts = false; bool part_completed; + static const u32 mmc_versions[] = { + MMC_VERSION_4, + MMC_VERSION_4_1, + MMC_VERSION_4_2, + MMC_VERSION_4_3, + MMC_VERSION_4_41, + MMC_VERSION_4_5, + MMC_VERSION_5_0, + MMC_VERSION_5_1 + }; + ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
if (IS_SD(mmc) || (mmc->version < MMC_VERSION_4)) @@ -1957,7 +1968,12 @@ static int mmc_startup_v4(struct mmc *mmc) return -ENOMEM; memcpy(mmc->ext_csd, ext_csd, MMC_MAX_BLOCK_LEN);
- if (ext_csd[EXT_CSD_REV] >= 2) { + if (ext_csd[EXT_CSD_REV] > ARRAY_SIZE(mmc_versions)) + return -EINVAL; + + mmc->version = mmc_versions[ext_csd[EXT_CSD_REV]]; + + if (mmc->version >= MMC_VERSION_4_2) { /* * According to the JEDEC Standard, the value of * ext_csd's capacity is valid if the value is more @@ -1972,30 +1988,6 @@ static int mmc_startup_v4(struct mmc *mmc) mmc->capacity_user = capacity; }
- switch (ext_csd[EXT_CSD_REV]) { - case 1: - mmc->version = MMC_VERSION_4_1; - break; - case 2: - mmc->version = MMC_VERSION_4_2; - break; - case 3: - mmc->version = MMC_VERSION_4_3; - break; - case 5: - mmc->version = MMC_VERSION_4_41; - break; - case 6: - mmc->version = MMC_VERSION_4_5; - break; - case 7: - mmc->version = MMC_VERSION_5_0; - break; - case 8: - mmc->version = MMC_VERSION_5_1; - break; - } - /* The partition data may be non-zero but it is only * effective if PARTITION_SETTING_COMPLETED is set in * EXT_CSD, so ignore any data if this bit is not set,

This allows using CONFIG_IS_ENABLED(MMC_WRITE) to compile out code needed only if write support is required. The option is added for u-boot and for SPL
Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com
---
Changes in v2: - fixed usage of CONFIG_IS_ENABLED() in the definition of mmc_blk_ops - default SPL_MMC_WRITE to 'n'
cmd/mvebu/bubt.c | 2 +- common/spl/Kconfig | 9 +++++++++ drivers/mmc/Kconfig | 7 +++++++ drivers/mmc/Makefile | 4 +--- drivers/mmc/mmc-uclass.c | 2 +- drivers/mmc/mmc_private.h | 4 ++-- 6 files changed, 21 insertions(+), 7 deletions(-)
diff --git a/cmd/mvebu/bubt.c b/cmd/mvebu/bubt.c index a1997ac..23fb8cd 100644 --- a/cmd/mvebu/bubt.c +++ b/cmd/mvebu/bubt.c @@ -110,7 +110,7 @@ static ulong get_load_addr(void) /******************************************************************** * eMMC services ********************************************************************/ -#ifdef CONFIG_DM_MMC +#if CONFIG_IS_ENABLED(DM_MMC) && CONFIG_IS_ENABLED(MMC_WRITE) static int mmc_burn_image(size_t image_size) { struct mmc *mmc; diff --git a/common/spl/Kconfig b/common/spl/Kconfig index aef0034..0c50f92 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -301,6 +301,7 @@ config SPL_ENV_SUPPORT config SPL_SAVEENV bool "Support save environment" depends on SPL_ENV_SUPPORT + select SPL_MMC_WRITE if ENV_IS_IN_MMC help Enable save environment support in SPL after setenv. By default the saveenv option is not provided in SPL, but some boards need @@ -415,6 +416,14 @@ config SPL_MMC_SUPPORT this option to build the drivers in drivers/mmc as part of an SPL build.
+config SPL_MMC_WRITE + bool "MMC/SD/SDIO card support for write operations in SPL" + depends on SPL_MMC_SUPPORT + default n + help + Enable write access to MMC and SD Cards in SPL + + config SPL_MPC8XXX_INIT_DDR_SUPPORT bool "Support MPC8XXX DDR init" help diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index d196eed..ab0627a 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -10,6 +10,13 @@ config MMC If you want MMC/SD/SDIO support, you should say Y here and also to your specific host controller driver.
+config MMC_WRITE + bool "support for MMC/SD write operations" + depends on MMC + default y + help + Enable write access to MMC and SD Cards + config DM_MMC bool "Enable MMC controllers using Driver Model" depends on DM diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 9af375b..64b6f21 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -7,6 +7,7 @@
obj-y += mmc.o obj-$(CONFIG_$(SPL_)DM_MMC) += mmc-uclass.o +obj-$(CONFIG_$(SPL_)MMC_WRITE) += mmc_write.o
ifndef CONFIG_$(SPL_)BLK obj-y += mmc_legacy.o @@ -16,9 +17,6 @@ obj-$(CONFIG_SUPPORT_EMMC_BOOT) += mmc_boot.o
ifdef CONFIG_SPL_BUILD obj-$(CONFIG_SPL_MMC_BOOT) += fsl_esdhc_spl.o -obj-$(CONFIG_SPL_SAVEENV) += mmc_write.o -else -obj-y += mmc_write.o endif
obj-$(CONFIG_ARM_PL180_MMCI) += arm_pl180_mmci.o diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c index 793196b..26c6ab7 100644 --- a/drivers/mmc/mmc-uclass.c +++ b/drivers/mmc/mmc-uclass.c @@ -370,7 +370,7 @@ static int mmc_blk_probe(struct udevice *dev)
static const struct blk_ops mmc_blk_ops = { .read = mmc_bread, -#ifndef CONFIG_SPL_BUILD +#if CONFIG_IS_ENABLED(MMC_WRITE) .write = mmc_bwrite, .erase = mmc_berase, #endif diff --git a/drivers/mmc/mmc_private.h b/drivers/mmc/mmc_private.h index 1290eed..a9be4b0 100644 --- a/drivers/mmc/mmc_private.h +++ b/drivers/mmc/mmc_private.h @@ -28,7 +28,7 @@ ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, void *dst); #endif
-#if !(defined(CONFIG_SPL_BUILD) && !defined(CONFIG_SPL_SAVEENV)) +#if CONFIG_IS_ENABLED(MMC_WRITE)
#if CONFIG_IS_ENABLED(BLK) ulong mmc_bwrite(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, @@ -40,7 +40,7 @@ ulong mmc_bwrite(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, ulong mmc_berase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt); #endif
-#else /* CONFIG_SPL_BUILD and CONFIG_SPL_SAVEENV is not defined */ +#else /* CONFIG_SPL_MMC_WRITE is not defined */
/* declare dummies to reduce code size. */

The content of ssr is useful only for erase operations. on ARM, removing sd_read_ssr() saves around 300 bytes.
Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com ---
Changes in v2: None
drivers/mmc/mmc.c | 25 ++++++++++++++----------- include/mmc.h | 2 ++ 2 files changed, 16 insertions(+), 11 deletions(-)
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 5255c0d..fd94987 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -22,14 +22,6 @@ #include <div64.h> #include "mmc_private.h"
-static const unsigned int sd_au_size[] = { - 0, SZ_16K / 512, SZ_32K / 512, - SZ_64K / 512, SZ_128K / 512, SZ_256K / 512, - SZ_512K / 512, SZ_1M / 512, SZ_2M / 512, - SZ_4M / 512, SZ_8M / 512, (SZ_8M + SZ_4M) / 512, - SZ_16M / 512, (SZ_16M + SZ_8M) / 512, SZ_32M / 512, SZ_64M / 512, -}; - static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage); static int mmc_power_cycle(struct mmc *mmc); static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps); @@ -1376,8 +1368,17 @@ int sd_select_bus_width(struct mmc *mmc, int w) return 0; }
+#if CONFIG_IS_ENABLED(MMC_WRITE) static int sd_read_ssr(struct mmc *mmc) { + static const unsigned int sd_au_size[] = { + 0, SZ_16K / 512, SZ_32K / 512, + SZ_64K / 512, SZ_128K / 512, SZ_256K / 512, + SZ_512K / 512, SZ_1M / 512, SZ_2M / 512, + SZ_4M / 512, SZ_8M / 512, (SZ_8M + SZ_4M) / 512, + SZ_16M / 512, (SZ_16M + SZ_8M) / 512, SZ_32M / 512, + SZ_64M / 512, + }; int err, i; struct mmc_cmd cmd; ALLOC_CACHE_ALIGN_BUFFER(uint, ssr, 16); @@ -1431,7 +1432,7 @@ retry_ssr:
return 0; } - +#endif /* frequency bases */ /* divided by 10 to be nice to platforms without floating point */ static const int fbase[] = { @@ -1689,12 +1690,14 @@ static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps) } #endif
+#if CONFIG_IS_ENABLED(MMC_WRITE) err = sd_read_ssr(mmc); if (!err) + pr_warn("unable to read ssr\n"); +#endif + if (!err) return 0;
- pr_warn("bad ssr\n"); - error: /* revert to a safer bus speed */ mmc_select_mode(mmc, SD_LEGACY); diff --git a/include/mmc.h b/include/mmc.h index e89ba95..f50c714 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -588,7 +588,9 @@ struct mmc { uint write_bl_len; uint erase_grp_size; /* in 512-byte sectors */ uint hc_wp_grp_size; /* in 512-byte sectors */ +#if CONFIG_IS_ENABLED(MMC_WRITE) struct sd_ssr ssr; /* SD status register */ +#endif u64 capacity; u64 capacity_user; u64 capacity_boot;

Also remove erase_grp_size and write_bl_len from struct mmc as they are not used anymore. On ARM, removing them saves about 100 bytes of code space in SPL.
Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com ---
Changes in v2: None
cmd/mmc.c | 8 ++++++++ drivers/mmc/mmc.c | 16 ++++++++++++++-- include/mmc.h | 2 ++ 3 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/cmd/mmc.c b/cmd/mmc.c index 9a95293..65601d8 100644 --- a/cmd/mmc.c +++ b/cmd/mmc.c @@ -45,8 +45,10 @@ static void print_mmcinfo(struct mmc *mmc) printf("Bus Width: %d-bit%s\n", mmc->bus_width, mmc->ddr_mode ? " DDR" : "");
+#if CONFIG_IS_ENABLED(MMC_WRITE) puts("Erase Group Size: "); print_size(((u64)mmc->erase_grp_size) << 9, "\n"); +#endif
if (!IS_SD(mmc) && mmc->version >= MMC_VERSION_4_41) { bool has_enh = (mmc->part_support & ENHNCD_SUPPORT) != 0; @@ -302,6 +304,8 @@ static int do_mmc_read(cmd_tbl_t *cmdtp, int flag,
return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE; } + +#if CONFIG_IS_ENABLED(MMC_WRITE) static int do_mmc_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { @@ -360,6 +364,8 @@ static int do_mmc_erase(cmd_tbl_t *cmdtp, int flag,
return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE; } +#endif + static int do_mmc_rescan(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { @@ -792,8 +798,10 @@ static int do_mmc_bkops_enable(cmd_tbl_t *cmdtp, int flag, static cmd_tbl_t cmd_mmc[] = { U_BOOT_CMD_MKENT(info, 1, 0, do_mmcinfo, "", ""), U_BOOT_CMD_MKENT(read, 4, 1, do_mmc_read, "", ""), +#if CONFIG_IS_ENABLED(MMC_WRITE) U_BOOT_CMD_MKENT(write, 4, 0, do_mmc_write, "", ""), U_BOOT_CMD_MKENT(erase, 3, 0, do_mmc_erase, "", ""), +#endif U_BOOT_CMD_MKENT(rescan, 1, 1, do_mmc_rescan, "", ""), U_BOOT_CMD_MKENT(part, 1, 1, do_mmc_part, "", ""), U_BOOT_CMD_MKENT(dev, 3, 0, do_mmc_dev, "", ""), diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index fd94987..3930aad 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -2066,9 +2066,11 @@ static int mmc_startup_v4(struct mmc *mmc) }
if (ext_csd[EXT_CSD_ERASE_GROUP_DEF] & 0x01) { +#if CONFIG_IS_ENABLED(MMC_WRITE) /* Read out group size from ext_csd */ mmc->erase_grp_size = ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * 1024; +#endif /* * if high capacity and partition setting completed * SEC_COUNT is valid even if it is smaller than 2 GiB @@ -2082,7 +2084,9 @@ static int mmc_startup_v4(struct mmc *mmc) capacity *= MMC_MAX_BLOCK_LEN; mmc->capacity_user = capacity; } - } else { + } +#if CONFIG_IS_ENABLED(MMC_WRITE) + else { /* Calculate the group size from the csd value. */ int erase_gsz, erase_gmul;
@@ -2091,7 +2095,7 @@ static int mmc_startup_v4(struct mmc *mmc) mmc->erase_grp_size = (erase_gsz + 1) * (erase_gmul + 1); } - +#endif mmc->hc_wp_grp_size = 1024 * ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * ext_csd[EXT_CSD_HC_WP_GRP_SIZE]; @@ -2222,11 +2226,13 @@ static int mmc_startup(struct mmc *mmc)
mmc->dsr_imp = ((cmd.response[1] >> 12) & 0x1); mmc->read_bl_len = 1 << ((cmd.response[1] >> 16) & 0xf); +#if CONFIG_IS_ENABLED(MMC_WRITE)
if (IS_SD(mmc)) mmc->write_bl_len = mmc->read_bl_len; else mmc->write_bl_len = 1 << ((cmd.response[3] >> 22) & 0xf); +#endif
if (mmc->high_capacity) { csize = (mmc->csd[1] & 0x3f) << 16 @@ -2248,8 +2254,10 @@ static int mmc_startup(struct mmc *mmc) if (mmc->read_bl_len > MMC_MAX_BLOCK_LEN) mmc->read_bl_len = MMC_MAX_BLOCK_LEN;
+#if CONFIG_IS_ENABLED(MMC_WRITE) if (mmc->write_bl_len > MMC_MAX_BLOCK_LEN) mmc->write_bl_len = MMC_MAX_BLOCK_LEN; +#endif
if ((mmc->dsr_imp) && (0xffffffff != mmc->dsr)) { cmd.cmdidx = MMC_CMD_SET_DSR; @@ -2273,7 +2281,9 @@ static int mmc_startup(struct mmc *mmc) /* * For SD, its erase group is always one sector */ +#if CONFIG_IS_ENABLED(MMC_WRITE) mmc->erase_grp_size = 1; +#endif mmc->part_config = MMCPART_NOAVAILABLE;
err = mmc_startup_v4(mmc); @@ -2304,7 +2314,9 @@ static int mmc_startup(struct mmc *mmc) /* Fix the block length for DDR mode */ if (mmc->ddr_mode) { mmc->read_bl_len = MMC_MAX_BLOCK_LEN; +#if CONFIG_IS_ENABLED(MMC_WRITE) mmc->write_bl_len = MMC_MAX_BLOCK_LEN; +#endif }
/* fill in device description */ diff --git a/include/mmc.h b/include/mmc.h index f50c714..3abeb58 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -585,8 +585,10 @@ struct mmc { uint tran_speed; uint legacy_speed; /* speed for the legacy mode provided by the card */ uint read_bl_len; +#if CONFIG_IS_ENABLED(MMC_WRITE) uint write_bl_len; uint erase_grp_size; /* in 512-byte sectors */ +#endif uint hc_wp_grp_size; /* in 512-byte sectors */ #if CONFIG_IS_ENABLED(MMC_WRITE) struct sd_ssr ssr; /* SD status register */

This information is only used by the "mmc info" command. On ARM removing this information from SPL saves about 140 of code space.
Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com ---
Changes in v2: None
drivers/mmc/mmc.c | 2 ++ include/mmc.h | 2 ++ 2 files changed, 4 insertions(+)
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 3930aad..c1ba57f 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -2028,6 +2028,7 @@ static int mmc_startup_v4(struct mmc *mmc) mmc->capacity_gp[i] <<= 19; }
+#ifndef CONFIG_SPL_BUILD if (part_completed) { mmc->enh_user_size = (ext_csd[EXT_CSD_ENH_SIZE_MULT + 2] << 16) + @@ -2044,6 +2045,7 @@ static int mmc_startup_v4(struct mmc *mmc) if (mmc->high_capacity) mmc->enh_user_start <<= 9; } +#endif
/* * Host needs to enable ERASE_GRP_DEF bit if device is diff --git a/include/mmc.h b/include/mmc.h index 3abeb58..cd068b9 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -598,8 +598,10 @@ struct mmc { u64 capacity_boot; u64 capacity_rpmb; u64 capacity_gp[4]; +#ifndef CONFIG_SPL_BUILD u64 enh_user_start; u64 enh_user_size; +#endif #if !CONFIG_IS_ENABLED(BLK) struct blk_desc block_dev; #endif

hc_wp_grp_size is needed only if hardware partitionning is used. On ARM removing it saves about 30 bytes of code space.
Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com
---
Changes in v2: - removed patch 'mmc: remove unneeded verification in mmc_set_card_speed()'
cmd/mmc.c | 2 ++ drivers/mmc/mmc.c | 2 ++ include/mmc.h | 2 ++ 3 files changed, 6 insertions(+)
diff --git a/cmd/mmc.c b/cmd/mmc.c index 65601d8..58fdc36 100644 --- a/cmd/mmc.c +++ b/cmd/mmc.c @@ -54,8 +54,10 @@ static void print_mmcinfo(struct mmc *mmc) bool has_enh = (mmc->part_support & ENHNCD_SUPPORT) != 0; bool usr_enh = has_enh && (mmc->part_attr & EXT_CSD_ENH_USR);
+#if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING) puts("HC WP Group Size: "); print_size(((u64)mmc->hc_wp_grp_size) << 9, "\n"); +#endif
puts("User Capacity: "); print_size(mmc->capacity_user, usr_enh ? " ENH" : ""); diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index c1ba57f..53c8191 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -2098,9 +2098,11 @@ static int mmc_startup_v4(struct mmc *mmc) * (erase_gmul + 1); } #endif +#if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING) mmc->hc_wp_grp_size = 1024 * ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * ext_csd[EXT_CSD_HC_WP_GRP_SIZE]; +#endif
mmc->wr_rel_set = ext_csd[EXT_CSD_WR_REL_SET];
diff --git a/include/mmc.h b/include/mmc.h index cd068b9..a46eaed 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -589,7 +589,9 @@ struct mmc { uint write_bl_len; uint erase_grp_size; /* in 512-byte sectors */ #endif +#if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING) uint hc_wp_grp_size; /* in 512-byte sectors */ +#endif #if CONFIG_IS_ENABLED(MMC_WRITE) struct sd_ssr ssr; /* SD status register */ #endif

On Thu, 2018-01-04 at 15:23 +0100, Jean-Jacques Hiblot wrote:
CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you recognize the sender and know the content is safe.
This series applies on u-boot/next
It aims at reducing the size taken by the mmc core in the SPL. Recent changes (for which I'm to blame) have bloated the mmc core and have broken platforms that were already tight on code space. This is achieved mostly by compiling out parts of the initialization process that are not required when the SD/MMC write operations are not used.
I have not looked at the code so maybe this off ...
You can save a lot of space/code if you avoid static/global variables. Instead of #define MYSTR "some cool feature" static char *mystr = MYSTR; do fun() { char *mystr = MYSTR; ... }
Avoid static/global vars at all cost!
Jocke

On 01/04/2018 11:23 PM, Jean-Jacques Hiblot wrote:
This series applies on u-boot/next
It aims at reducing the size taken by the mmc core in the SPL. Recent changes (for which I'm to blame) have bloated the mmc core and have broken platforms that were already tight on code space. This is achieved mostly by compiling out parts of the initialization process that are not required when the SD/MMC write operations are not used.
Using am335x_hs_evm_config and Linaro GCC 6.2-2016.11 toolchain, this series saves 624 bytes of sram (512 bytes of code and 112 bytes of rodata). This doesn't looks like much but it allows building the platform without removing features from its config file (tested with commit d2ac491 ("am335x_hs_evm: Trim options in SPL to reduce binary size") reverted)
Changes in v2:
- atmel_mci: fixed v1 bug by setting the block length before each transfer.
- atmel_mci: removed loop to read/write dummy data as it is not needed anymore
- compile out code for HS200 in mmc_get_capabilities()
- fixed usage of CONFIG_IS_ENABLED() in the definition of mmc_blk_ops
- default SPL_MMC_WRITE to 'n'
- removed patch 'mmc: remove unneeded verification in mmc_set_card_speed()'
Jean-Jacques Hiblot (9): common: do not compile common fastboot code when building the SPL mmc: atmel: when sending a data command, use the provided block size mmc: compile out more code if support for UHS and HS200 is not enabled mmc: reworked version lookup in mmc_startup_v4 mmc: add a Kconfig option to enable the support for MMC write operations mmc: read ssr only if MMC write support is enabled mmc: compile out erase and write mmc commands if write operations are not enabled mmc: don't read the size of eMMC enhanced user data area in SPL mmc: remove hc_wp_grp_size from struct mmc if not needed
Applied to u-boot-mmc. Thanks!
Best Regards, Jaehoon Chung
cmd/mmc.c | 10 +++++ cmd/mvebu/bubt.c | 2 +- common/Makefile | 2 + common/spl/Kconfig | 9 +++++ drivers/mmc/Kconfig | 7 ++++ drivers/mmc/Makefile | 4 +- drivers/mmc/gen_atmel_mci.c | 42 +++++++++---------- drivers/mmc/mmc-uclass.c | 2 +- drivers/mmc/mmc.c | 99 +++++++++++++++++++++++++++------------------ drivers/mmc/mmc_private.h | 4 +- include/mmc.h | 8 ++++ 11 files changed, 121 insertions(+), 68 deletions(-)
participants (3)
-
Jaehoon Chung
-
Jean-Jacques Hiblot
-
Joakim Tjernlund