diff options
-rw-r--r-- | drivers/mmc/mmc-uclass.c | 16 | ||||
-rw-r--r-- | drivers/mmc/mmc.c | 16 | ||||
-rw-r--r-- | include/mmc.h | 16 |
3 files changed, 46 insertions, 2 deletions
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c index c75892a72c..cb26d841be 100644 --- a/drivers/mmc/mmc-uclass.c +++ b/drivers/mmc/mmc-uclass.c @@ -13,6 +13,22 @@ #include <linux/compat.h> #include "mmc_private.h" +int dm_mmc_get_b_max(struct udevice *dev, void *dst, lbaint_t blkcnt) +{ + struct dm_mmc_ops *ops = mmc_get_ops(dev); + struct mmc *mmc = mmc_get_mmc_dev(dev); + + if (ops->get_b_max) + return ops->get_b_max(dev, dst, blkcnt); + else + return mmc->cfg->b_max; +} + +int mmc_get_b_max(struct mmc *mmc, void *dst, lbaint_t blkcnt) +{ + return dm_mmc_get_b_max(mmc->dev, dst, blkcnt); +} + int dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, struct mmc_data *data) { diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index fc3123c3c3..523c055967 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -409,6 +409,16 @@ static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start, return blkcnt; } +#if !CONFIG_IS_ENABLED(DM_MMC) +static int mmc_get_b_max(struct mmc *mmc, void *dst, lbaint_t blkcnt) +{ + if (mmc->cfg->ops->get_b_max) + return mmc->cfg->ops->get_b_max(mmc, dst, blkcnt); + else + return mmc->cfg->b_max; +} +#endif + #if CONFIG_IS_ENABLED(BLK) ulong mmc_bread(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, void *dst) #else @@ -422,6 +432,7 @@ ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, int dev_num = block_dev->devnum; int err; lbaint_t cur, blocks_todo = blkcnt; + uint b_max; if (blkcnt == 0) return 0; @@ -451,9 +462,10 @@ ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, return 0; } + b_max = mmc_get_b_max(mmc, dst, blkcnt); + do { - cur = (blocks_todo > mmc->cfg->b_max) ? - mmc->cfg->b_max : blocks_todo; + cur = (blocks_todo > b_max) ? b_max : blocks_todo; if (mmc_read_blocks(mmc, dst, start, cur) != cur) { pr_debug("%s: Failed to read blocks\n", __func__); return 0; diff --git a/include/mmc.h b/include/mmc.h index e92e920560..5e9d15cb41 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -491,6 +491,19 @@ struct dm_mmc_ops { * @return 0 if not present, 1 if present, -ve on error */ int (*host_power_cycle)(struct udevice *dev); + + /** + * get_b_max - get maximum length of single transfer + * Called before reading blocks from the card, + * useful for system which have e.g. DMA limits + * on various memory ranges. + * + * @dev: Device to check + * @dst: Destination buffer in memory + * @blkcnt: Total number of blocks in this transfer + * @return maximum number of blocks for this transfer + */ + int (*get_b_max)(struct udevice *dev, void *dst, lbaint_t blkcnt); }; #define mmc_get_ops(dev) ((struct dm_mmc_ops *)(dev)->driver->ops) @@ -504,6 +517,7 @@ int dm_mmc_execute_tuning(struct udevice *dev, uint opcode); int dm_mmc_wait_dat0(struct udevice *dev, int state, int timeout_us); int dm_mmc_host_power_cycle(struct udevice *dev); int dm_mmc_deferred_probe(struct udevice *dev); +int dm_mmc_get_b_max(struct udevice *dev, void *dst, lbaint_t blkcnt); /* Transition functions for compatibility */ int mmc_set_ios(struct mmc *mmc); @@ -514,6 +528,7 @@ int mmc_wait_dat0(struct mmc *mmc, int state, int timeout_us); int mmc_set_enhanced_strobe(struct mmc *mmc); int mmc_host_power_cycle(struct mmc *mmc); int mmc_deferred_probe(struct mmc *mmc); +int mmc_get_b_max(struct mmc *mmc, void *dst, lbaint_t blkcnt); #else struct mmc_ops { @@ -524,6 +539,7 @@ struct mmc_ops { int (*getcd)(struct mmc *mmc); int (*getwp)(struct mmc *mmc); int (*host_power_cycle)(struct mmc *mmc); + int (*get_b_max)(struct mmc *mmc, void *dst, lbaint_t blkcnt); }; #endif |