diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-19 14:33:58 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-19 14:33:58 -0500 |
| commit | 1282ac407cf4c3eaeaddd8d776a7ffbd2b94c2e7 (patch) | |
| tree | 5f08c67b59e09886e926e3027758e4c44df2181a | |
| parent | 34258a32d9a9fc9e38fb549efe1692301cc31f85 (diff) | |
| parent | d3df0465db00cf4ed9f90d0bfc3b827d32b9c796 (diff) | |
Merge tag 'mmc-v4.4-rc1' of git://git.linaro.org/people/ulf.hansson/mmc
Pull MMC fixes from Ulf Hansson:
"Here are some mmc fixes intended for v4.4 rc2. It's based on a commit
prior rc1 as I wanted to get them a bit more tested in next before
sending you the pull request.
MMC core:
- Improve reliability when selecting HS200 mode
- Improve reliability when selecting HS400 mode
- mmc: remove bondage between REQ_META and reliable write
MMC host:
- pxamci: Fix read-only gpio detection polarity
- mtk-sd: Preinitialize delay_phase to fix the case when delay is zero
- android-goldfish: Fix build dependency by adding HAS_DMA
- dw_mmc: Remove Seungwon Jeon from MAINTAINERS"
* tag 'mmc-v4.4-rc1' of git://git.linaro.org/people/ulf.hansson/mmc:
mmc: remove bondage between REQ_META and reliable write
mmc: MMC_GOLDFISH should depend on HAS_DMA
mmc: mediatek: Preinitialize delay_phase in get_best_delay()
MAINTAINERS: mmc: Remove Seungwon Jeon from dw_mmc
mmc: mmc: Improve reliability of mmc_select_hs400()
mmc: mmc: Move mmc_switch_status()
mmc: mmc: Fix HS setting in mmc_select_hs400()
mmc: mmc: Improve reliability of mmc_select_hs200()
mmc: pxamci: fix read-only gpio detection polarity
| -rw-r--r-- | MAINTAINERS | 1 | ||||
| -rw-r--r-- | drivers/mmc/card/block.c | 11 | ||||
| -rw-r--r-- | drivers/mmc/core/mmc.c | 93 | ||||
| -rw-r--r-- | drivers/mmc/host/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/mmc/host/mtk-sd.c | 2 | ||||
| -rw-r--r-- | drivers/mmc/host/pxamci.c | 2 |
6 files changed, 75 insertions, 35 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index ea1751283b49..b16bffabe70a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -9315,7 +9315,6 @@ F: drivers/i2c/busses/i2c-designware-* | |||
| 9315 | F: include/linux/platform_data/i2c-designware.h | 9315 | F: include/linux/platform_data/i2c-designware.h |
| 9316 | 9316 | ||
| 9317 | SYNOPSYS DESIGNWARE MMC/SD/SDIO DRIVER | 9317 | SYNOPSYS DESIGNWARE MMC/SD/SDIO DRIVER |
| 9318 | M: Seungwon Jeon <tgih.jun@samsung.com> | ||
| 9319 | M: Jaehoon Chung <jh80.chung@samsung.com> | 9318 | M: Jaehoon Chung <jh80.chung@samsung.com> |
| 9320 | L: linux-mmc@vger.kernel.org | 9319 | L: linux-mmc@vger.kernel.org |
| 9321 | S: Maintained | 9320 | S: Maintained |
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 23b6c8e8701c..d8486168415a 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
| @@ -65,8 +65,7 @@ MODULE_ALIAS("mmc:block"); | |||
| 65 | #define MMC_SANITIZE_REQ_TIMEOUT 240000 | 65 | #define MMC_SANITIZE_REQ_TIMEOUT 240000 |
| 66 | #define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16) | 66 | #define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16) |
| 67 | 67 | ||
| 68 | #define mmc_req_rel_wr(req) (((req->cmd_flags & REQ_FUA) || \ | 68 | #define mmc_req_rel_wr(req) ((req->cmd_flags & REQ_FUA) && \ |
| 69 | (req->cmd_flags & REQ_META)) && \ | ||
| 70 | (rq_data_dir(req) == WRITE)) | 69 | (rq_data_dir(req) == WRITE)) |
| 71 | #define PACKED_CMD_VER 0x01 | 70 | #define PACKED_CMD_VER 0x01 |
| 72 | #define PACKED_CMD_WR 0x02 | 71 | #define PACKED_CMD_WR 0x02 |
| @@ -1467,13 +1466,9 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, | |||
| 1467 | 1466 | ||
| 1468 | /* | 1467 | /* |
| 1469 | * Reliable writes are used to implement Forced Unit Access and | 1468 | * Reliable writes are used to implement Forced Unit Access and |
| 1470 | * REQ_META accesses, and are supported only on MMCs. | 1469 | * are supported only on MMCs. |
| 1471 | * | ||
| 1472 | * XXX: this really needs a good explanation of why REQ_META | ||
| 1473 | * is treated special. | ||
| 1474 | */ | 1470 | */ |
| 1475 | bool do_rel_wr = ((req->cmd_flags & REQ_FUA) || | 1471 | bool do_rel_wr = (req->cmd_flags & REQ_FUA) && |
| 1476 | (req->cmd_flags & REQ_META)) && | ||
| 1477 | (rq_data_dir(req) == WRITE) && | 1472 | (rq_data_dir(req) == WRITE) && |
| 1478 | (md->flags & MMC_BLK_REL_WR); | 1473 | (md->flags & MMC_BLK_REL_WR); |
| 1479 | 1474 | ||
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index c793fda27321..3a9a79ec4343 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
| @@ -1040,9 +1040,24 @@ static int mmc_select_hs_ddr(struct mmc_card *card) | |||
| 1040 | return err; | 1040 | return err; |
| 1041 | } | 1041 | } |
| 1042 | 1042 | ||
| 1043 | /* Caller must hold re-tuning */ | ||
| 1044 | static int mmc_switch_status(struct mmc_card *card) | ||
| 1045 | { | ||
| 1046 | u32 status; | ||
| 1047 | int err; | ||
| 1048 | |||
| 1049 | err = mmc_send_status(card, &status); | ||
| 1050 | if (err) | ||
| 1051 | return err; | ||
| 1052 | |||
| 1053 | return mmc_switch_status_error(card->host, status); | ||
| 1054 | } | ||
| 1055 | |||
| 1043 | static int mmc_select_hs400(struct mmc_card *card) | 1056 | static int mmc_select_hs400(struct mmc_card *card) |
| 1044 | { | 1057 | { |
| 1045 | struct mmc_host *host = card->host; | 1058 | struct mmc_host *host = card->host; |
| 1059 | bool send_status = true; | ||
| 1060 | unsigned int max_dtr; | ||
| 1046 | int err = 0; | 1061 | int err = 0; |
| 1047 | u8 val; | 1062 | u8 val; |
| 1048 | 1063 | ||
| @@ -1053,25 +1068,36 @@ static int mmc_select_hs400(struct mmc_card *card) | |||
| 1053 | host->ios.bus_width == MMC_BUS_WIDTH_8)) | 1068 | host->ios.bus_width == MMC_BUS_WIDTH_8)) |
| 1054 | return 0; | 1069 | return 0; |
| 1055 | 1070 | ||
| 1056 | /* | 1071 | if (host->caps & MMC_CAP_WAIT_WHILE_BUSY) |
| 1057 | * Before switching to dual data rate operation for HS400, | 1072 | send_status = false; |
| 1058 | * it is required to convert from HS200 mode to HS mode. | ||
| 1059 | */ | ||
| 1060 | mmc_set_timing(card->host, MMC_TIMING_MMC_HS); | ||
| 1061 | mmc_set_bus_speed(card); | ||
| 1062 | 1073 | ||
| 1074 | /* Reduce frequency to HS frequency */ | ||
| 1075 | max_dtr = card->ext_csd.hs_max_dtr; | ||
| 1076 | mmc_set_clock(host, max_dtr); | ||
| 1077 | |||
| 1078 | /* Switch card to HS mode */ | ||
| 1063 | val = EXT_CSD_TIMING_HS | | 1079 | val = EXT_CSD_TIMING_HS | |
| 1064 | card->drive_strength << EXT_CSD_DRV_STR_SHIFT; | 1080 | card->drive_strength << EXT_CSD_DRV_STR_SHIFT; |
| 1065 | err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | 1081 | err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
| 1066 | EXT_CSD_HS_TIMING, val, | 1082 | EXT_CSD_HS_TIMING, val, |
| 1067 | card->ext_csd.generic_cmd6_time, | 1083 | card->ext_csd.generic_cmd6_time, |
| 1068 | true, true, true); | 1084 | true, send_status, true); |
| 1069 | if (err) { | 1085 | if (err) { |
| 1070 | pr_err("%s: switch to high-speed from hs200 failed, err:%d\n", | 1086 | pr_err("%s: switch to high-speed from hs200 failed, err:%d\n", |
| 1071 | mmc_hostname(host), err); | 1087 | mmc_hostname(host), err); |
| 1072 | return err; | 1088 | return err; |
| 1073 | } | 1089 | } |
| 1074 | 1090 | ||
| 1091 | /* Set host controller to HS timing */ | ||
| 1092 | mmc_set_timing(card->host, MMC_TIMING_MMC_HS); | ||
| 1093 | |||
| 1094 | if (!send_status) { | ||
| 1095 | err = mmc_switch_status(card); | ||
| 1096 | if (err) | ||
| 1097 | goto out_err; | ||
| 1098 | } | ||
| 1099 | |||
| 1100 | /* Switch card to DDR */ | ||
| 1075 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | 1101 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
| 1076 | EXT_CSD_BUS_WIDTH, | 1102 | EXT_CSD_BUS_WIDTH, |
| 1077 | EXT_CSD_DDR_BUS_WIDTH_8, | 1103 | EXT_CSD_DDR_BUS_WIDTH_8, |
| @@ -1082,22 +1108,35 @@ static int mmc_select_hs400(struct mmc_card *card) | |||
| 1082 | return err; | 1108 | return err; |
| 1083 | } | 1109 | } |
| 1084 | 1110 | ||
| 1111 | /* Switch card to HS400 */ | ||
| 1085 | val = EXT_CSD_TIMING_HS400 | | 1112 | val = EXT_CSD_TIMING_HS400 | |
| 1086 | card->drive_strength << EXT_CSD_DRV_STR_SHIFT; | 1113 | card->drive_strength << EXT_CSD_DRV_STR_SHIFT; |
| 1087 | err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | 1114 | err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
| 1088 | EXT_CSD_HS_TIMING, val, | 1115 | EXT_CSD_HS_TIMING, val, |
| 1089 | card->ext_csd.generic_cmd6_time, | 1116 | card->ext_csd.generic_cmd6_time, |
| 1090 | true, true, true); | 1117 | true, send_status, true); |
| 1091 | if (err) { | 1118 | if (err) { |
| 1092 | pr_err("%s: switch to hs400 failed, err:%d\n", | 1119 | pr_err("%s: switch to hs400 failed, err:%d\n", |
| 1093 | mmc_hostname(host), err); | 1120 | mmc_hostname(host), err); |
| 1094 | return err; | 1121 | return err; |
| 1095 | } | 1122 | } |
| 1096 | 1123 | ||
| 1124 | /* Set host controller to HS400 timing and frequency */ | ||
| 1097 | mmc_set_timing(host, MMC_TIMING_MMC_HS400); | 1125 | mmc_set_timing(host, MMC_TIMING_MMC_HS400); |
| 1098 | mmc_set_bus_speed(card); | 1126 | mmc_set_bus_speed(card); |
| 1099 | 1127 | ||
| 1128 | if (!send_status) { | ||
| 1129 | err = mmc_switch_status(card); | ||
| 1130 | if (err) | ||
| 1131 | goto out_err; | ||
| 1132 | } | ||
| 1133 | |||
| 1100 | return 0; | 1134 | return 0; |
| 1135 | |||
| 1136 | out_err: | ||
| 1137 | pr_err("%s: %s failed, error %d\n", mmc_hostname(card->host), | ||
| 1138 | __func__, err); | ||
| 1139 | return err; | ||
| 1101 | } | 1140 | } |
| 1102 | 1141 | ||
| 1103 | int mmc_hs200_to_hs400(struct mmc_card *card) | 1142 | int mmc_hs200_to_hs400(struct mmc_card *card) |
| @@ -1105,19 +1144,6 @@ int mmc_hs200_to_hs400(struct mmc_card *card) | |||
| 1105 | return mmc_select_hs400(card); | 1144 | return mmc_select_hs400(card); |
| 1106 | } | 1145 | } |
| 1107 | 1146 | ||
| 1108 | /* Caller must hold re-tuning */ | ||
| 1109 | static int mmc_switch_status(struct mmc_card *card) | ||
| 1110 | { | ||
| 1111 | u32 status; | ||
| 1112 | int err; | ||
| 1113 | |||
| 1114 | err = mmc_send_status(card, &status); | ||
| 1115 | if (err) | ||
| 1116 | return err; | ||
| 1117 | |||
| 1118 | return mmc_switch_status_error(card->host, status); | ||
| 1119 | } | ||
| 1120 | |||
| 1121 | int mmc_hs400_to_hs200(struct mmc_card *card) | 1147 | int mmc_hs400_to_hs200(struct mmc_card *card) |
| 1122 | { | 1148 | { |
| 1123 | struct mmc_host *host = card->host; | 1149 | struct mmc_host *host = card->host; |
| @@ -1219,6 +1245,8 @@ static void mmc_select_driver_type(struct mmc_card *card) | |||
| 1219 | static int mmc_select_hs200(struct mmc_card *card) | 1245 | static int mmc_select_hs200(struct mmc_card *card) |
| 1220 | { | 1246 | { |
| 1221 | struct mmc_host *host = card->host; | 1247 | struct mmc_host *host = card->host; |
| 1248 | bool send_status = true; | ||
| 1249 | unsigned int old_timing; | ||
| 1222 | int err = -EINVAL; | 1250 | int err = -EINVAL; |
| 1223 | u8 val; | 1251 | u8 val; |
| 1224 | 1252 | ||
| @@ -1234,6 +1262,9 @@ static int mmc_select_hs200(struct mmc_card *card) | |||
| 1234 | 1262 | ||
| 1235 | mmc_select_driver_type(card); | 1263 | mmc_select_driver_type(card); |
| 1236 | 1264 | ||
| 1265 | if (host->caps & MMC_CAP_WAIT_WHILE_BUSY) | ||
| 1266 | send_status = false; | ||
| 1267 | |||
| 1237 | /* | 1268 | /* |
| 1238 | * Set the bus width(4 or 8) with host's support and | 1269 | * Set the bus width(4 or 8) with host's support and |
| 1239 | * switch to HS200 mode if bus width is set successfully. | 1270 | * switch to HS200 mode if bus width is set successfully. |
| @@ -1245,11 +1276,25 @@ static int mmc_select_hs200(struct mmc_card *card) | |||
| 1245 | err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | 1276 | err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
| 1246 | EXT_CSD_HS_TIMING, val, | 1277 | EXT_CSD_HS_TIMING, val, |
| 1247 | card->ext_csd.generic_cmd6_time, | 1278 | card->ext_csd.generic_cmd6_time, |
| 1248 | true, true, true); | 1279 | true, send_status, true); |
| 1249 | if (!err) | 1280 | if (err) |
| 1250 | mmc_set_timing(host, MMC_TIMING_MMC_HS200); | 1281 | goto err; |
| 1282 | old_timing = host->ios.timing; | ||
| 1283 | mmc_set_timing(host, MMC_TIMING_MMC_HS200); | ||
| 1284 | if (!send_status) { | ||
| 1285 | err = mmc_switch_status(card); | ||
| 1286 | /* | ||
| 1287 | * mmc_select_timing() assumes timing has not changed if | ||
| 1288 | * it is a switch error. | ||
| 1289 | */ | ||
| 1290 | if (err == -EBADMSG) | ||
| 1291 | mmc_set_timing(host, old_timing); | ||
| 1292 | } | ||
| 1251 | } | 1293 | } |
| 1252 | err: | 1294 | err: |
| 1295 | if (err) | ||
| 1296 | pr_err("%s: %s failed, error %d\n", mmc_hostname(card->host), | ||
| 1297 | __func__, err); | ||
| 1253 | return err; | 1298 | return err; |
| 1254 | } | 1299 | } |
| 1255 | 1300 | ||
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index af71de5fda3b..1dee533634c9 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
| @@ -473,6 +473,7 @@ config MMC_DAVINCI | |||
| 473 | 473 | ||
| 474 | config MMC_GOLDFISH | 474 | config MMC_GOLDFISH |
| 475 | tristate "goldfish qemu Multimedia Card Interface support" | 475 | tristate "goldfish qemu Multimedia Card Interface support" |
| 476 | depends on HAS_DMA | ||
| 476 | depends on GOLDFISH || COMPILE_TEST | 477 | depends on GOLDFISH || COMPILE_TEST |
| 477 | help | 478 | help |
| 478 | This selects the Goldfish Multimedia card Interface emulation | 479 | This selects the Goldfish Multimedia card Interface emulation |
diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index 39568cc29a2a..33dfd7e72516 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c | |||
| @@ -1276,7 +1276,7 @@ static struct msdc_delay_phase get_best_delay(struct msdc_host *host, u32 delay) | |||
| 1276 | int start = 0, len = 0; | 1276 | int start = 0, len = 0; |
| 1277 | int start_final = 0, len_final = 0; | 1277 | int start_final = 0, len_final = 0; |
| 1278 | u8 final_phase = 0xff; | 1278 | u8 final_phase = 0xff; |
| 1279 | struct msdc_delay_phase delay_phase; | 1279 | struct msdc_delay_phase delay_phase = { 0, }; |
| 1280 | 1280 | ||
| 1281 | if (delay == 0) { | 1281 | if (delay == 0) { |
| 1282 | dev_err(host->dev, "phase error: [map:%x]\n", delay); | 1282 | dev_err(host->dev, "phase error: [map:%x]\n", delay); |
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 8cadd74e8407..ce08896b9d69 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c | |||
| @@ -805,7 +805,7 @@ static int pxamci_probe(struct platform_device *pdev) | |||
| 805 | goto out; | 805 | goto out; |
| 806 | } else { | 806 | } else { |
| 807 | mmc->caps |= host->pdata->gpio_card_ro_invert ? | 807 | mmc->caps |= host->pdata->gpio_card_ro_invert ? |
| 808 | MMC_CAP2_RO_ACTIVE_HIGH : 0; | 808 | 0 : MMC_CAP2_RO_ACTIVE_HIGH; |
| 809 | } | 809 | } |
| 810 | 810 | ||
| 811 | if (gpio_is_valid(gpio_cd)) | 811 | if (gpio_is_valid(gpio_cd)) |
