aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/core/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/core/core.c')
-rw-r--r--drivers/mmc/core/core.c152
1 files changed, 90 insertions, 62 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 9584bffa8b22..23f10f72e5f3 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -40,6 +40,7 @@
40#include "bus.h" 40#include "bus.h"
41#include "host.h" 41#include "host.h"
42#include "sdio_bus.h" 42#include "sdio_bus.h"
43#include "pwrseq.h"
43 44
44#include "mmc_ops.h" 45#include "mmc_ops.h"
45#include "sd_ops.h" 46#include "sd_ops.h"
@@ -185,13 +186,14 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
185 186
186EXPORT_SYMBOL(mmc_request_done); 187EXPORT_SYMBOL(mmc_request_done);
187 188
188static void 189static int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
189mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
190{ 190{
191#ifdef CONFIG_MMC_DEBUG 191#ifdef CONFIG_MMC_DEBUG
192 unsigned int i, sz; 192 unsigned int i, sz;
193 struct scatterlist *sg; 193 struct scatterlist *sg;
194#endif 194#endif
195 if (mmc_card_removed(host->card))
196 return -ENOMEDIUM;
195 197
196 if (mrq->sbc) { 198 if (mrq->sbc) {
197 pr_debug("<%s: starting CMD%u arg %08x flags %08x>\n", 199 pr_debug("<%s: starting CMD%u arg %08x flags %08x>\n",
@@ -251,6 +253,8 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
251 mmc_host_clk_hold(host); 253 mmc_host_clk_hold(host);
252 led_trigger_event(host->led, LED_FULL); 254 led_trigger_event(host->led, LED_FULL);
253 host->ops->request(host, mrq); 255 host->ops->request(host, mrq);
256
257 return 0;
254} 258}
255 259
256/** 260/**
@@ -271,7 +275,7 @@ void mmc_start_bkops(struct mmc_card *card, bool from_exception)
271 275
272 BUG_ON(!card); 276 BUG_ON(!card);
273 277
274 if (!card->ext_csd.bkops_en || mmc_card_doing_bkops(card)) 278 if (!card->ext_csd.man_bkops_en || mmc_card_doing_bkops(card))
275 return; 279 return;
276 280
277 err = mmc_read_bkops_status(card); 281 err = mmc_read_bkops_status(card);
@@ -345,29 +349,34 @@ static void mmc_wait_done(struct mmc_request *mrq)
345 */ 349 */
346static int __mmc_start_data_req(struct mmc_host *host, struct mmc_request *mrq) 350static int __mmc_start_data_req(struct mmc_host *host, struct mmc_request *mrq)
347{ 351{
352 int err;
353
348 mrq->done = mmc_wait_data_done; 354 mrq->done = mmc_wait_data_done;
349 mrq->host = host; 355 mrq->host = host;
350 if (mmc_card_removed(host->card)) { 356
351 mrq->cmd->error = -ENOMEDIUM; 357 err = mmc_start_request(host, mrq);
358 if (err) {
359 mrq->cmd->error = err;
352 mmc_wait_data_done(mrq); 360 mmc_wait_data_done(mrq);
353 return -ENOMEDIUM;
354 } 361 }
355 mmc_start_request(host, mrq);
356 362
357 return 0; 363 return err;
358} 364}
359 365
360static int __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq) 366static int __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq)
361{ 367{
368 int err;
369
362 init_completion(&mrq->completion); 370 init_completion(&mrq->completion);
363 mrq->done = mmc_wait_done; 371 mrq->done = mmc_wait_done;
364 if (mmc_card_removed(host->card)) { 372
365 mrq->cmd->error = -ENOMEDIUM; 373 err = mmc_start_request(host, mrq);
374 if (err) {
375 mrq->cmd->error = err;
366 complete(&mrq->completion); 376 complete(&mrq->completion);
367 return -ENOMEDIUM;
368 } 377 }
369 mmc_start_request(host, mrq); 378
370 return 0; 379 return err;
371} 380}
372 381
373/* 382/*
@@ -1077,6 +1086,30 @@ void mmc_set_ungated(struct mmc_host *host)
1077} 1086}
1078#endif 1087#endif
1079 1088
1089int mmc_execute_tuning(struct mmc_card *card)
1090{
1091 struct mmc_host *host = card->host;
1092 u32 opcode;
1093 int err;
1094
1095 if (!host->ops->execute_tuning)
1096 return 0;
1097
1098 if (mmc_card_mmc(card))
1099 opcode = MMC_SEND_TUNING_BLOCK_HS200;
1100 else
1101 opcode = MMC_SEND_TUNING_BLOCK;
1102
1103 mmc_host_clk_hold(host);
1104 err = host->ops->execute_tuning(host, opcode);
1105 mmc_host_clk_release(host);
1106
1107 if (err)
1108 pr_err("%s: tuning execution failed\n", mmc_hostname(host));
1109
1110 return err;
1111}
1112
1080/* 1113/*
1081 * Change the bus mode (open drain/push-pull) of a host. 1114 * Change the bus mode (open drain/push-pull) of a host.
1082 */ 1115 */
@@ -1232,6 +1265,34 @@ EXPORT_SYMBOL(mmc_of_parse_voltage);
1232 1265
1233#endif /* CONFIG_OF */ 1266#endif /* CONFIG_OF */
1234 1267
1268static int mmc_of_get_func_num(struct device_node *node)
1269{
1270 u32 reg;
1271 int ret;
1272
1273 ret = of_property_read_u32(node, "reg", &reg);
1274 if (ret < 0)
1275 return ret;
1276
1277 return reg;
1278}
1279
1280struct device_node *mmc_of_find_child_device(struct mmc_host *host,
1281 unsigned func_num)
1282{
1283 struct device_node *node;
1284
1285 if (!host->parent || !host->parent->of_node)
1286 return NULL;
1287
1288 for_each_child_of_node(host->parent->of_node, node) {
1289 if (mmc_of_get_func_num(node) == func_num)
1290 return node;
1291 }
1292
1293 return NULL;
1294}
1295
1235#ifdef CONFIG_REGULATOR 1296#ifdef CONFIG_REGULATOR
1236 1297
1237/** 1298/**
@@ -1555,6 +1616,8 @@ void mmc_power_up(struct mmc_host *host, u32 ocr)
1555 1616
1556 mmc_host_clk_hold(host); 1617 mmc_host_clk_hold(host);
1557 1618
1619 mmc_pwrseq_pre_power_on(host);
1620
1558 host->ios.vdd = fls(ocr) - 1; 1621 host->ios.vdd = fls(ocr) - 1;
1559 host->ios.power_mode = MMC_POWER_UP; 1622 host->ios.power_mode = MMC_POWER_UP;
1560 /* Set initial state and call mmc_set_ios */ 1623 /* Set initial state and call mmc_set_ios */
@@ -1574,6 +1637,8 @@ void mmc_power_up(struct mmc_host *host, u32 ocr)
1574 */ 1637 */
1575 mmc_delay(10); 1638 mmc_delay(10);
1576 1639
1640 mmc_pwrseq_post_power_on(host);
1641
1577 host->ios.clock = host->f_init; 1642 host->ios.clock = host->f_init;
1578 1643
1579 host->ios.power_mode = MMC_POWER_ON; 1644 host->ios.power_mode = MMC_POWER_ON;
@@ -1595,6 +1660,8 @@ void mmc_power_off(struct mmc_host *host)
1595 1660
1596 mmc_host_clk_hold(host); 1661 mmc_host_clk_hold(host);
1597 1662
1663 mmc_pwrseq_power_off(host);
1664
1598 host->ios.clock = 0; 1665 host->ios.clock = 0;
1599 host->ios.vdd = 0; 1666 host->ios.vdd = 0;
1600 1667
@@ -2245,67 +2312,28 @@ static void mmc_hw_reset_for_init(struct mmc_host *host)
2245 mmc_host_clk_release(host); 2312 mmc_host_clk_release(host);
2246} 2313}
2247 2314
2248int mmc_can_reset(struct mmc_card *card) 2315int mmc_hw_reset(struct mmc_host *host)
2249{
2250 u8 rst_n_function;
2251
2252 if (!mmc_card_mmc(card))
2253 return 0;
2254 rst_n_function = card->ext_csd.rst_n_function;
2255 if ((rst_n_function & EXT_CSD_RST_N_EN_MASK) != EXT_CSD_RST_N_ENABLED)
2256 return 0;
2257 return 1;
2258}
2259EXPORT_SYMBOL(mmc_can_reset);
2260
2261static int mmc_do_hw_reset(struct mmc_host *host, int check)
2262{ 2316{
2263 struct mmc_card *card = host->card; 2317 int ret;
2264
2265 if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset)
2266 return -EOPNOTSUPP;
2267 2318
2268 if (!card) 2319 if (!host->card)
2269 return -EINVAL; 2320 return -EINVAL;
2270 2321
2271 if (!mmc_can_reset(card)) 2322 mmc_bus_get(host);
2323 if (!host->bus_ops || host->bus_dead || !host->bus_ops->reset) {
2324 mmc_bus_put(host);
2272 return -EOPNOTSUPP; 2325 return -EOPNOTSUPP;
2273
2274 mmc_host_clk_hold(host);
2275 mmc_set_clock(host, host->f_init);
2276
2277 host->ops->hw_reset(host);
2278
2279 /* If the reset has happened, then a status command will fail */
2280 if (check) {
2281 u32 status;
2282
2283 if (!mmc_send_status(card, &status)) {
2284 mmc_host_clk_release(host);
2285 return -ENOSYS;
2286 }
2287 } 2326 }
2288 2327
2289 /* Set initial state and call mmc_set_ios */ 2328 ret = host->bus_ops->reset(host);
2290 mmc_set_initial_state(host); 2329 mmc_bus_put(host);
2291 2330
2292 mmc_host_clk_release(host); 2331 pr_warn("%s: tried to reset card\n", mmc_hostname(host));
2293 2332
2294 return host->bus_ops->power_restore(host); 2333 return ret;
2295}
2296
2297int mmc_hw_reset(struct mmc_host *host)
2298{
2299 return mmc_do_hw_reset(host, 0);
2300} 2334}
2301EXPORT_SYMBOL(mmc_hw_reset); 2335EXPORT_SYMBOL(mmc_hw_reset);
2302 2336
2303int mmc_hw_reset_check(struct mmc_host *host)
2304{
2305 return mmc_do_hw_reset(host, 1);
2306}
2307EXPORT_SYMBOL(mmc_hw_reset_check);
2308
2309static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq) 2337static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
2310{ 2338{
2311 host->f_init = freq; 2339 host->f_init = freq;