Commit e95504497ecac46907204b0ee3460b708a2981ac

Authored by Che-Liang Chiou
Committed by Andy Fleming
1 parent 5ed6f447af

mmc: Split device init to decouple OCR-polling delay

Most of time that MMC driver spends on initializing a device is polling
OCR (operation conditions register).  To decouple this polling loop,
device init is split into two parts: The first part fires the OCR query
command, and the second part polls the result.  So the caller is now no
longer bound to the OCR-polling delay; he may fire the query, go
somewhere and then come back later for the result.

To use this, call mmc_set_preinit() on any device which needs this.

This can save significant amounts of time on boot (e.g. 200ms) by
hiding the MMC init time behind other init.

Signed-off-by: Che-Liang Chiou <clchiou@chromium.org>
Signed-off-by: Simon Glass <sjg@chromium.org>
Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
Signed-off-by: Andy Fleming <afleming@freescale.com>

Showing 2 changed files with 135 additions and 32 deletions Side-by-side Diff

... ... @@ -524,49 +524,71 @@
524 524 return 0;
525 525 }
526 526  
527   -static int mmc_send_op_cond(struct mmc *mmc)
  527 +/* We pass in the cmd since otherwise the init seems to fail */
  528 +static int mmc_send_op_cond_iter(struct mmc *mmc, struct mmc_cmd *cmd,
  529 + int use_arg)
528 530 {
529   - int timeout = 10000;
530   - struct mmc_cmd cmd;
531 531 int err;
532 532  
  533 + cmd->cmdidx = MMC_CMD_SEND_OP_COND;
  534 + cmd->resp_type = MMC_RSP_R3;
  535 + cmd->cmdarg = 0;
  536 + if (use_arg && !mmc_host_is_spi(mmc)) {
  537 + cmd->cmdarg =
  538 + (mmc->voltages &
  539 + (mmc->op_cond_response & OCR_VOLTAGE_MASK)) |
  540 + (mmc->op_cond_response & OCR_ACCESS_MODE);
  541 +
  542 + if (mmc->host_caps & MMC_MODE_HC)
  543 + cmd->cmdarg |= OCR_HCS;
  544 + }
  545 + err = mmc_send_cmd(mmc, cmd, NULL);
  546 + if (err)
  547 + return err;
  548 + mmc->op_cond_response = cmd->response[0];
  549 + return 0;
  550 +}
  551 +
  552 +int mmc_send_op_cond(struct mmc *mmc)
  553 +{
  554 + struct mmc_cmd cmd;
  555 + int err, i;
  556 +
533 557 /* Some cards seem to need this */
534 558 mmc_go_idle(mmc);
535 559  
536 560 /* Asking to the card its capabilities */
537   - cmd.cmdidx = MMC_CMD_SEND_OP_COND;
538   - cmd.resp_type = MMC_RSP_R3;
539   - cmd.cmdarg = 0;
  561 + mmc->op_cond_pending = 1;
  562 + for (i = 0; i < 2; i++) {
  563 + err = mmc_send_op_cond_iter(mmc, &cmd, i != 0);
  564 + if (err)
  565 + return err;
540 566  
541   - err = mmc_send_cmd(mmc, &cmd, NULL);
  567 + /* exit if not busy (flag seems to be inverted) */
  568 + if (mmc->op_cond_response & OCR_BUSY)
  569 + return 0;
  570 + }
  571 + return IN_PROGRESS;
  572 +}
542 573  
543   - if (err)
544   - return err;
  574 +int mmc_complete_op_cond(struct mmc *mmc)
  575 +{
  576 + struct mmc_cmd cmd;
  577 + int timeout = 1000;
  578 + uint start;
  579 + int err;
545 580  
546   - udelay(1000);
547   -
  581 + mmc->op_cond_pending = 0;
  582 + start = get_timer(0);
548 583 do {
549   - cmd.cmdidx = MMC_CMD_SEND_OP_COND;
550   - cmd.resp_type = MMC_RSP_R3;
551   - cmd.cmdarg = (mmc_host_is_spi(mmc) ? 0 :
552   - (mmc->voltages &
553   - (cmd.response[0] & OCR_VOLTAGE_MASK)) |
554   - (cmd.response[0] & OCR_ACCESS_MODE));
555   -
556   - if (mmc->host_caps & MMC_MODE_HC)
557   - cmd.cmdarg |= OCR_HCS;
558   -
559   - err = mmc_send_cmd(mmc, &cmd, NULL);
560   -
  584 + err = mmc_send_op_cond_iter(mmc, &cmd, 1);
561 585 if (err)
562 586 return err;
  587 + if (get_timer(start) > timeout)
  588 + return UNUSABLE_ERR;
  589 + udelay(100);
  590 + } while (!(mmc->op_cond_response & OCR_BUSY));
563 591  
564   - udelay(1000);
565   - } while (!(cmd.response[0] & OCR_BUSY) && timeout--);
566   -
567   - if (timeout <= 0)
568   - return UNUSABLE_ERR;
569   -
570 592 if (mmc_host_is_spi(mmc)) { /* read OCR for spi */
571 593 cmd.cmdidx = MMC_CMD_SPI_READ_OCR;
572 594 cmd.resp_type = MMC_RSP_R3;
... ... @@ -1274,7 +1296,7 @@
1274 1296 }
1275 1297 #endif
1276 1298  
1277   -int mmc_init(struct mmc *mmc)
  1299 +int mmc_start_init(struct mmc *mmc)
1278 1300 {
1279 1301 int err;
1280 1302  
1281 1303  
1282 1304  
1283 1305  
... ... @@ -1314,20 +1336,51 @@
1314 1336 if (err == TIMEOUT) {
1315 1337 err = mmc_send_op_cond(mmc);
1316 1338  
1317   - if (err) {
  1339 + if (err && err != IN_PROGRESS) {
1318 1340 printf("Card did not respond to voltage select!\n");
1319 1341 return UNUSABLE_ERR;
1320 1342 }
1321 1343 }
1322 1344  
1323   - err = mmc_startup(mmc);
  1345 + if (err == IN_PROGRESS)
  1346 + mmc->init_in_progress = 1;
  1347 +
  1348 + return err;
  1349 +}
  1350 +
  1351 +static int mmc_complete_init(struct mmc *mmc)
  1352 +{
  1353 + int err = 0;
  1354 +
  1355 + if (mmc->op_cond_pending)
  1356 + err = mmc_complete_op_cond(mmc);
  1357 +
  1358 + if (!err)
  1359 + err = mmc_startup(mmc);
1324 1360 if (err)
1325 1361 mmc->has_init = 0;
1326 1362 else
1327 1363 mmc->has_init = 1;
  1364 + mmc->init_in_progress = 0;
1328 1365 return err;
1329 1366 }
1330 1367  
  1368 +int mmc_init(struct mmc *mmc)
  1369 +{
  1370 + int err = IN_PROGRESS;
  1371 + unsigned start = get_timer(0);
  1372 +
  1373 + if (mmc->has_init)
  1374 + return 0;
  1375 + if (!mmc->init_in_progress)
  1376 + err = mmc_start_init(mmc);
  1377 +
  1378 + if (!err || err == IN_PROGRESS)
  1379 + err = mmc_complete_init(mmc);
  1380 + debug("%s: %d, time %lu\n", __func__, err, get_timer(start));
  1381 + return err;
  1382 +}
  1383 +
1331 1384 /*
1332 1385 * CPU and board-specific MMC initializations. Aliased function
1333 1386 * signals caller to move on
... ... @@ -1362,6 +1415,25 @@
1362 1415 return cur_dev_num;
1363 1416 }
1364 1417  
  1418 +void mmc_set_preinit(struct mmc *mmc, int preinit)
  1419 +{
  1420 + mmc->preinit = preinit;
  1421 +}
  1422 +
  1423 +static void do_preinit(void)
  1424 +{
  1425 + struct mmc *m;
  1426 + struct list_head *entry;
  1427 +
  1428 + list_for_each(entry, &mmc_devices) {
  1429 + m = list_entry(entry, struct mmc, link);
  1430 +
  1431 + if (m->preinit)
  1432 + mmc_start_init(m);
  1433 + }
  1434 +}
  1435 +
  1436 +
1365 1437 int mmc_initialize(bd_t *bis)
1366 1438 {
1367 1439 INIT_LIST_HEAD (&mmc_devices);
... ... @@ -1372,6 +1444,7 @@
1372 1444  
1373 1445 print_mmc_devices(',');
1374 1446  
  1447 + do_preinit();
1375 1448 return 0;
1376 1449 }
... ... @@ -68,6 +68,7 @@
68 68 #define UNUSABLE_ERR -17 /* Unusable Card */
69 69 #define COMM_ERR -18 /* Communications Error */
70 70 #define TIMEOUT -19
  71 +#define IN_PROGRESS -20 /* operation is in progress */
71 72  
72 73 #define MMC_CMD_GO_IDLE_STATE 0
73 74 #define MMC_CMD_SEND_OP_COND 1
... ... @@ -270,6 +271,10 @@
270 271 int (*getcd)(struct mmc *mmc);
271 272 int (*getwp)(struct mmc *mmc);
272 273 uint b_max;
  274 + char op_cond_pending; /* 1 if we are waiting on an op_cond command */
  275 + char init_in_progress; /* 1 if we have done mmc_start_init() */
  276 + char preinit; /* start init as early as possible */
  277 + uint op_cond_response; /* the response byte from the last op_cond */
273 278 };
274 279  
275 280 int mmc_register(struct mmc *mmc);
... ... @@ -286,6 +291,31 @@
286 291 int mmc_getcd(struct mmc *mmc);
287 292 int mmc_getwp(struct mmc *mmc);
288 293 void spl_mmc_load(void) __noreturn;
  294 +
  295 +/**
  296 + * Start device initialization and return immediately; it does not block on
  297 + * polling OCR (operation condition register) status. Then you should call
  298 + * mmc_init, which would block on polling OCR status and complete the device
  299 + * initializatin.
  300 + *
  301 + * @param mmc Pointer to a MMC device struct
  302 + * @return 0 on success, IN_PROGRESS on waiting for OCR status, <0 on error.
  303 + */
  304 +int mmc_start_init(struct mmc *mmc);
  305 +
  306 +/**
  307 + * Set preinit flag of mmc device.
  308 + *
  309 + * This will cause the device to be pre-inited during mmc_initialize(),
  310 + * which may save boot time if the device is not accessed until later.
  311 + * Some eMMC devices take 200-300ms to init, but unfortunately they
  312 + * must be sent a series of commands to even get them to start preparing
  313 + * for operation.
  314 + *
  315 + * @param mmc Pointer to a MMC device struct
  316 + * @param preinit preinit flag value
  317 + */
  318 +void mmc_set_preinit(struct mmc *mmc, int preinit);
289 319  
290 320 #ifdef CONFIG_GENERIC_MMC
291 321 #define mmc_host_is_spi(mmc) ((mmc)->host_caps & MMC_MODE_SPI)