From 959a4d84f2bac654c2e78ddc68fde0aba5bf32d9 Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Fri, 29 Oct 2021 15:13:52 +0800 Subject: [PATCH] mmc: dw_mmc-rockchip: Improve v2 tuning v2 tuning has a defect that if invalid space is laid between 90 and 180, and the PVT might make the invalid space back and forth. To overcome this weakness, we don't need to select phase from beginning, and should directly chose the next one against the last phase selected. Signed-off-by: Shawn Lin Change-Id: I0cbeb1dba524c2e23a3719d28b868af3ed49e20b --- drivers/mmc/host/dw_mmc-rockchip.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c index e04b90430211..391cdde3e926 100644 --- a/drivers/mmc/host/dw_mmc-rockchip.c +++ b/drivers/mmc/host/dw_mmc-rockchip.c @@ -143,22 +143,29 @@ static int dw_mci_v2_execute_tuning(struct dw_mci_slot *slot, u32 opcode) struct dw_mci *host = slot->host; struct dw_mci_rockchip_priv_data *priv = host->priv; struct mmc_host *mmc = slot->mmc; - u32 degrees[4] = {90, 180, 270, 360}; + u32 degrees[4] = {0, 90, 180, 270}, degree; int i; static bool inherit = true; if (inherit) { inherit = false; - i = clk_get_phase(priv->sample_clk) / 90 - 1; + i = clk_get_phase(priv->sample_clk) / 90; + degree = degrees[i]; goto done; } - /* v2 only support 4 degrees in theory */ + /* + * v2 only support 4 degrees in theory. + * First we inherit sample phases from firmware, which should + * be able work fine, at least in the first place. + * If retune is needed, we search forward to pick the last + * one phase from degree list and loop around until we get one. + * It's impossible all 4 fixed phase won't be able to work. + */ for (i = 0; i < ARRAY_SIZE(degrees); i++) { - if (degrees[i] == priv->last_degree) - continue; - - clk_set_phase(priv->sample_clk, degrees[i]); + degree = degrees[i] + priv->last_degree; + degree = degree % 360; + clk_set_phase(priv->sample_clk, degree); if (!mmc_send_tuning(mmc, opcode, NULL)) break; } @@ -170,7 +177,7 @@ static int dw_mci_v2_execute_tuning(struct dw_mci_slot *slot, u32 opcode) done: dev_info(host->dev, "Successfully tuned phase to %d\n", degrees[i]); - priv->last_degree = degrees[i]; + priv->last_degree = degree; return 0; }