diff options
author | Peng Fan <van.freenix@gmail.com> | 2016-09-01 11:13:38 +0800 |
---|---|---|
committer | Peng Fan <peng.fan@nxp.com> | 2016-10-18 15:34:02 +0800 |
commit | be950ab9d0625ae1a23c7a5e03dde8e5a676ea80 (patch) | |
tree | fbca2e9b5349521ca5601c2bbc934f1087d393ac /drivers/mmc | |
parent | 5ad998cbb8698052315d29bffaa4e264ebe4aad4 (diff) | |
download | u-boot-imx-be950ab9d0625ae1a23c7a5e03dde8e5a676ea80.zip u-boot-imx-be950ab9d0625ae1a23c7a5e03dde8e5a676ea80.tar.gz u-boot-imx-be950ab9d0625ae1a23c7a5e03dde8e5a676ea80.tar.bz2 |
mmc: sd: extracting erase related information from sd status
Add function to read SD_STATUS information.
According to the information, get erase_timeout/erase_size/erase_offset.
Add a structure sd_ssr to include the erase related information.
Signed-off-by: Peng Fan <peng.fan@nxp.com>
Cc: Jaehoon Chung <jh80.chung@samsung.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Bin Meng <bmeng.cn@gmail.com>
Cc: Stefan Wahren <stefan.wahren@i2se.com>
Cc: Clemens Gruber <clemens.gruber@pqgruber.com>
Cc: Kever Yang <kever.yang@rock-chips.com>
Cc: Eric Nelson <eric@nelint.com>
Cc: Stephen Warren <swarren@nvidia.com>
(cherry picked from commit 3697e5992f89c923aca17d7d9174739da28cb3cd)
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/mmc.c | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index ede5d6e..d189924 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -24,6 +24,14 @@ static struct list_head mmc_devices; static int cur_dev_num = -1; +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, +}; + __weak int board_mmc_getwp(struct mmc *mmc) { return -1; @@ -967,6 +975,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[] = { @@ -1366,6 +1430,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 |