]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
mmc: dw_mmc: Extract divider update to a separate function
authorSam Protsenko <semen.protsenko@linaro.org>
Thu, 8 Aug 2024 03:14:11 +0000 (22:14 -0500)
committerMinkyu Kang <mk7.kang@samsung.com>
Mon, 19 Aug 2024 07:09:06 +0000 (16:09 +0900)
Extract the clock divider update into dwmci_update_div() function. It's
a procedure recommended in TRM, so it's better to keep it in a dedicated
function to make the code clearer.

While at it also extract the clock control code into a separate routine
to avoid code duplication in dwmci_setup_bus().

No functional change.

Signed-off-by: Sam Protsenko <semen.protsenko@linaro.org>
Signed-off-by: Minkyu Kang <mk7.kang@samsung.com>
drivers/mmc/dw_mmc.c

index 4a9e57165fbbb7a5c4a7c03226fee4f960273127..b9c14fe6857bff19eb8249e42fa3280b6ee2fc76 100644 (file)
@@ -410,11 +410,56 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
        return ret;
 }
 
-static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
+static int dwmci_control_clken(struct dwmci_host *host, bool on)
 {
-       u32 div, status;
+       const u32 val = on ? DWMCI_CLKEN_ENABLE | DWMCI_CLKEN_LOW_PWR : 0;
+       const u32 cmd_only_clk = DWMCI_CMD_PRV_DAT_WAIT | DWMCI_CMD_UPD_CLK;
        int timeout = 10000;
+       u32 status;
+
+       dwmci_writel(host, DWMCI_CLKENA, val);
+
+       /* Inform CIU */
+       dwmci_writel(host, DWMCI_CMD, DWMCI_CMD_START | cmd_only_clk);
+       do {
+               status = dwmci_readl(host, DWMCI_CMD);
+               if (timeout-- < 0) {
+                       debug("%s: Timeout!\n", __func__);
+                       return -ETIMEDOUT;
+               }
+       } while (status & DWMCI_CMD_START);
+
+       return 0;
+}
+
+/*
+ * Update the clock divider.
+ *
+ * To prevent a clock glitch keep the clock stopped during the update of
+ * clock divider and clock source.
+ */
+static int dwmci_update_div(struct dwmci_host *host, u32 div)
+{
+       int ret;
+
+       /* Disable clock */
+       ret = dwmci_control_clken(host, false);
+       if (ret)
+               return ret;
+
+       /* Set clock to desired speed */
+       dwmci_writel(host, DWMCI_CLKDIV, div);
+       dwmci_writel(host, DWMCI_CLKSRC, 0);
+
+       /* Enable clock */
+       return dwmci_control_clken(host, true);
+}
+
+static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
+{
+       u32 div;
        unsigned long sclk;
+       int ret;
 
        if ((freq == host->clock) || (freq == 0))
                return 0;
@@ -437,35 +482,9 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
        else
                div = DIV_ROUND_UP(sclk, 2 * freq);
 
-       dwmci_writel(host, DWMCI_CLKENA, 0);
-       dwmci_writel(host, DWMCI_CLKSRC, 0);
-
-       dwmci_writel(host, DWMCI_CLKDIV, div);
-       dwmci_writel(host, DWMCI_CMD, DWMCI_CMD_PRV_DAT_WAIT |
-                       DWMCI_CMD_UPD_CLK | DWMCI_CMD_START);
-
-       do {
-               status = dwmci_readl(host, DWMCI_CMD);
-               if (timeout-- < 0) {
-                       debug("%s: Timeout!\n", __func__);
-                       return -ETIMEDOUT;
-               }
-       } while (status & DWMCI_CMD_START);
-
-       dwmci_writel(host, DWMCI_CLKENA, DWMCI_CLKEN_ENABLE |
-                       DWMCI_CLKEN_LOW_PWR);
-
-       dwmci_writel(host, DWMCI_CMD, DWMCI_CMD_PRV_DAT_WAIT |
-                       DWMCI_CMD_UPD_CLK | DWMCI_CMD_START);
-
-       timeout = 10000;
-       do {
-               status = dwmci_readl(host, DWMCI_CMD);
-               if (timeout-- < 0) {
-                       debug("%s: Timeout!\n", __func__);
-                       return -ETIMEDOUT;
-               }
-       } while (status & DWMCI_CMD_START);
+       ret = dwmci_update_div(host, div);
+       if (ret)
+               return ret;
 
        host->clock = freq;