|
@@ -21,6 +21,14 @@
|
|
|
#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,
|
|
|
+};
|
|
|
+
|
|
|
#ifndef CONFIG_DM_MMC_OPS
|
|
|
__weak int board_mmc_getwp(struct mmc *mmc)
|
|
|
{
|
|
@@ -945,6 +953,62 @@ retry_scr:
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int sd_read_ssr(struct mmc *mmc)
|
|
|
+{
|
|
|
+ int err, i;
|
|
|
+ struct mmc_cmd cmd;
|
|
|
+ ALLOC_CACHE_ALIGN_BUFFER(uint, ssr, 16);
|
|
|
+ struct mmc_data data;
|
|
|
+ int timeout = 3;
|
|
|
+ unsigned int au, eo, et, es;
|
|
|
+
|
|
|
+ cmd.cmdidx = MMC_CMD_APP_CMD;
|
|
|
+ cmd.resp_type = MMC_RSP_R1;
|
|
|
+ cmd.cmdarg = mmc->rca << 16;
|
|
|
+
|
|
|
+ err = mmc_send_cmd(mmc, &cmd, NULL);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ cmd.cmdidx = SD_CMD_APP_SD_STATUS;
|
|
|
+ cmd.resp_type = MMC_RSP_R1;
|
|
|
+ cmd.cmdarg = 0;
|
|
|
+
|
|
|
+retry_ssr:
|
|
|
+ data.dest = (char *)ssr;
|
|
|
+ data.blocksize = 64;
|
|
|
+ data.blocks = 1;
|
|
|
+ data.flags = MMC_DATA_READ;
|
|
|
+
|
|
|
+ err = mmc_send_cmd(mmc, &cmd, &data);
|
|
|
+ if (err) {
|
|
|
+ if (timeout--)
|
|
|
+ goto retry_ssr;
|
|
|
+
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0; i < 16; i++)
|
|
|
+ ssr[i] = be32_to_cpu(ssr[i]);
|
|
|
+
|
|
|
+ au = (ssr[2] >> 12) & 0xF;
|
|
|
+ if ((au <= 9) || (mmc->version == SD_VERSION_3)) {
|
|
|
+ mmc->ssr.au = sd_au_size[au];
|
|
|
+ es = (ssr[3] >> 24) & 0xFF;
|
|
|
+ es |= (ssr[2] & 0xFF) << 8;
|
|
|
+ et = (ssr[3] >> 18) & 0x3F;
|
|
|
+ if (es && et) {
|
|
|
+ eo = (ssr[3] >> 16) & 0x3;
|
|
|
+ mmc->ssr.erase_timeout = (et * 1000) / es;
|
|
|
+ mmc->ssr.erase_offset = eo * 1000;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ debug("Invalid Allocation Unit Size.\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/* frequency bases */
|
|
|
/* divided by 10 to be nice to platforms without floating point */
|
|
|
static const int fbase[] = {
|
|
@@ -1350,6 +1414,10 @@ static int mmc_startup(struct mmc *mmc)
|
|
|
mmc_set_bus_width(mmc, 4);
|
|
|
}
|
|
|
|
|
|
+ err = sd_read_ssr(mmc);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+
|
|
|
if (mmc->card_caps & MMC_MODE_HS)
|
|
|
mmc->tran_speed = 50000000;
|
|
|
else
|