Commit 3697e5992f89c923aca17d7d9174739da28cb3cd
Committed by
Jaehoon Chung
1 parent
65a25b2086
Exists in
v2017.01-smarct4x
and in
25 other branches
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>
Showing 2 changed files with 77 additions and 0 deletions Side-by-side Diff
drivers/mmc/mmc.c
... | ... | @@ -21,6 +21,14 @@ |
21 | 21 | #include <div64.h> |
22 | 22 | #include "mmc_private.h" |
23 | 23 | |
24 | +static const unsigned int sd_au_size[] = { | |
25 | + 0, SZ_16K / 512, SZ_32K / 512, | |
26 | + SZ_64K / 512, SZ_128K / 512, SZ_256K / 512, | |
27 | + SZ_512K / 512, SZ_1M / 512, SZ_2M / 512, | |
28 | + SZ_4M / 512, SZ_8M / 512, (SZ_8M + SZ_4M) / 512, | |
29 | + SZ_16M / 512, (SZ_16M + SZ_8M) / 512, SZ_32M / 512, SZ_64M / 512, | |
30 | +}; | |
31 | + | |
24 | 32 | #ifndef CONFIG_DM_MMC_OPS |
25 | 33 | __weak int board_mmc_getwp(struct mmc *mmc) |
26 | 34 | { |
... | ... | @@ -945,6 +953,62 @@ |
945 | 953 | return 0; |
946 | 954 | } |
947 | 955 | |
956 | +static int sd_read_ssr(struct mmc *mmc) | |
957 | +{ | |
958 | + int err, i; | |
959 | + struct mmc_cmd cmd; | |
960 | + ALLOC_CACHE_ALIGN_BUFFER(uint, ssr, 16); | |
961 | + struct mmc_data data; | |
962 | + int timeout = 3; | |
963 | + unsigned int au, eo, et, es; | |
964 | + | |
965 | + cmd.cmdidx = MMC_CMD_APP_CMD; | |
966 | + cmd.resp_type = MMC_RSP_R1; | |
967 | + cmd.cmdarg = mmc->rca << 16; | |
968 | + | |
969 | + err = mmc_send_cmd(mmc, &cmd, NULL); | |
970 | + if (err) | |
971 | + return err; | |
972 | + | |
973 | + cmd.cmdidx = SD_CMD_APP_SD_STATUS; | |
974 | + cmd.resp_type = MMC_RSP_R1; | |
975 | + cmd.cmdarg = 0; | |
976 | + | |
977 | +retry_ssr: | |
978 | + data.dest = (char *)ssr; | |
979 | + data.blocksize = 64; | |
980 | + data.blocks = 1; | |
981 | + data.flags = MMC_DATA_READ; | |
982 | + | |
983 | + err = mmc_send_cmd(mmc, &cmd, &data); | |
984 | + if (err) { | |
985 | + if (timeout--) | |
986 | + goto retry_ssr; | |
987 | + | |
988 | + return err; | |
989 | + } | |
990 | + | |
991 | + for (i = 0; i < 16; i++) | |
992 | + ssr[i] = be32_to_cpu(ssr[i]); | |
993 | + | |
994 | + au = (ssr[2] >> 12) & 0xF; | |
995 | + if ((au <= 9) || (mmc->version == SD_VERSION_3)) { | |
996 | + mmc->ssr.au = sd_au_size[au]; | |
997 | + es = (ssr[3] >> 24) & 0xFF; | |
998 | + es |= (ssr[2] & 0xFF) << 8; | |
999 | + et = (ssr[3] >> 18) & 0x3F; | |
1000 | + if (es && et) { | |
1001 | + eo = (ssr[3] >> 16) & 0x3; | |
1002 | + mmc->ssr.erase_timeout = (et * 1000) / es; | |
1003 | + mmc->ssr.erase_offset = eo * 1000; | |
1004 | + } | |
1005 | + } else { | |
1006 | + debug("Invalid Allocation Unit Size.\n"); | |
1007 | + } | |
1008 | + | |
1009 | + return 0; | |
1010 | +} | |
1011 | + | |
948 | 1012 | /* frequency bases */ |
949 | 1013 | /* divided by 10 to be nice to platforms without floating point */ |
950 | 1014 | static const int fbase[] = { |
... | ... | @@ -1349,6 +1413,10 @@ |
1349 | 1413 | |
1350 | 1414 | mmc_set_bus_width(mmc, 4); |
1351 | 1415 | } |
1416 | + | |
1417 | + err = sd_read_ssr(mmc); | |
1418 | + if (err) | |
1419 | + return err; | |
1352 | 1420 | |
1353 | 1421 | if (mmc->card_caps & MMC_MODE_HS) |
1354 | 1422 | mmc->tran_speed = 50000000; |
include/mmc.h
... | ... | @@ -11,6 +11,7 @@ |
11 | 11 | #define _MMC_H_ |
12 | 12 | |
13 | 13 | #include <linux/list.h> |
14 | +#include <linux/sizes.h> | |
14 | 15 | #include <linux/compiler.h> |
15 | 16 | #include <part.h> |
16 | 17 | |
... | ... | @@ -102,6 +103,7 @@ |
102 | 103 | #define SD_CMD_SWITCH_UHS18V 11 |
103 | 104 | |
104 | 105 | #define SD_CMD_APP_SET_BUS_WIDTH 6 |
106 | +#define SD_CMD_APP_SD_STATUS 13 | |
105 | 107 | #define SD_CMD_ERASE_WR_BLK_START 32 |
106 | 108 | #define SD_CMD_ERASE_WR_BLK_END 33 |
107 | 109 | #define SD_CMD_APP_SEND_OP_COND 41 |
... | ... | @@ -392,6 +394,12 @@ |
392 | 394 | unsigned char part_type; |
393 | 395 | }; |
394 | 396 | |
397 | +struct sd_ssr { | |
398 | + unsigned int au; /* In sectors */ | |
399 | + unsigned int erase_timeout; /* In milliseconds */ | |
400 | + unsigned int erase_offset; /* In milliseconds */ | |
401 | +}; | |
402 | + | |
395 | 403 | /* |
396 | 404 | * With CONFIG_DM_MMC enabled, struct mmc can be accessed from the MMC device |
397 | 405 | * with mmc_get_mmc_dev(). |
... | ... | @@ -426,6 +434,7 @@ |
426 | 434 | uint write_bl_len; |
427 | 435 | uint erase_grp_size; /* in 512-byte sectors */ |
428 | 436 | uint hc_wp_grp_size; /* in 512-byte sectors */ |
437 | + struct sd_ssr ssr; /* SD status register */ | |
429 | 438 | u64 capacity; |
430 | 439 | u64 capacity_user; |
431 | 440 | u64 capacity_boot; |