diff options
Diffstat (limited to 'drivers/mmc/core/mmc.c')
-rw-r--r-- | drivers/mmc/core/mmc.c | 101 |
1 files changed, 53 insertions, 48 deletions
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 7466ce098e60..1d41e8541f38 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
@@ -483,11 +483,13 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) | |||
483 | /* check whether the eMMC card supports BKOPS */ | 483 | /* check whether the eMMC card supports BKOPS */ |
484 | if (ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1) { | 484 | if (ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1) { |
485 | card->ext_csd.bkops = 1; | 485 | card->ext_csd.bkops = 1; |
486 | card->ext_csd.bkops_en = ext_csd[EXT_CSD_BKOPS_EN]; | 486 | card->ext_csd.man_bkops_en = |
487 | (ext_csd[EXT_CSD_BKOPS_EN] & | ||
488 | EXT_CSD_MANUAL_BKOPS_MASK); | ||
487 | card->ext_csd.raw_bkops_status = | 489 | card->ext_csd.raw_bkops_status = |
488 | ext_csd[EXT_CSD_BKOPS_STATUS]; | 490 | ext_csd[EXT_CSD_BKOPS_STATUS]; |
489 | if (!card->ext_csd.bkops_en) | 491 | if (!card->ext_csd.man_bkops_en) |
490 | pr_info("%s: BKOPS_EN bit is not set\n", | 492 | pr_info("%s: MAN_BKOPS_EN bit is not set\n", |
491 | mmc_hostname(card->host)); | 493 | mmc_hostname(card->host)); |
492 | } | 494 | } |
493 | 495 | ||
@@ -1155,38 +1157,6 @@ bus_speed: | |||
1155 | return err; | 1157 | return err; |
1156 | } | 1158 | } |
1157 | 1159 | ||
1158 | const u8 tuning_blk_pattern_4bit[MMC_TUNING_BLK_PATTERN_4BIT_SIZE] = { | ||
1159 | 0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc, | ||
1160 | 0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef, | ||
1161 | 0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb, | ||
1162 | 0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef, | ||
1163 | 0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c, | ||
1164 | 0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee, | ||
1165 | 0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff, | ||
1166 | 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde, | ||
1167 | }; | ||
1168 | EXPORT_SYMBOL(tuning_blk_pattern_4bit); | ||
1169 | |||
1170 | const u8 tuning_blk_pattern_8bit[MMC_TUNING_BLK_PATTERN_8BIT_SIZE] = { | ||
1171 | 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, | ||
1172 | 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc, | ||
1173 | 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff, | ||
1174 | 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff, | ||
1175 | 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd, | ||
1176 | 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, | ||
1177 | 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff, | ||
1178 | 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff, | ||
1179 | 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, | ||
1180 | 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, | ||
1181 | 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, | ||
1182 | 0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, | ||
1183 | 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, | ||
1184 | 0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, | ||
1185 | 0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, | ||
1186 | 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, | ||
1187 | }; | ||
1188 | EXPORT_SYMBOL(tuning_blk_pattern_8bit); | ||
1189 | |||
1190 | /* | 1160 | /* |
1191 | * Execute tuning sequence to seek the proper bus operating | 1161 | * Execute tuning sequence to seek the proper bus operating |
1192 | * conditions for HS200 and HS400, which sends CMD21 to the device. | 1162 | * conditions for HS200 and HS400, which sends CMD21 to the device. |
@@ -1194,7 +1164,6 @@ EXPORT_SYMBOL(tuning_blk_pattern_8bit); | |||
1194 | static int mmc_hs200_tuning(struct mmc_card *card) | 1164 | static int mmc_hs200_tuning(struct mmc_card *card) |
1195 | { | 1165 | { |
1196 | struct mmc_host *host = card->host; | 1166 | struct mmc_host *host = card->host; |
1197 | int err = 0; | ||
1198 | 1167 | ||
1199 | /* | 1168 | /* |
1200 | * Timing should be adjusted to the HS400 target | 1169 | * Timing should be adjusted to the HS400 target |
@@ -1205,18 +1174,7 @@ static int mmc_hs200_tuning(struct mmc_card *card) | |||
1205 | if (host->ops->prepare_hs400_tuning) | 1174 | if (host->ops->prepare_hs400_tuning) |
1206 | host->ops->prepare_hs400_tuning(host, &host->ios); | 1175 | host->ops->prepare_hs400_tuning(host, &host->ios); |
1207 | 1176 | ||
1208 | if (host->ops->execute_tuning) { | 1177 | return mmc_execute_tuning(card); |
1209 | mmc_host_clk_hold(host); | ||
1210 | err = host->ops->execute_tuning(host, | ||
1211 | MMC_SEND_TUNING_BLOCK_HS200); | ||
1212 | mmc_host_clk_release(host); | ||
1213 | |||
1214 | if (err) | ||
1215 | pr_err("%s: tuning execution failed\n", | ||
1216 | mmc_hostname(host)); | ||
1217 | } | ||
1218 | |||
1219 | return err; | ||
1220 | } | 1178 | } |
1221 | 1179 | ||
1222 | /* | 1180 | /* |
@@ -1297,6 +1255,12 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
1297 | } | 1255 | } |
1298 | 1256 | ||
1299 | /* | 1257 | /* |
1258 | * Call the optional HC's init_card function to handle quirks. | ||
1259 | */ | ||
1260 | if (host->ops->init_card) | ||
1261 | host->ops->init_card(host, card); | ||
1262 | |||
1263 | /* | ||
1300 | * For native busses: set card RCA and quit open drain mode. | 1264 | * For native busses: set card RCA and quit open drain mode. |
1301 | */ | 1265 | */ |
1302 | if (!mmc_host_is_spi(host)) { | 1266 | if (!mmc_host_is_spi(host)) { |
@@ -1821,6 +1785,46 @@ static int mmc_power_restore(struct mmc_host *host) | |||
1821 | return ret; | 1785 | return ret; |
1822 | } | 1786 | } |
1823 | 1787 | ||
1788 | int mmc_can_reset(struct mmc_card *card) | ||
1789 | { | ||
1790 | u8 rst_n_function; | ||
1791 | |||
1792 | rst_n_function = card->ext_csd.rst_n_function; | ||
1793 | if ((rst_n_function & EXT_CSD_RST_N_EN_MASK) != EXT_CSD_RST_N_ENABLED) | ||
1794 | return 0; | ||
1795 | return 1; | ||
1796 | } | ||
1797 | EXPORT_SYMBOL(mmc_can_reset); | ||
1798 | |||
1799 | static int mmc_reset(struct mmc_host *host) | ||
1800 | { | ||
1801 | struct mmc_card *card = host->card; | ||
1802 | u32 status; | ||
1803 | |||
1804 | if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset) | ||
1805 | return -EOPNOTSUPP; | ||
1806 | |||
1807 | if (!mmc_can_reset(card)) | ||
1808 | return -EOPNOTSUPP; | ||
1809 | |||
1810 | mmc_host_clk_hold(host); | ||
1811 | mmc_set_clock(host, host->f_init); | ||
1812 | |||
1813 | host->ops->hw_reset(host); | ||
1814 | |||
1815 | /* If the reset has happened, then a status command will fail */ | ||
1816 | if (!mmc_send_status(card, &status)) { | ||
1817 | mmc_host_clk_release(host); | ||
1818 | return -ENOSYS; | ||
1819 | } | ||
1820 | |||
1821 | /* Set initial state and call mmc_set_ios */ | ||
1822 | mmc_set_initial_state(host); | ||
1823 | mmc_host_clk_release(host); | ||
1824 | |||
1825 | return mmc_power_restore(host); | ||
1826 | } | ||
1827 | |||
1824 | static const struct mmc_bus_ops mmc_ops = { | 1828 | static const struct mmc_bus_ops mmc_ops = { |
1825 | .remove = mmc_remove, | 1829 | .remove = mmc_remove, |
1826 | .detect = mmc_detect, | 1830 | .detect = mmc_detect, |
@@ -1831,6 +1835,7 @@ static const struct mmc_bus_ops mmc_ops = { | |||
1831 | .power_restore = mmc_power_restore, | 1835 | .power_restore = mmc_power_restore, |
1832 | .alive = mmc_alive, | 1836 | .alive = mmc_alive, |
1833 | .shutdown = mmc_shutdown, | 1837 | .shutdown = mmc_shutdown, |
1838 | .reset = mmc_reset, | ||
1834 | }; | 1839 | }; |
1835 | 1840 | ||
1836 | /* | 1841 | /* |