diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/card/block.c | 1 | ||||
-rw-r--r-- | drivers/mmc/core/core.c | 49 | ||||
-rw-r--r-- | drivers/mmc/core/host.h | 21 | ||||
-rw-r--r-- | drivers/mmc/core/mmc.c | 26 | ||||
-rw-r--r-- | drivers/mmc/core/sd.c | 22 | ||||
-rw-r--r-- | drivers/mmc/core/sdio.c | 7 | ||||
-rw-r--r-- | drivers/mmc/core/sdio_irq.c | 10 | ||||
-rw-r--r-- | drivers/mmc/host/Kconfig | 1 | ||||
-rw-r--r-- | drivers/mmc/host/atmel-mci.c | 3 | ||||
-rw-r--r-- | drivers/mmc/host/dw_mmc.c | 144 | ||||
-rw-r--r-- | drivers/mmc/host/of_mmc_spi.c | 4 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-of-esdhc.c | 32 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-pci.c | 2 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-pltfm.c | 10 | ||||
-rw-r--r-- | drivers/mmc/host/sh_mmcif.c | 16 | ||||
-rw-r--r-- | drivers/mmc/host/tmio_mmc.h | 7 | ||||
-rw-r--r-- | drivers/mmc/host/tmio_mmc_dma.c | 12 | ||||
-rw-r--r-- | drivers/mmc/host/tmio_mmc_pio.c | 6 |
18 files changed, 241 insertions, 132 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 0cad48a284a8..c6a383d0244d 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
@@ -1694,6 +1694,7 @@ static int mmc_add_disk(struct mmc_blk_data *md) | |||
1694 | 1694 | ||
1695 | md->power_ro_lock.show = power_ro_lock_show; | 1695 | md->power_ro_lock.show = power_ro_lock_show; |
1696 | md->power_ro_lock.store = power_ro_lock_store; | 1696 | md->power_ro_lock.store = power_ro_lock_store; |
1697 | sysfs_attr_init(&md->power_ro_lock.attr); | ||
1697 | md->power_ro_lock.attr.mode = mode; | 1698 | md->power_ro_lock.attr.mode = mode; |
1698 | md->power_ro_lock.attr.name = | 1699 | md->power_ro_lock.attr.name = |
1699 | "ro_lock_until_next_power_on"; | 1700 | "ro_lock_until_next_power_on"; |
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index f545a3e6eb80..690255c7d4dc 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
@@ -290,8 +290,11 @@ static void mmc_wait_for_req_done(struct mmc_host *host, | |||
290 | static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq, | 290 | static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq, |
291 | bool is_first_req) | 291 | bool is_first_req) |
292 | { | 292 | { |
293 | if (host->ops->pre_req) | 293 | if (host->ops->pre_req) { |
294 | mmc_host_clk_hold(host); | ||
294 | host->ops->pre_req(host, mrq, is_first_req); | 295 | host->ops->pre_req(host, mrq, is_first_req); |
296 | mmc_host_clk_release(host); | ||
297 | } | ||
295 | } | 298 | } |
296 | 299 | ||
297 | /** | 300 | /** |
@@ -306,8 +309,11 @@ static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq, | |||
306 | static void mmc_post_req(struct mmc_host *host, struct mmc_request *mrq, | 309 | static void mmc_post_req(struct mmc_host *host, struct mmc_request *mrq, |
307 | int err) | 310 | int err) |
308 | { | 311 | { |
309 | if (host->ops->post_req) | 312 | if (host->ops->post_req) { |
313 | mmc_host_clk_hold(host); | ||
310 | host->ops->post_req(host, mrq, err); | 314 | host->ops->post_req(host, mrq, err); |
315 | mmc_host_clk_release(host); | ||
316 | } | ||
311 | } | 317 | } |
312 | 318 | ||
313 | /** | 319 | /** |
@@ -620,7 +626,9 @@ int mmc_host_enable(struct mmc_host *host) | |||
620 | int err; | 626 | int err; |
621 | 627 | ||
622 | host->en_dis_recurs = 1; | 628 | host->en_dis_recurs = 1; |
629 | mmc_host_clk_hold(host); | ||
623 | err = host->ops->enable(host); | 630 | err = host->ops->enable(host); |
631 | mmc_host_clk_release(host); | ||
624 | host->en_dis_recurs = 0; | 632 | host->en_dis_recurs = 0; |
625 | 633 | ||
626 | if (err) { | 634 | if (err) { |
@@ -640,7 +648,9 @@ static int mmc_host_do_disable(struct mmc_host *host, int lazy) | |||
640 | int err; | 648 | int err; |
641 | 649 | ||
642 | host->en_dis_recurs = 1; | 650 | host->en_dis_recurs = 1; |
651 | mmc_host_clk_hold(host); | ||
643 | err = host->ops->disable(host, lazy); | 652 | err = host->ops->disable(host, lazy); |
653 | mmc_host_clk_release(host); | ||
644 | host->en_dis_recurs = 0; | 654 | host->en_dis_recurs = 0; |
645 | 655 | ||
646 | if (err < 0) { | 656 | if (err < 0) { |
@@ -1121,6 +1131,10 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc, | |||
1121 | * might not allow this operation | 1131 | * might not allow this operation |
1122 | */ | 1132 | */ |
1123 | voltage = regulator_get_voltage(supply); | 1133 | voltage = regulator_get_voltage(supply); |
1134 | |||
1135 | if (mmc->caps2 & MMC_CAP2_BROKEN_VOLTAGE) | ||
1136 | min_uV = max_uV = voltage; | ||
1137 | |||
1124 | if (voltage < 0) | 1138 | if (voltage < 0) |
1125 | result = voltage; | 1139 | result = voltage; |
1126 | else if (voltage < min_uV || voltage > max_uV) | 1140 | else if (voltage < min_uV || voltage > max_uV) |
@@ -1203,8 +1217,11 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, bool cmd11 | |||
1203 | 1217 | ||
1204 | host->ios.signal_voltage = signal_voltage; | 1218 | host->ios.signal_voltage = signal_voltage; |
1205 | 1219 | ||
1206 | if (host->ops->start_signal_voltage_switch) | 1220 | if (host->ops->start_signal_voltage_switch) { |
1221 | mmc_host_clk_hold(host); | ||
1207 | err = host->ops->start_signal_voltage_switch(host, &host->ios); | 1222 | err = host->ops->start_signal_voltage_switch(host, &host->ios); |
1223 | mmc_host_clk_release(host); | ||
1224 | } | ||
1208 | 1225 | ||
1209 | return err; | 1226 | return err; |
1210 | } | 1227 | } |
@@ -1239,6 +1256,7 @@ static void mmc_poweroff_notify(struct mmc_host *host) | |||
1239 | int err = 0; | 1256 | int err = 0; |
1240 | 1257 | ||
1241 | card = host->card; | 1258 | card = host->card; |
1259 | mmc_claim_host(host); | ||
1242 | 1260 | ||
1243 | /* | 1261 | /* |
1244 | * Send power notify command only if card | 1262 | * Send power notify command only if card |
@@ -1269,6 +1287,7 @@ static void mmc_poweroff_notify(struct mmc_host *host) | |||
1269 | /* Set the card state to no notification after the poweroff */ | 1287 | /* Set the card state to no notification after the poweroff */ |
1270 | card->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION; | 1288 | card->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION; |
1271 | } | 1289 | } |
1290 | mmc_release_host(host); | ||
1272 | } | 1291 | } |
1273 | 1292 | ||
1274 | /* | 1293 | /* |
@@ -1327,12 +1346,28 @@ static void mmc_power_up(struct mmc_host *host) | |||
1327 | 1346 | ||
1328 | void mmc_power_off(struct mmc_host *host) | 1347 | void mmc_power_off(struct mmc_host *host) |
1329 | { | 1348 | { |
1349 | int err = 0; | ||
1330 | mmc_host_clk_hold(host); | 1350 | mmc_host_clk_hold(host); |
1331 | 1351 | ||
1332 | host->ios.clock = 0; | 1352 | host->ios.clock = 0; |
1333 | host->ios.vdd = 0; | 1353 | host->ios.vdd = 0; |
1334 | 1354 | ||
1335 | mmc_poweroff_notify(host); | 1355 | /* |
1356 | * For eMMC 4.5 device send AWAKE command before | ||
1357 | * POWER_OFF_NOTIFY command, because in sleep state | ||
1358 | * eMMC 4.5 devices respond to only RESET and AWAKE cmd | ||
1359 | */ | ||
1360 | if (host->card && mmc_card_is_sleep(host->card) && | ||
1361 | host->bus_ops->resume) { | ||
1362 | err = host->bus_ops->resume(host); | ||
1363 | |||
1364 | if (!err) | ||
1365 | mmc_poweroff_notify(host); | ||
1366 | else | ||
1367 | pr_warning("%s: error %d during resume " | ||
1368 | "(continue with poweroff sequence)\n", | ||
1369 | mmc_hostname(host), err); | ||
1370 | } | ||
1336 | 1371 | ||
1337 | /* | 1372 | /* |
1338 | * Reset ocr mask to be the highest possible voltage supported for | 1373 | * Reset ocr mask to be the highest possible voltage supported for |
@@ -2386,12 +2421,6 @@ int mmc_suspend_host(struct mmc_host *host) | |||
2386 | */ | 2421 | */ |
2387 | if (mmc_try_claim_host(host)) { | 2422 | if (mmc_try_claim_host(host)) { |
2388 | if (host->bus_ops->suspend) { | 2423 | if (host->bus_ops->suspend) { |
2389 | /* | ||
2390 | * For eMMC 4.5 device send notify command | ||
2391 | * before sleep, because in sleep state eMMC 4.5 | ||
2392 | * devices respond to only RESET and AWAKE cmd | ||
2393 | */ | ||
2394 | mmc_poweroff_notify(host); | ||
2395 | err = host->bus_ops->suspend(host); | 2424 | err = host->bus_ops->suspend(host); |
2396 | } | 2425 | } |
2397 | mmc_do_release_host(host); | 2426 | mmc_do_release_host(host); |
diff --git a/drivers/mmc/core/host.h b/drivers/mmc/core/host.h index fb8a5cd2e4a1..08a7852ade44 100644 --- a/drivers/mmc/core/host.h +++ b/drivers/mmc/core/host.h | |||
@@ -14,27 +14,6 @@ | |||
14 | 14 | ||
15 | int mmc_register_host_class(void); | 15 | int mmc_register_host_class(void); |
16 | void mmc_unregister_host_class(void); | 16 | void mmc_unregister_host_class(void); |
17 | |||
18 | #ifdef CONFIG_MMC_CLKGATE | ||
19 | void mmc_host_clk_hold(struct mmc_host *host); | ||
20 | void mmc_host_clk_release(struct mmc_host *host); | ||
21 | unsigned int mmc_host_clk_rate(struct mmc_host *host); | ||
22 | |||
23 | #else | ||
24 | static inline void mmc_host_clk_hold(struct mmc_host *host) | ||
25 | { | ||
26 | } | ||
27 | |||
28 | static inline void mmc_host_clk_release(struct mmc_host *host) | ||
29 | { | ||
30 | } | ||
31 | |||
32 | static inline unsigned int mmc_host_clk_rate(struct mmc_host *host) | ||
33 | { | ||
34 | return host->ios.clock; | ||
35 | } | ||
36 | #endif | ||
37 | |||
38 | void mmc_host_deeper_disable(struct work_struct *work); | 17 | void mmc_host_deeper_disable(struct work_struct *work); |
39 | 18 | ||
40 | #endif | 19 | #endif |
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 59b9ba52e66a..a48066344fa8 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
@@ -376,7 +376,7 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) | |||
376 | } | 376 | } |
377 | 377 | ||
378 | card->ext_csd.raw_hc_erase_gap_size = | 378 | card->ext_csd.raw_hc_erase_gap_size = |
379 | ext_csd[EXT_CSD_PARTITION_ATTRIBUTE]; | 379 | ext_csd[EXT_CSD_HC_WP_GRP_SIZE]; |
380 | card->ext_csd.raw_sec_trim_mult = | 380 | card->ext_csd.raw_sec_trim_mult = |
381 | ext_csd[EXT_CSD_SEC_TRIM_MULT]; | 381 | ext_csd[EXT_CSD_SEC_TRIM_MULT]; |
382 | card->ext_csd.raw_sec_erase_mult = | 382 | card->ext_csd.raw_sec_erase_mult = |
@@ -551,7 +551,7 @@ static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width) | |||
551 | goto out; | 551 | goto out; |
552 | 552 | ||
553 | /* only compare read only fields */ | 553 | /* only compare read only fields */ |
554 | err = (!(card->ext_csd.raw_partition_support == | 554 | err = !((card->ext_csd.raw_partition_support == |
555 | bw_ext_csd[EXT_CSD_PARTITION_SUPPORT]) && | 555 | bw_ext_csd[EXT_CSD_PARTITION_SUPPORT]) && |
556 | (card->ext_csd.raw_erased_mem_count == | 556 | (card->ext_csd.raw_erased_mem_count == |
557 | bw_ext_csd[EXT_CSD_ERASED_MEM_CONT]) && | 557 | bw_ext_csd[EXT_CSD_ERASED_MEM_CONT]) && |
@@ -1006,7 +1006,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
1006 | err = mmc_select_hs200(card); | 1006 | err = mmc_select_hs200(card); |
1007 | else if (host->caps & MMC_CAP_MMC_HIGHSPEED) | 1007 | else if (host->caps & MMC_CAP_MMC_HIGHSPEED) |
1008 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | 1008 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
1009 | EXT_CSD_HS_TIMING, 1, 0); | 1009 | EXT_CSD_HS_TIMING, 1, |
1010 | card->ext_csd.generic_cmd6_time); | ||
1010 | 1011 | ||
1011 | if (err && err != -EBADMSG) | 1012 | if (err && err != -EBADMSG) |
1012 | goto free_card; | 1013 | goto free_card; |
@@ -1116,7 +1117,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
1116 | * Activate wide bus and DDR (if supported). | 1117 | * Activate wide bus and DDR (if supported). |
1117 | */ | 1118 | */ |
1118 | if (!mmc_card_hs200(card) && | 1119 | if (!mmc_card_hs200(card) && |
1119 | (card->csd.mmca_vsn >= CSD_SPEC_VER_3) && | 1120 | (card->csd.mmca_vsn >= CSD_SPEC_VER_4) && |
1120 | (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) { | 1121 | (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) { |
1121 | static unsigned ext_csd_bits[][2] = { | 1122 | static unsigned ext_csd_bits[][2] = { |
1122 | { EXT_CSD_BUS_WIDTH_8, EXT_CSD_DDR_BUS_WIDTH_8 }, | 1123 | { EXT_CSD_BUS_WIDTH_8, EXT_CSD_DDR_BUS_WIDTH_8 }, |
@@ -1315,11 +1316,13 @@ static int mmc_suspend(struct mmc_host *host) | |||
1315 | BUG_ON(!host->card); | 1316 | BUG_ON(!host->card); |
1316 | 1317 | ||
1317 | mmc_claim_host(host); | 1318 | mmc_claim_host(host); |
1318 | if (mmc_card_can_sleep(host)) | 1319 | if (mmc_card_can_sleep(host)) { |
1319 | err = mmc_card_sleep(host); | 1320 | err = mmc_card_sleep(host); |
1320 | else if (!mmc_host_is_spi(host)) | 1321 | if (!err) |
1322 | mmc_card_set_sleep(host->card); | ||
1323 | } else if (!mmc_host_is_spi(host)) | ||
1321 | mmc_deselect_cards(host); | 1324 | mmc_deselect_cards(host); |
1322 | host->card->state &= ~MMC_STATE_HIGHSPEED; | 1325 | host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200); |
1323 | mmc_release_host(host); | 1326 | mmc_release_host(host); |
1324 | 1327 | ||
1325 | return err; | 1328 | return err; |
@@ -1339,7 +1342,11 @@ static int mmc_resume(struct mmc_host *host) | |||
1339 | BUG_ON(!host->card); | 1342 | BUG_ON(!host->card); |
1340 | 1343 | ||
1341 | mmc_claim_host(host); | 1344 | mmc_claim_host(host); |
1342 | err = mmc_init_card(host, host->ocr, host->card); | 1345 | if (mmc_card_is_sleep(host->card)) { |
1346 | err = mmc_card_awake(host); | ||
1347 | mmc_card_clr_sleep(host->card); | ||
1348 | } else | ||
1349 | err = mmc_init_card(host, host->ocr, host->card); | ||
1343 | mmc_release_host(host); | 1350 | mmc_release_host(host); |
1344 | 1351 | ||
1345 | return err; | 1352 | return err; |
@@ -1349,7 +1356,8 @@ static int mmc_power_restore(struct mmc_host *host) | |||
1349 | { | 1356 | { |
1350 | int ret; | 1357 | int ret; |
1351 | 1358 | ||
1352 | host->card->state &= ~MMC_STATE_HIGHSPEED; | 1359 | host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200); |
1360 | mmc_card_clr_sleep(host->card); | ||
1353 | mmc_claim_host(host); | 1361 | mmc_claim_host(host); |
1354 | ret = mmc_init_card(host, host->ocr, host->card); | 1362 | ret = mmc_init_card(host, host->ocr, host->card); |
1355 | mmc_release_host(host); | 1363 | mmc_release_host(host); |
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index c63ad03c29c7..5017f9354ce2 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c | |||
@@ -451,9 +451,11 @@ static int sd_select_driver_type(struct mmc_card *card, u8 *status) | |||
451 | * information and let the hardware specific code | 451 | * information and let the hardware specific code |
452 | * return what is possible given the options | 452 | * return what is possible given the options |
453 | */ | 453 | */ |
454 | mmc_host_clk_hold(card->host); | ||
454 | drive_strength = card->host->ops->select_drive_strength( | 455 | drive_strength = card->host->ops->select_drive_strength( |
455 | card->sw_caps.uhs_max_dtr, | 456 | card->sw_caps.uhs_max_dtr, |
456 | host_drv_type, card_drv_type); | 457 | host_drv_type, card_drv_type); |
458 | mmc_host_clk_release(card->host); | ||
457 | 459 | ||
458 | err = mmc_sd_switch(card, 1, 2, drive_strength, status); | 460 | err = mmc_sd_switch(card, 1, 2, drive_strength, status); |
459 | if (err) | 461 | if (err) |
@@ -660,9 +662,12 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card) | |||
660 | goto out; | 662 | goto out; |
661 | 663 | ||
662 | /* SPI mode doesn't define CMD19 */ | 664 | /* SPI mode doesn't define CMD19 */ |
663 | if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning) | 665 | if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning) { |
666 | mmc_host_clk_hold(card->host); | ||
664 | err = card->host->ops->execute_tuning(card->host, | 667 | err = card->host->ops->execute_tuning(card->host, |
665 | MMC_SEND_TUNING_BLOCK); | 668 | MMC_SEND_TUNING_BLOCK); |
669 | mmc_host_clk_release(card->host); | ||
670 | } | ||
666 | 671 | ||
667 | out: | 672 | out: |
668 | kfree(status); | 673 | kfree(status); |
@@ -850,8 +855,11 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card, | |||
850 | if (!reinit) { | 855 | if (!reinit) { |
851 | int ro = -1; | 856 | int ro = -1; |
852 | 857 | ||
853 | if (host->ops->get_ro) | 858 | if (host->ops->get_ro) { |
859 | mmc_host_clk_hold(card->host); | ||
854 | ro = host->ops->get_ro(host); | 860 | ro = host->ops->get_ro(host); |
861 | mmc_host_clk_release(card->host); | ||
862 | } | ||
855 | 863 | ||
856 | if (ro < 0) { | 864 | if (ro < 0) { |
857 | pr_warning("%s: host does not " | 865 | pr_warning("%s: host does not " |
@@ -967,8 +975,11 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, | |||
967 | * Since initialization is now complete, enable preset | 975 | * Since initialization is now complete, enable preset |
968 | * value registers for UHS-I cards. | 976 | * value registers for UHS-I cards. |
969 | */ | 977 | */ |
970 | if (host->ops->enable_preset_value) | 978 | if (host->ops->enable_preset_value) { |
979 | mmc_host_clk_hold(card->host); | ||
971 | host->ops->enable_preset_value(host, true); | 980 | host->ops->enable_preset_value(host, true); |
981 | mmc_host_clk_release(card->host); | ||
982 | } | ||
972 | } else { | 983 | } else { |
973 | /* | 984 | /* |
974 | * Attempt to change to high-speed (if supported) | 985 | * Attempt to change to high-speed (if supported) |
@@ -1151,8 +1162,11 @@ int mmc_attach_sd(struct mmc_host *host) | |||
1151 | return err; | 1162 | return err; |
1152 | 1163 | ||
1153 | /* Disable preset value enable if already set since last time */ | 1164 | /* Disable preset value enable if already set since last time */ |
1154 | if (host->ops->enable_preset_value) | 1165 | if (host->ops->enable_preset_value) { |
1166 | mmc_host_clk_hold(host); | ||
1155 | host->ops->enable_preset_value(host, false); | 1167 | host->ops->enable_preset_value(host, false); |
1168 | mmc_host_clk_release(host); | ||
1169 | } | ||
1156 | 1170 | ||
1157 | err = mmc_send_app_op_cond(host, 0, &ocr); | 1171 | err = mmc_send_app_op_cond(host, 0, &ocr); |
1158 | if (err) | 1172 | if (err) |
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index bd7bacc950dc..12cde6ee17f5 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c | |||
@@ -98,10 +98,11 @@ fail: | |||
98 | return ret; | 98 | return ret; |
99 | } | 99 | } |
100 | 100 | ||
101 | static int sdio_read_cccr(struct mmc_card *card) | 101 | static int sdio_read_cccr(struct mmc_card *card, u32 ocr) |
102 | { | 102 | { |
103 | int ret; | 103 | int ret; |
104 | int cccr_vsn; | 104 | int cccr_vsn; |
105 | int uhs = ocr & R4_18V_PRESENT; | ||
105 | unsigned char data; | 106 | unsigned char data; |
106 | unsigned char speed; | 107 | unsigned char speed; |
107 | 108 | ||
@@ -149,7 +150,7 @@ static int sdio_read_cccr(struct mmc_card *card) | |||
149 | card->scr.sda_spec3 = 0; | 150 | card->scr.sda_spec3 = 0; |
150 | card->sw_caps.sd3_bus_mode = 0; | 151 | card->sw_caps.sd3_bus_mode = 0; |
151 | card->sw_caps.sd3_drv_type = 0; | 152 | card->sw_caps.sd3_drv_type = 0; |
152 | if (cccr_vsn >= SDIO_CCCR_REV_3_00) { | 153 | if (cccr_vsn >= SDIO_CCCR_REV_3_00 && uhs) { |
153 | card->scr.sda_spec3 = 1; | 154 | card->scr.sda_spec3 = 1; |
154 | ret = mmc_io_rw_direct(card, 0, 0, | 155 | ret = mmc_io_rw_direct(card, 0, 0, |
155 | SDIO_CCCR_UHS, 0, &data); | 156 | SDIO_CCCR_UHS, 0, &data); |
@@ -712,7 +713,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, | |||
712 | /* | 713 | /* |
713 | * Read the common registers. | 714 | * Read the common registers. |
714 | */ | 715 | */ |
715 | err = sdio_read_cccr(card); | 716 | err = sdio_read_cccr(card, ocr); |
716 | if (err) | 717 | if (err) |
717 | goto remove; | 718 | goto remove; |
718 | 719 | ||
diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c index 68f81b9ee0fb..f573e7f9f740 100644 --- a/drivers/mmc/core/sdio_irq.c +++ b/drivers/mmc/core/sdio_irq.c | |||
@@ -146,15 +146,21 @@ static int sdio_irq_thread(void *_host) | |||
146 | } | 146 | } |
147 | 147 | ||
148 | set_current_state(TASK_INTERRUPTIBLE); | 148 | set_current_state(TASK_INTERRUPTIBLE); |
149 | if (host->caps & MMC_CAP_SDIO_IRQ) | 149 | if (host->caps & MMC_CAP_SDIO_IRQ) { |
150 | mmc_host_clk_hold(host); | ||
150 | host->ops->enable_sdio_irq(host, 1); | 151 | host->ops->enable_sdio_irq(host, 1); |
152 | mmc_host_clk_release(host); | ||
153 | } | ||
151 | if (!kthread_should_stop()) | 154 | if (!kthread_should_stop()) |
152 | schedule_timeout(period); | 155 | schedule_timeout(period); |
153 | set_current_state(TASK_RUNNING); | 156 | set_current_state(TASK_RUNNING); |
154 | } while (!kthread_should_stop()); | 157 | } while (!kthread_should_stop()); |
155 | 158 | ||
156 | if (host->caps & MMC_CAP_SDIO_IRQ) | 159 | if (host->caps & MMC_CAP_SDIO_IRQ) { |
160 | mmc_host_clk_hold(host); | ||
157 | host->ops->enable_sdio_irq(host, 0); | 161 | host->ops->enable_sdio_irq(host, 0); |
162 | mmc_host_clk_release(host); | ||
163 | } | ||
158 | 164 | ||
159 | pr_debug("%s: IRQ thread exiting with code %d\n", | 165 | pr_debug("%s: IRQ thread exiting with code %d\n", |
160 | mmc_hostname(host), ret); | 166 | mmc_hostname(host), ret); |
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index cf444b0ca2cc..00fcbed1afd2 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
@@ -477,7 +477,6 @@ config MMC_SDHI | |||
477 | config MMC_CB710 | 477 | config MMC_CB710 |
478 | tristate "ENE CB710 MMC/SD Interface support" | 478 | tristate "ENE CB710 MMC/SD Interface support" |
479 | depends on PCI | 479 | depends on PCI |
480 | select MISC_DEVICES | ||
481 | select CB710_CORE | 480 | select CB710_CORE |
482 | help | 481 | help |
483 | This option enables support for MMC/SD part of ENE CB710/720 Flash | 482 | This option enables support for MMC/SD part of ENE CB710/720 Flash |
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index fcfe1eb5acc8..6985cdb0bb26 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c | |||
@@ -969,11 +969,14 @@ static void atmci_start_request(struct atmel_mci *host, | |||
969 | host->data_status = 0; | 969 | host->data_status = 0; |
970 | 970 | ||
971 | if (host->need_reset) { | 971 | if (host->need_reset) { |
972 | iflags = atmci_readl(host, ATMCI_IMR); | ||
973 | iflags &= (ATMCI_SDIOIRQA | ATMCI_SDIOIRQB); | ||
972 | atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST); | 974 | atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST); |
973 | atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN); | 975 | atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN); |
974 | atmci_writel(host, ATMCI_MR, host->mode_reg); | 976 | atmci_writel(host, ATMCI_MR, host->mode_reg); |
975 | if (host->caps.has_cfg_reg) | 977 | if (host->caps.has_cfg_reg) |
976 | atmci_writel(host, ATMCI_CFG, host->cfg_reg); | 978 | atmci_writel(host, ATMCI_CFG, host->cfg_reg); |
979 | atmci_writel(host, ATMCI_IER, iflags); | ||
977 | host->need_reset = false; | 980 | host->need_reset = false; |
978 | } | 981 | } |
979 | atmci_writel(host, ATMCI_SDCR, slot->sdc_reg); | 982 | atmci_writel(host, ATMCI_SDCR, slot->sdc_reg); |
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 0e342793ff14..8bec1c36b159 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/ioport.h> | 22 | #include <linux/ioport.h> |
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
25 | #include <linux/scatterlist.h> | ||
26 | #include <linux/seq_file.h> | 25 | #include <linux/seq_file.h> |
27 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
28 | #include <linux/stat.h> | 27 | #include <linux/stat.h> |
@@ -502,8 +501,14 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data) | |||
502 | host->dir_status = DW_MCI_SEND_STATUS; | 501 | host->dir_status = DW_MCI_SEND_STATUS; |
503 | 502 | ||
504 | if (dw_mci_submit_data_dma(host, data)) { | 503 | if (dw_mci_submit_data_dma(host, data)) { |
504 | int flags = SG_MITER_ATOMIC; | ||
505 | if (host->data->flags & MMC_DATA_READ) | ||
506 | flags |= SG_MITER_TO_SG; | ||
507 | else | ||
508 | flags |= SG_MITER_FROM_SG; | ||
509 | |||
510 | sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); | ||
505 | host->sg = data->sg; | 511 | host->sg = data->sg; |
506 | host->pio_offset = 0; | ||
507 | host->part_buf_start = 0; | 512 | host->part_buf_start = 0; |
508 | host->part_buf_count = 0; | 513 | host->part_buf_count = 0; |
509 | 514 | ||
@@ -972,6 +977,7 @@ static void dw_mci_tasklet_func(unsigned long priv) | |||
972 | * generates a block interrupt, hence setting | 977 | * generates a block interrupt, hence setting |
973 | * the scatter-gather pointer to NULL. | 978 | * the scatter-gather pointer to NULL. |
974 | */ | 979 | */ |
980 | sg_miter_stop(&host->sg_miter); | ||
975 | host->sg = NULL; | 981 | host->sg = NULL; |
976 | ctrl = mci_readl(host, CTRL); | 982 | ctrl = mci_readl(host, CTRL); |
977 | ctrl |= SDMMC_CTRL_FIFO_RESET; | 983 | ctrl |= SDMMC_CTRL_FIFO_RESET; |
@@ -1311,54 +1317,44 @@ static void dw_mci_pull_data(struct dw_mci *host, void *buf, int cnt) | |||
1311 | 1317 | ||
1312 | static void dw_mci_read_data_pio(struct dw_mci *host) | 1318 | static void dw_mci_read_data_pio(struct dw_mci *host) |
1313 | { | 1319 | { |
1314 | struct scatterlist *sg = host->sg; | 1320 | struct sg_mapping_iter *sg_miter = &host->sg_miter; |
1315 | void *buf = sg_virt(sg); | 1321 | void *buf; |
1316 | unsigned int offset = host->pio_offset; | 1322 | unsigned int offset; |
1317 | struct mmc_data *data = host->data; | 1323 | struct mmc_data *data = host->data; |
1318 | int shift = host->data_shift; | 1324 | int shift = host->data_shift; |
1319 | u32 status; | 1325 | u32 status; |
1320 | unsigned int nbytes = 0, len; | 1326 | unsigned int nbytes = 0, len; |
1327 | unsigned int remain, fcnt; | ||
1321 | 1328 | ||
1322 | do { | 1329 | do { |
1323 | len = host->part_buf_count + | 1330 | if (!sg_miter_next(sg_miter)) |
1324 | (SDMMC_GET_FCNT(mci_readl(host, STATUS)) << shift); | 1331 | goto done; |
1325 | if (offset + len <= sg->length) { | 1332 | |
1333 | host->sg = sg_miter->__sg; | ||
1334 | buf = sg_miter->addr; | ||
1335 | remain = sg_miter->length; | ||
1336 | offset = 0; | ||
1337 | |||
1338 | do { | ||
1339 | fcnt = (SDMMC_GET_FCNT(mci_readl(host, STATUS)) | ||
1340 | << shift) + host->part_buf_count; | ||
1341 | len = min(remain, fcnt); | ||
1342 | if (!len) | ||
1343 | break; | ||
1326 | dw_mci_pull_data(host, (void *)(buf + offset), len); | 1344 | dw_mci_pull_data(host, (void *)(buf + offset), len); |
1327 | |||
1328 | offset += len; | 1345 | offset += len; |
1329 | nbytes += len; | 1346 | nbytes += len; |
1330 | 1347 | remain -= len; | |
1331 | if (offset == sg->length) { | 1348 | } while (remain); |
1332 | flush_dcache_page(sg_page(sg)); | 1349 | sg_miter->consumed = offset; |
1333 | host->sg = sg = sg_next(sg); | ||
1334 | if (!sg) | ||
1335 | goto done; | ||
1336 | |||
1337 | offset = 0; | ||
1338 | buf = sg_virt(sg); | ||
1339 | } | ||
1340 | } else { | ||
1341 | unsigned int remaining = sg->length - offset; | ||
1342 | dw_mci_pull_data(host, (void *)(buf + offset), | ||
1343 | remaining); | ||
1344 | nbytes += remaining; | ||
1345 | |||
1346 | flush_dcache_page(sg_page(sg)); | ||
1347 | host->sg = sg = sg_next(sg); | ||
1348 | if (!sg) | ||
1349 | goto done; | ||
1350 | |||
1351 | offset = len - remaining; | ||
1352 | buf = sg_virt(sg); | ||
1353 | dw_mci_pull_data(host, buf, offset); | ||
1354 | nbytes += offset; | ||
1355 | } | ||
1356 | 1350 | ||
1357 | status = mci_readl(host, MINTSTS); | 1351 | status = mci_readl(host, MINTSTS); |
1358 | mci_writel(host, RINTSTS, SDMMC_INT_RXDR); | 1352 | mci_writel(host, RINTSTS, SDMMC_INT_RXDR); |
1359 | if (status & DW_MCI_DATA_ERROR_FLAGS) { | 1353 | if (status & DW_MCI_DATA_ERROR_FLAGS) { |
1360 | host->data_status = status; | 1354 | host->data_status = status; |
1361 | data->bytes_xfered += nbytes; | 1355 | data->bytes_xfered += nbytes; |
1356 | sg_miter_stop(sg_miter); | ||
1357 | host->sg = NULL; | ||
1362 | smp_wmb(); | 1358 | smp_wmb(); |
1363 | 1359 | ||
1364 | set_bit(EVENT_DATA_ERROR, &host->pending_events); | 1360 | set_bit(EVENT_DATA_ERROR, &host->pending_events); |
@@ -1367,65 +1363,66 @@ static void dw_mci_read_data_pio(struct dw_mci *host) | |||
1367 | return; | 1363 | return; |
1368 | } | 1364 | } |
1369 | } while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/ | 1365 | } while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/ |
1370 | host->pio_offset = offset; | ||
1371 | data->bytes_xfered += nbytes; | 1366 | data->bytes_xfered += nbytes; |
1367 | |||
1368 | if (!remain) { | ||
1369 | if (!sg_miter_next(sg_miter)) | ||
1370 | goto done; | ||
1371 | sg_miter->consumed = 0; | ||
1372 | } | ||
1373 | sg_miter_stop(sg_miter); | ||
1372 | return; | 1374 | return; |
1373 | 1375 | ||
1374 | done: | 1376 | done: |
1375 | data->bytes_xfered += nbytes; | 1377 | data->bytes_xfered += nbytes; |
1378 | sg_miter_stop(sg_miter); | ||
1379 | host->sg = NULL; | ||
1376 | smp_wmb(); | 1380 | smp_wmb(); |
1377 | set_bit(EVENT_XFER_COMPLETE, &host->pending_events); | 1381 | set_bit(EVENT_XFER_COMPLETE, &host->pending_events); |
1378 | } | 1382 | } |
1379 | 1383 | ||
1380 | static void dw_mci_write_data_pio(struct dw_mci *host) | 1384 | static void dw_mci_write_data_pio(struct dw_mci *host) |
1381 | { | 1385 | { |
1382 | struct scatterlist *sg = host->sg; | 1386 | struct sg_mapping_iter *sg_miter = &host->sg_miter; |
1383 | void *buf = sg_virt(sg); | 1387 | void *buf; |
1384 | unsigned int offset = host->pio_offset; | 1388 | unsigned int offset; |
1385 | struct mmc_data *data = host->data; | 1389 | struct mmc_data *data = host->data; |
1386 | int shift = host->data_shift; | 1390 | int shift = host->data_shift; |
1387 | u32 status; | 1391 | u32 status; |
1388 | unsigned int nbytes = 0, len; | 1392 | unsigned int nbytes = 0, len; |
1393 | unsigned int fifo_depth = host->fifo_depth; | ||
1394 | unsigned int remain, fcnt; | ||
1389 | 1395 | ||
1390 | do { | 1396 | do { |
1391 | len = ((host->fifo_depth - | 1397 | if (!sg_miter_next(sg_miter)) |
1392 | SDMMC_GET_FCNT(mci_readl(host, STATUS))) << shift) | 1398 | goto done; |
1393 | - host->part_buf_count; | 1399 | |
1394 | if (offset + len <= sg->length) { | 1400 | host->sg = sg_miter->__sg; |
1401 | buf = sg_miter->addr; | ||
1402 | remain = sg_miter->length; | ||
1403 | offset = 0; | ||
1404 | |||
1405 | do { | ||
1406 | fcnt = ((fifo_depth - | ||
1407 | SDMMC_GET_FCNT(mci_readl(host, STATUS))) | ||
1408 | << shift) - host->part_buf_count; | ||
1409 | len = min(remain, fcnt); | ||
1410 | if (!len) | ||
1411 | break; | ||
1395 | host->push_data(host, (void *)(buf + offset), len); | 1412 | host->push_data(host, (void *)(buf + offset), len); |
1396 | |||
1397 | offset += len; | 1413 | offset += len; |
1398 | nbytes += len; | 1414 | nbytes += len; |
1399 | if (offset == sg->length) { | 1415 | remain -= len; |
1400 | host->sg = sg = sg_next(sg); | 1416 | } while (remain); |
1401 | if (!sg) | 1417 | sg_miter->consumed = offset; |
1402 | goto done; | ||
1403 | |||
1404 | offset = 0; | ||
1405 | buf = sg_virt(sg); | ||
1406 | } | ||
1407 | } else { | ||
1408 | unsigned int remaining = sg->length - offset; | ||
1409 | |||
1410 | host->push_data(host, (void *)(buf + offset), | ||
1411 | remaining); | ||
1412 | nbytes += remaining; | ||
1413 | |||
1414 | host->sg = sg = sg_next(sg); | ||
1415 | if (!sg) | ||
1416 | goto done; | ||
1417 | |||
1418 | offset = len - remaining; | ||
1419 | buf = sg_virt(sg); | ||
1420 | host->push_data(host, (void *)buf, offset); | ||
1421 | nbytes += offset; | ||
1422 | } | ||
1423 | 1418 | ||
1424 | status = mci_readl(host, MINTSTS); | 1419 | status = mci_readl(host, MINTSTS); |
1425 | mci_writel(host, RINTSTS, SDMMC_INT_TXDR); | 1420 | mci_writel(host, RINTSTS, SDMMC_INT_TXDR); |
1426 | if (status & DW_MCI_DATA_ERROR_FLAGS) { | 1421 | if (status & DW_MCI_DATA_ERROR_FLAGS) { |
1427 | host->data_status = status; | 1422 | host->data_status = status; |
1428 | data->bytes_xfered += nbytes; | 1423 | data->bytes_xfered += nbytes; |
1424 | sg_miter_stop(sg_miter); | ||
1425 | host->sg = NULL; | ||
1429 | 1426 | ||
1430 | smp_wmb(); | 1427 | smp_wmb(); |
1431 | 1428 | ||
@@ -1435,12 +1432,20 @@ static void dw_mci_write_data_pio(struct dw_mci *host) | |||
1435 | return; | 1432 | return; |
1436 | } | 1433 | } |
1437 | } while (status & SDMMC_INT_TXDR); /* if TXDR write again */ | 1434 | } while (status & SDMMC_INT_TXDR); /* if TXDR write again */ |
1438 | host->pio_offset = offset; | ||
1439 | data->bytes_xfered += nbytes; | 1435 | data->bytes_xfered += nbytes; |
1436 | |||
1437 | if (!remain) { | ||
1438 | if (!sg_miter_next(sg_miter)) | ||
1439 | goto done; | ||
1440 | sg_miter->consumed = 0; | ||
1441 | } | ||
1442 | sg_miter_stop(sg_miter); | ||
1440 | return; | 1443 | return; |
1441 | 1444 | ||
1442 | done: | 1445 | done: |
1443 | data->bytes_xfered += nbytes; | 1446 | data->bytes_xfered += nbytes; |
1447 | sg_miter_stop(sg_miter); | ||
1448 | host->sg = NULL; | ||
1444 | smp_wmb(); | 1449 | smp_wmb(); |
1445 | set_bit(EVENT_XFER_COMPLETE, &host->pending_events); | 1450 | set_bit(EVENT_XFER_COMPLETE, &host->pending_events); |
1446 | } | 1451 | } |
@@ -1643,6 +1648,7 @@ static void dw_mci_work_routine_card(struct work_struct *work) | |||
1643 | * block interrupt, hence setting the | 1648 | * block interrupt, hence setting the |
1644 | * scatter-gather pointer to NULL. | 1649 | * scatter-gather pointer to NULL. |
1645 | */ | 1650 | */ |
1651 | sg_miter_stop(&host->sg_miter); | ||
1646 | host->sg = NULL; | 1652 | host->sg = NULL; |
1647 | 1653 | ||
1648 | ctrl = mci_readl(host, CTRL); | 1654 | ctrl = mci_readl(host, CTRL); |
diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c index ab66f2454dc4..1534b582c419 100644 --- a/drivers/mmc/host/of_mmc_spi.c +++ b/drivers/mmc/host/of_mmc_spi.c | |||
@@ -113,8 +113,8 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi) | |||
113 | const int j = i * 2; | 113 | const int j = i * 2; |
114 | u32 mask; | 114 | u32 mask; |
115 | 115 | ||
116 | mask = mmc_vddrange_to_ocrmask(voltage_ranges[j], | 116 | mask = mmc_vddrange_to_ocrmask(be32_to_cpu(voltage_ranges[j]), |
117 | voltage_ranges[j + 1]); | 117 | be32_to_cpu(voltage_ranges[j + 1])); |
118 | if (!mask) { | 118 | if (!mask) { |
119 | ret = -EINVAL; | 119 | ret = -EINVAL; |
120 | dev_err(dev, "OF: voltage-range #%d is invalid\n", i); | 120 | dev_err(dev, "OF: voltage-range #%d is invalid\n", i); |
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index ff4adc018041..5d876ff86f37 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c | |||
@@ -38,6 +38,23 @@ static u8 esdhc_readb(struct sdhci_host *host, int reg) | |||
38 | int base = reg & ~0x3; | 38 | int base = reg & ~0x3; |
39 | int shift = (reg & 0x3) * 8; | 39 | int shift = (reg & 0x3) * 8; |
40 | u8 ret = (in_be32(host->ioaddr + base) >> shift) & 0xff; | 40 | u8 ret = (in_be32(host->ioaddr + base) >> shift) & 0xff; |
41 | |||
42 | /* | ||
43 | * "DMA select" locates at offset 0x28 in SD specification, but on | ||
44 | * P5020 or P3041, it locates at 0x29. | ||
45 | */ | ||
46 | if (reg == SDHCI_HOST_CONTROL) { | ||
47 | u32 dma_bits; | ||
48 | |||
49 | dma_bits = in_be32(host->ioaddr + reg); | ||
50 | /* DMA select is 22,23 bits in Protocol Control Register */ | ||
51 | dma_bits = (dma_bits >> 5) & SDHCI_CTRL_DMA_MASK; | ||
52 | |||
53 | /* fixup the result */ | ||
54 | ret &= ~SDHCI_CTRL_DMA_MASK; | ||
55 | ret |= dma_bits; | ||
56 | } | ||
57 | |||
41 | return ret; | 58 | return ret; |
42 | } | 59 | } |
43 | 60 | ||
@@ -56,6 +73,21 @@ static void esdhc_writew(struct sdhci_host *host, u16 val, int reg) | |||
56 | 73 | ||
57 | static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg) | 74 | static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg) |
58 | { | 75 | { |
76 | /* | ||
77 | * "DMA select" location is offset 0x28 in SD specification, but on | ||
78 | * P5020 or P3041, it's located at 0x29. | ||
79 | */ | ||
80 | if (reg == SDHCI_HOST_CONTROL) { | ||
81 | u32 dma_bits; | ||
82 | |||
83 | /* DMA select is 22,23 bits in Protocol Control Register */ | ||
84 | dma_bits = (val & SDHCI_CTRL_DMA_MASK) << 5; | ||
85 | clrsetbits_be32(host->ioaddr + reg , SDHCI_CTRL_DMA_MASK << 5, | ||
86 | dma_bits); | ||
87 | val &= ~SDHCI_CTRL_DMA_MASK; | ||
88 | val |= in_be32(host->ioaddr + reg) & SDHCI_CTRL_DMA_MASK; | ||
89 | } | ||
90 | |||
59 | /* Prevent SDHCI core from writing reserved bits (e.g. HISPD). */ | 91 | /* Prevent SDHCI core from writing reserved bits (e.g. HISPD). */ |
60 | if (reg == SDHCI_HOST_CONTROL) | 92 | if (reg == SDHCI_HOST_CONTROL) |
61 | val &= ~ESDHC_HOST_CONTROL_RES; | 93 | val &= ~ESDHC_HOST_CONTROL_RES; |
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 7165e6a09274..6ebdc4010e7c 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
@@ -250,7 +250,7 @@ static int mfd_emmc_probe_slot(struct sdhci_pci_slot *slot) | |||
250 | 250 | ||
251 | static int mfd_sdio_probe_slot(struct sdhci_pci_slot *slot) | 251 | static int mfd_sdio_probe_slot(struct sdhci_pci_slot *slot) |
252 | { | 252 | { |
253 | slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD; | 253 | slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE; |
254 | return 0; | 254 | return 0; |
255 | } | 255 | } |
256 | 256 | ||
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index 03970bcb3495..c5c2a48bdd94 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * sdhci-pltfm.c Support for SDHCI platform devices | 2 | * sdhci-pltfm.c Support for SDHCI platform devices |
3 | * Copyright (c) 2009 Intel Corporation | 3 | * Copyright (c) 2009 Intel Corporation |
4 | * | 4 | * |
5 | * Copyright (c) 2007 Freescale Semiconductor, Inc. | 5 | * Copyright (c) 2007, 2011 Freescale Semiconductor, Inc. |
6 | * Copyright (c) 2009 MontaVista Software, Inc. | 6 | * Copyright (c) 2009 MontaVista Software, Inc. |
7 | * | 7 | * |
8 | * Authors: Xiaobo Xie <X.Xie@freescale.com> | 8 | * Authors: Xiaobo Xie <X.Xie@freescale.com> |
@@ -71,6 +71,14 @@ void sdhci_get_of_property(struct platform_device *pdev) | |||
71 | if (sdhci_of_wp_inverted(np)) | 71 | if (sdhci_of_wp_inverted(np)) |
72 | host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT; | 72 | host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT; |
73 | 73 | ||
74 | if (of_device_is_compatible(np, "fsl,p2020-rev1-esdhc")) | ||
75 | host->quirks |= SDHCI_QUIRK_BROKEN_DMA; | ||
76 | |||
77 | if (of_device_is_compatible(np, "fsl,p2020-esdhc") || | ||
78 | of_device_is_compatible(np, "fsl,p1010-esdhc") || | ||
79 | of_device_is_compatible(np, "fsl,mpc8536-esdhc")) | ||
80 | host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; | ||
81 | |||
74 | clk = of_get_property(np, "clock-frequency", &size); | 82 | clk = of_get_property(np, "clock-frequency", &size); |
75 | if (clk && size == sizeof(*clk) && *clk) | 83 | if (clk && size == sizeof(*clk) && *clk) |
76 | pltfm_host->clock = be32_to_cpup(clk); | 84 | pltfm_host->clock = be32_to_cpup(clk); |
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index f5d8b53be333..352d4797865b 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c | |||
@@ -1327,7 +1327,7 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev) | |||
1327 | if (ret < 0) | 1327 | if (ret < 0) |
1328 | goto clean_up2; | 1328 | goto clean_up2; |
1329 | 1329 | ||
1330 | mmc_add_host(mmc); | 1330 | INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work); |
1331 | 1331 | ||
1332 | sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); | 1332 | sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); |
1333 | 1333 | ||
@@ -1338,22 +1338,24 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev) | |||
1338 | } | 1338 | } |
1339 | ret = request_threaded_irq(irq[1], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:int", host); | 1339 | ret = request_threaded_irq(irq[1], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:int", host); |
1340 | if (ret) { | 1340 | if (ret) { |
1341 | free_irq(irq[0], host); | ||
1342 | dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n"); | 1341 | dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n"); |
1343 | goto clean_up3; | 1342 | goto clean_up4; |
1344 | } | 1343 | } |
1345 | 1344 | ||
1346 | INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work); | 1345 | ret = mmc_add_host(mmc); |
1347 | 1346 | if (ret < 0) | |
1348 | mmc_detect_change(host->mmc, 0); | 1347 | goto clean_up5; |
1349 | 1348 | ||
1350 | dev_info(&pdev->dev, "driver version %s\n", DRIVER_VERSION); | 1349 | dev_info(&pdev->dev, "driver version %s\n", DRIVER_VERSION); |
1351 | dev_dbg(&pdev->dev, "chip ver H'%04x\n", | 1350 | dev_dbg(&pdev->dev, "chip ver H'%04x\n", |
1352 | sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0x0000ffff); | 1351 | sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0x0000ffff); |
1353 | return ret; | 1352 | return ret; |
1354 | 1353 | ||
1354 | clean_up5: | ||
1355 | free_irq(irq[1], host); | ||
1356 | clean_up4: | ||
1357 | free_irq(irq[0], host); | ||
1355 | clean_up3: | 1358 | clean_up3: |
1356 | mmc_remove_host(mmc); | ||
1357 | pm_runtime_suspend(&pdev->dev); | 1359 | pm_runtime_suspend(&pdev->dev); |
1358 | clean_up2: | 1360 | clean_up2: |
1359 | pm_runtime_disable(&pdev->dev); | 1361 | pm_runtime_disable(&pdev->dev); |
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index a95e6d901726..f96c536d130a 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h | |||
@@ -20,8 +20,8 @@ | |||
20 | #include <linux/mmc/tmio.h> | 20 | #include <linux/mmc/tmio.h> |
21 | #include <linux/mutex.h> | 21 | #include <linux/mutex.h> |
22 | #include <linux/pagemap.h> | 22 | #include <linux/pagemap.h> |
23 | #include <linux/spinlock.h> | ||
24 | #include <linux/scatterlist.h> | 23 | #include <linux/scatterlist.h> |
24 | #include <linux/spinlock.h> | ||
25 | 25 | ||
26 | /* Definitions for values the CTRL_SDIO_STATUS register can take. */ | 26 | /* Definitions for values the CTRL_SDIO_STATUS register can take. */ |
27 | #define TMIO_SDIO_STAT_IOIRQ 0x0001 | 27 | #define TMIO_SDIO_STAT_IOIRQ 0x0001 |
@@ -120,6 +120,7 @@ void tmio_mmc_start_dma(struct tmio_mmc_host *host, struct mmc_data *data); | |||
120 | void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable); | 120 | void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable); |
121 | void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata); | 121 | void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata); |
122 | void tmio_mmc_release_dma(struct tmio_mmc_host *host); | 122 | void tmio_mmc_release_dma(struct tmio_mmc_host *host); |
123 | void tmio_mmc_abort_dma(struct tmio_mmc_host *host); | ||
123 | #else | 124 | #else |
124 | static inline void tmio_mmc_start_dma(struct tmio_mmc_host *host, | 125 | static inline void tmio_mmc_start_dma(struct tmio_mmc_host *host, |
125 | struct mmc_data *data) | 126 | struct mmc_data *data) |
@@ -140,6 +141,10 @@ static inline void tmio_mmc_request_dma(struct tmio_mmc_host *host, | |||
140 | static inline void tmio_mmc_release_dma(struct tmio_mmc_host *host) | 141 | static inline void tmio_mmc_release_dma(struct tmio_mmc_host *host) |
141 | { | 142 | { |
142 | } | 143 | } |
144 | |||
145 | static inline void tmio_mmc_abort_dma(struct tmio_mmc_host *host) | ||
146 | { | ||
147 | } | ||
143 | #endif | 148 | #endif |
144 | 149 | ||
145 | #ifdef CONFIG_PM | 150 | #ifdef CONFIG_PM |
diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c index 7a6e6cc8f8b8..8253ec12003e 100644 --- a/drivers/mmc/host/tmio_mmc_dma.c +++ b/drivers/mmc/host/tmio_mmc_dma.c | |||
@@ -34,6 +34,18 @@ void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable) | |||
34 | #endif | 34 | #endif |
35 | } | 35 | } |
36 | 36 | ||
37 | void tmio_mmc_abort_dma(struct tmio_mmc_host *host) | ||
38 | { | ||
39 | tmio_mmc_enable_dma(host, false); | ||
40 | |||
41 | if (host->chan_rx) | ||
42 | dmaengine_terminate_all(host->chan_rx); | ||
43 | if (host->chan_tx) | ||
44 | dmaengine_terminate_all(host->chan_tx); | ||
45 | |||
46 | tmio_mmc_enable_dma(host, true); | ||
47 | } | ||
48 | |||
37 | static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host) | 49 | static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host) |
38 | { | 50 | { |
39 | struct scatterlist *sg = host->sg_ptr, *sg_tmp; | 51 | struct scatterlist *sg = host->sg_ptr, *sg_tmp; |
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index abad01b37cfb..5f9ad74fbf80 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c | |||
@@ -41,8 +41,8 @@ | |||
41 | #include <linux/platform_device.h> | 41 | #include <linux/platform_device.h> |
42 | #include <linux/pm_runtime.h> | 42 | #include <linux/pm_runtime.h> |
43 | #include <linux/scatterlist.h> | 43 | #include <linux/scatterlist.h> |
44 | #include <linux/workqueue.h> | ||
45 | #include <linux/spinlock.h> | 44 | #include <linux/spinlock.h> |
45 | #include <linux/workqueue.h> | ||
46 | 46 | ||
47 | #include "tmio_mmc.h" | 47 | #include "tmio_mmc.h" |
48 | 48 | ||
@@ -246,6 +246,7 @@ static void tmio_mmc_reset_work(struct work_struct *work) | |||
246 | /* Ready for new calls */ | 246 | /* Ready for new calls */ |
247 | host->mrq = NULL; | 247 | host->mrq = NULL; |
248 | 248 | ||
249 | tmio_mmc_abort_dma(host); | ||
249 | mmc_request_done(host->mmc, mrq); | 250 | mmc_request_done(host->mmc, mrq); |
250 | } | 251 | } |
251 | 252 | ||
@@ -272,6 +273,9 @@ static void tmio_mmc_finish_request(struct tmio_mmc_host *host) | |||
272 | host->mrq = NULL; | 273 | host->mrq = NULL; |
273 | spin_unlock_irqrestore(&host->lock, flags); | 274 | spin_unlock_irqrestore(&host->lock, flags); |
274 | 275 | ||
276 | if (mrq->cmd->error || (mrq->data && mrq->data->error)) | ||
277 | tmio_mmc_abort_dma(host); | ||
278 | |||
275 | mmc_request_done(host->mmc, mrq); | 279 | mmc_request_done(host->mmc, mrq); |
276 | } | 280 | } |
277 | 281 | ||