Hi Paul,

On Sep 6, 2013, at 4:43 PM, Paul Burton wrote:

> For SPL builds this is just dead code since we'll only need to read.
> Eliminating it results in a significant size reduction for the SPL
> binary, which may be critical for certain platforms where the binary
> size is highly constrained.
> 
> Signed-off-by: Paul Burton <paul.bur...@imgtec.com>
> ---
> Changes in v2:
>  - Move the mmc_bwrite & mmc_berase functions to a new mmc_write.c
>    file which is only compiled for non-SPL builds, as per a request
>    from Pantelis Antoniou. This requires that a few formerly static
>    functions in mmc.c be accessible to the new file, so they are
>    declared in a new mmc_private.h header along with the write &
>    erase functions. For what it's worth I prefered v1, but hey ho.
> ---
> drivers/mmc/Makefile      |   2 +
> drivers/mmc/mmc.c         | 186 +--------------------------------------------
> drivers/mmc/mmc_private.h |  45 +++++++++++
> drivers/mmc/mmc_write.c   | 189 ++++++++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 240 insertions(+), 182 deletions(-)
> create mode 100644 drivers/mmc/mmc_private.h
> create mode 100644 drivers/mmc/mmc_write.c
> 
> diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
> index bedf833..06280d1 100644
> --- a/drivers/mmc/Makefile
> +++ b/drivers/mmc/Makefile
> @@ -34,6 +34,8 @@ COBJS-$(CONFIG_EXYNOS_DWMMC) += exynos_dw_mmc.o
> COBJS-$(CONFIG_ZYNQ_SDHCI) += zynq_sdhci.o
> ifdef CONFIG_SPL_BUILD
> COBJS-$(CONFIG_SPL_MMC_BOOT) += fsl_esdhc_spl.o
> +else
> +COBJS-$(CONFIG_GENERIC_MMC) += mmc_write.o
> endif
> 
> COBJS := $(COBJS-y)
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index 30a985b..666f77b 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -15,6 +15,7 @@
> #include <malloc.h>
> #include <linux/list.h>
> #include <div64.h>
> +#include "mmc_private.h"
> 
> /* Set block count limit because of 16 bit register limit on some hardware*/
> #ifndef CONFIG_SYS_MMC_MAX_BLK_COUNT
> @@ -52,8 +53,7 @@ int __board_mmc_getcd(struct mmc *mmc) {
> int board_mmc_getcd(struct mmc *mmc)__attribute__((weak,
>       alias("__board_mmc_getcd")));
> 
> -static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
> -                     struct mmc_data *data)
> +int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
> {
>       struct mmc_data backup;
>       int ret;
> @@ -114,7 +114,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd 
> *cmd,
>       return ret;
> }
> 
> -static int mmc_send_status(struct mmc *mmc, int timeout)
> +int mmc_send_status(struct mmc *mmc, int timeout)
> {
>       struct mmc_cmd cmd;
>       int err, retries = 5;
> @@ -162,7 +162,7 @@ static int mmc_send_status(struct mmc *mmc, int timeout)
>       return 0;
> }
> 
> -static int mmc_set_blocklen(struct mmc *mmc, int len)
> +int mmc_set_blocklen(struct mmc *mmc, int len)
> {
>       struct mmc_cmd cmd;
> 
> @@ -192,184 +192,6 @@ struct mmc *find_mmc_device(int dev_num)
>       return NULL;
> }
> 
> -static ulong mmc_erase_t(struct mmc *mmc, ulong start, lbaint_t blkcnt)
> -{
> -     struct mmc_cmd cmd;
> -     ulong end;
> -     int err, start_cmd, end_cmd;
> -
> -     if (mmc->high_capacity)
> -             end = start + blkcnt - 1;
> -     else {
> -             end = (start + blkcnt - 1) * mmc->write_bl_len;
> -             start *= mmc->write_bl_len;
> -     }
> -
> -     if (IS_SD(mmc)) {
> -             start_cmd = SD_CMD_ERASE_WR_BLK_START;
> -             end_cmd = SD_CMD_ERASE_WR_BLK_END;
> -     } else {
> -             start_cmd = MMC_CMD_ERASE_GROUP_START;
> -             end_cmd = MMC_CMD_ERASE_GROUP_END;
> -     }
> -
> -     cmd.cmdidx = start_cmd;
> -     cmd.cmdarg = start;
> -     cmd.resp_type = MMC_RSP_R1;
> -
> -     err = mmc_send_cmd(mmc, &cmd, NULL);
> -     if (err)
> -             goto err_out;
> -
> -     cmd.cmdidx = end_cmd;
> -     cmd.cmdarg = end;
> -
> -     err = mmc_send_cmd(mmc, &cmd, NULL);
> -     if (err)
> -             goto err_out;
> -
> -     cmd.cmdidx = MMC_CMD_ERASE;
> -     cmd.cmdarg = SECURE_ERASE;
> -     cmd.resp_type = MMC_RSP_R1b;
> -
> -     err = mmc_send_cmd(mmc, &cmd, NULL);
> -     if (err)
> -             goto err_out;
> -
> -     return 0;
> -
> -err_out:
> -#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
> -     puts("mmc erase failed\n");
> -#endif
> -     return err;
> -}
> -
> -static unsigned long
> -mmc_berase(int dev_num, lbaint_t start, lbaint_t blkcnt)
> -{
> -     int err = 0;
> -     struct mmc *mmc = find_mmc_device(dev_num);
> -     lbaint_t blk = 0, blk_r = 0;
> -     int timeout = 1000;
> -
> -     if (!mmc)
> -             return -1;
> -
> -#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
> -     if ((start % mmc->erase_grp_size) || (blkcnt % mmc->erase_grp_size))
> -             printf("\n\nCaution! Your devices Erase group is 0x%x\n"
> -                    "The erase range would be change to "
> -                    "0x" LBAF "~0x" LBAF "\n\n",
> -                    mmc->erase_grp_size, start & ~(mmc->erase_grp_size - 1),
> -                    ((start + blkcnt + mmc->erase_grp_size)
> -                    & ~(mmc->erase_grp_size - 1)) - 1);
> -#endif
> -
> -     while (blk < blkcnt) {
> -             blk_r = ((blkcnt - blk) > mmc->erase_grp_size) ?
> -                     mmc->erase_grp_size : (blkcnt - blk);
> -             err = mmc_erase_t(mmc, start + blk, blk_r);
> -             if (err)
> -                     break;
> -
> -             blk += blk_r;
> -
> -             /* Waiting for the ready status */
> -             if (mmc_send_status(mmc, timeout))
> -                     return 0;
> -     }
> -
> -     return blk;
> -}
> -
> -static ulong
> -mmc_write_blocks(struct mmc *mmc, lbaint_t 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) {
> -#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
> -             printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
> -                     start + blkcnt, mmc->block_dev.lba);
> -#endif
> -             return 0;
> -     }
> -
> -     if (blkcnt == 0)
> -             return 0;
> -     else if (blkcnt == 1)
> -             cmd.cmdidx = MMC_CMD_WRITE_SINGLE_BLOCK;
> -     else
> -             cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK;
> -
> -     if (mmc->high_capacity)
> -             cmd.cmdarg = start;
> -     else
> -             cmd.cmdarg = start * mmc->write_bl_len;
> -
> -     cmd.resp_type = MMC_RSP_R1;
> -
> -     data.src = src;
> -     data.blocks = blkcnt;
> -     data.blocksize = mmc->write_bl_len;
> -     data.flags = MMC_DATA_WRITE;
> -
> -     if (mmc_send_cmd(mmc, &cmd, &data)) {
> -#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
> -             printf("mmc write failed\n");
> -#endif
> -             return 0;
> -     }
> -
> -     /* SPI multiblock writes terminate using a special
> -      * token, not a STOP_TRANSMISSION request.
> -      */
> -     if (!mmc_host_is_spi(mmc) && blkcnt > 1) {
> -             cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
> -             cmd.cmdarg = 0;
> -             cmd.resp_type = MMC_RSP_R1b;
> -             if (mmc_send_cmd(mmc, &cmd, NULL)) {
> -#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
> -                     printf("mmc fail to send stop cmd\n");
> -#endif
> -                     return 0;
> -             }
> -     }
> -
> -     /* Waiting for the ready status */
> -     if (mmc_send_status(mmc, timeout))
> -             return 0;
> -
> -     return blkcnt;
> -}
> -
> -static ulong
> -mmc_bwrite(int dev_num, lbaint_t start, lbaint_t blkcnt, const void*src)
> -{
> -     lbaint_t cur, blocks_todo = blkcnt;
> -
> -     struct mmc *mmc = find_mmc_device(dev_num);
> -     if (!mmc)
> -             return 0;
> -
> -     if (mmc_set_blocklen(mmc, mmc->write_bl_len))
> -             return 0;
> -
> -     do {
> -             cur = (blocks_todo > mmc->b_max) ?  mmc->b_max : blocks_todo;
> -             if(mmc_write_blocks(mmc, start, cur, src) != cur)
> -                     return 0;
> -             blocks_todo -= cur;
> -             start += cur;
> -             src += cur * mmc->write_bl_len;
> -     } while (blocks_todo > 0);
> -
> -     return blkcnt;
> -}
> -
> static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
>                          lbaint_t blkcnt)
> {
> diff --git a/drivers/mmc/mmc_private.h b/drivers/mmc/mmc_private.h
> new file mode 100644
> index 0000000..16dcf9f
> --- /dev/null
> +++ b/drivers/mmc/mmc_private.h
> @@ -0,0 +1,45 @@
> +/*
> + * Copyright 2008,2010 Freescale Semiconductor, Inc
> + * Andy Fleming
> + *
> + * Based (loosely) on the Linux code
> + *
> + * SPDX-License-Identifier:  GPL-2.0+
> + */
> +
> +#ifndef _MMC_PRIVATE_H_
> +#define _MMC_PRIVATE_H_
> +
> +#include <mmc.h>
> +
> +extern int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
> +                     struct mmc_data *data);
> +extern int mmc_send_status(struct mmc *mmc, int timeout);
> +extern int mmc_set_blocklen(struct mmc *mmc, int len);
> +
> +#ifndef CONFIG_SPL_BUILD
> +
> +extern unsigned long mmc_berase(int dev_num, lbaint_t start, lbaint_t 
> blkcnt);
> +
> +extern ulong mmc_bwrite(int dev_num, lbaint_t start, lbaint_t blkcnt,
> +             const void *src);
> +
> +#else /* CONFIG_SPL_BUILD */
> +
> +/* SPL will never write or erase, declare dummies to reduce code size. */
> +
> +static inline unsigned long mmc_berase(int dev_num, lbaint_t start,
> +             lbaint_t blkcnt)
> +{
> +     return 0;
> +}
> +
> +static inline ulong mmc_bwrite(int dev_num, lbaint_t start, lbaint_t blkcnt,
> +             const void *src)
> +{
> +     return 0;
> +}
> +
> +#endif /* CONFIG_SPL_BUILD */
> +
> +#endif /* _MMC_PRIVATE_H_ */
> diff --git a/drivers/mmc/mmc_write.c b/drivers/mmc/mmc_write.c
> new file mode 100644
> index 0000000..dde5cf2
> --- /dev/null
> +++ b/drivers/mmc/mmc_write.c
> @@ -0,0 +1,189 @@
> +/*
> + * Copyright 2008, Freescale Semiconductor, Inc
> + * Andy Fleming
> + *
> + * Based vaguely on the Linux code
> + *
> + * SPDX-License-Identifier:  GPL-2.0+
> + */
> +
> +#include <config.h>
> +#include <common.h>
> +#include <part.h>
> +#include "mmc_private.h"
> +
> +static ulong mmc_erase_t(struct mmc *mmc, ulong start, lbaint_t blkcnt)
> +{
> +     struct mmc_cmd cmd;
> +     ulong end;
> +     int err, start_cmd, end_cmd;
> +
> +     if (mmc->high_capacity) {
> +             end = start + blkcnt - 1;
> +     } else {
> +             end = (start + blkcnt - 1) * mmc->write_bl_len;
> +             start *= mmc->write_bl_len;
> +     }
> +
> +     if (IS_SD(mmc)) {
> +             start_cmd = SD_CMD_ERASE_WR_BLK_START;
> +             end_cmd = SD_CMD_ERASE_WR_BLK_END;
> +     } else {
> +             start_cmd = MMC_CMD_ERASE_GROUP_START;
> +             end_cmd = MMC_CMD_ERASE_GROUP_END;
> +     }
> +
> +     cmd.cmdidx = start_cmd;
> +     cmd.cmdarg = start;
> +     cmd.resp_type = MMC_RSP_R1;
> +
> +     err = mmc_send_cmd(mmc, &cmd, NULL);
> +     if (err)
> +             goto err_out;
> +
> +     cmd.cmdidx = end_cmd;
> +     cmd.cmdarg = end;
> +
> +     err = mmc_send_cmd(mmc, &cmd, NULL);
> +     if (err)
> +             goto err_out;
> +
> +     cmd.cmdidx = MMC_CMD_ERASE;
> +     cmd.cmdarg = SECURE_ERASE;
> +     cmd.resp_type = MMC_RSP_R1b;
> +
> +     err = mmc_send_cmd(mmc, &cmd, NULL);
> +     if (err)
> +             goto err_out;
> +
> +     return 0;
> +
> +err_out:
> +#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
> +     puts("mmc erase failed\n");
> +#endif
> +     return err;
> +}
> +
> +unsigned long mmc_berase(int dev_num, lbaint_t start, lbaint_t blkcnt)
> +{
> +     int err = 0;
> +     struct mmc *mmc = find_mmc_device(dev_num);
> +     lbaint_t blk = 0, blk_r = 0;
> +     int timeout = 1000;
> +
> +     if (!mmc)
> +             return -1;
> +
> +#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
> +     if ((start % mmc->erase_grp_size) || (blkcnt % mmc->erase_grp_size))
> +             printf("\n\nCaution! Your devices Erase group is 0x%x\n"
> +                    "The erase range would be change to "
> +                    "0x" LBAF "~0x" LBAF "\n\n",
> +                    mmc->erase_grp_size, start & ~(mmc->erase_grp_size - 1),
> +                    ((start + blkcnt + mmc->erase_grp_size)
> +                    & ~(mmc->erase_grp_size - 1)) - 1);
> +#endif
> +
> +     while (blk < blkcnt) {
> +             blk_r = ((blkcnt - blk) > mmc->erase_grp_size) ?
> +                     mmc->erase_grp_size : (blkcnt - blk);
> +             err = mmc_erase_t(mmc, start + blk, blk_r);
> +             if (err)
> +                     break;
> +
> +             blk += blk_r;
> +
> +             /* Waiting for the ready status */
> +             if (mmc_send_status(mmc, timeout))
> +                     return 0;
> +     }
> +
> +     return blk;
> +}
> +
> +static ulong mmc_write_blocks(struct mmc *mmc, lbaint_t 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) {
> +#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
> +             printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
> +                    start + blkcnt, mmc->block_dev.lba);
> +#endif
> +             return 0;
> +     }
> +
> +     if (blkcnt == 0)
> +             return 0;
> +     else if (blkcnt == 1)
> +             cmd.cmdidx = MMC_CMD_WRITE_SINGLE_BLOCK;
> +     else
> +             cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK;
> +
> +     if (mmc->high_capacity)
> +             cmd.cmdarg = start;
> +     else
> +             cmd.cmdarg = start * mmc->write_bl_len;
> +
> +     cmd.resp_type = MMC_RSP_R1;
> +
> +     data.src = src;
> +     data.blocks = blkcnt;
> +     data.blocksize = mmc->write_bl_len;
> +     data.flags = MMC_DATA_WRITE;
> +
> +     if (mmc_send_cmd(mmc, &cmd, &data)) {
> +#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
> +             printf("mmc write failed\n");
> +#endif
> +             return 0;
> +     }
> +
> +     /* SPI multiblock writes terminate using a special
> +      * token, not a STOP_TRANSMISSION request.
> +      */
> +     if (!mmc_host_is_spi(mmc) && blkcnt > 1) {
> +             cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
> +             cmd.cmdarg = 0;
> +             cmd.resp_type = MMC_RSP_R1b;
> +             if (mmc_send_cmd(mmc, &cmd, NULL)) {
> +#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
> +                     printf("mmc fail to send stop cmd\n");
> +#endif
> +                     return 0;
> +             }
> +     }
> +
> +     /* Waiting for the ready status */
> +     if (mmc_send_status(mmc, timeout))
> +             return 0;
> +
> +     return blkcnt;
> +}
> +
> +ulong mmc_bwrite(int dev_num, lbaint_t start, lbaint_t blkcnt, const void 
> *src)
> +{
> +     lbaint_t cur, blocks_todo = blkcnt;
> +
> +     struct mmc *mmc = find_mmc_device(dev_num);
> +     if (!mmc)
> +             return 0;
> +
> +     if (mmc_set_blocklen(mmc, mmc->write_bl_len))
> +             return 0;
> +
> +     do {
> +             cur = (blocks_todo > mmc->b_max) ?  mmc->b_max : blocks_todo;
> +             if (mmc_write_blocks(mmc, start, cur, src) != cur)
> +                     return 0;
> +             blocks_todo -= cur;
> +             start += cur;
> +             src += cur * mmc->write_bl_len;
> +     } while (blocks_todo > 0);
> +
> +     return blkcnt;
> +}
> -- 
> 1.8.4
> 
> 

Acked-by: Pantelis Antoniou <pa...@antoniou-consulting.com>

Looks good to me; let's hear what other people say too.

Tom?

Regards

-- Pantelis


_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to