diff mbox

[U-Boot] mmc: dcache: allocate cache aligned buffer for scr and switch_status

Message ID 1314119037-2835-1-git-send-email-robotboy@chromium.org
State Rejected
Headers show

Commit Message

Anton staaf Aug. 23, 2011, 5:03 p.m. UTC
Currently the sd_change_freq function allocates two buffers on the
stack that it passes down to the MMC device driver.  These buffers
could be unaligned to the L1 dcache line size.  This causes problems
when using DMA and with caches enabled.

This patch correctly cache alignes the buffers used for reading the
scr register and switch status values from an MMC device.

Change-Id: Ifa8414f572ef907681bd2d5ff3950285a215357d
Signed-off-by: Anton Staaf <robotboy@chromium.org>
Cc: Lukasz Majewski <l.majewski@samsung.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Albert ARIBAUD <albert.u.boot@aribaud.net>
---

This patch depends on Lukasz Majewski's dcache line size patch sent to the
list in: http://patchwork.ozlabs.org/patch/110501/

 drivers/mmc/mmc.c |   44 ++++++++++++++++++++++++--------------------
 1 files changed, 24 insertions(+), 20 deletions(-)
diff mbox

Patch

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 7e703c0..55cf9b4 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -699,17 +699,19 @@  int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp)
 
 int sd_change_freq(struct mmc *mmc)
 {
-	int err;
+	int err = 0;
 	struct mmc_cmd cmd;
-	uint scr[2];
-	uint switch_status[16];
+	uint *buffer = memalign(get_dcache_line_size(), 64);
 	struct mmc_data data;
 	int timeout;
 
+	if (buffer == NULL)
+		return -ENOMEM;
+
 	mmc->card_caps = 0;
 
 	if (mmc_host_is_spi(mmc))
-		return 0;
+		goto out;
 
 	/* Read the SCR to find out if this card supports higher speeds */
 	cmd.cmdidx = MMC_CMD_APP_CMD;
@@ -720,7 +722,7 @@  int sd_change_freq(struct mmc *mmc)
 	err = mmc_send_cmd(mmc, &cmd, NULL);
 
 	if (err)
-		return err;
+		goto out;
 
 	cmd.cmdidx = SD_CMD_APP_SEND_SCR;
 	cmd.resp_type = MMC_RSP_R1;
@@ -730,7 +732,7 @@  int sd_change_freq(struct mmc *mmc)
 	timeout = 3;
 
 retry_scr:
-	data.dest = (char *)&scr;
+	data.dest = (char *)buffer;
 	data.blocksize = 8;
 	data.blocks = 1;
 	data.flags = MMC_DATA_READ;
@@ -741,11 +743,11 @@  retry_scr:
 		if (timeout--)
 			goto retry_scr;
 
-		return err;
+		goto out;
 	}
 
-	mmc->scr[0] = __be32_to_cpu(scr[0]);
-	mmc->scr[1] = __be32_to_cpu(scr[1]);
+	mmc->scr[0] = __be32_to_cpu(buffer[0]);
+	mmc->scr[1] = __be32_to_cpu(buffer[1]);
 
 	switch ((mmc->scr[0] >> 24) & 0xf) {
 		case 0:
@@ -767,34 +769,36 @@  retry_scr:
 
 	/* Version 1.0 doesn't support switching */
 	if (mmc->version == SD_VERSION_1_0)
-		return 0;
+		goto out
 
 	timeout = 4;
 	while (timeout--) {
-		err = sd_switch(mmc, SD_SWITCH_CHECK, 0, 1,
-				(u8 *)&switch_status);
+		err = sd_switch(mmc, SD_SWITCH_CHECK, 0, 1, (u8 *)buffer);
 
 		if (err)
-			return err;
+			goto out;
 
 		/* The high-speed function is busy.  Try again */
-		if (!(__be32_to_cpu(switch_status[7]) & SD_HIGHSPEED_BUSY))
+		if (!(__be32_to_cpu(buffer[7]) & SD_HIGHSPEED_BUSY))
 			break;
 	}
 
 	/* If high-speed isn't supported, we return */
-	if (!(__be32_to_cpu(switch_status[3]) & SD_HIGHSPEED_SUPPORTED))
-		return 0;
+	if (!(__be32_to_cpu(buffer[3]) & SD_HIGHSPEED_SUPPORTED))
+		goto out;
 
-	err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, 1, (u8 *)&switch_status);
+	err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, 1, (u8 *)buffer);
 
 	if (err)
-		return err;
+		goto out;
 
-	if ((__be32_to_cpu(switch_status[4]) & 0x0f000000) == 0x01000000)
+	if ((__be32_to_cpu(buffer[4]) & 0x0f000000) == 0x01000000)
 		mmc->card_caps |= MMC_MODE_HS;
 
-	return 0;
+ out:
+	free(buffer);
+
+	return err;
 }
 
 /* frequency bases */