.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * linux/drivers/mmc/core/mmc.c |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2003-2004 Russell King, All Rights Reserved. |
---|
5 | 6 | * Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved. |
---|
6 | 7 | * MMCv4 support Copyright (C) 2006 Philip Langdale, All Rights Reserved. |
---|
7 | | - * |
---|
8 | | - * This program is free software; you can redistribute it and/or modify |
---|
9 | | - * it under the terms of the GNU General Public License version 2 as |
---|
10 | | - * published by the Free Software Foundation. |
---|
11 | 8 | */ |
---|
12 | 9 | |
---|
13 | 10 | #include <linux/err.h> |
---|
.. | .. |
---|
661 | 658 | mmc_hostname(card->host), |
---|
662 | 659 | card->ext_csd.cmdq_depth); |
---|
663 | 660 | } |
---|
| 661 | + card->ext_csd.enhanced_rpmb_supported = |
---|
| 662 | + (card->ext_csd.rel_param & |
---|
| 663 | + EXT_CSD_WR_REL_PARAM_EN_RPMB_REL_WR); |
---|
664 | 664 | } |
---|
665 | 665 | out: |
---|
666 | 666 | return err; |
---|
.. | .. |
---|
697 | 697 | u8 *ext_csd; |
---|
698 | 698 | int err; |
---|
699 | 699 | #ifdef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC |
---|
700 | | - void *ecsd = NULL; |
---|
| 700 | + void *ecsd; |
---|
701 | 701 | bool valid_ecsd = false; |
---|
702 | 702 | bool valid_reserved = false; |
---|
703 | 703 | struct device_node *mem; |
---|
.. | .. |
---|
875 | 875 | card->ext_csd.enhanced_area_offset); |
---|
876 | 876 | MMC_DEV_ATTR(enhanced_area_size, "%u\n", card->ext_csd.enhanced_area_size); |
---|
877 | 877 | MMC_DEV_ATTR(raw_rpmb_size_mult, "%#x\n", card->ext_csd.raw_rpmb_size_mult); |
---|
| 878 | +MMC_DEV_ATTR(enhanced_rpmb_supported, "%#x\n", |
---|
| 879 | + card->ext_csd.enhanced_rpmb_supported); |
---|
878 | 880 | MMC_DEV_ATTR(rel_sectors, "%#x\n", card->ext_csd.rel_sectors); |
---|
879 | 881 | MMC_DEV_ATTR(ocr, "0x%08x\n", card->ocr); |
---|
880 | 882 | MMC_DEV_ATTR(rca, "0x%04x\n", card->rca); |
---|
.. | .. |
---|
932 | 934 | &dev_attr_enhanced_area_offset.attr, |
---|
933 | 935 | &dev_attr_enhanced_area_size.attr, |
---|
934 | 936 | &dev_attr_raw_rpmb_size_mult.attr, |
---|
| 937 | + &dev_attr_enhanced_rpmb_supported.attr, |
---|
935 | 938 | &dev_attr_rel_sectors.attr, |
---|
936 | 939 | &dev_attr_ocr.attr, |
---|
937 | 940 | &dev_attr_rca.attr, |
---|
.. | .. |
---|
1048 | 1051 | /* |
---|
1049 | 1052 | * Set the bus speed for the selected speed mode. |
---|
1050 | 1053 | */ |
---|
1051 | | -static void mmc_set_bus_speed(struct mmc_card *card) |
---|
| 1054 | +void mmc_set_bus_speed(struct mmc_card *card) |
---|
1052 | 1055 | { |
---|
1053 | 1056 | unsigned int max_dtr = (unsigned int)-1; |
---|
1054 | 1057 | |
---|
.. | .. |
---|
1068 | 1071 | * If the bus width is changed successfully, return the selected width value. |
---|
1069 | 1072 | * Zero is returned instead of error value if the wide width is not supported. |
---|
1070 | 1073 | */ |
---|
1071 | | -static int mmc_select_bus_width(struct mmc_card *card) |
---|
| 1074 | +int mmc_select_bus_width(struct mmc_card *card) |
---|
1072 | 1075 | { |
---|
1073 | 1076 | static unsigned ext_csd_bits[] = { |
---|
1074 | 1077 | EXT_CSD_BUS_WIDTH_8, |
---|
.. | .. |
---|
1134 | 1137 | |
---|
1135 | 1138 | return err; |
---|
1136 | 1139 | } |
---|
| 1140 | +EXPORT_SYMBOL_GPL(mmc_select_bus_width); |
---|
1137 | 1141 | |
---|
1138 | 1142 | /* |
---|
1139 | 1143 | * Switch to the high-speed mode |
---|
1140 | 1144 | */ |
---|
1141 | | -static int mmc_select_hs(struct mmc_card *card) |
---|
| 1145 | +int mmc_select_hs(struct mmc_card *card) |
---|
1142 | 1146 | { |
---|
1143 | 1147 | int err; |
---|
1144 | 1148 | |
---|
1145 | 1149 | err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
---|
1146 | 1150 | EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS, |
---|
1147 | 1151 | card->ext_csd.generic_cmd6_time, MMC_TIMING_MMC_HS, |
---|
1148 | | - true, true, true); |
---|
| 1152 | + true, true); |
---|
1149 | 1153 | if (err) |
---|
1150 | 1154 | pr_warn("%s: switch to high-speed failed, err:%d\n", |
---|
1151 | 1155 | mmc_hostname(card->host), err); |
---|
1152 | 1156 | |
---|
1153 | 1157 | return err; |
---|
1154 | 1158 | } |
---|
| 1159 | +EXPORT_SYMBOL_GPL(mmc_select_hs); |
---|
1155 | 1160 | |
---|
1156 | 1161 | /* |
---|
1157 | 1162 | * Activate wide bus and DDR if supported. |
---|
1158 | 1163 | */ |
---|
1159 | | -static int mmc_select_hs_ddr(struct mmc_card *card) |
---|
| 1164 | +int mmc_select_hs_ddr(struct mmc_card *card) |
---|
1160 | 1165 | { |
---|
1161 | 1166 | struct mmc_host *host = card->host; |
---|
1162 | 1167 | u32 bus_width, ext_csd_bits; |
---|
.. | .. |
---|
1177 | 1182 | ext_csd_bits, |
---|
1178 | 1183 | card->ext_csd.generic_cmd6_time, |
---|
1179 | 1184 | MMC_TIMING_MMC_DDR52, |
---|
1180 | | - true, true, true); |
---|
| 1185 | + true, true); |
---|
1181 | 1186 | if (err) { |
---|
1182 | 1187 | pr_err("%s: switch to bus width %d ddr failed\n", |
---|
1183 | 1188 | mmc_hostname(host), 1 << bus_width); |
---|
.. | .. |
---|
1225 | 1230 | |
---|
1226 | 1231 | return err; |
---|
1227 | 1232 | } |
---|
| 1233 | +EXPORT_SYMBOL_GPL(mmc_select_hs_ddr); |
---|
1228 | 1234 | |
---|
1229 | | -static int mmc_select_hs400(struct mmc_card *card) |
---|
| 1235 | +int mmc_select_hs400(struct mmc_card *card) |
---|
1230 | 1236 | { |
---|
1231 | 1237 | struct mmc_host *host = card->host; |
---|
1232 | 1238 | unsigned int max_dtr; |
---|
.. | .. |
---|
1245 | 1251 | err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
---|
1246 | 1252 | EXT_CSD_HS_TIMING, val, |
---|
1247 | 1253 | card->ext_csd.generic_cmd6_time, 0, |
---|
1248 | | - true, false, true); |
---|
| 1254 | + false, true); |
---|
1249 | 1255 | if (err) { |
---|
1250 | 1256 | pr_err("%s: switch to high-speed from hs200 failed, err:%d\n", |
---|
1251 | 1257 | mmc_hostname(host), err); |
---|
1252 | 1258 | return err; |
---|
1253 | 1259 | } |
---|
1254 | 1260 | |
---|
1255 | | - /* Set host controller to HS timing */ |
---|
1256 | | - mmc_set_timing(card->host, MMC_TIMING_MMC_HS); |
---|
1257 | | - |
---|
1258 | 1261 | /* Prepare host to downgrade to HS timing */ |
---|
1259 | 1262 | if (host->ops->hs400_downgrade) |
---|
1260 | 1263 | host->ops->hs400_downgrade(host); |
---|
| 1264 | + |
---|
| 1265 | + /* Set host controller to HS timing */ |
---|
| 1266 | + mmc_set_timing(host, MMC_TIMING_MMC_HS); |
---|
1261 | 1267 | |
---|
1262 | 1268 | /* Reduce frequency to HS frequency */ |
---|
1263 | 1269 | max_dtr = card->ext_csd.hs_max_dtr; |
---|
1264 | 1270 | mmc_set_clock(host, max_dtr); |
---|
1265 | 1271 | |
---|
1266 | | - err = mmc_switch_status(card); |
---|
| 1272 | + err = mmc_switch_status(card, true); |
---|
1267 | 1273 | if (err) |
---|
1268 | 1274 | goto out_err; |
---|
| 1275 | + |
---|
| 1276 | + if (host->ops->hs400_prepare_ddr) |
---|
| 1277 | + host->ops->hs400_prepare_ddr(host); |
---|
1269 | 1278 | |
---|
1270 | 1279 | /* Switch card to DDR */ |
---|
1271 | 1280 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
---|
.. | .. |
---|
1284 | 1293 | err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
---|
1285 | 1294 | EXT_CSD_HS_TIMING, val, |
---|
1286 | 1295 | card->ext_csd.generic_cmd6_time, 0, |
---|
1287 | | - true, false, true); |
---|
| 1296 | + false, true); |
---|
1288 | 1297 | if (err) { |
---|
1289 | 1298 | pr_err("%s: switch to hs400 failed, err:%d\n", |
---|
1290 | 1299 | mmc_hostname(host), err); |
---|
.. | .. |
---|
1298 | 1307 | if (host->ops->hs400_complete) |
---|
1299 | 1308 | host->ops->hs400_complete(host); |
---|
1300 | 1309 | |
---|
1301 | | - err = mmc_switch_status(card); |
---|
| 1310 | + err = mmc_switch_status(card, true); |
---|
1302 | 1311 | if (err) |
---|
1303 | 1312 | goto out_err; |
---|
1304 | 1313 | |
---|
.. | .. |
---|
1309 | 1318 | __func__, err); |
---|
1310 | 1319 | return err; |
---|
1311 | 1320 | } |
---|
| 1321 | +EXPORT_SYMBOL_GPL(mmc_select_hs400); |
---|
1312 | 1322 | |
---|
1313 | 1323 | int mmc_hs200_to_hs400(struct mmc_card *card) |
---|
1314 | 1324 | { |
---|
.. | .. |
---|
1330 | 1340 | val = EXT_CSD_TIMING_HS; |
---|
1331 | 1341 | err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, |
---|
1332 | 1342 | val, card->ext_csd.generic_cmd6_time, 0, |
---|
1333 | | - true, false, true); |
---|
| 1343 | + false, true); |
---|
1334 | 1344 | if (err) |
---|
1335 | 1345 | goto out_err; |
---|
1336 | 1346 | |
---|
| 1347 | + if (host->ops->hs400_downgrade) |
---|
| 1348 | + host->ops->hs400_downgrade(host); |
---|
| 1349 | + |
---|
1337 | 1350 | mmc_set_timing(host, MMC_TIMING_MMC_DDR52); |
---|
1338 | 1351 | |
---|
1339 | | - err = mmc_switch_status(card); |
---|
| 1352 | + err = mmc_switch_status(card, true); |
---|
1340 | 1353 | if (err) |
---|
1341 | 1354 | goto out_err; |
---|
1342 | 1355 | |
---|
1343 | 1356 | /* Switch HS DDR to HS */ |
---|
1344 | 1357 | err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, |
---|
1345 | 1358 | EXT_CSD_BUS_WIDTH_8, card->ext_csd.generic_cmd6_time, |
---|
1346 | | - 0, true, false, true); |
---|
| 1359 | + 0, false, true); |
---|
1347 | 1360 | if (err) |
---|
1348 | 1361 | goto out_err; |
---|
1349 | 1362 | |
---|
1350 | 1363 | mmc_set_timing(host, MMC_TIMING_MMC_HS); |
---|
1351 | 1364 | |
---|
1352 | | - if (host->ops->hs400_downgrade) |
---|
1353 | | - host->ops->hs400_downgrade(host); |
---|
1354 | | - |
---|
1355 | | - err = mmc_switch_status(card); |
---|
| 1365 | + err = mmc_switch_status(card, true); |
---|
1356 | 1366 | if (err) |
---|
1357 | 1367 | goto out_err; |
---|
1358 | 1368 | |
---|
.. | .. |
---|
1361 | 1371 | card->drive_strength << EXT_CSD_DRV_STR_SHIFT; |
---|
1362 | 1372 | err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, |
---|
1363 | 1373 | val, card->ext_csd.generic_cmd6_time, 0, |
---|
1364 | | - true, false, true); |
---|
| 1374 | + false, true); |
---|
1365 | 1375 | if (err) |
---|
1366 | 1376 | goto out_err; |
---|
1367 | 1377 | |
---|
.. | .. |
---|
1372 | 1382 | * failed. If there really is a problem, we would expect tuning will |
---|
1373 | 1383 | * fail and the result ends up the same. |
---|
1374 | 1384 | */ |
---|
1375 | | - err = __mmc_switch_status(card, false); |
---|
| 1385 | + err = mmc_switch_status(card, false); |
---|
1376 | 1386 | if (err) |
---|
1377 | 1387 | goto out_err; |
---|
1378 | 1388 | |
---|
.. | .. |
---|
1445 | 1455 | err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
---|
1446 | 1456 | EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS, |
---|
1447 | 1457 | card->ext_csd.generic_cmd6_time, 0, |
---|
1448 | | - true, false, true); |
---|
| 1458 | + false, true); |
---|
1449 | 1459 | if (err) { |
---|
1450 | 1460 | pr_err("%s: switch to hs for hs400es failed, err:%d\n", |
---|
1451 | 1461 | mmc_hostname(host), err); |
---|
1452 | 1462 | goto out_err; |
---|
1453 | 1463 | } |
---|
1454 | 1464 | |
---|
| 1465 | + /* |
---|
| 1466 | + * Bump to HS timing and frequency. Some cards don't handle |
---|
| 1467 | + * SEND_STATUS reliably at the initial frequency. |
---|
| 1468 | + */ |
---|
1455 | 1469 | mmc_set_timing(host, MMC_TIMING_MMC_HS); |
---|
1456 | 1470 | /* Set clock immediately after changing timing */ |
---|
1457 | | - mmc_set_clock(host, card->ext_csd.hs_max_dtr); |
---|
| 1471 | + mmc_set_bus_speed(card); |
---|
1458 | 1472 | |
---|
1459 | | - err = mmc_switch_status(card); |
---|
| 1473 | + err = mmc_switch_status(card, true); |
---|
1460 | 1474 | if (err) |
---|
1461 | 1475 | goto out_err; |
---|
1462 | 1476 | |
---|
.. | .. |
---|
1480 | 1494 | err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
---|
1481 | 1495 | EXT_CSD_HS_TIMING, val, |
---|
1482 | 1496 | card->ext_csd.generic_cmd6_time, 0, |
---|
1483 | | - true, false, true); |
---|
| 1497 | + false, true); |
---|
1484 | 1498 | if (err) { |
---|
1485 | 1499 | pr_err("%s: switch to hs400es failed, err:%d\n", |
---|
1486 | 1500 | mmc_hostname(host), err); |
---|
.. | .. |
---|
1495 | 1509 | if (host->ops->hs400_enhanced_strobe) |
---|
1496 | 1510 | host->ops->hs400_enhanced_strobe(host, &host->ios); |
---|
1497 | 1511 | |
---|
1498 | | - /* some emmc device need a delay before read status */ |
---|
1499 | | - usleep_range(100, 200); |
---|
1500 | | - |
---|
1501 | | - err = mmc_switch_status(card); |
---|
| 1512 | + err = mmc_switch_status(card, true); |
---|
1502 | 1513 | if (err) |
---|
1503 | 1514 | goto out_err; |
---|
1504 | 1515 | |
---|
.. | .. |
---|
1520 | 1531 | static int mmc_select_hs200(struct mmc_card *card) |
---|
1521 | 1532 | { |
---|
1522 | 1533 | struct mmc_host *host = card->host; |
---|
1523 | | - unsigned int old_timing, old_signal_voltage; |
---|
| 1534 | + unsigned int old_timing, old_signal_voltage, old_clock; |
---|
1524 | 1535 | int err = -EINVAL; |
---|
1525 | 1536 | u8 val; |
---|
1526 | 1537 | |
---|
.. | .. |
---|
1548 | 1559 | err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
---|
1549 | 1560 | EXT_CSD_HS_TIMING, val, |
---|
1550 | 1561 | card->ext_csd.generic_cmd6_time, 0, |
---|
1551 | | - true, false, true); |
---|
| 1562 | + false, true); |
---|
1552 | 1563 | if (err) |
---|
1553 | 1564 | goto err; |
---|
| 1565 | + |
---|
| 1566 | + /* |
---|
| 1567 | + * Bump to HS timing and frequency. Some cards don't handle |
---|
| 1568 | + * SEND_STATUS reliably at the initial frequency. |
---|
| 1569 | + * NB: We can't move to full (HS200) speeds until after we've |
---|
| 1570 | + * successfully switched over. |
---|
| 1571 | + */ |
---|
1554 | 1572 | old_timing = host->ios.timing; |
---|
| 1573 | + old_clock = host->ios.clock; |
---|
1555 | 1574 | mmc_set_timing(host, MMC_TIMING_MMC_HS200); |
---|
| 1575 | + mmc_set_clock(card->host, card->ext_csd.hs_max_dtr); |
---|
1556 | 1576 | |
---|
1557 | 1577 | /* |
---|
1558 | 1578 | * For HS200, CRC errors are not a reliable way to know the |
---|
1559 | 1579 | * switch failed. If there really is a problem, we would expect |
---|
1560 | 1580 | * tuning will fail and the result ends up the same. |
---|
1561 | 1581 | */ |
---|
1562 | | - err = __mmc_switch_status(card, false); |
---|
| 1582 | + err = mmc_switch_status(card, false); |
---|
1563 | 1583 | |
---|
1564 | 1584 | /* |
---|
1565 | 1585 | * mmc_select_timing() assumes timing has not changed if |
---|
1566 | 1586 | * it is a switch error. |
---|
1567 | 1587 | */ |
---|
1568 | | - if (err == -EBADMSG) |
---|
| 1588 | + if (err == -EBADMSG) { |
---|
| 1589 | + mmc_set_clock(host, old_clock); |
---|
1569 | 1590 | mmc_set_timing(host, old_timing); |
---|
| 1591 | + } |
---|
1570 | 1592 | } |
---|
1571 | 1593 | err: |
---|
1572 | 1594 | if (err) { |
---|
.. | .. |
---|
1583 | 1605 | /* |
---|
1584 | 1606 | * Activate High Speed, HS200 or HS400ES mode if supported. |
---|
1585 | 1607 | */ |
---|
1586 | | -static int mmc_select_timing(struct mmc_card *card) |
---|
| 1608 | +int mmc_select_timing(struct mmc_card *card) |
---|
1587 | 1609 | { |
---|
1588 | 1610 | int err = 0; |
---|
1589 | 1611 | |
---|
.. | .. |
---|
1608 | 1630 | mmc_set_bus_speed(card); |
---|
1609 | 1631 | return 0; |
---|
1610 | 1632 | } |
---|
| 1633 | +EXPORT_SYMBOL_GPL(mmc_select_timing); |
---|
1611 | 1634 | |
---|
1612 | 1635 | /* |
---|
1613 | 1636 | * Execute tuning sequence to seek the proper bus operating |
---|
1614 | 1637 | * conditions for HS200 and HS400, which sends CMD21 to the device. |
---|
1615 | 1638 | */ |
---|
1616 | | -static int mmc_hs200_tuning(struct mmc_card *card) |
---|
| 1639 | +int mmc_hs200_tuning(struct mmc_card *card) |
---|
1617 | 1640 | { |
---|
1618 | 1641 | struct mmc_host *host = card->host; |
---|
1619 | 1642 | |
---|
.. | .. |
---|
1628 | 1651 | |
---|
1629 | 1652 | return mmc_execute_tuning(card); |
---|
1630 | 1653 | } |
---|
| 1654 | +EXPORT_SYMBOL_GPL(mmc_hs200_tuning); |
---|
1631 | 1655 | |
---|
1632 | 1656 | /* |
---|
1633 | 1657 | * Handle the detection and initialisation of a card. |
---|
.. | .. |
---|
1683 | 1707 | |
---|
1684 | 1708 | if (oldcard) { |
---|
1685 | 1709 | if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) { |
---|
| 1710 | + pr_debug("%s: Perhaps the card was replaced\n", |
---|
| 1711 | + mmc_hostname(host)); |
---|
1686 | 1712 | err = -ENOENT; |
---|
1687 | 1713 | goto err; |
---|
1688 | 1714 | } |
---|
.. | .. |
---|
1836 | 1862 | card->ext_csd.power_off_notification = EXT_CSD_POWER_ON; |
---|
1837 | 1863 | } |
---|
1838 | 1864 | |
---|
| 1865 | + /* set erase_arg */ |
---|
| 1866 | + if (mmc_can_discard(card)) |
---|
| 1867 | + card->erase_arg = MMC_DISCARD_ARG; |
---|
| 1868 | + else if (mmc_can_trim(card)) |
---|
| 1869 | + card->erase_arg = MMC_TRIM_ARG; |
---|
| 1870 | + else |
---|
| 1871 | + card->erase_arg = MMC_ERASE_ARG; |
---|
| 1872 | + |
---|
1839 | 1873 | /* |
---|
1840 | 1874 | * Select timing interface |
---|
1841 | 1875 | */ |
---|
.. | .. |
---|
1844 | 1878 | goto free_card; |
---|
1845 | 1879 | |
---|
1846 | 1880 | if (mmc_card_hs200(card)) { |
---|
| 1881 | + host->doing_init_tune = 1; |
---|
| 1882 | + |
---|
1847 | 1883 | err = mmc_hs200_tuning(card); |
---|
| 1884 | + if (!err) |
---|
| 1885 | + err = mmc_select_hs400(card); |
---|
| 1886 | + |
---|
| 1887 | + host->doing_init_tune = 0; |
---|
| 1888 | + |
---|
1848 | 1889 | if (err) |
---|
1849 | 1890 | goto free_card; |
---|
1850 | 1891 | |
---|
1851 | | - err = mmc_select_hs400(card); |
---|
1852 | | - if (err) |
---|
1853 | | - goto free_card; |
---|
1854 | 1892 | } else if (!mmc_card_hs400es(card)) { |
---|
1855 | 1893 | /* Select the desired bus width optionally */ |
---|
1856 | 1894 | err = mmc_select_bus_width(card); |
---|
.. | .. |
---|
2050 | 2088 | |
---|
2051 | 2089 | err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
---|
2052 | 2090 | EXT_CSD_POWER_OFF_NOTIFICATION, |
---|
2053 | | - notify_type, timeout, 0, true, false, false); |
---|
| 2091 | + notify_type, timeout, 0, false, false); |
---|
2054 | 2092 | if (err) |
---|
2055 | 2093 | pr_err("%s: Power Off Notification timed out, %u\n", |
---|
2056 | 2094 | mmc_hostname(card->host), timeout); |
---|
.. | .. |
---|
2121 | 2159 | if (mmc_card_suspended(host->card)) |
---|
2122 | 2160 | goto out; |
---|
2123 | 2161 | |
---|
2124 | | - if (mmc_card_doing_bkops(host->card)) { |
---|
2125 | | - err = mmc_stop_bkops(host->card); |
---|
2126 | | - if (err) |
---|
2127 | | - goto out; |
---|
2128 | | - } |
---|
2129 | | - |
---|
2130 | 2162 | err = mmc_flush_cache(host->card); |
---|
2131 | 2163 | if (err) |
---|
2132 | 2164 | goto out; |
---|
2133 | 2165 | |
---|
2134 | 2166 | if (mmc_can_poweroff_notify(host->card) && |
---|
2135 | | - ((host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) || !is_suspend)) |
---|
| 2167 | + ((host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) || !is_suspend || |
---|
| 2168 | + (host->caps2 & MMC_CAP2_FULL_PWR_CYCLE_IN_SUSPEND))) |
---|
2136 | 2169 | err = mmc_poweroff_notify(host->card, notify_type); |
---|
2137 | 2170 | else if (mmc_can_sleep(host->card)) |
---|
2138 | 2171 | err = mmc_sleep(host); |
---|