mirror of
https://github.com/torvalds/linux.git
synced 2026-09-24 06:24:02 +02:00
mmc: sdhci_am654: Fallback to DT-provided itap delay on DDR50 tuning failure
DDR50 mode is not required to support the tuning command CMD19, meaning
that calibration may fail on cards that do not implement it, in which
case a known-good itap delay value should be programmed into the host
controller.
Do this by reading the (already defined) itap delay DT property for DDR50
and, if tuning fails for this mode, fall back to the DT-provided itap delay
value. If the DT does not provide a value for DDR50 fallback then this
simply disables using itapdly.
Fixes: 901d16e462 ("mmc: sdhci_am654: Add retry tuning")
Cc: stable@vger.kernel.org
Signed-off-by: Diogo Ivo (Schneider Electric) <diogo.ivo@bootlin.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Reviewed-by: Judith Mendez <jm@ti.com>
Signed-off-by: Ulf Hansson <ulfh@kernel.org>
This commit is contained in:
parent
c9f47cc8c3
commit
308d052252
|
|
@ -126,7 +126,7 @@ static const struct timing_data td[] = {
|
|||
NULL,
|
||||
MMC_CAP_UHS_SDR104},
|
||||
[MMC_TIMING_UHS_DDR50] = {"ti,otap-del-sel-ddr50",
|
||||
NULL,
|
||||
"ti,itap-del-sel-ddr50",
|
||||
MMC_CAP_UHS_DDR50},
|
||||
[MMC_TIMING_MMC_DDR52] = {"ti,otap-del-sel-ddr52",
|
||||
"ti,itap-del-sel-ddr52",
|
||||
|
|
@ -144,6 +144,8 @@ struct sdhci_am654_data {
|
|||
u32 otap_del_sel[ARRAY_SIZE(td)];
|
||||
u32 itap_del_sel[ARRAY_SIZE(td)];
|
||||
u32 itap_del_ena[ARRAY_SIZE(td)];
|
||||
u32 itap_del_sel_dt_ddr50;
|
||||
u32 itap_del_ena_dt_ddr50;
|
||||
int clkbuf_sel;
|
||||
int trm_icp;
|
||||
int drv_strength;
|
||||
|
|
@ -579,10 +581,19 @@ static int sdhci_am654_platform_execute_tuning(struct sdhci_host *host,
|
|||
} while (++tuning_loop < RETRY_TUNING_MAX);
|
||||
|
||||
if (itapdly < 0) {
|
||||
dev_err(dev, "Failed to find itapdly, fail tuning\n");
|
||||
sdhci_am654_write_itapdly(sdhci_am654, 0, 0);
|
||||
sdhci_am654->itap_del_ena[timing] = 0;
|
||||
sdhci_am654->itap_del_sel[timing] = 0;
|
||||
if (timing == MMC_TIMING_UHS_DDR50) {
|
||||
dev_dbg(dev, "Failed DDR50 tuning, fallback to DT ITAP\n");
|
||||
sdhci_am654->itap_del_sel[timing] = sdhci_am654->itap_del_sel_dt_ddr50;
|
||||
sdhci_am654->itap_del_ena[timing] = sdhci_am654->itap_del_ena_dt_ddr50;
|
||||
} else {
|
||||
dev_err(dev, "Failed to find itapdly, fail tuning\n");
|
||||
sdhci_am654->itap_del_ena[timing] = 0;
|
||||
sdhci_am654->itap_del_sel[timing] = 0;
|
||||
}
|
||||
|
||||
sdhci_am654_write_itapdly(sdhci_am654,
|
||||
sdhci_am654->itap_del_sel[timing],
|
||||
sdhci_am654->itap_del_ena[timing]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -758,6 +769,11 @@ static int sdhci_am654_get_otap_delay(struct sdhci_host *host,
|
|||
}
|
||||
}
|
||||
|
||||
sdhci_am654->itap_del_sel_dt_ddr50 =
|
||||
sdhci_am654->itap_del_sel[MMC_TIMING_UHS_DDR50];
|
||||
sdhci_am654->itap_del_ena_dt_ddr50 =
|
||||
sdhci_am654->itap_del_ena[MMC_TIMING_UHS_DDR50];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user