|
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