summaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
authorlitchipi <litchi.pi@protonmail.com>2021-06-15 11:53:06 +0300
committerPeng Fan <peng.fan@nxp.com>2021-07-30 12:12:15 +0300
commita9f7be509af90fa5f2c308867ad3b0bd48532c6e (patch)
tree25a6adaf951e33440574d5b1c33badc76700d790 /drivers/mmc
parent15f7e0dc01d8a851fb1bfbf0e47eab5b67ed26b3 (diff)
downloadu-boot-a9f7be509af90fa5f2c308867ad3b0bd48532c6e.tar.xz
mmc: rpmb: Fix driver routing memory alignment with tmp buffer
Fix mmc_rpmb_route_frames() implementation to comply with most MMC drivers that expect some alignment of MMC data frames in memory. When called from drivers/tee/optee/rpmb.c, the address passed is not aligned properly. OP-TEE OS inserts a 6-byte header before a raw RPMB frame which makes RPMB data buffer not 32bit aligned. To prevent breaking ABI with OPTEE-OS RPC memrefs, allocate a temporary buffer to copy the data into an aligned memory. Many RPMB drivers implicitly expect 32bit alignment of the eMMC frame including arm_pl180_mmci.c, sandbox_mmc.c and stm32_sdmmc2.c Signed-off-by: Timothée Cercueil <timothee.cercueil@st.com> Signed-off-by: Timothée Cercueil <litchi.pi@protonmail.com> Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/rpmb.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/drivers/mmc/rpmb.c b/drivers/mmc/rpmb.c
index ea7e506666..b68d98573c 100644
--- a/drivers/mmc/rpmb.c
+++ b/drivers/mmc/rpmb.c
@@ -480,10 +480,24 @@ int mmc_rpmb_route_frames(struct mmc *mmc, void *req, unsigned long reqlen,
* and possibly just delay an eventual error which will be harder
* to track down.
*/
+ void *rpmb_data = NULL;
+ int ret;
if (reqlen % sizeof(struct s_rpmb) || rsplen % sizeof(struct s_rpmb))
return -EINVAL;
- return rpmb_route_frames(mmc, req, reqlen / sizeof(struct s_rpmb),
- rsp, rsplen / sizeof(struct s_rpmb));
+ if (!IS_ALIGNED((uintptr_t)req, ARCH_DMA_MINALIGN)) {
+ /* Memory alignment is required by MMC driver */
+ rpmb_data = malloc(reqlen);
+ if (!rpmb_data)
+ return -ENOMEM;
+
+ memcpy(rpmb_data, req, reqlen);
+ req = rpmb_data;
+ }
+
+ ret = rpmb_route_frames(mmc, req, reqlen / sizeof(struct s_rpmb),
+ rsp, rsplen / sizeof(struct s_rpmb));
+ free(rpmb_data);
+ return ret;
}