|
86 | 86 |
|
87 | 87 | #define CLOCK_TOO_SLOW_HZ 50000000 |
88 | 88 | #define SDHCI_AM654_AUTOSUSPEND_DELAY -1 |
| 89 | +#define RETRY_TUNING_MAX 10 |
89 | 90 |
|
90 | 91 | /* Command Queue Host Controller Interface Base address */ |
91 | 92 | #define SDHCI_AM654_CQE_BASE_ADDR 0x200 |
@@ -151,6 +152,7 @@ struct sdhci_am654_data { |
151 | 152 | u32 flags; |
152 | 153 | u32 quirks; |
153 | 154 | bool dll_enable; |
| 155 | + u32 tuning_loop; |
154 | 156 |
|
155 | 157 | #define SDHCI_AM654_QUIRK_FORCE_CDTEST BIT(0) |
156 | 158 | }; |
@@ -443,22 +445,23 @@ static u32 sdhci_am654_cqhci_irq(struct sdhci_host *host, u32 intmask) |
443 | 445 | #define ITAPDLY_LENGTH 32 |
444 | 446 | #define ITAPDLY_LAST_INDEX (ITAPDLY_LENGTH - 1) |
445 | 447 |
|
446 | | -static u32 sdhci_am654_calculate_itap(struct sdhci_host *host, struct window |
| 448 | +static int sdhci_am654_calculate_itap(struct sdhci_host *host, struct window |
447 | 449 | *fail_window, u8 num_fails, bool circular_buffer) |
448 | 450 | { |
449 | 451 | u8 itap = 0, start_fail = 0, end_fail = 0, pass_length = 0; |
450 | 452 | u8 first_fail_start = 0, last_fail_end = 0; |
451 | | - struct device *dev = mmc_dev(host->mmc); |
452 | 453 | struct window pass_window = {0, 0, 0}; |
453 | 454 | int prev_fail_end = -1; |
454 | 455 | u8 i; |
455 | 456 |
|
456 | | - if (!num_fails) |
457 | | - return ITAPDLY_LAST_INDEX >> 1; |
| 457 | + if (!num_fails) { |
| 458 | + /* Retry tuning */ |
| 459 | + return -1; |
| 460 | + } |
458 | 461 |
|
459 | 462 | if (fail_window->length == ITAPDLY_LENGTH) { |
460 | | - dev_err(dev, "No passing ITAPDLY, return 0\n"); |
461 | | - return 0; |
| 463 | + /* Retry tuning */ |
| 464 | + return -1; |
462 | 465 | } |
463 | 466 |
|
464 | 467 | first_fail_start = fail_window->start; |
@@ -494,8 +497,8 @@ static u32 sdhci_am654_calculate_itap(struct sdhci_host *host, struct window |
494 | 497 | return (itap > ITAPDLY_LAST_INDEX) ? ITAPDLY_LAST_INDEX >> 1 : itap; |
495 | 498 | } |
496 | 499 |
|
497 | | -static int sdhci_am654_platform_execute_tuning(struct sdhci_host *host, |
498 | | - u32 opcode) |
| 500 | +static int sdhci_am654_do_tuning(struct sdhci_host *host, |
| 501 | + u32 opcode) |
499 | 502 | { |
500 | 503 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
501 | 504 | struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host); |
@@ -532,13 +535,30 @@ static int sdhci_am654_platform_execute_tuning(struct sdhci_host *host, |
532 | 535 | if (fail_window[fail_index].length != 0) |
533 | 536 | fail_index++; |
534 | 537 |
|
535 | | - itap = sdhci_am654_calculate_itap(host, fail_window, fail_index, |
536 | | - sdhci_am654->dll_enable); |
| 538 | + return sdhci_am654_calculate_itap(host, fail_window, fail_index, |
| 539 | + sdhci_am654->dll_enable); |
| 540 | +} |
537 | 541 |
|
538 | | - sdhci_am654_write_itapdly(sdhci_am654, itap, sdhci_am654->itap_del_ena[timing]); |
| 542 | +static int sdhci_am654_platform_execute_tuning(struct sdhci_host *host, |
| 543 | + u32 opcode) |
| 544 | +{ |
| 545 | + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
| 546 | + struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host); |
| 547 | + unsigned char timing = host->mmc->ios.timing; |
| 548 | + int itapdly; |
539 | 549 |
|
| 550 | + do { |
| 551 | + itapdly = sdhci_am654_do_tuning(host, opcode); |
| 552 | + if (itapdly >= 0) |
| 553 | + break; |
| 554 | + } while (++sdhci_am654->tuning_loop < RETRY_TUNING_MAX); |
| 555 | + |
| 556 | + if (itapdly < 0) |
| 557 | + return -1; |
| 558 | + |
| 559 | + sdhci_am654_write_itapdly(sdhci_am654, itapdly, sdhci_am654->itap_del_ena[timing]); |
540 | 560 | /* Save ITAPDLY */ |
541 | | - sdhci_am654->itap_del_sel[timing] = itap; |
| 561 | + sdhci_am654->itap_del_sel[timing] = itapdly; |
542 | 562 |
|
543 | 563 | return 0; |
544 | 564 | } |
@@ -742,6 +762,9 @@ static int sdhci_am654_init(struct sdhci_host *host) |
742 | 762 | regmap_update_bits(sdhci_am654->base, CTL_CFG_3, TUNINGFORSDR50_MASK, |
743 | 763 | TUNINGFORSDR50_MASK); |
744 | 764 |
|
| 765 | + /* Use to re-execute tuning */ |
| 766 | + sdhci_am654->tuning_loop = 0; |
| 767 | + |
745 | 768 | ret = sdhci_setup_host(host); |
746 | 769 | if (ret) |
747 | 770 | return ret; |
|
0 commit comments